CPCWiki forum

General Category => Programming => Topic started by: AMSDOS on 01:03, 15 October 15

Title: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: AMSDOS on 01:03, 15 October 15
Well this is certainly one I didn't know about, firmware addresses for instructions LDIR & LDDR.

I can only presume that a CALL or JP to these addresses is going to be slower than performing a LDIR or LDDR direct.

How do the timings compare between those and the instructions?  :)
Title: Re: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: IanS on 02:31, 15 October 15
They ultimately call LDIR or LDDR, but they make sure the rom state is correct (disabled) first.
Title: Re: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: andycadley on 06:04, 15 October 15
And, just as importantly, put it all back again afterwards. It's obviously slower than doing it directly, but much more convenient for ROM code to call, since that might end up having to do all the work anyway.
Title: Re: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: TFM on 23:43, 15 October 15
The coders of the CPC's firmware obviously have been 8080 coders (its not only me who told so), they haven't been acquainted to the additional commands of the Z80. This can be seen at many examples:

- The previously described LDIR case - imho a waste of space and totally needless
- No proper use of IM 2 which would have been really nice (ok, lack of proper daisy chain either)
- no usage of the 2nd register set at all (except ints)
- often: using routines clearly made for the 8080, a Z80 implementation would look different (shorter, more quick)
- Usage of the index registers (not per se, but the way how they use em)
- Waste of alternate registers for interrupt handling, which is the most stupid and sad problem:

Let me elaborate on this: An interrupt occurs every 1/300 seconds. This is once in 3330 us. To use EXX and EX AF,AF twice (save & restore) takes 4 us. PUSH and POP these registers would take 4 * (4+3) = 40 us.

So, using 2nd registers instead of PUSH/POP saves 36 us every interrupt!

Now if we would be able to use the 2nd register set then we could perform two routines or more similar, have Z80 registers instead of RAM registers (access is four times more quick, example EX AF,AF' is 1 us, but LD (xxxx),A is 4 us). So being able to use the 2nd register set boosts processing power between 30% and 200%. Lets say we only get the small 30% out of it. 30% of 3330 us is 999 us.

So, using 2nd register set for code (not interrupts) saves 999 us between two interrupts!

This is: 2775%

Of course there are some people telling: Oh you can use the 2nd register set. Yes that's true! I can do this by:
- Switching off interrupts
- Saving 2nd reg. file to RAM
- call routine
- Restoring 2nd reg.set
- Enabling Interrupts again.
Of course this is totally senseless, because all the speed up the 2nd reg.file brings get lost by the need of saving them to RAM all time long, also I probably will miss some interrupts and screw something.

I don't want to offend somebody, but it was about time to talk about it.  :) :) :)
Title: Re: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: AMSDOS on 03:07, 16 October 15
I can follow some of the stuff your saying TFM, but when it comes to the Alternative Register Set, I don't know much about it. Initially I got more excited when AA had a guide for the undocumented register set and had a Sprite Driver from an earlier AA which used a couple of them (instead of copying values to memory locations), though I'm unsure if any Assembler for the Amstrad supported that, so one had to resort to the opcodes.  :D

My fault for asking complicated questions that I don't quite know the answers to.
Title: Re: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: andycadley on 08:47, 16 October 15
I'm not sure I entirely agree, the original reason for including the alternate register set on the Z80 was for interrupt service routines to use. It's like a very primitive version of the kernel/user mode separation that you see on modern CPUs. I'd agree that from a M/C programmers point of view reserving them is undesirable, but I think the designers of the time were well aware that performance software was always going to push the OS out of the way and "hit the metal" directly. Contemporary Z80 based OS's tended to reserve them too, the Spectrum for example reserves both the alternate registers and the IY register (and it's OS is nowhere near as cleanly designed).

As to the KL LDIR/LDDR routines, they are absolutely necessary. If you want to be able to do a block copy from anywhere in the 64K of RAM to anywhere else you need to have disabled any ROM that is over the source area, which may well be where your current executing code is. The only way to guarantee it'll work is an indirection via a RAM routine. Again, most M/C programmers won't be in that situation, but the kernel programmers would often have been given that user programs will often be sat directly under the Lower ROM.
Title: Re: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: FloppySoftware on 11:39, 16 October 15
Use of alternate registers can be problematic.

For example standard CP/M don't use any Z80 instruction, only 8080.

That's cool. We can use the alternate registers freely in our CP/M programs if our machine has a Z80 cpu.

Can we?


The BIOS could use them for interrupts, etc., and some of them will not save them between calls.


It depends. On calls to the OS we can save/restore their values.

But what about interrupts?

IMHO this is the cause because some of use don't use the alternate registers, specially for generic Z80 or CP/M code.

Title: Re: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: arnoldemu on 11:55, 16 October 15
firmware uses BC' too. B is set to 0x07f. C is used to change mode and rom state.
Title: Re: KL LDIR (&B91B) & KL LDDR (&B91E)
Post by: TFM on 19:37, 16 October 15
Thanks guys for the interesting POV's an comments. Of course from a historical POV (like CP/M) it was quite a long way. Today things are different and we can use the full potential of our little friend the Z80.  ;)