| The simplest emulator in the world would be like this one: unsigned char memory[65536]; int reg[8]; int main(void) { int pc = 0;
/* In this point you read something into memory */
while (1) {
instruction = memory[pc];
if (instruction == 0x76) break; /* HLT */
pc = (pc + 1) & 0xffff;
if ((instruction & 0xc0) == 0x40) /* Handle MOV r,r (opcodes 0x40-0x7f) */
reg[(instruction >> 3) & 7] = reg[instruction & 7];
}
return 0;
}What it does? It simply reads each instruction from memory (PC is the Program Counter), and increments PC continuously limiting it to 16-bit. It does a comparison for each possible instruction, for this example I only handled the most basic one of 8080 (MOV r,r) and HLT, but this is already 64 cases of the 256 possible! Then I added iteratively chunks of opcodes to emulate and used language C macros to reduce the code size. For example, there is #define d(e) to join two 8-bit registers into a 16-bit value, and #define Q to read the accumulator. In the end, to stay inside the size limit of the IOCCC, I removed the tree of 'if' statements and replaced it with a tree of trinary operators ?: (a way of doing 'if' inside an expression) and this is what the macros C and S does. |