Add APSR support (#53)

* Add APSR support

* #issuecomment-284826572

* APSR tests

* cspr to aspr
This commit is contained in:
feliam 2017-03-08 17:17:05 -03:00 committed by GitHub
parent ef6e21b865
commit 1cc66f16ca
2 changed files with 65 additions and 2 deletions

View File

@ -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]

View File

@ -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)