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:
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",&regs[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