ref: 1bdf54041fbe740c98bae75f879678141dc494c9
dir: /5551e.c/
/* 5552 cpu emulator */ #include "5552.h" struct mach { word reg[REGS]; /* both are nibbles currently, but for convience */ word op; word mode; word arg1; word arg2; byte mem[MMAX]; }; /* int btoi(int b[], int len) { char arr[10]; int res = 0, i = 0, j = len; while (i <= len) { arr[i] = b[j] ? '1' : '0'; i++; j--; } sscanf(arr, "%d", &res); return res; } */ int mach_drd(word dev, word src, word dst) { switch(dev) { case REG: regs[dst] = regs[src]; break; case MEM: regs[dst] = mem[src]; break; case GPIO: switch(src) { case SERIAL: read(0, regs+dst, sizeof(Word)); break; default: break; } default: break; } } int mach_dwr(word dev, word src, word dst) { switch(dev) { case REG: regs[src] = regs[dst]; break; case MEM: regs[src] = mem[dst]; break; case GPIO: switch(dst) { case SERIAL: write(0, regs+src, sizeof(Word)); break; default: break; } default: break; } } int mach_dwr(word dev, word src, word dst) { switch(dev) { case REG: regs[src] = regs[dst]; break; case MEM: regs[src] = mem[dst]; break; case GPIO: switch(dst) { case SERIAL: write(0, regs+src, sizeof(Word)); break; default: break; } default: break; } } int mach_not(word mode, word arg1, word arg2) { switch(mode) { case REG: regs[RES] = ~regs[arg1]; break; case INLINE: regs[RES] = ~((arg1 << (sizeof Word) * 8) & arg2); break; case DIRECT: default: break; } } int mach_and(Word mode, Word arg1, Word arg2) { switch(mode) { case REG: regs[RES] = regs[arg1] & regs[arg2]; break; case INLINE: regs[RES] = arg1 & arg2; break; case DIRECT: regs[RES] = regs[arg1] & arg2; break; default: break; } } int mach_nor(Word mode, Word arg1, Word arg2) { switch(mode) { case REG: regs[RES] = !(regs[arg1] | regs[arg2]); break; case INLINE: regs[RES] = !(arg1 | arg2); break; case DIRECT: regs[RES] = !(regs[arg1] & arg2); break; default: break; } } int mach_xor(Word mode, Word arg1, Word arg2) { switch(mode) { case REG: regs[RES] = regs[arg1] ^ regs[arg2]; break; case INLINE: regs[RES] = arg1 ^ arg2; break; case DIRECT: regs[RES] = regs[arg1] ^ arg2; break; default: break; } } int mach_add(Word mode, Word arg1, Word arg2) { int result; switch(mode) { case REG: result = (int)regs[arg1] + (int)regs[arg2]; break; case INLINE: result = (int)arg1 + (int)arg2; break; case DIRECT: result = (int)regs[arg1] + (int)arg2; break; default: break; } if(intsize(result) > sizeof Word) regs[CRR] = (Word)(result % 2 << (sizeof Word * 8)); regs[RES] = (Word)result; } int mach_sub(Word mode, Word arg1, Word arg2) { int result; switch(mode) { case REG: result = (int)regs[arg1] - (int)regs[arg2]; break; case INLINE: result = (int)arg1 - (int)arg2; break; case DIRECT: result = (int)regs[arg1] - (int)arg2; break; default: break; } if(intsize(result) > sizeof Word * 8) regs[CRR] = (Word)(result % 2 << (sizeof Word * 8)); regs[RES] = (Word)result; } int mach_mul(Word mode, Word arg1, Word arg2) { int result; switch(mode) { case REG: result = (int)regs[arg1] * (int)regs[arg2]; break; case INLINE: result = (int)arg1 * (int)arg2; break; case DIRECT: result = (int)regs[arg1] * (int)arg2; break; default: break; } if(intsize(result) > sizeof Word * 8) regs[CRR] = (Word)(result % 2 << (sizeof Word * 8)); regs[RES] = (Word)result; } int mach_div(Word mode, Word arg1, Word arg2) { int result; switch(mode) { case REG: result = (int)regs[arg1] / (int)regs[arg2]; break; case INLINE: result = (int)arg1 / (int)arg2; break; case DIRECT: result = (int)regs[arg1] / (int)arg2; break; default: break; } regs[RES] = (Word)result; } int mach_mul(Word mode, Word arg1, Word arg2) { int result; switch(mode) { case REG: result = (int)regs[arg1] * (int)regs[arg2]; break; case INLINE: result = (int)arg1 * (int)arg2; break; case DIRECT: result = (int)regs[arg1] * (int)arg2; break; default: break; } if(intsize(result) > sizeof Word * 8) regs[CRR] = (Word)(result % 2 << (sizeof Word * 8)); regs[RES] = (Word)result; } void main(void) { char *input; void *buf; int arg, prev; input = malloc(OPLEN); if(input < 0) panic("Not enough memory\n"); mach.reg[STATE] = ON; while(mach.state == ON) { if(read(1, buf, 3) < 3) { panic("EOF?\n"); } mach.op = buf[0] >> 4; mach.mode = buf[0] & (1 << 4) - 1; mach.arg1 = buf[1]; mach.arg2 = buf[2]; for(int i = 0; i < sizeof(optab) ; i++) { if(mach.op == operators[i].op) { operators[i].exec(mach.mode, mach.arg1, mach.arg2); break; } } } } int main(void) { char string[16]; r.flags[ON] = 1; r.flags[NSIGN] = false; unsigned int op, a, b, c, ind = 0; bool barr[10]; /* there is no space between op and args since some can have no args */ while(r.flags[ON] && scanf("%u %[^\n]", &op, string)) { sscanf(string, "%u %u %u", &a, &b, &c); switch(op) { case DIE: r.flags[ON] = 0; break; case OUT: /* just in case output is "manfi" */ if(r.flags[NSIGN]) printf("-%u\n", r.regs[a]); else printf("%u\n", r.regs[a]); break; case NOT: r.regs[b] = !a; break; case AND: r.regs[c] = a & b; break; case NOR: r.regs[c] = !(a | b); break; case XOR: r.regs[c] = a ^ b; break; case SUB: b = ~b; r.regs[CARRY] = 1; r.flags[NSIGN] = (a < b); r.regs[c] = r.flags[NSIGN] ? b - a : a - b; case ADD: r.flags[NSIGN] = false; r.regs[c] = a + b; break; r.flags[NSIGN] = false; r.regs[b] = a + 1; break; case DEC: r.regs[b] = a - 1; r.flags[NSIGN] = (r.regs[b] < 0); break; case SHR: r.regs[c] = a >> b; break; case SHL: r.regs[c] = a << b; break; case PUT: memory[b] = a; case MOV: memory[b] = r.regs[a]; break; case LDM: r.regs[b] = memory[a]; break; case NTH: r.regs[c] = a >> b; break; default: fprintf(stderr, "unknown op\n"); return 1; } /* clear them */ a = 0; b = 0; op = 0; string[0] = '\0'; } return 0; }