summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBenedikt Böhm <bb@xnull.de>2009-07-04 10:49:19 +0200
committerBenedikt Böhm <bb@xnull.de>2009-07-04 10:49:19 +0200
commit6165e2dde32a8f425e54d4f061146b366d5a2e0a (patch)
tree857b1884e30c5b38ac8c915e37b8ee0bd52d712e /src
parent11545b9e323084482673b8732b89711ae7e19928 (diff)
downloadswppy-6165e2dde32a8f425e54d4f061146b366d5a2e0a.tar.gz
swppy-6165e2dde32a8f425e54d4f061146b366d5a2e0a.tar.xz
swppy-6165e2dde32a8f425e54d4f061146b366d5a2e0a.zip
adapt emulator for generator changes:
- new instructions (push, pop, call, ret) - new pseudo-registers (bp, sp, rv) - new binary format - dynamic register file size - removed obsolete instructions
Diffstat (limited to 'src')
-rw-r--r--src/emu/asm.c49
-rw-r--r--src/emu/cpu.c175
-rw-r--r--src/emu/cpu.h17
-rw-r--r--src/emu/mem.c36
-rw-r--r--src/emu/mem.h9
-rw-r--r--src/emu/opc.c53
-rw-r--r--src/emu/opc.h47
-rw-r--r--src/emu/riscas.c2
-rw-r--r--src/emu/risci.c89
-rw-r--r--src/emu/syscall.c12
-rw-r--r--src/emu/test1bin0 -> 456 bytes
-rw-r--r--src/emu/test1.S126
-rw-r--r--src/emu/test4bin0 -> 216 bytes
-rw-r--r--src/emu/test4.S54
14 files changed, 450 insertions, 219 deletions
diff --git a/src/emu/asm.c b/src/emu/asm.c
index caca72a..8e39202 100644
--- a/src/emu/asm.c
+++ b/src/emu/asm.c
@@ -5,28 +5,49 @@
#include "log.h"
#include "opc.h"
+#define REGa(x) (((x) & 0x1F) << 21)
+#define REGb(x) (((x) & 0x1F) << 16)
+#define REGc(x) (((x) & 0x1F) << 11)
+#define IMMc(x) ((x) & 0xFFFF)
+
uint32_t compile(const char *line)
{
- char mnem[4];
+ char mnem[5];
int32_t a = 0, b = 0, c = 0;
+ static size_t regs = 0;
+
+ /* register file size */
+ if (sscanf(line, ".REGS %d", &a) == 1) {
+ regs = a;
+ return a;
+ }
+
+ /* ADD, SUB, MUL, DIV, MOD, AND, OR */
+ if (sscanf(line, "%s r%d, r%d, r%d", mnem, &a, &b, &c) == 4)
+ return mnemonic2opc(mnem) | REGa(a) | REGb(b) | REGc(c);
+
+ /* LW, SW */
+ if (sscanf(line, "%s r%d, r%d, %d", mnem, &a, &b, &c) == 4)
+ return mnemonic2opc(mnem) | REGa(a) | REGb(b) | IMMc(c);
- /* arithmetic & logic */
- if (sscanf(line, "%3s r%2d, r%2d, r%2d", mnem, &a, &b, &c) == 4)
- return mnemonic2opc(mnem) | ((a & 0x1F) << 21) | ((b & 0x1F) << 16) | ((c & 0x1F) << 11);
+ /* CMP */
+ if (sscanf(line, "%s r%d, r%d", mnem, &a, &b) == 3)
+ return mnemonic2opc(mnem) | REGa(a) | REGb(b);
- /* load/store & branch */
- if (sscanf(line, "%3s r%2d, r%2d, %d", mnem, &a, &b, &c) == 4)
- return mnemonic2opc(mnem) | ((a & 0x1F) << 21) | ((b & 0x1F) << 16) | (c & 0xFFFF);
+ /* MOV, BEZ */
+ if (sscanf(line, "%s r%2d, %d", mnem, &a, &c) == 3)
+ return mnemonic2opc(mnem) | REGa(a) | IMMc(c);
- if (sscanf(line, "%3s r%2d, %d", mnem, &b, &c) == 3)
- return mnemonic2opc(mnem) | ((b & 0x1F) << 16) | (c & 0xFFFF);
+ /* EQ, NE, LT, LE, GE, GT, PUSH, POP */
+ if (sscanf(line, "%s r%d", mnem, &a) == 2)
+ return mnemonic2opc(mnem) | REGa(a);
- /* jump */
- if (sscanf(line, "%3s r%2d", mnem, &a) == 2)
- return mnemonic2opc(mnem) | ((a & 0x1F) << 21);
+ /* JMP, CALL */
+ if (sscanf(line, "%s %d", mnem, &c) == 2)
+ return mnemonic2opc(mnem) | IMMc(c);
- /* misc */
- if (sscanf(line, "%3s", mnem) == 1)
+ /* RET, SYS */
+ if (sscanf(line, "%s", mnem) == 1)
return mnemonic2opc(mnem);
return 0xFFFFFFFF;
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;
}
diff --git a/src/emu/cpu.h b/src/emu/cpu.h
index 43ccf00..4867a8a 100644
--- a/src/emu/cpu.h
+++ b/src/emu/cpu.h
@@ -14,14 +14,23 @@ enum {
void trap(int num);
-/* program counter */
-extern uint32_t PC;
+/* stack pointer */
+extern uint32_t SP;
+
+/* base pointer */
+extern uint32_t BP;
+
+/* return value */
+extern uint32_t RV;
+
+/* instruction pointer */
+extern uint32_t IP;
/* status bits */
extern bool N, Z;
-/* 32 general purpose registers */
-extern uint32_t GPR[32];
+/* general purpose registers */
+extern uint32_t *GPR;
/* main cpu execution function */
void execute(uint32_t IR);
diff --git a/src/emu/mem.c b/src/emu/mem.c
index e102eaf..cdbf2ae 100644
--- a/src/emu/mem.c
+++ b/src/emu/mem.c
@@ -1,3 +1,37 @@
+#include <stdint.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "cpu.h"
#include "mem.h"
-uint8_t MEM[4096];
+uint8_t *MEM;
+
+void store(size_t addr, uint32_t value)
+{
+ if (addr & 0x2)
+ trap(TRP_UNALIGNED);
+ memcpy(&MEM[addr], &value, 4);
+}
+
+uint32_t load(size_t addr)
+{
+ uint32_t tmp32;
+ if (addr & 0x2)
+ trap(TRP_UNALIGNED);
+ memcpy(&tmp32, &MEM[addr], 4);
+ return tmp32;
+}
+
+void push(uint32_t value)
+{
+ GPR[SP] -= 4;
+ store(GPR[SP], value);
+}
+
+uint32_t pop(void)
+{
+ uint32_t tmp32 = load(GPR[SP]);
+ GPR[SP] += 4;
+ return tmp32;
+}
diff --git a/src/emu/mem.h b/src/emu/mem.h
index 34b13fa..985a838 100644
--- a/src/emu/mem.h
+++ b/src/emu/mem.h
@@ -2,7 +2,14 @@
#define _MEM_H
#include <stdint.h>
+#include <sys/types.h>
-extern uint8_t MEM[];
+extern uint8_t *MEM;
+
+void store(size_t addr, uint32_t value);
+uint32_t load(size_t addr);
+
+void push(uint32_t value);
+uint32_t pop(void);
#endif
diff --git a/src/emu/opc.c b/src/emu/opc.c
index fa46b26..3d62479 100644
--- a/src/emu/opc.c
+++ b/src/emu/opc.c
@@ -9,35 +9,30 @@ typedef struct opc_mapping {
} opc_mapping_t;
opc_mapping_t opc_map[] = {
- { "ADD", OPC_ADD },
- { "SUB", OPC_SUB },
- { "MUL", OPC_MUL },
- { "DIV", OPC_DIV },
- { "MOD", OPC_MOD },
- { "SHL", OPC_SHL },
- { "SHR", OPC_SHR },
- { "AND", OPC_AND },
- { "OR", OPC_OR },
- { "XOR", OPC_XOR },
- { "NOR", OPC_NOR },
- { "MOV", OPC_MOV },
- { "LB", OPC_LB },
- { "LH", OPC_LH },
- { "LW", OPC_LW },
- { "SB", OPC_SB },
- { "SH", OPC_SH },
- { "SW", OPC_SW },
- { "CMP", OPC_CMP },
- { "BEZ", OPC_BEZ },
- { "EQ", OPC_EQ },
- { "NE", OPC_NE },
- { "LT", OPC_LT },
- { "GE", OPC_GE },
- { "LE", OPC_LE },
- { "GT", OPC_GT },
- { "J", OPC_J },
- { "JAL", OPC_JAL },
- { "SYS", OPC_SYS },
+ { "ADD", OPC_ADD },
+ { "SUB", OPC_SUB },
+ { "MUL", OPC_MUL },
+ { "DIV", OPC_DIV },
+ { "MOD", OPC_MOD },
+ { "AND", OPC_AND },
+ { "OR", OPC_OR },
+ { "CMP", OPC_CMP },
+ { "EQ", OPC_EQ },
+ { "NE", OPC_NE },
+ { "LT", OPC_LT },
+ { "GE", OPC_GE },
+ { "LE", OPC_LE },
+ { "GT", OPC_GT },
+ { "MOV", OPC_MOV },
+ { "LW", OPC_LW },
+ { "SW", OPC_SW },
+ { "PUSH", OPC_PUSH },
+ { "POP", OPC_POP },
+ { "BEZ", OPC_BEZ },
+ { "JMP", OPC_JMP },
+ { "CALL", OPC_CALL },
+ { "RET", OPC_RET },
+ { "SYS", OPC_SYS },
{ NULL, 0 }
};
diff --git a/src/emu/opc.h b/src/emu/opc.h
index b766afa..179f7b2 100644
--- a/src/emu/opc.h
+++ b/src/emu/opc.h
@@ -10,12 +10,12 @@
* |000|xxx|aaaaa|bbbbb|ccccc|00000000000|
* logic:
* |001|xxx|aaaaa|bbbbb|ccccc|00000000000|
+ * comparison:
+ * |010|xxx|aaaaa|bbbbb|0000000000000000|
* load & store:
- * |010|xxx|aaaaa|bbbbb|cccccccccccccccc|
- * branch:
* |011|xxx|aaaaa|bbbbb|cccccccccccccccc|
* jump:
- * |100|xxx|aaaaa|000000000000000000000|
+ * |100|xxx|aaaaa|00000|cccccccccccccccc|
* misc:
* |111|xxx|??????????????????????????|
*
@@ -27,37 +27,32 @@
#define OPC_MUL 002
#define OPC_DIV 003
#define OPC_MOD 004
-#define OPC_SHL 005
-#define OPC_SHR 006
/* logic */
#define OPC_AND 010
#define OPC_OR 011
-#define OPC_XOR 012
-#define OPC_NOR 013
-/* load & store */
-#define OPC_MOV 020
-#define OPC_LB 021
-#define OPC_LH 022
-#define OPC_LW 023
-#define OPC_SB 024
-#define OPC_SH 025
-#define OPC_SW 026
+/* comparison */
+#define OPC_CMP 020
+#define OPC_EQ 021
+#define OPC_NE 022
+#define OPC_LT 023
+#define OPC_LE 024
+#define OPC_GE 025
+#define OPC_GT 026
-/* branch instructions */
-#define OPC_CMP 030
-#define OPC_BEZ 031
-#define OPC_EQ 032
-#define OPC_NE 033
-#define OPC_LT 034
-#define OPC_LE 035
-#define OPC_GE 036
-#define OPC_GT 037
+/* load & store */
+#define OPC_MOV 030
+#define OPC_LW 031
+#define OPC_SW 032
+#define OPC_PUSH 033
+#define OPC_POP 034
/* jump instructions */
-#define OPC_J 040
-#define OPC_JAL 041
+#define OPC_BEZ 040
+#define OPC_JMP 041
+#define OPC_CALL 042
+#define OPC_RET 043
/* misc */
#define OPC_SYS 070
diff --git a/src/emu/riscas.c b/src/emu/riscas.c
index e4180b2..7a4af47 100644
--- a/src/emu/riscas.c
+++ b/src/emu/riscas.c
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
if (IR == 0xFFFFFFFF)
die("illegal instruction: %s", line);
- fwrite(&IR, sizeof(uint32_t), 1, pfd);
+ fwrite(&IR, 4, 1, pfd);
}
return 0;
diff --git a/src/emu/risci.c b/src/emu/risci.c
index 8c4e30f..704ece8 100644
--- a/src/emu/risci.c
+++ b/src/emu/risci.c
@@ -1,9 +1,11 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
+#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <signal.h>
+#include <assert.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <readline/readline.h>
@@ -11,13 +13,12 @@
#include "asm.h"
#include "cpu.h"
#include "log.h"
+#include "mem.h"
#include "opc.h"
bool is_debug = false;
-bool is_interactive = false;
-
-/* global program buffer */
-uint8_t *P = NULL;
+size_t mem_size = 64 * 1024 * 1024;
+size_t reg_size = 0;
static
void usage(int rc)
@@ -27,27 +28,11 @@ void usage(int rc)
}
static
-void signal_handler(int sig)
+void dump_registers(void)
{
- switch (sig) {
- case SIGILL:
- /* SIGILL is raised by the cpu for an unknown instruction */
- error("ERROR: illegal instruction.");
- if (!is_interactive)
- exit(-1);
- break;
- case SIGSEGV:
- /* SIGSEGV is raised for unaligned memory access */
- error("ERROR: unaligned memory access.");
- if (!is_interactive)
- exit(-1);
- break;
- case SIGFPE:
- /* SIGFPE is raised by devision with zero */
- error("ERROR: division by zero.");
- exit(-1);
- break;
- }
+ fprintf(stderr, "REGISTER DUMP:\n");
+ for (size_t i = 0; i < reg_size; i++)
+ fprintf(stderr, "\tr%zu = %"PRIu32"\n", i, GPR[i]);
}
static
@@ -57,31 +42,34 @@ void read_program(const char *program)
if (lstat(program, &sb) == -1)
pdie("cannot stat program");
- if (sb.st_size % sizeof(uint32_t))
- die("program does not align to op-code size of %u bytes", sizeof(uint32_t));
+ if (sb.st_size % 4)
+ die("program does not align to op-code size of 4 bytes");
int pfd;
if ((pfd = open(program, O_RDONLY)) == -1)
pdie("could not open program");
- P = malloc(sb.st_size + sizeof(uint32_t));
- if (read(pfd, P, sb.st_size) != sb.st_size)
- die("premature end of program");
+ /* initialize register file */
+ assert(read(pfd, &reg_size, 4) == 4);
+ reg_size += 4;
+ GPR = calloc(reg_size, 4);
- memset(P + sb.st_size, 0xFF, sizeof(uint32_t));
+ /* initialize pseudo registers */
+ BP = reg_size - 3;
+ SP = reg_size - 2;
+ RV = reg_size - 1;
+ GPR[BP] = GPR[SP] = mem_size;
+ GPR[RV] = 0;
+
+ assert(read(pfd, MEM, sb.st_size - 4) == sb.st_size - 4);
+ memset(MEM + sb.st_size + 4, 0xFF, 4);
}
static
uint32_t next_instruction(void)
{
- if (is_interactive) {
- /* read next instruction from stdin */
- printf("%03d", PC/4);
- return compile(readline("> "));
- }
-
uint32_t tmp;
- memcpy(&tmp, &P[PC], sizeof(uint32_t));
+ memcpy(&tmp, &MEM[IP], 4);
return tmp;
}
@@ -89,15 +77,15 @@ int main(int argc, char *argv[])
{
int ch;
- while ((ch = getopt(argc, argv, "dhi")) != -1) {
+ while ((ch = getopt(argc, argv, "dhm")) != -1) {
switch (ch) {
case 'd':
is_debug = true;
break;
case 'h':
usage(EXIT_SUCCESS);
- case 'i':
- is_interactive = true;
+ case 'm':
+ mem_size = atoi(optarg) * 4;
break;
case '?':
default:
@@ -108,26 +96,21 @@ int main(int argc, char *argv[])
argc -= optind;
argv += optind;
- /* catch cpu signal traps */
- signal(SIGILL, signal_handler);
- signal(SIGFPE, signal_handler);
- signal(SIGSEGV, signal_handler);
-
- /* load program from file if we're not in interactive mode */
- if (!is_interactive) {
- if (argc < 1)
- usage(EXIT_FAILURE);
+ /* reserve memory */
+ MEM = calloc(mem_size, sizeof(char));
- read_program(argv[0]);
- }
+ /* load program from file */
+ if (argc < 1)
+ usage(EXIT_FAILURE);
+ read_program(argv[0]);
/* reset program counter to first instruction */
- PC = 0;
+ IP = 0;
/* start instruction loop */
while (1) {
+ //dump_registers();
execute(next_instruction());
- PC += 4;
}
/* not reached, program is terminated by signal traps from the cpu */
diff --git a/src/emu/syscall.c b/src/emu/syscall.c
index fe0d83e..625bbf4 100644
--- a/src/emu/syscall.c
+++ b/src/emu/syscall.c
@@ -5,19 +5,21 @@
#include "mem.h"
#include "syscall.h"
+#define arg(n) load(GPR[SP] + 4*n)
+
void do_syscall(void)
{
- switch (GPR[1]) {
+ switch (arg(0)) {
case SYS_exit:
- exit(GPR[2]);
+ exit(arg(1));
break;
case SYS_read:
- GPR[2] = read(GPR[2], &MEM[GPR[3]], GPR[4]);
+ push(read(arg(1), &MEM[arg(2)], arg(3)));
break;
case SYS_write:
- GPR[2] = write(GPR[2], &MEM[GPR[3]], GPR[4]);
+ push(write(arg(1), &MEM[arg(2)], arg(3)));
break;
default:
- GPR[2] = -1;
+ push(-1);
}
}
diff --git a/src/emu/test1 b/src/emu/test1
new file mode 100644
index 0000000..e2cbe0a
--- /dev/null
+++ b/src/emu/test1
Binary files differ
diff --git a/src/emu/test1.S b/src/emu/test1.S
new file mode 100644
index 0000000..1feae7a
--- /dev/null
+++ b/src/emu/test1.S
@@ -0,0 +1,126 @@
+.REGS 23
+JMP 53
+PUSH r24
+ADD r24, r0, r25
+PUSH r1
+PUSH r2
+PUSH r3
+PUSH r4
+PUSH r5
+PUSH r6
+PUSH r7
+PUSH r8
+PUSH r9
+PUSH r10
+LW r24, r2, 8
+MOV r3, 2
+CMP r2, r3
+LT r1
+BEZ r1, 4
+MOV r4, 1
+ADD r26, r0, r4
+JMP 20
+LW r24, r5, 8
+MOV r6, 1
+SUB r5, r5, r6
+PUSH r5
+CALL -24
+ADD r7, r0, r26
+POP r0
+LW r24, r8, 8
+MOV r9, 2
+SUB r8, r8, r9
+PUSH r8
+CALL -31
+ADD r10, r0, r26
+POP r0
+ADD r7, r7, r10
+ADD r26, r0, r7
+JMP 3
+ADD r26, r0, r0
+JMP 1
+POP r10
+POP r9
+POP r8
+POP r7
+POP r6
+POP r5
+POP r4
+POP r3
+POP r2
+POP r1
+ADD r25, r0, r24
+POP r24
+RET
+PUSH r24
+ADD r24, r0, r25
+PUSH r0
+PUSH r0
+PUSH r0
+PUSH r11
+PUSH r12
+PUSH r13
+PUSH r14
+PUSH r15
+PUSH r16
+PUSH r17
+PUSH r18
+PUSH r19
+PUSH r20
+PUSH r21
+PUSH r22
+PUSH r23
+MOV r11, 0
+SW r24, r11, -4
+MOV r12, 0
+SW r24, r12, -8
+LW r24, r14, -8
+MOV r15, 10
+CMP r14, r15
+LT r13
+BEZ r13, 14
+LW r24, r16, -4
+LW r24, r17, -8
+PUSH r17
+CALL -82
+ADD r18, r0, r26
+POP r0
+ADD r16, r16, r18
+SW r24, r16, -4
+LW r24, r19, -8
+MOV r20, 1
+ADD r19, r19, r20
+SW r24, r19, -8
+JMP -17
+MOV r21, 3
+PUSH r21
+CALL -94
+ADD r22, r0, r26
+POP r0
+SW r24, r22, -12
+LW r24, r23, -4
+ADD r26, r0, r23
+JMP 3
+ADD r26, r0, r0
+JMP 1
+POP r0
+POP r0
+POP r0
+POP r23
+POP r22
+POP r21
+POP r20
+POP r19
+POP r18
+POP r17
+POP r16
+POP r15
+POP r14
+POP r13
+POP r12
+POP r11
+ADD r25, r0, r24
+POP r24
+PUSH r26
+PUSH r0
+SYS
diff --git a/src/emu/test4 b/src/emu/test4
new file mode 100644
index 0000000..6219e58
--- /dev/null
+++ b/src/emu/test4
Binary files differ
diff --git a/src/emu/test4.S b/src/emu/test4.S
new file mode 100644
index 0000000..08e5375
--- /dev/null
+++ b/src/emu/test4.S
@@ -0,0 +1,54 @@
+.REGS 7
+JMP 17
+PUSH r8
+ADD r8, r0, r9
+PUSH r1
+PUSH r2
+LW r8, r1, 8
+MOV r2, 2
+MUL r1, r1, r2
+ADD r10, r0, r1
+JMP 3
+ADD r10, r0, r0
+JMP 1
+POP r2
+POP r1
+ADD r9, r0, r8
+POP r8
+RET
+PUSH r8
+ADD r8, r0, r9
+PUSH r0
+PUSH r0
+PUSH r3
+PUSH r4
+PUSH r5
+PUSH r6
+PUSH r7
+MOV r3, 10
+MOV r4, 5
+ADD r3, r3, r4
+SW r8, r3, -4
+LW r8, r5, -4
+PUSH r5
+CALL -31
+ADD r6, r0, r10
+POP r0
+SW r8, r6, -8
+LW r8, r7, -8
+ADD r10, r0, r7
+JMP 3
+ADD r10, r0, r0
+JMP 1
+POP r0
+POP r0
+POP r7
+POP r6
+POP r5
+POP r4
+POP r3
+ADD r9, r0, r8
+POP r8
+PUSH r10
+PUSH r0
+SYS