Shadow registers.

edited March 2012 in Development
I assume it's faster to transfer the registers to the shadow registers rather than using the stack? Let's say that I want to temporarily preserve the values of af and hl only, should I transfer af to the shadow and push hl? Or will ex af, af' and exx work quicker in this case (even though I'm also swapping bc and de with exx)?

Regards,

Shaun.
Post edited by Shaun.Bebbington on

Comments

  • oboobo
    edited March 2012
    Both EX AF,AF' and EXX are just 4 t-states each, so they're as fast as a NOP -- much faster than a push (11T) and pop (10T) combo. If changing BC+DE isn't a problem it's probably the best approach.

    If you need to use A for something else you could also just assign it to a different spare register, which is also as fast as EX AF,AF'. As a bonus it doesn't affect the current flags, if you need them.

    Except for advanced techniques for batch filling and copying, stack operations are fairly slow, and best avoided in speed-critical code. It's convenient though, so still well worth using for other cases.
  • edited March 2012
    Each exchange only takes four cycles - that's as fast as you can get, the same as a NOP. PUSH and POP take longer at 11 and 10 cycles each, assuming the memory isn't in contention. Or add on another four for PUSH/POP IX/IY (and you can't exchange them).

    If you are exchanging AF, remember that you've altered the flags as well as A. And you could be more efficient by making sure what you want to save is in BC, DE and/or HL so they all get saved with just one instruction.

    And unless you're using it to actually address memory, the IX/IY instructions only add another four cycles to each instruction so sometimes it's easier to use one of those than do exchanges or use the stack. (If you do use them to read or write an address in memory, there's a bit longer while the processor adds on an offset as part of the instruction).
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2012
    Actually, here's something I've never tried. If you can do:

    EX DE,HL

    Can you also do:

    EX DE,IX
    and EX DE,IY ?
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2012
    And to answer my own question, according to this:
    http://www.worldofspectrum.org/z88forever/dn327/z80undoc.htm

    No.
    Main instruction                Effect of preceding DD
    
    LD H,(HL)                       Causes LD H,(IX+d)
    LD (HL),H                       Causes LD (IX+d),H
    LD L,(HL)                       Causes LD L,(IX+d)
    LD (HL),L                       Causes LD (IX+d),L
    EX DE,HL                        None (left as EX DE,HL)
    EXX                             None (left as EXX)
    
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2012
    deleted
  • edited March 2012
    deleted
  • edited March 2012
    Thanks guys, that makes sense.

    Regards,

    Shaun.
  • edited March 2012
    joefish wrote: »
    Each exchange only takes four cycles - that's as fast as you can get, the same as a NOP. PUSH and POP take longer at 11 and 10 cycles each, assuming the memory isn't in contention. Or add on another four for PUSH/POP IX/IY (and you can't exchange them).

    If you are exchanging AF, remember that you've altered the flags as well as A. And you could be more efficient by making sure what you want to save is in BC, DE and/or HL so they all get saved with just one instruction.

    And unless you're using it to actually address memory, the IX/IY instructions only add another four cycles to each instruction so sometimes it's easier to use one of those than do exchanges or use the stack. (If you do use them to read or write an address in memory, there's a bit longer while the processor adds on an offset as part of the instruction).
    So, a safe and fast way to do it would be to exx first (frees up, say, BC), and then transfer af to bc, do some code, transfer bc back and then exx again before returning. Okay, sounds good.

    Regards,

    Shaun.
  • edited March 2012
    joefish wrote: »
    Actually, here's something I've never tried. If you can do:

    EX DE,HL

    Can you also do:

    EX DE,IX
    and EX DE,IY ?

    You've already worked out the answer, but the reason for this is that EX DE, HL is implemented as an internal toggle in the Z80 which swaps where the core looks when asked for "DE" or "HL". (This is also why EX DE, HL is as fast as a NOP - because it's not actually moving any data around at all).
  • edited March 2012
    So, a safe and fast way to do it would be to exx first (frees up, say, BC), and then transfer af to bc, do some code, transfer bc back and then exx again before returning. Okay, sounds good.

    Regards,

    Shaun.

    It's not what I meant; you can if you want to, but only with the 8-bit value of A. You can't copy F to or from another register.

    What I meant was, if you're trying to save something in HL and A at the same time, instead of using A, consider using B or C for that job instead (if you can). Then when you do EXX it saves them both in one go.

    But if you want to do HL and AF separately, you can do so easily with the EXX and EX AF,AF' instructions.

    What obo was saying is that if you copy A into B and get it back again later (i.e. LD B,A then later LD A,B) it takes exactly the same time as doing EX AF,AF' twice. (Though it won't save or alter the flags in F).
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2012
    joefish wrote: »
    Can you also do:

    EX DE,IX
    and EX DE,IY ?

    I previously mapped all these cases here.

    The only one that works with IX is EX (SP),IX.
    Creator of ZXDB, BIFROST/NIRVANA, ZX7/RCS, etc. I don't frequent this forum anymore, please look for me elsewhere.
  • edited March 2012
    I previously mapped all these cases here.

    The only one that works with IX is EX (SP),IX.

    lol i remember the same conversation from 15 years ago. when topics keep recycling one's probably been here too long :P
  • edited March 2012
    So, a safe and fast way to do it would be to exx first (frees up, say, BC), and then transfer af to bc, do some code, transfer bc back and then exx again before returning. Okay, sounds good.

    As you've found out, EXX means you've lost access to the data in registers you were working on, data which you may need to continue processing post-EXX. This makes using EXX less attractive because you need to forward data somehow across the EXX. This can be done through AF, IX, or IY which are unaffected by the EXX. You may even succumb to a push/exx/pop to communicate the data.

    EXX works really well if you are doing two almost parallel things at once. Otherwise it is *usually* quicker and more compact to use IX or IY as an extra register. You can split IX and IY into their 8 bit constituents (just as you can split HL into H and L) and use them as extra 8-bit registers with only a 4-cycle penalty.

    Though undocumented, the 8-bit split of IX/IY is not undocumented in the sense that -- omg -- this happens by some accident of random logic on the chip. These instructions have always been designed into the z80 core but were left undocumented to improve on chip yields in the very early days of the z80's manufacture. Every z80, in particular the later CMOS version, will work with these instructions so it is fine to use them in general sw.
Sign In or Register to comment.