D
Dan Pop
In said:[email protected] (Dan Pop) wrote in message news: said:In said:[Registers and register pairs on a Z80 and how to handle a
simulation of them in C]
The "no assumptions" solution is to simply use an array of unsigned char
for storing the values of the individual registers, in the order
B, C, D, E, H, L, padding or F, A. This order is made obvious by the
Z80/8080 instruction encoding.
When you need a register pair, you compute it on the fly:
words[DE] = (unsigned)regs[D] << 8 + regs[E];
When an instruction has modified a register pair (few Z80 and even fewer
8080 instructions can do that), you update the individual registers:
regs[D] = words[DE] >> 8;
regs[E] = words[DE] & 0xFF;
I also believe that this approach will actually simplify the overall
coding of your simulator, because it allows using the register fields
inside the opcodes to be used as indices in the array, so you never have
to figure out what is the variable corresponding to a value of 2 in the
register field, you simply use 2 as an index in the registers array.
The instruction decoding becomes a piece of cake, this way.
While it looks like this approach will require some quite extensive
reworking of my code - which I hoped to avoid -, it does look
extremely interesting. I'll do it.
To show you how it works, here's a function covering a quarter of the 8080
opcode space:
#define BC 0
#define DE 1
#define HL 2
#define COMP(rp) ((unsigned)regs[rp * 2] << 8 + regs[rp * 2 + 1])
#define SYNC(rp) (words[rp] = COMP(rp))
#define SPILL(rp) (regs[rp * 2] = words[rp] >> 8,\
regs[rp * 2 + 1] = words[rp] & 0xFF)
unsigned char regs[8], shadowregs[8], mem[0x10000];
unsigned words[3], ix, iy, pc, sp;
void ld8rr(int opcode)
{
int dest = (opcode & 0x38) >> 3;
int src = opcode & 7;
assert(opcode != 0x76); /* that's the HALT opcode! */
if (dest != 6 && src != 6) {
regs[dest] = regs[src];
return;
}
if (dest == 6) {
mem[COMP(HL)] = regs[src];
return;
}
regs[dest] = mem[COMP(HL)];
return;
}
COMP merely computes the value of a register pair, while SYNC also
syncronizes the respective element of the words array. SPILL is used
to update the regs when a 16-bit instruction has changed the value of a
register pair.
Dan