summaryrefslogtreecommitdiff
path: root/miniemu
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-01-01 19:31:12 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2017-01-01 19:31:12 +0100
commit69fe7b182a1eedfb75c611f7dd35fa60200426f4 (patch)
tree329a0c6cc9b06c23d8782ece09f0f7dfa9b16b13 /miniemu
downloadcompilertests-69fe7b182a1eedfb75c611f7dd35fa60200426f4.tar.gz
compilertests-69fe7b182a1eedfb75c611f7dd35fa60200426f4.tar.bz2
initial checkin
Diffstat (limited to 'miniemu')
-rw-r--r--miniemu/README102
-rw-r--r--miniemu/TESTS2
-rw-r--r--miniemu/const.h5
-rw-r--r--miniemu/cpu.c457
-rw-r--r--miniemu/cpu.h25
-rw-r--r--miniemu/main.c46
-rw-r--r--miniemu/memory.c83
-rw-r--r--miniemu/memory.h14
-rw-r--r--miniemu/opcodes.h148
9 files changed, 882 insertions, 0 deletions
diff --git a/miniemu/README b/miniemu/README
new file mode 100644
index 0000000..6b27b32
--- /dev/null
+++ b/miniemu/README
@@ -0,0 +1,102 @@
+Design
+------
+
+- MISC or RISC
+- load/store or allow things like adding register to memory
+- make most aspect configurable at runtime because we want to use
+ it to stress the compiler (things like "what if we have 1k RAM
+ and 4 registers?")
+- fixed size instruction set or not or how much do we care about
+ being optimized to be implementable in hardware or in FPA?
+- the PDB-8 had 8 opcodes? MISC requires 32 or less opcodes
+- RISC requires operands to be part of the opcode, this is not
+ really practicable with 8-bit words, mostly RISCs are 32 or
+ 64 bit wasting tons of memory for code.
+- von Neumann or Harvard?
+
+Opcodes
+-------
+
+Load/Store
+
+MOV
+
+Integer Arithmetic and logical operations
+
+ADD
+SUB
+MUL
+DIV
+
+INC
+DEC
+
+AND
+OR
+NOT
+XOR
+NEG
+
+SHR
+SHL
+ROTR
+ROTL
+
+Floating Point Arithmetic
+
+FADD
+FSUB
+FMUL
+FDIV
+
+Testing and Branching
+
+CMP
+
+JC
+JNC
+JZ
+JNZ
+
+Subroutine
+
+CALL
+RET
+
+Not sure about those
+
+Stack
+
+PUSH
+POP
+
+I/O-ports
+
+GET
+PUT
+
+Other
+
+HLT
+NOP
+
+not sure about NOP, as long as we don't do branch-prediction or
+code patching for relocation?
+
+Building
+--------
+
+gcc -I../minilib -g -O0 -m32 -march=i386 -ffreestanding -Werror -Wall -Wno-return-type -pedantic -std=c89 -o miniemu *.c ../minilib/*.c
+clang -I../minilib -g -O0 -march=i386 -fno-builtin -std=c89 -Werror -Wall -Wno-return-type -o miniemu *.c ../minilib/*.c
+
+Usage
+-----
+
+./miniemu test1.bin
+./miniemu test2.bin
+./miniemu test3.bin
+./miniemu test4.bin
+./miniemu test5.bin
+./miniemu test6.bin
+./miniemu test7.bin
+./miniemu test8.bin
diff --git a/miniemu/TESTS b/miniemu/TESTS
new file mode 100644
index 0000000..b233c35
--- /dev/null
+++ b/miniemu/TESTS
@@ -0,0 +1,2 @@
+test1.bin - illegal opcode
+test2.bin - sequence of nops and a terminating halt
diff --git a/miniemu/const.h b/miniemu/const.h
new file mode 100644
index 0000000..76ed52d
--- /dev/null
+++ b/miniemu/const.h
@@ -0,0 +1,5 @@
+#pragma once
+
+enum {
+ DEFAULT_MEMORY_SIZE = 256
+};
diff --git a/miniemu/cpu.c b/miniemu/cpu.c
new file mode 100644
index 0000000..26e1469
--- /dev/null
+++ b/miniemu/cpu.c
@@ -0,0 +1,457 @@
+#include "cpu.h"
+#include "memory.h"
+#include "io.h"
+#include "string.h"
+#include "utils.h"
+#include "const.h"
+#include "opcodes.h"
+#include "utils.h"
+#include "minilib.h"
+
+void cpu_init( Cpu *cpu, struct Memory *memory )
+{
+ cpu->memory = memory;
+ cpu_reset( cpu );
+}
+
+void cpu_done( Cpu *cpu )
+{
+}
+
+void cpu_reset( Cpu *cpu )
+{
+ cpu->PC = 0;
+ cpu->AX = 0;
+ cpu->BX = 0;
+ cpu->CX = 0;
+ cpu->DX = 0;
+ cpu->SP = cpu->memory->size - 1;
+ cpu->stopped = 0;
+ cpu->error = 0;
+ cpu->debug = 0;
+ cpu->memory->m[cpu->PC] = OPCODE_HLT;
+ cpu->Z = 0;
+ cpu->C = 0;
+}
+
+static int read_src_value( Cpu *cpu, int instruction )
+{
+ int value;
+
+ switch( instruction & OPCODE_SRC_MASK ) {
+ case OPCODE_SRC_AX_REG:
+ value = cpu->AX;
+ break;
+
+ case OPCODE_SRC_BX_REG:
+ value = cpu->BX;
+ break;
+
+ case OPCODE_SRC_CX_REG:
+ value = cpu->CX;
+ break;
+
+ case OPCODE_SRC_DX_REG:
+ value = cpu->DX;
+ break;
+
+ case OPCODE_SRC_CONST:
+ cpu->PC++;
+ value = memory_read( cpu->memory, cpu->PC );
+ break;
+ }
+
+ return value;
+}
+
+static int read_dst_value( Cpu *cpu, int instruction )
+{
+ int value;
+
+ switch( instruction & OPCODE_DST_MASK ) {
+ case OPCODE_DST_AX_REG:
+ value = cpu->AX;
+ break;
+
+ case OPCODE_DST_BX_REG:
+ value = cpu->BX;
+ break;
+
+ case OPCODE_DST_CX_REG:
+ value = cpu->CX;
+ break;
+
+ case OPCODE_DST_DX_REG:
+ value = cpu->DX;
+ break;
+ }
+
+ return value;
+}
+
+static int write_dst_value( Cpu *cpu, int instruction, int value )
+{
+ switch( instruction & OPCODE_DST_MASK ) {
+ case OPCODE_DST_AX_REG:
+ cpu->AX = value;
+ break;
+
+ case OPCODE_DST_BX_REG:
+ cpu->BX = value;
+ break;
+
+ case OPCODE_DST_CX_REG:
+ cpu->CX = value;
+ break;
+
+ case OPCODE_DST_DX_REG:
+ cpu->DX = value;
+ break;
+ }
+}
+
+static int write_src_value( Cpu *cpu, int instruction, int value )
+{
+ switch( instruction & OPCODE_SRC_MASK ) {
+ case OPCODE_SRC_AX_REG:
+ cpu->AX = value;
+ break;
+
+ case OPCODE_SRC_BX_REG:
+ cpu->BX = value;
+ break;
+
+ case OPCODE_SRC_CX_REG:
+ cpu->CX = value;
+ break;
+
+ case OPCODE_SRC_DX_REG:
+ cpu->DX = value;
+ break;
+ }
+}
+
+static void execute_jmp( Cpu *cpu, int instruction )
+{
+ int address;
+ int condition;
+
+ cpu->PC++;
+ address = memory_read( cpu->memory, cpu->PC );
+ condition = 0;
+
+ switch( instruction & OPCODE_JMP_MASK ) {
+ case OPCODE_JMP_JMP:
+ condition = 1;
+ break;
+
+ case OPCODE_JMP_JE:
+ condition = ( cpu->Z == 1 );
+ break;
+
+ case OPCODE_JMP_JNE:
+ condition = ( cpu->Z == 0 );
+ break;
+
+ case OPCODE_JMP_JB:
+ condition = ( cpu->C == 1 );
+ break;
+
+ case OPCODE_JMP_JBE:
+ condition = ( cpu->C == 1 ) || ( cpu->Z == 1 );
+ break;
+
+ case OPCODE_JMP_JA:
+ condition = ( cpu->C == 0 ) && ( cpu->Z == 0 );
+ break;
+
+ case OPCODE_JMP_JAE:
+ condition = ( cpu->C == 0 );
+ break;
+
+ case OPCODE_JMP_JSR:
+ condition = 1;
+ memory_write( cpu->memory, cpu->SP, cpu->PC + 1 );
+ cpu->SP--;
+ break;
+
+ default:
+ print( "ILLEGAL JUMP INSTRUCTION" );
+ cpu->stopped = 1;
+ cpu->error = 1;
+ return;
+ }
+
+ if( condition ) {
+ cpu->PC = address;
+ } else {
+ cpu->PC++;
+ }
+}
+
+static void execute_not( Cpu *cpu, int instruction )
+{
+ int value;
+
+ value = read_src_value( cpu, instruction );
+ write_src_value( cpu, instruction, (unsigned char)~value );
+
+ cpu->PC++;
+}
+
+static void execute_stack( Cpu *cpu, int instruction )
+{
+ int value;
+
+ switch( instruction & OPCODE_STACK_POP ) {
+ case OPCODE_STACK_PUSH:
+ value = read_src_value( cpu, instruction & OPCODE_STACK_OPERAND_MASK );
+ memory_write( cpu->memory, cpu->SP, value );
+ cpu->SP--;
+ break;
+
+ case OPCODE_STACK_POP:
+ cpu->SP++;
+ value = memory_read( cpu->memory, cpu->SP );
+ write_src_value( cpu, instruction & OPCODE_STACK_OPERAND_MASK, value );
+ break;
+ }
+
+ cpu->PC++;
+}
+
+static void execute_mov_ld( Cpu *cpu, int instruction )
+{
+ int value;
+
+ value = read_src_value( cpu, instruction );
+ write_dst_value( cpu, instruction, value );
+
+ cpu->PC++;
+}
+
+static void execute_or( Cpu *cpu, int instruction )
+{
+ int value1;
+ int value2;
+
+ value1 = read_src_value( cpu, instruction );
+ value2 = read_dst_value( cpu, instruction );
+
+ write_dst_value( cpu, instruction, value2 | value1 );
+
+ cpu->PC++;
+}
+
+static void execute_and( Cpu *cpu, int instruction )
+{
+ int value1;
+ int value2;
+
+ value1 = read_src_value( cpu, instruction );
+ value2 = read_dst_value( cpu, instruction );
+
+ write_dst_value( cpu, instruction, value2 & value1 );
+
+ cpu->PC++;
+}
+
+static void execute_sub( Cpu *cpu, int instruction )
+{
+ int value1;
+ int value2;
+
+ value1 = read_src_value( cpu, instruction );
+ value2 = read_dst_value( cpu, instruction );
+
+ write_dst_value( cpu, instruction, value2 - value1 );
+
+ cpu->PC++;
+}
+
+static void execute_cmp( Cpu *cpu, int instruction )
+{
+ int value1;
+ int value2;
+
+ value1 = read_src_value( cpu, instruction );
+ value2 = read_dst_value( cpu, instruction );
+
+ cpu->Z = ( value1 - value2 == 0 );
+ cpu->C = ( value1 - value2 < 0 );
+
+ cpu->PC++;
+}
+
+static void execute_add( Cpu *cpu, int instruction )
+{
+ int value1;
+ int value2;
+
+ value1 = read_src_value( cpu, instruction );
+ value2 = read_dst_value( cpu, instruction );
+
+ write_dst_value( cpu, instruction, value1 + value2 );
+
+ cpu->PC++;
+}
+
+static void execute_ret( Cpu *cpu, int instruction )
+{
+ cpu->SP++;
+
+ if( cpu->SP > DEFAULT_MEMORY_SIZE ) {
+ print( "ERROR STACK OVERFLOW" );
+ cpu->error = 1;
+ cpu->stopped = 1;
+ return;
+ }
+
+ cpu->PC = memory_read( cpu->memory, cpu->SP );
+}
+
+void cpu_step( Cpu *cpu )
+{
+ unsigned char instruction;
+
+ instruction = (unsigned char)memory_read( cpu->memory, cpu->PC );
+
+ if( cpu->debug ) {
+ char s[10];
+ char buf[5];
+ *buf = '\0';
+ inttohex( instruction, buf );
+ *s = '\0';
+ strcat( s, "INSTR: " );
+ strcat( s, buf );
+ print( s );
+ }
+
+ if( instruction & OPCODE_GROUP_TWO_OPERANDS ) {
+ switch( instruction & OPCODE_GROUP_TWO_OPERANDS ) {
+ case OPCODE_MOV_LD:
+ execute_mov_ld( cpu, instruction );
+ break;
+
+ case OPCODE_OR:
+ execute_or( cpu, instruction );
+ break;
+
+ case OPCODE_AND:
+ execute_and( cpu, instruction );
+ break;
+
+ case OPCODE_SUB:
+ execute_sub( cpu, instruction );
+ break;
+
+ case OPCODE_CMP:
+ execute_cmp( cpu, instruction );
+ break;
+
+ case OPCODE_ADD:
+ execute_add( cpu, instruction );
+ break;
+
+ default:
+ print( "ILLEGAL TWO OPERAND INSTRUCTION" );
+ cpu->stopped = 1;
+ cpu->error = 1;
+ }
+ } else if( ( instruction & OPCODE_GROUP_ONE_OPERAND ) ) {
+ switch( instruction & OPCODE_GROUP_ONE_OPERAND ) {
+ case OPCODE_JMP:
+ execute_jmp( cpu, instruction );
+ break;
+
+ case OPCODE_NOT:
+ execute_not( cpu, instruction );
+ break;
+
+ case OPCODE_STACK:
+ execute_stack( cpu, instruction );
+ break;
+
+ default:
+ print( "ILLEGAL ONE OPERAND INSTRUCTION" );
+ cpu->stopped = 1;
+ cpu->error = 1;
+ }
+ } else if( ( instruction & OPCODE_GROUP_ZERO_OPERANDS ) ) {
+ switch( instruction & OPCODE_GROUP_ZERO_OPERANDS ) {
+ case OPCODE_HLT:
+ print( "CPU HALTED" );
+ cpu->stopped = 1;
+ cpu->PC++;
+ break;
+
+ case OPCODE_NOP:
+ cpu->PC++;
+ break;
+
+ case OPCODE_RET:
+ execute_ret( cpu, instruction );
+ break;
+
+ default:
+ print( "ILLEGAL ZERO OPERAND INSTRUCTION" );
+ cpu->stopped = 1;
+ cpu->error = 1;
+ }
+ } else {
+ print( "ILLEGAL INSTRUCTION GROUP" );
+ cpu->stopped = 1;
+ cpu->error = 1;
+ }
+}
+
+int cpu_stopped( Cpu *cpu )
+{
+ return cpu->stopped;
+}
+
+int cpu_has_errors( Cpu *cpu )
+{
+ return cpu->error;
+}
+
+void cpu_debug( Cpu *cpu, int enable )
+{
+ cpu->debug = enable;
+
+ if( cpu->debug ) {
+ print( "DEBUGGING ENABLED" );
+ } else {
+ print( "DEBUGGING DISABLED" );
+ }
+}
+
+static void print_register( char *name, int v )
+{
+ char s[10];
+ char buf[5];
+
+ *s = '\0';
+ strcat( s, " " );
+ strcat( s, name );
+ strcat( s, ": " );
+
+ *buf = '\0';
+ inttohex( v, buf );
+ strcat( s, buf );
+
+ print( s );
+}
+
+void cpu_print_dump( Cpu *cpu )
+{
+ print_register( "PC", cpu->PC );
+ print_register( "AX", cpu->AX );
+ print_register( "BX", cpu->BX );
+ print_register( "CX", cpu->CX );
+ print_register( "DX", cpu->DX );
+ print_register( "SP", cpu->SP );
+ print_register( "Z", cpu->Z );
+ print_register( "C", cpu->C );
+ print_register( "F", cpu->error );
+}
diff --git a/miniemu/cpu.h b/miniemu/cpu.h
new file mode 100644
index 0000000..7a3d554
--- /dev/null
+++ b/miniemu/cpu.h
@@ -0,0 +1,25 @@
+#pragma once
+
+typedef struct Cpu {
+ int PC;
+ int AX;
+ int BX;
+ int CX;
+ int DX;
+ int SP;
+ struct Memory *memory;
+ int stopped;
+ int error;
+ int debug;
+ int Z;
+ int C;
+} Cpu;
+
+extern void cpu_init( Cpu *cpu, struct Memory *memory );
+extern void cpu_done( Cpu *cpu );
+extern void cpu_reset( Cpu *cpu );
+extern void cpu_step( Cpu *cpu );
+extern int cpu_stopped( Cpu *cpu );
+extern int cpu_has_errors( Cpu *cpu );
+extern void cpu_debug( Cpu *cpu, int enable );
+extern void cpu_print_dump( Cpu *cpu );
diff --git a/miniemu/main.c b/miniemu/main.c
new file mode 100644
index 0000000..f05973e
--- /dev/null
+++ b/miniemu/main.c
@@ -0,0 +1,46 @@
+#include "const.h"
+#include "cpu.h"
+#include "memory.h"
+#include "io.h"
+#include "opcodes.h"
+
+int main( int argc, char *argv[] )
+{
+ Cpu cpu;
+ Memory memory;
+ int retcode;
+
+ if( argc != 2 ) {
+ print( "USAGE: miniemu <memory.bin>" );
+ return 1;
+ }
+
+ memory_init( &memory, DEFAULT_MEMORY_SIZE );
+ cpu_init( &cpu, &memory );
+
+ print( "EMULATOR STARTED" );
+
+ print( "LOADING MEMORY DUMP" );
+ memory_read_from_file( &memory, argv[1] );
+
+ cpu_debug( &cpu, 1 );
+
+ while( !cpu_stopped( &cpu ) ) {
+ cpu_step( &cpu );
+ }
+
+ retcode = cpu_has_errors( &cpu );
+
+ print( "CPU" );
+ cpu_print_dump( &cpu );
+
+ print( "MEMORY" );
+ memory_print_dump( &memory );
+
+ cpu_done( &cpu );
+ memory_done( &memory );
+
+ print( "EMULATOR TERMINATED" );
+
+ return retcode;
+}
diff --git a/miniemu/memory.c b/miniemu/memory.c
new file mode 100644
index 0000000..2f1efb4
--- /dev/null
+++ b/miniemu/memory.c
@@ -0,0 +1,83 @@
+#include "memory.h"
+#include "arena.h"
+#include "io.h"
+#include "minilib.h"
+#include "string.h"
+#include "utils.h"
+#include "io.h"
+
+void memory_init( Memory *memory, int size )
+{
+ memory->size = size;
+ memory->m = allocate( size );
+ memory_reset( memory );
+}
+
+void memory_done( Memory *memory )
+{
+ deallocate( (void **)&memory->m );
+}
+
+void memory_reset( Memory *memory )
+{
+ memset( memory->m, 0, memory->size );
+}
+
+void memory_write( Memory *memory, int addr, char v )
+{
+ if( addr < 0 || addr > memory->size ) {
+ print( "MEMORY WRITE ACCESS VIOLATION" );
+ halt( );
+ }
+
+ memory->m[addr] = v;
+}
+
+char memory_read( Memory *memory, int addr )
+{
+ if( addr < 0 || addr > memory->size ) {
+ print( "MEMORY READ ACCESS VIOLATION" );
+ halt( );
+ }
+
+ return memory->m[addr];
+}
+
+void memory_print_dump( Memory *memory )
+{
+ int i;
+ char *s = allocate( memory->size * 4 );
+ char buf[4];
+ s[0] = '\0';
+
+ strcat( s, " 00: " );
+ for( i = 0; i < memory->size; i++ ) {
+ strtohex( &memory->m[i], 1, buf );
+ strcat( s, buf );
+ strcat( s, " " );
+ if( i % 16 == 15 ) {
+ print( s );
+ *s = '\0';
+ inttohex( i + 1, buf );
+ strcat( s, " " );
+ strcat( s, buf );
+ strcat( s, ": " );
+ } else {
+ if( i % 8 == 7 ) {
+ strcat( s, " " );
+ }
+ }
+ }
+
+ print( s );
+
+ deallocate( (void **)&s );
+}
+
+void memory_read_from_file( Memory *memory, char *filename )
+{
+ if( readfile( filename, memory->m, memory->size ) < 0 ) {
+ print( "MEMORY DUMP LOAD ERROR" );
+ halt( );
+ }
+}
diff --git a/miniemu/memory.h b/miniemu/memory.h
new file mode 100644
index 0000000..312a42f
--- /dev/null
+++ b/miniemu/memory.h
@@ -0,0 +1,14 @@
+#pragma once
+
+typedef struct Memory {
+ int size;
+ char *m;
+} Memory;
+
+extern void memory_init( Memory *memory, int size );
+extern void memory_done( Memory *memory );
+extern void memory_reset( Memory *memory );
+extern void memory_write( Memory *memory, int addr, char v );
+extern char memory_read( Memory *memory, int addr );
+extern void memory_print_dump( Memory *memory );
+extern void memory_read_from_file( Memory *memory, char *filename );
diff --git a/miniemu/opcodes.h b/miniemu/opcodes.h
new file mode 100644
index 0000000..37d0922
--- /dev/null
+++ b/miniemu/opcodes.h
@@ -0,0 +1,148 @@
+#pragma once
+
+/*
+ * Follows the general 8-bit opcodes:
+ *
+ * See http://www.c-jump.com/CIS77/CPU/IsaDesign/lecture.html
+ *
+ * iiirrmmm (general two operand opcode format)
+ *
+ * iii instruction/opcode group
+ * rr register operand
+ * mmm second operand
+ *
+ * iii = 000 special commands (zero or one operand)
+ * = 001 or
+ * = 010 and
+ * = 011 cmp
+ * = 100 sub
+ * = 101 add
+ * = 11x mov
+ * = 110 mov (load)
+ * = 111 mov (store)
+ *
+ * rr = 00 AX
+ * 01 BX
+ * 10 CX
+ * 11 DX
+ *
+ * mmm = 000 AX
+ * 001 BX
+ * 010 CX
+ * 011 DX
+ * 100 illegal
+ * 101 illegal
+ * 110 direct memory
+ * 111 constant
+ *
+ * 000iimmm (general one operand opcode format)
+ *
+ * ii instruction/opcode group
+ * mmm operand
+ *
+ * ii = 00 (special commands) zero-operand commands
+ * = 01 jump instructions
+ * = 10 not
+ * = 11 stack (push and pop registers to/from stack)
+ *
+ * for jmp:
+ *
+ * mmm = 000 je (Z set)
+ * 001 jne (Z not set)
+ * 010 jb (C set)
+ * 011 jbe (C set or Z set)
+ * 100 ja (C not set and Z not set)
+ * 101 jae (C not set)
+ * 110 jmp (unconditional)
+ * 111 jsr (subroutine call, push PC on stack)
+ *
+ * for not:
+ *
+ * mmm = 000 AX
+ * 001 BX
+ * 010 CX
+ * 011 DX
+ * 100 illegal
+ * 101 illegal
+ * 110 illegal
+ * 111 illegal
+ *
+ * for push/pop
+ *
+ * mmm = 000 push AX
+ * 001 push BX
+ * 010 push CX
+ * 011 push DX
+ * 100 pop AX
+ * 101 pop BX
+ * 110 pop CX
+ * 111 pop DX
+ *
+ * 00000iii zero-operand instructions
+ *
+ * iii instruction/opcode group
+ *
+ * iii = 000 illegal
+ * = 001 nop
+ * = 010 hlt
+ * = 011 ret (return from subroute call, restore PC from stack)
+ * = 100 illegal
+ * = 101 illegal
+ * = 110 illegal
+ * = 111 illegal
+ *
+ */
+typedef enum Opcode {
+ OPCODE_GROUP_ZERO_OPERANDS = (unsigned char)0x07,
+ OPCODE_GROUP_ONE_OPERAND = (unsigned char)0x18,
+ OPCODE_GROUP_TWO_OPERANDS = (unsigned char)0xe0,
+
+ OPCODE_MOV_MASK = (unsigned char)0xc0,
+ OPCODE_MOV_LD = (unsigned char)0xc0,
+ OPCODE_MOV_ST = (unsigned char)0xe8,
+
+ OPCODE_DST_MASK = (unsigned char)0x18,
+ OPCODE_DST_AX_REG = (unsigned char)0x00,
+ OPCODE_DST_BX_REG = (unsigned char)0x08,
+ OPCODE_DST_CX_REG = (unsigned char)0x10,
+ OPCODE_DST_DX_REG = (unsigned char)0x18,
+
+ OPCODE_SRC_MASK = (unsigned char)0x07,
+ OPCODE_SRC_AX_REG = (unsigned char)0x00,
+ OPCODE_SRC_BX_REG = (unsigned char)0x01,
+ OPCODE_SRC_CX_REG = (unsigned char)0x02,
+ OPCODE_SRC_DX_REG = (unsigned char)0x03,
+ OPCODE_SRC_CONST = (unsigned char)0x07,
+ OPCODE_SRC_MEMORY = (unsigned char)0x06,
+
+ OPCODE_OR = (unsigned char)0x20,
+ OPCODE_AND = (unsigned char)0x40,
+ OPCODE_CMP = (unsigned char)0x60,
+ OPCODE_SUB = (unsigned char)0x80,
+ OPCODE_ADD = (unsigned char)0xa0,
+
+ OPCODE_JMP = (unsigned char)0x08,
+
+ OPCODE_JMP_MASK = (unsigned char)0x07,
+ OPCODE_JMP_JE = (unsigned char)0x00,
+ OPCODE_JMP_JNE = (unsigned char)0x01,
+ OPCODE_JMP_JB = (unsigned char)0x02,
+ OPCODE_JMP_JBE = (unsigned char)0x03,
+ OPCODE_JMP_JA = (unsigned char)0x04,
+ OPCODE_JMP_JAE = (unsigned char)0x05,
+ OPCODE_JMP_JMP = (unsigned char)0x06,
+ OPCODE_JMP_JSR = (unsigned char)0x07,
+
+ OPCODE_NOT = (unsigned char)0x10,
+
+ OPCODE_STACK = (unsigned char)0x18,
+ OPCODE_STACK_OPERAND_MASK = (unsigned char)0x3,
+ OPCODE_STACK_PUSH = (unsigned char)0x0,
+ OPCODE_STACK_POP = (unsigned char)0x4,
+
+ OPCODE_ZERO_OPS_MASK = (unsigned char)0xf8,
+
+ OPCODE_NOP = (unsigned char)0x01,
+ OPCODE_HLT = (unsigned char)0x02,
+ OPCODE_RET = (unsigned char)0x03
+} Opcode;