From 6165e2dde32a8f425e54d4f061146b366d5a2e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benedikt=20B=C3=B6hm?= Date: Sat, 4 Jul 2009 10:49:19 +0200 Subject: 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 --- src/emu/asm.c | 49 ++++++++++----- src/emu/cpu.c | 175 ++++++++++++++++++++++++++++-------------------------- src/emu/cpu.h | 17 ++++-- src/emu/mem.c | 36 ++++++++++- src/emu/mem.h | 9 ++- src/emu/opc.c | 53 ++++++++--------- src/emu/opc.h | 47 +++++++-------- src/emu/riscas.c | 2 +- src/emu/risci.c | 89 +++++++++++---------------- src/emu/syscall.c | 12 ++-- src/emu/test1 | Bin 0 -> 456 bytes src/emu/test1.S | 126 +++++++++++++++++++++++++++++++++++++++ src/emu/test4 | Bin 0 -> 216 bytes src/emu/test4.S | 54 +++++++++++++++++ 14 files changed, 450 insertions(+), 219 deletions(-) create mode 100644 src/emu/test1 create mode 100644 src/emu/test1.S create mode 100644 src/emu/test4 create mode 100644 src/emu/test4.S 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 +#include +#include + +#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 +#include -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 #include #include +#include #include #include #include +#include #include #include #include @@ -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, ®_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 Binary files /dev/null and b/src/emu/test1 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 Binary files /dev/null and b/src/emu/test4 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 -- cgit v1.2.3