|
|
@ -22,241 +22,186 @@ class RV32I(InstructionSet):
|
|
|
|
See https://maxvytech.com/images/RV32I-11-2018.pdf for a more detailed overview
|
|
|
|
See https://maxvytech.com/images/RV32I-11-2018.pdf for a more detailed overview
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_lb(self, ins: 'Instruction'):
|
|
|
|
def instruction_lb(self, ins: "Instruction"):
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
self.regs.set(rd, Int32.sign_extend(self.mmu.read(addr.unsigned_value, 1), 8))
|
|
|
|
self.regs.set(rd, Int32.sign_extend(self.mmu.read(addr.unsigned_value, 1), 8))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_lh(self, ins: 'Instruction'):
|
|
|
|
def instruction_lh(self, ins: "Instruction"):
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
self.regs.set(rd, Int32.sign_extend(self.mmu.read(addr.unsigned_value, 2), 16))
|
|
|
|
self.regs.set(rd, Int32.sign_extend(self.mmu.read(addr.unsigned_value, 2), 16))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_lw(self, ins: 'Instruction'):
|
|
|
|
def instruction_lw(self, ins: "Instruction"):
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
self.regs.set(rd, Int32(self.mmu.read(addr.unsigned_value, 4)))
|
|
|
|
self.regs.set(rd, Int32(self.mmu.read(addr.unsigned_value, 4)))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_lbu(self, ins: 'Instruction'):
|
|
|
|
def instruction_lbu(self, ins: "Instruction"):
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
self.regs.set(rd, Int32(self.mmu.read(addr.unsigned_value, 1)))
|
|
|
|
self.regs.set(rd, Int32(self.mmu.read(addr.unsigned_value, 1)))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_lhu(self, ins: 'Instruction'):
|
|
|
|
def instruction_lhu(self, ins: "Instruction"):
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
self.regs.set(rd, Int32(self.mmu.read(addr.unsigned_value, 2)))
|
|
|
|
self.regs.set(rd, Int32(self.mmu.read(addr.unsigned_value, 2)))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sb(self, ins: 'Instruction'):
|
|
|
|
def instruction_sb(self, ins: "Instruction"):
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
self.mmu.write(addr.unsigned_value, 1, self.regs.get(rd).to_bytes(1))
|
|
|
|
self.mmu.write(addr.unsigned_value, 1, self.regs.get(rd).to_bytes(1))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sh(self, ins: 'Instruction'):
|
|
|
|
def instruction_sh(self, ins: "Instruction"):
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
self.mmu.write(addr.unsigned_value, 2, self.regs.get(rd).to_bytes(2))
|
|
|
|
self.mmu.write(addr.unsigned_value, 2, self.regs.get(rd).to_bytes(2))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sw(self, ins: 'Instruction'):
|
|
|
|
def instruction_sw(self, ins: "Instruction"):
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
rd, addr = self.parse_mem_ins(ins)
|
|
|
|
self.mmu.write(addr.unsigned_value, 4, self.regs.get(rd).to_bytes(4))
|
|
|
|
self.mmu.write(addr.unsigned_value, 4, self.regs.get(rd).to_bytes(4))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sll(self, ins: 'Instruction'):
|
|
|
|
def instruction_sll(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src2 = ins.get_reg(2)
|
|
|
|
src2 = ins.get_reg(2)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, self.regs.get(src1) << (self.regs.get(src2) & 0b11111))
|
|
|
|
dst,
|
|
|
|
|
|
|
|
self.regs.get(src1) << (self.regs.get(src2) & 0b11111)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_slli(self, ins: 'Instruction'):
|
|
|
|
def instruction_slli(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
imm = ins.get_imm(2)
|
|
|
|
imm = ins.get_imm(2)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, self.regs.get(src1) << (imm & 0b11111))
|
|
|
|
dst,
|
|
|
|
|
|
|
|
self.regs.get(src1) << (imm & 0b11111)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_srl(self, ins: 'Instruction'):
|
|
|
|
def instruction_srl(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src2 = ins.get_reg(2)
|
|
|
|
src2 = ins.get_reg(2)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(
|
|
|
|
dst,
|
|
|
|
dst, self.regs.get(src1).shift_right_logical(self.regs.get(src2) & 0b11111)
|
|
|
|
self.regs.get(src1).shift_right_logical(self.regs.get(src2) & 0b11111)
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_srli(self, ins: 'Instruction'):
|
|
|
|
def instruction_srli(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
imm = ins.get_imm(2)
|
|
|
|
imm = ins.get_imm(2)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, self.regs.get(src1).shift_right_logical(imm & 0b11111))
|
|
|
|
dst,
|
|
|
|
|
|
|
|
self.regs.get(src1).shift_right_logical(imm & 0b11111)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sra(self, ins: 'Instruction'):
|
|
|
|
def instruction_sra(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src2 = ins.get_reg(2)
|
|
|
|
src2 = ins.get_reg(2)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, self.regs.get(src1) >> (self.regs.get(src2) & 0b11111))
|
|
|
|
dst,
|
|
|
|
|
|
|
|
self.regs.get(src1) >> (self.regs.get(src2) & 0b11111)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_srai(self, ins: 'Instruction'):
|
|
|
|
def instruction_srai(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
ASSERT_LEN(ins.args, 3)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
dst = ins.get_reg(0)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
src1 = ins.get_reg(1)
|
|
|
|
imm = ins.get_imm(2)
|
|
|
|
imm = ins.get_imm(2)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, self.regs.get(src1) >> (imm & 0b11111))
|
|
|
|
dst,
|
|
|
|
|
|
|
|
self.regs.get(src1) >> (imm & 0b11111)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_add(self, ins: 'Instruction'):
|
|
|
|
def instruction_add(self, ins: "Instruction"):
|
|
|
|
# FIXME: once configuration is figured out, add flag to support immediate arg in add instruction
|
|
|
|
# FIXME: once configuration is figured out, add flag to support immediate arg in add instruction
|
|
|
|
dst, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
dst, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
|
|
|
|
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, rs1 + rs2)
|
|
|
|
dst,
|
|
|
|
|
|
|
|
rs1 + rs2
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_addi(self, ins: 'Instruction'):
|
|
|
|
def instruction_addi(self, ins: "Instruction"):
|
|
|
|
dst, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
dst, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, rs1 + imm)
|
|
|
|
dst,
|
|
|
|
|
|
|
|
rs1 + imm
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sub(self, ins: 'Instruction'):
|
|
|
|
def instruction_sub(self, ins: "Instruction"):
|
|
|
|
dst, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
dst, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, rs1 - rs2)
|
|
|
|
dst,
|
|
|
|
|
|
|
|
rs1 - rs2
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_lui(self, ins: 'Instruction'):
|
|
|
|
def instruction_lui(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
imm = UInt32(ins.get_imm(1) << 12)
|
|
|
|
imm = UInt32(ins.get_imm(1) << 12)
|
|
|
|
self.regs.set(reg, Int32(imm))
|
|
|
|
self.regs.set(reg, Int32(imm))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_auipc(self, ins: 'Instruction'):
|
|
|
|
def instruction_auipc(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
imm = UInt32(ins.get_imm(1) << 12)
|
|
|
|
imm = UInt32(ins.get_imm(1) << 12)
|
|
|
|
self.regs.set(reg, imm.signed() + self.pc)
|
|
|
|
self.regs.set(reg, imm.signed() + self.pc)
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_xor(self, ins: 'Instruction'):
|
|
|
|
def instruction_xor(self, ins: "Instruction"):
|
|
|
|
rd, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
rd, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(rd, rs1 ^ rs2)
|
|
|
|
rd,
|
|
|
|
|
|
|
|
rs1 ^ rs2
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_xori(self, ins: 'Instruction'):
|
|
|
|
def instruction_xori(self, ins: "Instruction"):
|
|
|
|
rd, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
rd, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(rd, rs1 ^ imm)
|
|
|
|
rd,
|
|
|
|
|
|
|
|
rs1 ^ imm
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_or(self, ins: 'Instruction'):
|
|
|
|
def instruction_or(self, ins: "Instruction"):
|
|
|
|
rd, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
rd, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(rd, rs1 | rs2)
|
|
|
|
rd,
|
|
|
|
|
|
|
|
rs1 | rs2
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_ori(self, ins: 'Instruction'):
|
|
|
|
def instruction_ori(self, ins: "Instruction"):
|
|
|
|
rd, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
rd, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(rd, rs1 | imm)
|
|
|
|
rd,
|
|
|
|
|
|
|
|
rs1 | imm
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_and(self, ins: 'Instruction'):
|
|
|
|
def instruction_and(self, ins: "Instruction"):
|
|
|
|
rd, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
rd, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(rd, rs1 & rs2)
|
|
|
|
rd,
|
|
|
|
|
|
|
|
rs1 & rs2
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_andi(self, ins: 'Instruction'):
|
|
|
|
def instruction_andi(self, ins: "Instruction"):
|
|
|
|
rd, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
rd, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(rd, rs1 & imm)
|
|
|
|
rd,
|
|
|
|
|
|
|
|
rs1 & imm
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_slt(self, ins: 'Instruction'):
|
|
|
|
def instruction_slt(self, ins: "Instruction"):
|
|
|
|
rd, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
rd, rs1, rs2 = self.parse_rd_rs_rs(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(rd, Int32(int(rs1 < rs2)))
|
|
|
|
rd,
|
|
|
|
|
|
|
|
Int32(int(rs1 < rs2))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_slti(self, ins: 'Instruction'):
|
|
|
|
def instruction_slti(self, ins: "Instruction"):
|
|
|
|
rd, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
rd, rs1, imm = self.parse_rd_rs_imm(ins)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(rd, Int32(int(rs1 < imm)))
|
|
|
|
rd,
|
|
|
|
|
|
|
|
Int32(int(rs1 < imm))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sltu(self, ins: 'Instruction'):
|
|
|
|
def instruction_sltu(self, ins: "Instruction"):
|
|
|
|
dst, rs1, rs2 = self.parse_rd_rs_rs(ins, signed=False)
|
|
|
|
dst, rs1, rs2 = self.parse_rd_rs_rs(ins, signed=False)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, Int32(int(rs1 < rs2)))
|
|
|
|
dst,
|
|
|
|
|
|
|
|
Int32(int(rs1 < rs2))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sltiu(self, ins: 'Instruction'):
|
|
|
|
def instruction_sltiu(self, ins: "Instruction"):
|
|
|
|
dst, rs1, imm = self.parse_rd_rs_imm(ins, signed=False)
|
|
|
|
dst, rs1, imm = self.parse_rd_rs_imm(ins, signed=False)
|
|
|
|
self.regs.set(
|
|
|
|
self.regs.set(dst, Int32(int(rs1 < imm)))
|
|
|
|
dst,
|
|
|
|
|
|
|
|
Int32(int(rs1 < imm))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_beq(self, ins: 'Instruction'):
|
|
|
|
def instruction_beq(self, ins: "Instruction"):
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
|
|
|
if rs1 == rs2:
|
|
|
|
if rs1 == rs2:
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_bne(self, ins: 'Instruction'):
|
|
|
|
def instruction_bne(self, ins: "Instruction"):
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
|
|
|
if rs1 != rs2:
|
|
|
|
if rs1 != rs2:
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_blt(self, ins: 'Instruction'):
|
|
|
|
def instruction_blt(self, ins: "Instruction"):
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
|
|
|
if rs1 < rs2:
|
|
|
|
if rs1 < rs2:
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_bge(self, ins: 'Instruction'):
|
|
|
|
def instruction_bge(self, ins: "Instruction"):
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
|
|
|
if rs1 >= rs2:
|
|
|
|
if rs1 >= rs2:
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_bltu(self, ins: 'Instruction'):
|
|
|
|
def instruction_bltu(self, ins: "Instruction"):
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins, signed=False)
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins, signed=False)
|
|
|
|
if rs1 < rs2:
|
|
|
|
if rs1 < rs2:
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_bgeu(self, ins: 'Instruction'):
|
|
|
|
def instruction_bgeu(self, ins: "Instruction"):
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins, signed=False)
|
|
|
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins, signed=False)
|
|
|
|
if rs1 >= rs2:
|
|
|
|
if rs1 >= rs2:
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
self.pc = dst.unsigned_value
|
|
|
|
|
|
|
|
|
|
|
|
# technically deprecated
|
|
|
|
# technically deprecated
|
|
|
|
def instruction_j(self, ins: 'Instruction'):
|
|
|
|
def instruction_j(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 1)
|
|
|
|
ASSERT_LEN(ins.args, 1)
|
|
|
|
addr = ins.get_imm(0)
|
|
|
|
addr = ins.get_imm(0)
|
|
|
|
self.pc = addr
|
|
|
|
self.pc = addr
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_jal(self, ins: 'Instruction'):
|
|
|
|
def instruction_jal(self, ins: "Instruction"):
|
|
|
|
reg = 'ra' # default register is ra
|
|
|
|
reg = "ra" # default register is ra
|
|
|
|
if len(ins.args) == 1:
|
|
|
|
if len(ins.args) == 1:
|
|
|
|
addr = ins.get_imm(0)
|
|
|
|
addr = ins.get_imm(0)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
@ -266,58 +211,60 @@ class RV32I(InstructionSet):
|
|
|
|
self.regs.set(reg, Int32(self.pc))
|
|
|
|
self.regs.set(reg, Int32(self.pc))
|
|
|
|
self.pc = addr
|
|
|
|
self.pc = addr
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_jalr(self, ins: 'Instruction'):
|
|
|
|
def instruction_jalr(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
addr = ins.get_imm(1)
|
|
|
|
addr = ins.get_imm(1)
|
|
|
|
self.regs.set(reg, Int32(self.pc))
|
|
|
|
self.regs.set(reg, Int32(self.pc))
|
|
|
|
self.pc = addr
|
|
|
|
self.pc = addr
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_ret(self, ins: 'Instruction'):
|
|
|
|
def instruction_ret(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 0)
|
|
|
|
ASSERT_LEN(ins.args, 0)
|
|
|
|
self.pc = self.regs.get('ra').value
|
|
|
|
self.pc = self.regs.get("ra").value
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_ecall(self, ins: 'Instruction'):
|
|
|
|
def instruction_ecall(self, ins: "Instruction"):
|
|
|
|
self.instruction_scall(ins)
|
|
|
|
self.instruction_scall(ins)
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_ebreak(self, ins: 'Instruction'):
|
|
|
|
def instruction_ebreak(self, ins: "Instruction"):
|
|
|
|
self.instruction_sbreak(ins)
|
|
|
|
self.instruction_sbreak(ins)
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_scall(self, ins: 'Instruction'):
|
|
|
|
def instruction_scall(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 0)
|
|
|
|
ASSERT_LEN(ins.args, 0)
|
|
|
|
|
|
|
|
|
|
|
|
if not isinstance(self.cpu, UserModeCPU):
|
|
|
|
if not isinstance(self.cpu, UserModeCPU):
|
|
|
|
# FIXME: add exception for syscall not supported or something
|
|
|
|
# FIXME: add exception for syscall not supported or something
|
|
|
|
raise
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
syscall = Syscall(self.regs.get('a7'), self.cpu)
|
|
|
|
syscall = Syscall(self.regs.get("a7"), self.cpu)
|
|
|
|
self.cpu.syscall_int.handle_syscall(syscall)
|
|
|
|
self.cpu.syscall_int.handle_syscall(syscall)
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_sbreak(self, ins: 'Instruction'):
|
|
|
|
def instruction_sbreak(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 0)
|
|
|
|
ASSERT_LEN(ins.args, 0)
|
|
|
|
if self.cpu.conf.debug_instruction:
|
|
|
|
if self.cpu.conf.debug_instruction:
|
|
|
|
print(FMT_DEBUG + "Debug instruction encountered at 0x{:08X}".format(self.pc - 1) + FMT_NONE)
|
|
|
|
print(
|
|
|
|
|
|
|
|
FMT_DEBUG
|
|
|
|
|
|
|
|
+ "Debug instruction encountered at 0x{:08X}".format(self.pc - 1)
|
|
|
|
|
|
|
|
+ FMT_NONE
|
|
|
|
|
|
|
|
)
|
|
|
|
raise LaunchDebuggerException()
|
|
|
|
raise LaunchDebuggerException()
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_nop(self, ins: 'Instruction'):
|
|
|
|
def instruction_nop(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 0)
|
|
|
|
ASSERT_LEN(ins.args, 0)
|
|
|
|
pass
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_li(self, ins: 'Instruction'):
|
|
|
|
def instruction_li(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
immediate = ins.get_imm(1)
|
|
|
|
immediate = ins.get_imm(1)
|
|
|
|
self.regs.set(reg, Int32(immediate))
|
|
|
|
self.regs.set(reg, Int32(immediate))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_la(self, ins: 'Instruction'):
|
|
|
|
def instruction_la(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
reg = ins.get_reg(0)
|
|
|
|
immediate = ins.get_imm(1)
|
|
|
|
immediate = ins.get_imm(1)
|
|
|
|
self.regs.set(reg, Int32(immediate))
|
|
|
|
self.regs.set(reg, Int32(immediate))
|
|
|
|
|
|
|
|
|
|
|
|
def instruction_mv(self, ins: 'Instruction'):
|
|
|
|
def instruction_mv(self, ins: "Instruction"):
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
ASSERT_LEN(ins.args, 2)
|
|
|
|
rd, rs = ins.get_reg(0), ins.get_reg(1)
|
|
|
|
rd, rs = ins.get_reg(0), ins.get_reg(1)
|
|
|
|
self.regs.set(rd, self.regs.get(rs))
|
|
|
|
self.regs.set(rd, self.regs.get(rs))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|