0

For a university assignment, I have to describe and draw the command cycle of the LD (nn), dd command. To be exact, I was given this command:

    LD (0x1000), BC

which I interpret as putting the low order byte of BC to the address 0x1000, and the upper one to the address 0x1001. (correct me if I'm wrong)

Now, I found the description of that command in the Z80 CPU Manual.

Here's an image of that specific page: Here's an image of that specific page.

It says that there are 6 machine cycles and 20 T-states, but I have no clue about what cycles exactly the command consists of, and how to draw them.

So my questions are:

  1. How (or where) can I find the instructions which make up the LD (nn), dd command?
  2. How can I draw the machine cycles? Which one of them is read, write, etc?

Any help is much appreciated. Let me know if I missed any details that might be necessary to understand the problem.

2
  • 4
    Simply read that very manual from the start. It's your assignment, isn't it?
    – Raffzahn
    Apr 27 at 17:32
  • 3
    Indeed, the Z80 manual is one of the most detailed with respect to the bus cycle descriptions and has definitely more interesting pages than the one you showed. You want to read the "Timing" chapter, the "[Extended] addressing" chapter and, maybe, reflect a bit on what needs to happen in the CPU in order to make the instruction do. You will be learning a lot more than by simply reading answers on SE. Your answer should more or less end up like a concatenation of the pictures in the Timing chapter.
    – tofro
    Apr 27 at 18:02
4

Comments have already covered that the CPU manual should answer all your questions, but above and beyond that, immediate observations:

  1. ld (nn), bc is encoded as ed43 so that's two reads;
  2. the actual address, 0x1000 is also two bytes long, so that's another two reads;
  3. bc is two bytes long, so that must be two writes.

In total that's six memory accesses, from which you can draw the reasonable (and, as it happens, correct) assumption that the six machine cycles are four sequential reads from the program counter followed by two writes to 0x1000 and 0x1001.

The (4, 4, 3, 3, 3, 3) gives you the lengths of the various machine cycles, which is also a big clue as to the specific bus cycles in use. If you check out the relevant part of the manual — which includes diagrams — you'll notice that M1 cycles are associated with instruction fetches and take four cycles, and that other memory accesses take three. So that lines up.

4
  • Thanks, that helps a lot! I have one more question, though: could you please explain why "RLC (IX+d)" consists of (4, 4, 3, 5, 4, 3)? What do they stand for, I'm especially curious about that 5 T-states one, can't find any operation with such a length.
    – nooblet
    Apr 27 at 19:05
  • 3
    I may not be the best person to respond to this as I don't have the Z80 user guide to hand and therefore can't give you the primary source. But: [non-M1] reads and writes are always three cycles, so when the Z80 needs more calculation time it ends the read/write, making MREQ inactive, but leaves the existing value on the address bus. So the 5 is a 3-cycle read following by two cycles of a held address.
    – Tommy
    Apr 27 at 19:23
  • 1
    @nooblet: Despite having 8-bit and 16-bit instructions, the Z80 only has a 4-bit ALU which generally needs a cycle to fetch four bits of the operands, and then a cycle to write back the results, but it can overlap a write with the next read. Operations with the ALU can be overlapped with other operations in such a way that it doesn't hurt performance of 8-bit computations, but it severely limits the performance of 16-bit computations. When processing RLC (IX+d), the CPU discovers after fetching the second byte of the instruction that it will be using (IX+d) addressing. At that point...
    – supercat
    Apr 28 at 19:16
  • ...it fetches the displacement from the third byte of the instruction (even though it doesn't yet know which kind of shifting operations it will be performing). Once it has that, it can start adding IX to d while it fetches the fourth byte of the instruction. That would take 4 cycles, except that the 16-bit address computation takes 5. Then the Z80 loads the data, performs the shift (which takes two cycle), and writes it back, starting the write just before the result becomes available.
    – supercat
    Apr 28 at 19:20
1

This is how my emulator stores this instruction:

----------------------------------------------------------------------
|opc      T0 T1 MC1   MC2   MC3   MC4   MC5   MC6   MC7   mnem       |
|--------------------------------------------------------------------|
|ED43L1H1 20 00 M1R 4 M1R 4 MRD 3 MRD 3 MWR 3 MWR 3 ... 0 LD (U16),BC|
----------------------------------------------------------------------

so it has 2x4T M1 cycles as prefix 0xED is present to read the opc

then 2x3T read cycles for the address (low byte first, high byte second)

and then 2x3T write cycles for storing BC (low byte C first, high byte B second)

Your next queried instruction is like this:

----------------------------------------------------------------------
|opc      T0 T1 MC1   MC2   MC3   MC4   MC5   MC6   MC7   mnem       |
|--------------------------------------------------------------------|
|DDCBS106 23 00 M1R 4 M1R 4 MRD 3 MRD 5 MRD 4 MWR 3 ... 0 RLC (IX+S8)|
----------------------------------------------------------------------

the offset is 3th byte and followed by last byte of opc !!!. The 5T cycle is reading that offset + doing 16 bit addition ix+offset that is why its 2T longer ...

Here notes to my iset database:

----------------------------------------------------------------------
                Spektra software and hardware
          Z80 CPU instruction set database ver: 3.0
----------------------------------------------------------------------

database example:
----------------------------------------------------------------------
|opc      T0 T1 MC1   MC2   MC3   MC4   MC5   MC6   MC7   mnem       |
|--------------------------------------------------------------------|
|ED53L1H1 20 00 M1R 4 M1R 4 MRD 3 MRD 3 MWR 3 MWR 3 ... 0 LD (U16),DE|
----------------------------------------------------------------------
opc:    operation code [hex]
        L1,H1,U1,S1 means first operand direct number or adress
        L2,H2,U2,S2 means second operand direct number or adress
        L3,H3,U3,S3 means third operand direct number or adress
        H,L ... U16 high and low byte
        U   ... U8 unsigned byte
        S   ... S8 signed byte

T0      normal instruction duration [T] always 2 decimal digits
T1      instruction duration if condition not met [T] always 2 decimal digits

MC1++   Machine cycle first is type,second is duration [T] always 1 decimal digit
        ...     unused
        M1R     M1 cycle
        MRD     memory read
        MWR     memory write
        IOR     IO read
        IOW     IO write
        NON     no external operation (internal computation)
        INT     interrupt cycle

mnem    instruction text (mnemonic)

emulator internal instructions (not in database):
----------------------------------------------------------------------
|opc      T0 T1 MC1   MC2   MC3   MC4   MC5   MC6   MC7   mnem       |
|--------------------------------------------------------------------|
| -       11 00 M1R 5 MWR 3 MWR 3 ... 0 ... 0 ... 0 ... 0 NMI        |
| -       02 00 INT 2 ... 0 ... 0 ... 0 ... 0 ... 0 ... 0 INT0       |  // IM0
| -       13 00 INT 7 MWR 3 MWR 3 ... 0 ... 0 ... 0 ... 0 INT1       |  // IM1
| -       19 00 INT 7 MWR 3 MWR 3 MRD 3 MRD 3 ... 0 ... 0 INT2       |  // IM2
----------------------------------------------------------------------

note1:  condition C (carry) is unrecognizable from register C (BC)
        to recognize which it is, conditions (flags) are used only in
        instructions: CALL, JR, JP, RET

note2:  max size of opc is 4 bytes (8 digits), if opc is shorter spaces are added
        max num of MC is 7
        max size of mnemonic is 15 characters

note3:  aditional spaces are not allowed

note4:  normalized mnemonics:
        jp (hl) -> jp hl
        jp (ix) -> jp ix
        jp (iy) -> jp iy
        sub r8  -> sub a,r8
        cp  r8  -> cp  a,r8
        and r8  -> and a,r8
        or  r8  -> or  a,r8
        xor r8  -> xor a,r8
        
zexfix: ( fcpu ~ 40MHz, 20min )

Z80all instruction exerciser 

<adc,sbc> hl,<bc,de,hl,sp>...OK
add hl,<bc,de,hl,sp>.........OK
add ix,<bc,de,ix,sp>.........OK
add iy,<bc,de,iy,sp>.........OK
aluop a,nn...................OK
aluop a,<b,c,d,e,h,l,(hl),a>.OK
aluop a,<ixh,ixl,iyh,iyl>....OK
aluop a,(<ix,iy>+1)..........OK
bit n,(<ix,iy>+1)............OK
bit n,<b,c,d,e,h,l,(hl),a>...OK
cpd<r>.......................OK
cpi<r>.......................OK
<daa,cpl,scf,ccf>............OK
<inc,dec> a..................OK
<inc,dec> b..................OK
<inc,dec> bc.................OK
<inc,dec> c..................OK
<inc,dec> d..................OK
<inc,dec> de.................OK
<inc,dec> e..................OK
<inc,dec> h..................OK
<inc,dec> hl.................OK
<inc,dec> ix.................OK
<inc,dec> iy.................OK
<inc,dec> l..................OK
<inc,dec> (hl)...............OK
<inc,dec> sp.................OK
<inc,dec> (<ix,iy>+1)........OK
<inc,dec> ixh................OK
<inc,dec> ixl................OK
<inc,dec>  iyh...............OK
<inc,dec> iyl................OK
ld <bc,de>,(nnnn)............OK
ld hl,(nnnn).................OK
ld sp,(nnnn).................OK
ld <ix,iy>,(nnnn)............OK
ld (nnnn),<bc,de>............OK
ld (nnnn),hl.................OK
ld (nnnn),sp.................OK
ld (nnnn),<ix,iy>............OK
ld <bc,de,hl,sp>,nnnn........OK
ld <ix,iy>,nnnn..............OK
ld a,<(bc),(de)>.............OK
ld <b,c,d,e,h,l,(hl),a>,nn...OK
ld (<ix,iy>+1),nn............OK
ld <b,c,d,e>,(<ix,iy>+1).....OK
ld <h,l>,(<ix,iy>+1).........OK
ld a,(<ix,iy>+1).............OK
ld <ixh,ixl,iyh,iyl>,nn......OK
ld <bcdehla>,<bcdehla>.......OK
ld <bcdexya>,<bcdexya>.......OK
ld a,(nnnn) / ld (nnnn),a....OK
ldd<r> (1)...................OK
ldd<r> (2)...................OK
ldi<r> (1)...................OK
ldi<r> (2)...................OK
neg..........................OK
<rrd,rld>....................OK
<rlca,rrca,rla,rra>..........OK
shf/rot (<ix,iy>+1)..........OK
shf/rot <b,c,d,e,h,l,(hl),a>.OK
<set,res> n,<bcdehl(hl)a>....OK
<set,res> n,(<ix,iy>+1)......OK
ld (<ix,iy>+1),<b,c,d,e>.....OK
ld (<ix,iy>+1),<h,l>.........OK
ld (<ix,iy>+1),a.............OK
ld (<bc,de>),a...............OK
Tests complete

The complete iset database of mine (passing 100% ZEXALL test) can be obtained in here:

Not the answer you're looking for? Browse other questions tagged or ask your own question.