squashing bugs related to Int32 wrapping and sign extension

assembly-parser-rework
Anton Lydike 3 years ago
parent c2b6385523
commit 4004c5ee6d

@ -24,11 +24,11 @@ class RV32I(InstructionSet):
def instruction_lb(self, ins: 'Instruction'):
rd, addr = self.parse_mem_ins(ins)
self.regs.set(rd, Int32(self.mmu.read(addr.unsigned_value, 1)))
self.regs.set(rd, Int32.sign_extend(self.mmu.read(addr.unsigned_value, 1), 8))
def instruction_lh(self, ins: 'Instruction'):
rd, addr = self.parse_mem_ins(ins)
self.regs.set(rd, Int32(self.mmu.read(addr.unsigned_value, 2)))
self.regs.set(rd, Int32.sign_extend(self.mmu.read(addr.unsigned_value, 2), 16))
def instruction_lw(self, ins: 'Instruction'):
rd, addr = self.parse_mem_ins(ins)
@ -36,23 +36,23 @@ class RV32I(InstructionSet):
def instruction_lbu(self, ins: 'Instruction'):
rd, addr = self.parse_mem_ins(ins)
self.regs.set(rd, UInt32(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'):
rd, addr = self.parse_mem_ins(ins)
self.regs.set(rd, UInt32(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'):
rd, addr = self.parse_mem_ins(ins)
self.mmu.write(addr.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'):
rd, addr = self.parse_mem_ins(ins)
self.mmu.write(addr.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'):
rd, addr = self.parse_mem_ins(ins)
self.mmu.write(addr.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'):
ASSERT_LEN(ins.args, 3)
@ -140,7 +140,7 @@ class RV32I(InstructionSet):
def instruction_lui(self, ins: 'Instruction'):
ASSERT_LEN(ins.args, 2)
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))
def instruction_auipc(self, ins: 'Instruction'):
@ -263,14 +263,14 @@ class RV32I(InstructionSet):
ASSERT_LEN(ins.args, 2)
reg = ins.get_reg(0)
addr = ins.get_imm(1)
self.regs.set(reg, self.pc)
self.regs.set(reg, Int32(self.pc))
self.pc = addr
def instruction_jalr(self, ins: 'Instruction'):
ASSERT_LEN(ins.args, 2)
reg = ins.get_reg(0)
addr = ins.get_imm(1)
self.regs.set(reg, self.pc)
self.regs.set(reg, Int32(self.pc))
self.pc = addr
def instruction_ret(self, ins: 'Instruction'):
@ -307,13 +307,13 @@ class RV32I(InstructionSet):
ASSERT_LEN(ins.args, 2)
reg = ins.get_reg(0)
immediate = ins.get_imm(1)
self.regs.set(reg, immediate)
self.regs.set(reg, Int32(immediate))
def instruction_la(self, ins: 'Instruction'):
ASSERT_LEN(ins.args, 2)
reg = ins.get_reg(0)
immediate = ins.get_imm(1)
self.regs.set(reg, immediate)
self.regs.set(reg, Int32(immediate))
def instruction_mv(self, ins: 'Instruction'):
ASSERT_LEN(ins.args, 2)

@ -109,7 +109,7 @@ class Registers:
if mark_set:
self.last_set = reg
# check 32 bit signed bounds
self.vals[reg] = val
self.vals[reg] = val.unsigned()
return True
def get(self, reg, mark_read=True) -> 'Int32':

@ -16,7 +16,8 @@ class Int32:
def __init__(self, val: Union[int, c_int32, c_uint32, 'Int32', bytes, bytearray] = 0):
if isinstance(val, (bytes, bytearray)):
self._val = self.__class__._type(int.from_bytes(val, 'little', signed=True))
signed = len(val) == 4 and self._type == c_int32
self._val = self.__class__._type(int.from_bytes(val, 'little', signed=signed))
elif isinstance(val, self.__class__._type):
self._val = val
elif isinstance(val, (c_uint32, c_int32, Int32)):
@ -187,7 +188,7 @@ class Int32:
:param bytes: The length of the bytearray
:return: A little-endian representation of the contained integer
"""
return bytearray(self.unsigned_value.to_bytes(bytes, 'little'))
return bytearray(self.unsigned_value.to_bytes(4, 'little'))[0:bytes]
def signed(self) -> 'Int32':
"""
@ -225,6 +226,25 @@ class Int32:
def __hex__(self):
return hex(self.value)
@classmethod
def sign_extend(cls, data: Union[bytes, bytearray, int], bits: int):
"""
Create an instance of Int32 by sign extending :param:bits bits from :param:data
to 32 bits
:param data: The source data
:param bits: The number of bits in the source data
:return: An instance of Int32, holding the sign-extended value
"""
if isinstance(data, (bytes, bytearray)):
data = int.from_bytes(data, 'little')
sign = data >> (bits - 1)
if sign > 1:
print("overflow in Int32.sext!")
if sign:
data = (data & (2 ** (bits - 1) - 1)) - 2**(bits-1)
return cls(data)
class UInt32(Int32):
"""

Loading…
Cancel
Save