arachneng
-
C,
pasted
on Apr 5:
|
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef uint16_t word;
typedef uint32_t xword;
#define CASEx8(x) \
case (x)+0: case (x)+1: case (x)+2: case (x)+3: \
case (x)+4: case (x)+5: case (x)+6: case (x)+7
int wc;
word pc, sp, of, reg[8], mem[1<<16];
void init(void)
{
wc = 0;
pc = 0x0000;
sp = 0xffff;
of = 0x0000;
memset(reg, 0, sizeof reg);
}
word *get(word v, word *sink)
{
switch (v) {
CASEx8(0x00): return ®[v];
CASEx8(0x08): return &mem[reg[v-0x08]];
CASEx8(0x10): ++wc; return &mem[reg[v-0x10] + mem[pc++]];
case 0x18: return &mem[sp++];
case 0x19: return &mem[sp];
case 0x1a: return &mem[--sp];
case 0x1b: return &sp;
case 0x1c: return &pc;
case 0x1d: return &of;
case 0x1e: ++wc; return &mem[mem[pc++]];
case 0x1f: ++wc; return &mem[pc++];
CASEx8(0x20):
CASEx8(0x28):
CASEx8(0x30):
CASEx8(0x3f): *sink = v-0x20; return sink; // OOPS!
default: abort();
}
}
void tick(void)
{
word c = mem[pc++];
word op = c & 15, aa = (c >> 4) & 63, bb = c >> 10;
if (op) { // typical opcodes
word a0, b0;
xword tmp;
word *a = get(aa, &a0);
word *b = get(bb, &b0);
switch (op) {
case 0x01: // SET
*a = *b;
wc += 1;
break;
case 0x02: // ADD
tmp = (xword)*a + (xword)*b;
of = (tmp >= 0x10000 ? 1 : 0);
*a = (word)(tmp & 0xffff);
wc += 2;
break;
case 0x03: // SUB
tmp = (xword)*a + (xword)~*b + 1;
of = (tmp >= 0x10000 ? 0xffff : 0);
*a = (word)(tmp & 0xffff);
wc += 2;
break;
case 0x04: // MUL
tmp = (xword)*a * (xword)*b;
of = (word)(tmp >> 16);
*a = (word)(tmp & 0xffff);
wc += 2;
break;
case 0x05: // DIV
tmp = (*b ? ((xword)*a << 16) / (xword)*b : 0);
of = (word)(tmp & 0xffff);
*a = (word)(tmp >> 16);
wc += 3;
break;
case 0x06: // MOD
*a = (*b ? *a % *b : 0);
wc += 3;
break;
case 0x07: // SHL
tmp = (*b >= 32 ? 0 : (xword)*a << (xword)*b);
of = (word)(tmp >> 16);
*a = (word)(tmp & 0xffff);
wc += 2;
break;
case 0x08: // SHR
tmp = (*b >= 32 ? 0 : ((xword)*a << 16) >> (xword)*b);
of = (word)(tmp & 0xffff);
*a = (word)(tmp >> 16);
wc += 2;
break;
case 0x09: // AND
*a = *a & *b;
wc += 1;
break;
case 0x0a: // BOR
*a = *a | *b;
wc += 1;
break;
case 0x0b: // XOR
*a = *a ^ *b;
wc += 1;
break;
case 0x0c: // IFE
if (*a == *b) {
wc += 1;
} else {
pc += 1;
wc += 2;
}
break;
case 0x0d: // IFN
if (*a != *b) {
wc += 1;
} else {
pc += 1;
wc += 2;
}
break;
case 0x0e: // IFG
if (*a > *b) {
wc += 1;
} else {
pc += 1;
wc += 2;
}
break;
case 0x0f: // IFB
if (*a & *b) {
wc += 1;
} else {
pc += 1;
wc += 2;
}
break;
default:
abort();
}
} else if (aa) {
word b0;
switch (aa) {
case 0x01: // JSR
mem[--sp] = pc;
pc = *get(bb, &b0);
wc += 2;
break;
default:
if (aa >= 0x02 && aa <= 0x3f) {
fprintf(stderr, "Reserved opcode %d:0\n", (int)aa);
wc += 1;
break;
}
abort();
}
} else {
fprintf(stderr, "Reserved opcode %d:0:0\n", (int)bb);
wc += 1;
}
}
int dumpv(word v, word pc)
{
static const char ops[8] = "ABCXYZIJ";
switch (v) {
CASEx8(0x00): putchar(ops[v]); return 0;
CASEx8(0x08): printf("[%c]", ops[v-0x08]); return 0;
CASEx8(0x10): printf("[%c%+d]", ops[v-0x10], (int)(int16_t)mem[pc]); return 1;
case 0x18: printf("[SP++]"); return 0;
case 0x19: printf("[SP]"); return 0;
case 0x1a: printf("[--SP]"); return 0;
case 0x1b: printf("SP"); return 0;
case 0x1c: printf("PC"); return 0;
case 0x1d: putchar('O'); return 0;
case 0x1e: printf("[%#x]", (int)(int16_t)mem[pc]); return 1;
case 0x1f: printf("%#x", (int)(int16_t)mem[pc]); return 1;
CASEx8(0x20):
CASEx8(0x28):
CASEx8(0x30):
CASEx8(0x3f): printf("%d", (int)(v-0x20)); return 0;
default: abort();
}
}
word dump(word pc)
{
word oldpc = pc;
word c = mem[pc++];
word op = c & 15, a = (c >> 4) & 63, b = c >> 10;
printf("%04x: ", oldpc);
if (op) {
static const char opcodes[16][4] = {
"???", "SET", "ADD", "SUB", "MUL", "DIV", "MOV", "SHL",
"SHR", "AND", "BOR", "XOR", "IFE", "IFN", "IFG", "IFB",
};
printf("%s ", opcodes[op]);
pc += dumpv(a, pc);
printf(", ");
pc += dumpv(b, pc);
printf("\n");
} else {
switch (a) {
case 0x00:
printf("; Reserved opcode %d:0:0\n", (int)b);
break;
case 0x01:
printf("JSR ");
pc += dumpv(b, pc);
printf("\n");
break;
default:
if (a >= 0x02 && a <= 0x3f) {
printf("; Reserved opcode %d:0\n", (int)a);
break;
}
abort();
}
}
return pc - oldpc;
}
void stat(void)
{
printf("PC=%04x SP=%04x O=%04x Reg=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x (t=%d)\n",
pc, sp, of, reg[0], reg[1], reg[2], reg[3], reg[4], reg[5], reg[6], reg[7], wc);
dump(pc);
}
int main(void) {
word initmem[] = {
0x7c01,0x0030,0x7de1,0x1000,0x0020,0x7803,0x1000,0xc00d,
0x7dc1,0x001a,0xa861,0x7c01,0x2000,0x2161,0x2000,0x8463,
0x806d,0x7dc1,0x000d,0x9031,0x7c10,0x0018,0x7dc1,0x001a,
0x9037,0x61c1,0x7dc1,0x001a,0x0000,0x0000,0x0000,0x0000,
};
int i;
for (i = 0; i < 32; ++i) mem[i] = initmem[i];
init();
while (wc < 100) {
stat();
tick();
}
return 0;
}
|
Output:
|
PC=0000 SP=ffff O=0000 Reg=0000:0000:0000:0000:0000:0000:0000:0000 (t=0)
0000: SET A, 0x30
PC=0002 SP=ffff O=0000 Reg=0030:0000:0000:0000:0000:0000:0000:0000 (t=2)
0002: SET [0x1000], 0x20
PC=0005 SP=ffff O=0000 Reg=0030:0000:0000:0000:0000:0000:0000:0000 (t=5)
0005: SUB A, [0x1000]
PC=0007 SP=ffff O=0000 Reg=0010:0000:0000:0000:0000:0000:0000:0000 (t=8)
0007: IFN A, 16
PC=0009 SP=ffff O=0000 Reg=0010:0000:0000:0000:0000:0000:0000:0000 (t=10)
0009: BOR B, A
PC=000a SP=ffff O=0000 Reg=0010:0010:0000:0000:0000:0000:0000:0000 (t=11)
000a: SET I, 10
PC=000b SP=ffff O=0000 Reg=0010:0010:0000:0000:0000:0000:000a:0000 (t=12)
000b: SET A, 0x2000
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:000a:0000 (t=14)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:000a:0000 (t=16)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0009:0000 (t=18)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0009:0000 (t=19)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0009:0000 (t=21)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0009:0000 (t=23)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0008:0000 (t=25)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0008:0000 (t=26)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0008:0000 (t=28)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0008:0000 (t=30)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0007:0000 (t=32)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0007:0000 (t=33)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0007:0000 (t=35)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0007:0000 (t=37)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0006:0000 (t=39)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0006:0000 (t=40)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0006:0000 (t=42)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0006:0000 (t=44)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0005:0000 (t=46)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0005:0000 (t=47)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0005:0000 (t=49)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0005:0000 (t=51)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0004:0000 (t=53)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0004:0000 (t=54)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0004:0000 (t=56)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0004:0000 (t=58)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0003:0000 (t=60)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0003:0000 (t=61)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0003:0000 (t=63)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0003:0000 (t=65)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0002:0000 (t=67)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0002:0000 (t=68)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0002:0000 (t=70)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0002:0000 (t=72)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0001:0000 (t=74)
0010: IFN I, 0
PC=0011 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0001:0000 (t=75)
0011: SET PC, 0xd
PC=000d SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0001:0000 (t=77)
000d: SET [I+8192], [A]
PC=000f SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0001:0000 (t=79)
000f: SUB I, 1
PC=0010 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0000:0000 (t=81)
0010: IFN I, 0
PC=0012 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0000:0000 (t=83)
0012: IFN A, A
PC=0014 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0000:0000 (t=85)
0014: JSR 0x18
PC=0018 SP=fffe O=0000 Reg=2000:0010:0000:0000:0000:0000:0000:0000 (t=88)
0018: SHL X, 4
PC=0019 SP=fffe O=0000 Reg=2000:0010:0000:0000:0000:0000:0000:0000 (t=90)
0019: SET PC, [SP++]
PC=0015 SP=ffff O=0000 Reg=2000:0010:0000:0000:0000:0000:0000:0000 (t=91)
0015: SHR B, A
PC=0016 SP=ffff O=0000 Reg=2000:0000:0000:0000:0000:0000:0000:0000 (t=93)
0016: SET PC, 0x1a
PC=001a SP=ffff O=0000 Reg=2000:0000:0000:0000:0000:0000:0000:0000 (t=95)
001a: SET PC, 0x1a
PC=001a SP=ffff O=0000 Reg=2000:0000:0000:0000:0000:0000:0000:0000 (t=97)
001a: SET PC, 0x1a
PC=001a SP=ffff O=0000 Reg=2000:0000:0000:0000:0000:0000:0000:0000 (t=99)
001a: SET PC, 0x1a
|
|