From ab276c733ce9dc80983e5c8ae5c530e1477cf990 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 31 Mar 2024 23:10:44 +0300 Subject: implement more meta instructions + Also have a working draft of ABI names for registers, matches qbt currently but should probably codify somewhere --- triscv/src/cpu.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++----- triscv/src/mem.c | 13 +++--- 2 files changed, 119 insertions(+), 15 deletions(-) (limited to 'triscv/src') diff --git a/triscv/src/cpu.c b/triscv/src/cpu.c index a47ec78..a2bc9fb 100644 --- a/triscv/src/cpu.c +++ b/triscv/src/cpu.c @@ -106,14 +106,50 @@ static void do_op_imm(struct cpu *cpu, tri_t i) set_gpr(cpu, rd, r); break; } - default: fprintf(stderr, "illegal/unimplemented OP_IMM at %lx," - "aborting\n", cpu->pc); + default: fprintf(stderr, "illegal/unimplemented OP_IMM at %lli, " + "aborting\n", (long long int)cpu->pc); abort(); } cpu->pc += 3; } +static void do_op(struct cpu *cpu, tri_t i) +{ + tri_t rd, fn0, rs1, rs2, fn5; + parse_r(i, &rd, &fn0, &rs1, &rs2, &fn5); + + tri_t src1 = get_gpr(cpu, rs1); + tri_t src2 = get_gpr(cpu, rs2); + + switch (fn5) { + case 0: + switch (fn0) { + case OP_ADD: { + tri_t r = tri_add(src1, src2); + set_gpr(cpu, rd, r); + break; + } + + case OP_SUB: { + tri_t r = tri_sub(src1, src2); + set_gpr(cpu, rd, r); + break; + } + default: fprintf(stderr, "illegal/unimplemented OP at %lli, " + "aborting\n", (long long int)cpu->pc); + abort(); + } + break; + + default: fprintf(stderr, "illegal/unimplemented OP at %lli, " + "aborting\n", (long long int)cpu->pc); + abort(); + } + + cpu->pc += 3; +} + static void do_system(struct cpu *cpu, tri_t i) { tri_t rd, fn0, rs1, imm9; @@ -131,8 +167,8 @@ static void do_system(struct cpu *cpu, tri_t i) break; } - default: fprintf(stderr, "illegal/unimplemented SYSTEM at %lx," - "aborting\n", cpu->pc); + default: fprintf(stderr, "illegal/unimplemented SYSTEM at %lli," + "aborting\n", (long long int)cpu->pc); abort(); } @@ -167,6 +203,34 @@ static void do_store(struct cpu *cpu, tri_t i) cpu->pc += 3; } +static void do_load(struct cpu *cpu, tri_t i) +{ + tri_t rd, fn0, rs1, imm9; + parse_i(i, &rd, &fn0, &rs1, &imm9); + + tri_t base = get_gpr(cpu, rs1); + + /* should maybe check that there's zeroes in other trits in fn0? */ + int w = tri_get_trit(fn0, 4); + + /* somewhat unsure if mmu should function in trinary or binary at this + * point */ + tri_t addr = tri_add(base, imm9); + vm_t a = tri_to(addr); + + tri_t r = 0; + switch (w) { + case 0: r = mmu_read1(cpu, cpu->mmu, a); break; + case 1: r = mmu_read3(cpu, cpu->mmu, a); break; + default: + /* illegal value */ + abort(); + } + + set_gpr(cpu, rd, r); + cpu->pc += 3; +} + static void do_lui(struct cpu *cpu, tri_t i) { tri_t rd, imm18; @@ -175,6 +239,16 @@ static void do_lui(struct cpu *cpu, tri_t i) cpu->pc += 3; } +static void do_auipc(struct cpu *cpu, tri_t i) +{ + tri_t rd, imm18; + parse_u(i, &rd, &imm18); + tri_t pc = tri_from(cpu->pc); + tri_t sum = tri_add(pc, tri_sl(imm18, 9)); + set_gpr(cpu, rd, sum); + cpu->pc += 3; +} + static void do_jal(struct cpu *cpu, tri_t i) { tri_t rd, imm9; @@ -192,16 +266,41 @@ static void do_jalr(struct cpu *cpu, tri_t i) tri_t rd, fn0, rs1, imm9; parse_i(i, &rd, &fn0, &rs1, &imm9); - tri_t p = tri_from(cpu->pc + 3); - set_gpr(cpu, rd, p); - tri_t t = get_gpr(cpu, rs1); t = tri_add(t, imm9); long long j = tri_to(t); + tri_t p = tri_from(cpu->pc + 3); + set_gpr(cpu, rd, p); + cpu->pc = j; } +static void do_branch(struct cpu *cpu, tri_t i) +{ + tri_t imm4, fn0, rs1, rs2, imm5; + parse_s(i, &imm4, &fn0, &rs1, &rs2, &imm5); + + tri_t imm9 = tri_sl(imm4, 5) | imm5; + + tri_t c0 = get_gpr(cpu, rs1); + tri_t c1 = get_gpr(cpu, rs2); + + long long t = tri_to(imm9) + cpu->pc; + long long f = cpu->pc + 3; + + bool take = false; + switch (fn0) { + case BRANCH_BLT: take = tri_lt(c0, c1); break; + case BRANCH_BGE: take = tri_ge(c0, c1); break; + default: fprintf(stderr, "illegal/unimplemented BRANCH at %lli," + "aborting\n", (long long int)cpu->pc); + abort(); + } + + cpu->pc = take ? t : f; +} + void cpu_reset(struct cpu *cpu) { csr_init(cpu); @@ -220,14 +319,18 @@ void cpu_run(struct cpu *cpu, vm_t start) switch (parse_opcode(i)) { case OPCODE_LUI: do_lui(cpu, i); break; case OPCODE_STORE: do_store(cpu, i); break; + case OPCODE_LOAD: do_load(cpu, i); break; case OPCODE_SYSTEM: do_system(cpu, i); break; case OPCODE_OP_IMM: do_op_imm(cpu, i); break; + case OPCODE_OP: do_op(cpu, i); break; + case OPCODE_AUIPC: do_auipc(cpu, i); break; case OPCODE_JAL: do_jal(cpu, i); break; case OPCODE_JALR: do_jalr(cpu, i); break; + case OPCODE_BRANCH: do_branch(cpu, i); break; default: /** @todo raise illegal instruction exception */ fprintf(stderr, "illegal/unimplemented " - "instruction at %lx, aborting\n", - cpu->pc); + "instruction at %lli, aborting\n", + (long long int)cpu->pc); abort(); break; } diff --git a/triscv/src/mem.c b/triscv/src/mem.c index 84bd71f..1bcecfc 100644 --- a/triscv/src/mem.c +++ b/triscv/src/mem.c @@ -26,17 +26,18 @@ void mem_init(struct mem *mem, const void *buf, size_t len) static void mem_write1(struct cpu *cpu, struct mem *mem, pm_t addr, tri_t t) { (void)cpu; - (void)mem; - (void)addr; - (void)t; + mem->buf[addr] = tri_mask(t, 9); } static void mem_write3(struct cpu *cpu, struct mem *mem, pm_t addr, tri_t t) { (void)cpu; - (void)mem; - (void)addr; - (void)t; + tri_t t0 = tri_mask(t, 9); + tri_t t1 = tri_mask(tri_sr(t, 9), 9); + tri_t t2 = tri_mask(tri_sr(t, 18), 9); + mem_write1(cpu, mem, addr + 0, t0); + mem_write1(cpu, mem, addr + 1, t1); + mem_write1(cpu, mem, addr + 2, t2); } static tri_t mem_read1(struct cpu *cpu, struct mem *mem, pm_t addr) -- cgit v1.3