_SIMULATION COMPILATION AND PORTABILITY_ by Marc Hoffman Listing One :::::::::::::: simcc.c :::::::::::::: /* Simulation compiler for SLM */ char *regs[] = { "rx","ry","ri","rj","rk", "pc", "ss" }; char *distemp[] = { "nop", "mov %1, %2", "mov (%1), %2", "mov %1, (%2)", "mov %k, rx", "mov %k, ry", "add %1, %2", "sub %1, %2", "mul %1, %2", "jmp %a", "jz %a", "jc %a", "halt", 0, 0, 0, }; char *simtemp[] = { "/* nothing */", "SETR (%2, %1);", "SETR (%1, mem [%2]);", "SETMEM (mem [%2], %1);", "SETR (rx, %k);", "SETR (ry, %k);", "SETR (%2, ALUOP (+, %2, %1));", "SETR (%2, ALUOP (-, %2, %1));", "SETR (%2, ALUOP (*, %2, %1));", "nextaddr = %a;", "if (ss.z) nextaddr = %a;", "if (ss.c) nextaddr = %a;", "return;", 0, 0, 0, }; disasm (int inst, char **templates) { char *template = templates[(inst>>8)&0xF]; char *p = template; if (template) { while (*p) { if (*p == '%') decode_operand (inst, ++p); else putchar (*p); p++; } } } decode_operand (int inst, char *p) { switch (*p++) { case '1': printf ("%s", regs[(inst>>4)&0xF]); break; case '2': printf ("%s", regs[inst&0xF]); break; case 'k': printf ("%d", (signed char)(inst&0xFF)); break; case 'a': printf ("%u", inst&0xFF); break; default: abort (); } } genc (int addr, int inst) { printf (" case 0x%04x: T(\"", addr); disasm (inst, distemp); printf ("\");\n"); printf (" "); disasm (inst, simtemp); printf ("\n"); printf (" break;\n"); } int prog[] = {9, 0x405,0x503,0x801,0x40F,0x701,0xA07,0xC00,0x601,0xC00}; main () { int i; printf ("#include \"slm.h\"\n" "main ()\n" "{\n" " while (1) {\n" " BEFORE_CYCLE ();\n" " switch (pc) {\n"); for (i=0; i 0x1ff) ? 1 : 0;\ ss.c = (scratch & 0x1ff) ? 1 : 0;\ ss.n = (scratch & 0x80) ? 1 : 0; #define BEFORE_CYCLE() pc = nextaddr; nextaddr++ #define AFTER_CYCLE() #define INVALID_PC_HANDLER() abort () #define T(x) printf ("%04x: %s\n", pc, x) Figure 1: while (1) { BEFORE_CYCLE (); switch (PC) { case ADDR: instruction; break ; default: INVALID_PC_HANDLER (); } AFTER_CYCLE (); } Figure 2: SLM: registers: rX, rY, rZ, rI, rJ, rK, PC, ss{z,n,v,c} 0, 1, 2, 3, 4, 5, 6, 7 addr: is 8bit 000 nop 1sd mov rsrc, rdst 2id mov (ri), rdst 3si mov rsrc, (ri) 4kk mov k, rx 5kk mov k, ry 6xx add src, dst 7xx sub src, dst 8xx mul src, dst 9xx jmp addr Axx jz addr Bxx jc addr Cxx halt Figure 3: char *regs[] = { "rx","ry","ri","rj","rk", "pc", "ss" }; char *distemp[] = { "nop", "mov %1, %2", "mov (%1), %2", "mov %1, (%2)", "mov %k, rx", "mov %k, ry", "add %1, %2", "sub %1, %2", "mul %1, %2", "jmp %a", "jz %a", "jc %a", "halt", 0, 0, 0, }; Figure 4: disasm (int inst) { char *template = distemp[(inst>>8)&0xF]; char *p = template; if (template) { while (*p) { if (*p == '%') decode_operand (inst, ++p); else putchar (*p); p++; } } } decode_operand (int inst, char *p) { switch (*p++) { case '1': printf ("%s", regs[(inst>>4)&0xF]); break; case '2': printf ("%s", regs[inst&0xF]); break; case 'k': printf ("%d", (singed char)(inst&0xFF)); break; case 'a': printf ("%u", inst&0xFF); break; default: abort (); } } Figure 5: #define SETR(x,y)\ x = y;\ ss.z = (x == 0) ? 1:0; ss.n = ((signed)x < 0) ? 1:0 #define SETMEM(x,y) x = y; #define ALUOP(op, rdst,rsrc)\ rdst = scratch = rdst op rsrc;\ ss.v = (scratch > 0x1ff) ? 1 : 0;\ ss.c = (scratch & 0x1ff) ? 1 : 0;\ ss.n = (scratch & 0x80) ? 1 : 0 char *distemp[] = { "/* nothing */", "SETR (%2, %1);", "SETR (%1, mem [%2]);", "SETMEM (mem [%2], %1);", "SETR (rx, %k);", "SETR (ry, %k);", "SETR (%2, ALUOP (+, %2, %1));", "SETR (%2, ALUOP (-, %2, %1));", "SETR (%2, ALUOP (*, %2, %1));", "nextaddr = %a;", "if (ss.z) nextaddr = %a;", "if (ss.c) nextaddr = %a;", "return", 0, 0, 0, }; Figure 6: 0000 405 mov 5, rx 0001 503 mov 3, ry 0002 801 mul rx, ry 0003 40F mov 15, rx 0004 701 sub rx, ry 0005 A07 jz ok 0006 C00 halt 0007 601 ok add rx, ry 0008 C00 halt