aboutsummaryrefslogtreecommitdiff
path: root/triscv/src
diff options
context:
space:
mode:
Diffstat (limited to 'triscv/src')
-rw-r--r--triscv/src/cpu.c121
-rw-r--r--triscv/src/mem.c13
2 files changed, 119 insertions, 15 deletions
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)