Pointing to high and low bytes of something

  • Thread starter Lorenzo J. Lucchini
  • Start date
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
 
C

Chris Torek

I have used this little program for many years to discover the machine
endian-ness. Use it in good health.

[most of it snipped, but here is the output line]
printf( " %x %s %x isBigEndian = %s(%d)\n",
*firstBytePtr, isBigEndian ? "!=" : "==", ( unsigned char )testValue,
isBigEndian ? "TRUE" : "FALSE", isBigEndian );

So, which endian-ness does this claim for the PDP-11? Which one
*should* it claim? The PDP-11 has little-endian bytes-in-16-bit-words
and big-endian 16-bit-words-in-32-bit-longs (and also in floats).

If you give up control of endian-ness and choose instead to match
the byte order of your local machine(s), be aware that there are
more than two.
 
D

Dan Pop

In said:
If you give up control of endian-ness and choose instead to match
the byte order of your local machine(s), be aware that there are
more than two.

However, the large popularity of the terms "big endian" and "little
endian" is a strong hint that all the others are history.

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,102
Messages
2,570,645
Members
47,247
Latest member
GabrieleL2

Latest Threads

Top