Add APSR support (#53)
* Add APSR support * #issuecomment-284826572 * APSR tests * cspr to aspr
This commit is contained in:
parent
ef6e21b865
commit
1cc66f16ca
@ -226,7 +226,8 @@ class Armv7RegisterFile(RegisterFile):
|
||||
ARM_REG_APSR_N: 48,
|
||||
ARM_REG_APSR_Z: 49,
|
||||
ARM_REG_APSR_C: 50,
|
||||
ARM_REG_APSR_V: 51
|
||||
ARM_REG_APSR_V: 51,
|
||||
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
@ -243,10 +244,50 @@ class Armv7RegisterFile(RegisterFile):
|
||||
bit_flags = [Register(1) for x in xrange(4)]
|
||||
self.regs = gpr + vec + bit_flags
|
||||
|
||||
def _read_APSR(self):
|
||||
N = self.read(ARM_REG_APSR_N)
|
||||
Z = self.read(ARM_REG_APSR_Z)
|
||||
C = self.read(ARM_REG_APSR_C)
|
||||
V = self.read(ARM_REG_APSR_V)
|
||||
apsr = 0
|
||||
|
||||
def make_apsr_flag(flag_expr, offset):
|
||||
'Helper for constructing an expression for the APSR register'
|
||||
return Operators.ITEBV(cpu.address_bit_size, flag_expr,
|
||||
BitVecConstant(cpu.address_bit_size, 1 << offset),
|
||||
BitVecConstant(cpu.address_bit_size, 0))
|
||||
if any(issymbolic(x) for x in [N, Z, C, V]):
|
||||
apsr = (make_apsr_flag(N, 31) |
|
||||
make_apsr_flag(Z, 30) |
|
||||
make_apsr_flag(C, 29) |
|
||||
make_apsr_flag(V, 28))
|
||||
else:
|
||||
if N: apsr |= 1 << 31
|
||||
if Z: apsr |= 1 << 30
|
||||
if C: apsr |= 1 << 29
|
||||
if V: apsr |= 1 << 28
|
||||
return apsr
|
||||
|
||||
def _write_APSR(self, apsr):
|
||||
V = Operators.EXTRACT(apsr, 28, 1)
|
||||
C = Operators.EXTRACT(apsr, 29, 1)
|
||||
Z = Operators.EXTRACT(apsr, 30, 1)
|
||||
N = Operators.EXTRACT(apsr, 31, 1)
|
||||
|
||||
self.write(ARM_REG_APSR_V, V)
|
||||
self.write(ARM_REG_APSR_C, C)
|
||||
self.write(ARM_REG_APSR_Z, Z)
|
||||
self.write(ARM_REG_APSR_N, N)
|
||||
|
||||
|
||||
def read(self, reg_id):
|
||||
if reg_id == ARM_REG_APSR:
|
||||
return self._read_APSR()
|
||||
return self.regs[self.REGMAP[reg_id]].read()
|
||||
|
||||
def write(self, reg_id, val):
|
||||
if reg_id == ARM_REG_APSR:
|
||||
return self._write_APSR(val)
|
||||
reg_offset = self.REGMAP[reg_id]
|
||||
reg = self.regs[reg_offset]
|
||||
reg.write(val)
|
||||
@ -259,7 +300,7 @@ class Armv7RegisterFile(RegisterFile):
|
||||
|
||||
@property
|
||||
def canonical_registers(self):
|
||||
return ('R0','R1','R2','R3','R4','R5','R6','R7','R8','R9','R10','R11','R12', 'SP', 'LR', 'PC')
|
||||
return ('R0','R1','R2','R3','R4','R5','R6','R7','R8','R9','R10','R11','R12', 'SP', 'LR', 'PC', 'APSR')
|
||||
|
||||
def reg_name(self, reg_id):
|
||||
reg_offset = self.REGMAP[reg_id]
|
||||
|
||||
@ -46,3 +46,25 @@ class Armv7RF(unittest.TestCase):
|
||||
def test_bad_reg_id(self):
|
||||
with self.assertRaises(KeyError):
|
||||
self.r.reg_id('XXX')
|
||||
|
||||
def test_flag_wr(self):
|
||||
self.r.write(ARM_REG_APSR, 0xffffffff)
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR), 0xf0000000) #4 more significant bits used
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR_V), True)
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR_C), True)
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR_Z), True)
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR_N), True)
|
||||
|
||||
self.r.write(ARM_REG_APSR_N, False)
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR), 0x70000000)
|
||||
|
||||
self.r.write(ARM_REG_APSR_Z, False)
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR), 0x30000000)
|
||||
|
||||
self.r.write(ARM_REG_APSR_C, False)
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR), 0x10000000)
|
||||
|
||||
self.r.write(ARM_REG_APSR_V, False)
|
||||
self.assertEqual(self.r.read(ARM_REG_APSR), 0x00000000)
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user