From d8f46c781c7dbe2af397eebdb825dce8623c6fc7 Mon Sep 17 00:00:00 2001 From: Anton Lydike Date: Mon, 19 Apr 2021 09:00:45 +0200 Subject: [PATCH] finished the RV32I instruction set --- riscemu/instructions/RV32I.py | 156 +++++++++++++++------------------- 1 file changed, 70 insertions(+), 86 deletions(-) diff --git a/riscemu/instructions/RV32I.py b/riscemu/instructions/RV32I.py index 82ca515..2bb9ea4 100644 --- a/riscemu/instructions/RV32I.py +++ b/riscemu/instructions/RV32I.py @@ -97,33 +97,24 @@ class RV32I(InstructionSet): ) def instruction_add(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - dst = ins.get_reg(0) - src1 = ins.get_reg(1) - src2 = ins.get_reg(2) + dst, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set( dst, - self.regs.get(src1) + self.regs.get(src2) + rs1 + rs2 ) def instruction_addi(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - dst = ins.get_reg(0) - src1 = ins.get_reg(1) - imm = ins.get_imm(2) + dst, rs1, imm = self.parse_rd_rs_imm(ins) self.regs.set( dst, - self.regs.get(src1) + imm + rs1 + imm ) def instruction_sub(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - dst = ins.get_reg(0) - src1 = ins.get_reg(1) - src2 = ins.get_reg(2) + dst, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set( dst, - self.regs.get(src1) - self.regs.get(src2) + rs1 - rs2 ) def instruction_lui(self, ins: 'LoadedInstruction'): @@ -133,120 +124,111 @@ class RV32I(InstructionSet): self.regs.set(reg, imm << 12) def instruction_auipc(self, ins: 'LoadedInstruction'): - INS_NOT_IMPLEMENTED(ins) + ASSERT_LEN(ins.args, 2) + reg = ins.get_reg(0) + imm = to_unsigned(ins.get_imm(1)) + self.pc += (imm << 12) + self.regs.set(reg, self.pc) def instruction_xor(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - dst = ins.get_reg(0) - src1 = ins.get_reg(1) - src2 = ins.get_reg(2) + rd, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set( - dst, - self.regs.get(src1) ^ self.regs.get(src2) + rd, + rs1 ^ rs2 ) def instruction_xori(self, ins: 'LoadedInstruction'): - INS_NOT_IMPLEMENTED(ins) + rd, rs1, imm = self.parse_rd_rs_imm(ins) + self.regs.set( + rd, + rs1 ^ imm + ) def instruction_or(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - dst = ins.get_reg(0) - src1 = ins.get_reg(1) - src2 = ins.get_reg(2) + rd, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set( - dst, - self.regs.get(src1) | self.regs.get(src2) + rd, + rs1 | rs2 ) def instruction_ori(self, ins: 'LoadedInstruction'): - INS_NOT_IMPLEMENTED(ins) + rd, rs1, imm = self.parse_rd_rs_imm(ins) + self.regs.set( + rd, + rs1 | imm + ) def instruction_and(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - dst = ins.get_reg(0) - src1 = ins.get_reg(1) - src2 = ins.get_reg(2) + rd, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set( - dst, - self.regs.get(src1) & self.regs.get(src2) + rd, + rs1 & rs2 ) def instruction_andi(self, ins: 'LoadedInstruction'): - INS_NOT_IMPLEMENTED(ins) + rd, rs1, imm = self.parse_rd_rs_imm(ins) + self.regs.set( + rd, + rs1 & imm + ) def instruction_slt(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - dst = ins.get_reg(0) - src1 = ins.get_reg(1) - src2 = ins.get_reg(2) + rd, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set( - dst, - int(self.regs.get(src1) < self.regs.get(src2)) + rd, + int(rs1 < rs2) ) def instruction_slti(self, ins: 'LoadedInstruction'): - INS_NOT_IMPLEMENTED(ins) + rd, rs1, imm = self.parse_rd_rs_imm(ins) + self.regs.set( + rd, + int(rs1 < imm) + ) def instruction_sltu(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - dst = ins.get_reg(0) - src1 = ins.get_reg(1) - src2 = ins.get_reg(2) + dst, rs1, rs2 = self.parse_rd_rs_rs(ins, signed=False) self.regs.set( dst, - int(to_unsigned(self.regs.get(src1)) < to_unsigned(self.regs.get(src2))) + int(rs1 < rs2) ) def instruction_sltiu(self, ins: 'LoadedInstruction'): - INS_NOT_IMPLEMENTED(ins) + dst, rs1, imm = self.parse_rd_rs_imm(ins, signed=False) + self.regs.set( + dst, + int(rs1 < imm) + ) def instruction_beq(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - reg1 = ins.get_reg(0) - reg2 = ins.get_reg(1) - dest = ins.get_imm(2) - if self.regs.get(reg1) == self.regs.get(reg2): - self.pc = dest + rs1, rs2, dst = self.parse_rs_rs_imm(ins) + if rs1 == rs2: + self.pc = dst def instruction_bne(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - reg1 = ins.get_reg(0) - reg2 = ins.get_reg(1) - dest = ins.get_imm(2) - if self.regs.get(reg1) != self.regs.get(reg2): - self.pc = dest + rs1, rs2, dst = self.parse_rs_rs_imm(ins) + if rs1 != rs2: + self.pc = dst def instruction_blt(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - reg1 = ins.get_reg(0) - reg2 = ins.get_reg(1) - dest = ins.get_imm(2) - if self.regs.get(reg1) < self.regs.get(reg2): - self.pc = dest + rs1, rs2, dst = self.parse_rs_rs_imm(ins) + if rs1 < rs2: + self.pc = dst def instruction_bge(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - reg1 = self.get_reg_content(ins, 0) - reg2 = self.get_reg_content(ins, 1) - dest = ins.get_imm(2) - if reg1 >= reg2: - self.pc = dest + rs1, rs2, dst = self.parse_rs_rs_imm(ins) + if rs1 >= rs2: + self.pc = dst def instruction_bltu(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - reg1 = self.get_reg_content(ins, 0) - reg2 = self.get_reg_content(ins, 1) - dest = ins.get_imm(2) - if to_unsigned(reg1) < to_unsigned(reg2): - self.pc = dest + rs1, rs2, dst = self.parse_rs_rs_imm(ins, signed=False) + if rs1 < rs2: + self.pc = dst def instruction_bgeu(self, ins: 'LoadedInstruction'): - ASSERT_LEN(ins.args, 3) - reg1 = to_unsigned(self.get_reg_content(ins, 0)) - reg2 = to_unsigned(self.get_reg_content(ins, 1)) - dest = ins.get_imm(2) - if reg1 >= reg2: - self.pc = dest + rs1, rs2, dst = self.parse_rs_rs_imm(ins, signed=False) + if rs1 >= rs2: + self.pc = dst # technically deprecated def instruction_j(self, ins: 'LoadedInstruction'): @@ -288,7 +270,9 @@ class RV32I(InstructionSet): self.cpu.syscall_int.handle_syscall(syscall) def instruction_sbreak(self, ins: 'LoadedInstruction'): + ASSERT_LEN(ins.args, 0) launch_debug_session(self.cpu, self.mmu, self.regs, "Debug instruction encountered at 0x{:08X}".format(self.pc)) def instruction_nop(self, ins: 'LoadedInstruction'): + ASSERT_LEN(ins.args, 0) pass