funk_emu: Funky Emulator
Memory
Used only for storing program instructions. Normally a single instruction (or integer) stored in memory spans
several bytes.
Registers
There are 8 registers numbered 0 through 7.
Fear registers 4 and 5--do not use them. All other registers are
free for
programmer use.
Instructions
Most instructions are 2 bytes long. The first byte indicates
what's happening, and the second byte indicates what it's happening
to. The first byte is usually written in hex; the second byte is
usually written in octal; but as explained below you can write any byte
in any base. Here's a selection of instructions, but see the whole list
below:
- 0xC3 Return from the emulator. The value in register 0 is printed out.
- 0xBd value "Move immediate". Sets register d to value. For example, "0xB3 7" sets register 3 to the value 7. Only unsigned byte values are supported.
- 0x03 03ds "Add". Increases the value in register d by the value in register s. For example, "0x03 0312" increases register 1 by register 2.
- 0x3B 03ab "Compare". Sets the less-than flag if the value in register a is less than the value in register b. For example, "0x3B 0312" will set less-than if register 1 is less than register 2.
- 0x7C offset "Jump if less-than". Adds the signed byte offsetto
the program counter if the less-than flag is set. The program
counter is relative to the start of the next instruction. For example,
"0x7C 0xFE" is an infinite loop if the less-than flag is set, because
it jumps back to the start of the jump instruction.
- 0xFF 0x57 0xv0 "Special". The only three-byte instruction. The function performed depends on the value of v.
"0xFF 0x57 0x00" dumps all registers. "0xFF 0x57 0x10" prints
register 0. "0xFF 0x57 0x20" reads an integer from the input file
into register 0.
Staring at the CPU::run code reveals all the instructions supported by funk_emu:
int opcode=mem[pc++]; /* First byte tells you what's happening */
int next=mem[pc++]; /* next byte tells you who it's happening to */
int dest=(next&070)>>3, src=next&007; /* destination and source registers */
/* decode instruction */
switch (opcode) {
case 0xC3: return regs[0]; break; /* RET--return a value to outside program */
/* Data moves */
case 0x8B: regs[dest] = regs[src]; break; /* MOV */
case 0xB0: case 0xB1: case 0xB2: case 0xB3: /* MOV immediate (0xB0+dest) */
regs[opcode&007] = next; break;
/* Arithmetic */
case 0x03: regs[dest] += regs[src]; break; /* ADD */
case 0x2B: regs[dest] -= regs[src]; break; /* SUB */
case 0x23: regs[dest] &= regs[src]; break; /* AND */
case 0x09: regs[dest] |= regs[src]; break; /* OR */
case 0x33: regs[dest] ^= regs[src]; break; /* XOR */
/* Control */
case 0x3B: lessflag = regs[dest]<regs[src]; break; /* CMP: compare */
case 0x7C: if (lessflag) pc+=(signed char)next; break; /* JL: jump-if-less */
case 0xEB: pc+=(signed char)next; break; /* JMP */
/* Special instructions */
case 0x90: break; /* NOP-- do nothing! */
case 0xFF:
if (next!=0x57) quit("Bad 0xFF instruction %02x at pc %d\n",pc-3);
else switch (mem[pc++]) {
case 0x00: dump(pc-3); break;
case 0x10: printf("Register 0 is %d (0x%08X)\n",regs[0],regs[0]); break;
case 0x20: fscanf(f,"%i",®s[0]); break;
default: quit("Unrecognized special 0xff function at pc %d\n",pc-3); break;
};
break;
default: quit("Unrecognized opcode 0x%x at pc %d\n",opcode,pc-2); break;
Input File
The first section of the input file consists of
bytes. Bytes can be written in hex (0xF3), octal (0312), or
decimal (17). All bytes are interpreted as machine-language
instructions. Exclamation marks (or anything else that
isn't a byte) will be treated as comments and the rest of the line will
be ignored.
The second section of the input file begins with a negative
number. -2 indicates verbose output is desired--the emulator will
print out lots of debugging crap. Any other integer indicates a
normal terse run.
Subsequent integers can be read by the program using the "0xFF 0x57 0x20" instruction.
You can pass the input filename in as a command-line parameter,
drag-and-drop the input file onto funk_emu, or copy the input file to
"input.txt" and run uemu without parameters.
See the examples/ directory for some simple example programs.
Be aware that the Windows version will expect Windows newline
characters in your input files. If your newlines get screwed up
(for example, the file looks weird in notepad and some of your
instructions don't dump out right) you can fix them by viewing the file
in a web browser and Save As text.
Download the source, Windows and Linux binary, and examples
(Zip, Tar-gzip).
O. Lawlor, ffosl@uaf.edu
Up to: Class Site, CS, UAF