Question

I'm currently developing an emulator for the good old GameBoy and I'm facing some problems understandig how some basic operation codes have to be implemented.

Right now I'm implementing the AND operations; the first few (0xA0 -> 0xA3; 0xA6 & 0xA7) are pretty straight forward but the AND operations for the registers H, L are a bit different.

You can download the documention of the z80 under this link: um0080.pdf (page 172)

Here are some examples to show what I mean (with pseudo-code) and basically what I do:

AND A,H (note the bit-shifting)

(read HL register; >> 8) save in cache C
R->C = R->HL >> 8;

perform AND operation with cache
AND_H(R->C);
R->A &= R->C;

AND A,L (note the bit-masking)

(read HL register; &0xFF) save in cache C
R->C = R->HL &0xFF;

I know all the bit-operations and I know what they do, but it seems that I can't figure out why its need to be done like that. I have some theories (correct me if I'm wrong :-)):

What I already understood is, that the registers H and L are basically the register HL, which is an 16-Bit register. Since the CPU/Bus can only handle 8-Bit operations, it needs to be splitted up; or the more logic suggestion: since its only one register, the values of H and L are masked in the register and they simply need to be separated from each other (higher/lower nibble?).

I would be deeply grateful if someone can make this more clear to me because I just want to have some more background knowledge (how all this stuff works internally) so its very important to me that I know what I'm doing.

Was it helpful?

Solution

As comments have pointed out, the fact that the implementation you have found stores the H and L registers together as the 16-bit entity HL and then decomposes that into H by shifting right and into L by masking off is purely an implementation specific.

The original z80 has a 4-bit ALU (see Shima's comments starting at the bottom of Page 9 in this transcript of a Computer History Museum panel) so it would actually (i) AND the low four bits of L and the accumulator; then (ii) AND the high four bits of L and the accumulator. However it exposes its registers as discrete 8-bit entities so the internal implementation is entirely hidden.

HL is called a register pair because it's two registers taken together to make a 16-bit quantity. Ignoring the shadow and index registers, the original z80 actually has three of those — HL, BC and DE. BC and DE survive in the Gameboy's CPU as alternative pairs for indirect loading (such as opcode 0x1a — LD A, (BC)) and for 16-bit arithmetic (eg, 0x09 ADD HL, BC) and have a few other uses on a z80.

SP and PC are generally regarded as indivisible 16-bit registers (though, of course, you can divide them by storing them to memory and reading the bytes back individually) and AF exists for pushing and popping but F is such a special case that AF isn't usually particularly useful as a 16-bit integer.

Short summary then: you're not having problems with understanding how opcodes have to be implemented, merely how they have been implemented by a particular author.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top