diff options
Diffstat (limited to 'src/emu/cpu.c')
-rw-r--r-- | src/emu/cpu.c | 175 |
1 files changed, 90 insertions, 85 deletions
diff --git a/src/emu/cpu.c b/src/emu/cpu.c index 7e62ffb..f32bb7f 100644 --- a/src/emu/cpu.c +++ b/src/emu/cpu.c @@ -11,16 +11,25 @@ #include "opc.h" #include "syscall.h" -// program counter -uint32_t PC; +/* stack pointer register*/ +uint32_t SP; -// status bits +/* base pointer register */ +uint32_t BP; + +/* return value register */ +uint32_t RV; + +/* instruction pointer */ +uint32_t IP; + +/* status bits */ bool N, Z; -// 32 general purpose registers -uint32_t GPR[32]; +/* general purpose registers */ +uint32_t *GPR; -/* extract operands from the instruction regiter */ +/* extract operands from the instruction register */ static inline uint32_t __OPEXT(uint32_t IR, uint8_t start, uint8_t length) { @@ -41,16 +50,19 @@ void trap(int num) { switch (num) { case TRP_UNALIGNED: - raise(SIGSEGV); + fprintf(stderr, "trap: unaligned memory access\n"); + abort(); break; case TRP_DIVBYZERO: - raise(SIGFPE); + fprintf(stderr, "trap: division by zero\n"); + abort(); break; case TRP_SYSCALL: do_syscall(); break; case TRP_ILL: - raise(SIGILL); + fprintf(stderr, "trap: illegal instruction\n"); + abort(); break; } } @@ -62,17 +74,17 @@ void execute(uint32_t IR) int32_t a, b, c; if (opcode < OPC_MOV) { - /* arithmetic & logic */ + /* arithmetic, logic, comparison */ a = REGa; b = REGb; c = REGc; - debug("PC@%#08x: %-3s r%i, r%i, r%i", PC, + debug("IP@%#08x: %-4s r%i, r%i, r%i", IP, opc2mnemonic(IR), a, b, c); } - else if (opcode < OPC_J) { - /* load/store & branch */ + else if (opcode < OPC_BEZ) { + /* load/store */ a = REGa; b = REGb; c = IMMc; @@ -81,40 +93,59 @@ void execute(uint32_t IR) if (c >= 0x8000) c -= 0x10000; - if (opcode < OPC_LB) { - debug("PC@%#08x: %-3s r%i, %i", PC, - opc2mnemonic(IR), b, c); - } else { - debug("PC@%#08x: %-3s r%i, r%i, %i", PC, + if (opcode < OPC_LW) { + debug("IP@%#08x: %-4s r%i, %i", IP, + opc2mnemonic(IR), a, c); + } else if (opcode < OPC_PUSH) { + debug("IP@%#08x: %-4s r%i, r%i, %i", IP, opc2mnemonic(IR), a, b, c); + } else { + debug("IP@%#08x: %-4s r%i", IP, + opc2mnemonic(IR), a); } } else if (opcode < OPC_SYS) { /* jump */ a = REGa; - b = c = 0; + b = 0; + c = IMMc; - debug("PC@%#08x: %-3s r%i", PC, - opc2mnemonic(IR), a); + /* sign extension */ + if (c >= 0x8000) + c -= 0x10000; + + switch (opcode) { + case OPC_BEZ: + debug("IP@%#08x: %-4s r%i, %i", IP, + opc2mnemonic(IR), a, c); + break; + case OPC_JMP: + debug("IP@%#08x: %-4s %i", IP, + opc2mnemonic(IR), c); + break; + case OPC_CALL: + debug("IP@%#08x: %-4s %i", IP, + opc2mnemonic(IR), c); + break; + case OPC_RET: + debug("IP@%#08x: %-4s", IP, + opc2mnemonic(IR)); + break; + } } else { /* misc */ a = b = c = 0; - debug("PC@%#08x: %-3s", PC, + debug("IP@%#08x: %-3s", IP, opc2mnemonic(IR)); } // make sure r0 is zero GPR[0] = 0; - // buffer for load/store instructions - uint8_t tmp8; - uint16_t tmp16; - uint32_t tmp32; - switch (opcode) { case OPC_ADD: // XXX: signed/unsigned? @@ -139,69 +170,16 @@ void execute(uint32_t IR) // XXX: signed/unsigned? GPR[a] = GPR[b] % GPR[c]; break; - case OPC_SHL: - // XXX: signed/unsigned? - GPR[a] = GPR[b] << GPR[c]; - break; - case OPC_SHR: - // XXX: signed/unsigned? - GPR[a] = GPR[b] >> GPR[c]; - break; case OPC_AND: GPR[a] = GPR[b] & GPR[c]; break; case OPC_OR: GPR[a] = GPR[b] | GPR[c]; break; - case OPC_XOR: - GPR[a] = GPR[b] ^ GPR[c]; - break; - case OPC_NOR: - GPR[a] = ~(GPR[b] & GPR[c]); - break; - case OPC_MOV: - GPR[b] = c; - break; - case OPC_LB: - memcpy(&tmp8, &MEM[GPR[a] + c], sizeof(uint8_t)); - GPR[b] = tmp8; - break; - case OPC_LH: - if ((GPR[a] + c) & 0x1) - trap(TRP_UNALIGNED); - memcpy(&tmp16, &MEM[GPR[a] + c], sizeof(uint16_t)); - GPR[b] = tmp16; - break; - case OPC_LW: - if ((GPR[a] + c) & 0x2) - trap(TRP_UNALIGNED); - memcpy(&tmp32, &MEM[GPR[a] + c], sizeof(uint32_t)); - GPR[b] = tmp32; - break; - case OPC_SB: - tmp8 = GPR[b]; - memcpy(&MEM[GPR[a] + c], &tmp8, sizeof(uint8_t)); - break; - case OPC_SH: - if ((GPR[a] + c) & 0x1) - trap(TRP_UNALIGNED); - tmp16 = GPR[b]; - memcpy(&MEM[GPR[a] + c], &tmp16, sizeof(uint16_t)); - break; - case OPC_SW: - if ((GPR[a] + c) & 0x2) - trap(TRP_UNALIGNED); - tmp32 = GPR[b]; - memcpy(&MEM[GPR[a] + c], &tmp32, sizeof(uint32_t)); - break; case OPC_CMP: Z = (GPR[a] == GPR[b]); N = (GPR[a] < GPR[b]); break; - case OPC_BEZ: - if (GPR[a] == 0) - PC += c * sizeof(uint32_t); - break; case OPC_EQ: GPR[a] = Z; break; @@ -219,12 +197,37 @@ void execute(uint32_t IR) break; case OPC_GT: GPR[a] = !Z && !N; - case OPC_J: - PC = GPR[a]; + case OPC_MOV: + GPR[a] = c; break; - case OPC_JAL: - GPR[31] = PC + sizeof(uint32_t); - PC = GPR[a]; + case OPC_LW: + GPR[b] = load(GPR[a] + c); + break; + case OPC_SW: + store(GPR[a] + c, GPR[b]); + break; + case OPC_PUSH: + push(GPR[a]); + break; + case OPC_POP: + GPR[a] = pop(); + break; + case OPC_BEZ: + if (GPR[a] == 0) { + IP += c * 4; + return; + } + break; + case OPC_JMP: + IP += c * 4; + return; + case OPC_CALL: + push(IP + 4); + IP += c * 4; + return; + case OPC_RET: + IP = pop(); + return; case OPC_SYS: trap(TRP_SYSCALL); break; @@ -232,4 +235,6 @@ void execute(uint32_t IR) /* illegal instruction */ trap(TRP_ILL); } + + IP += 4; } |