From 18a93f4049f6f9a72eb52aaeac13571f7b18c41a Mon Sep 17 00:00:00 2001
From: woni <81616747+W0ni@users.noreply.github.com>
Date: Wed, 6 Sep 2023 18:19:56 +0200
Subject: [PATCH 1/5] Add shifters for instructions that use shifter carry
---
miasm/arch/arm/sem.py | 230 ++++++++++++++++++++++++++++--------------
1 file changed, 154 insertions(+), 76 deletions(-)
diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py
index e507a0456..0c6234751 100644
--- a/miasm/arch/arm/sem.py
+++ b/miasm/arch/arm/sem.py
@@ -2,6 +2,7 @@
from future.utils import viewitems, viewvalues
from miasm.expression.expression import *
+from miasm.expression.simplifications import expr_simp
from miasm.ir.ir import Lifter, IRBlock, AssignBlock
from miasm.arch.arm.arch import mn_arm, mn_armt
from miasm.arch.arm.regs import *
@@ -253,6 +254,15 @@ def update_flag_zn(a):
return e
+# Instructions which use shifter's carry flag: ANDS, BICS, EORS, MOVS/RRX, MVNS, ORNS (TODO), ORRS, TEQ, TST
+def compute_rrx_carry(operation):
+ """
+ Returns a tuple (result, carry) corresponding to the RRX computation
+ @operation: The ExprOp operation
+ """
+ new_cf = operation.args[0][:1]
+ res = ExprCompose(operation.args[0][1:], cf)
+ return res, new_cf
# XXX TODO: set cf if ROT imm in argument
@@ -272,12 +282,12 @@ def update_flag_add_of(op1, op2):
def update_flag_sub_cf(op1, op2):
- "Compote CF in @op1 - @op2"
+ "Compute CF in @op1 - @op2"
return [ExprAssign(cf, ExprOp("FLAG_SUB_CF", op1, op2) ^ ExprInt(1, 1))]
def update_flag_sub_of(op1, op2):
- "Compote OF in @op1 - @op2"
+ "Compute OF in @op1 - @op2"
return [ExprAssign(of, ExprOp("FLAG_SUB_OF", op1, op2))]
@@ -424,11 +434,18 @@ def add(ir, instr, a, b, c=None):
def l_and(ir, instr, a, b, c=None):
- e = []
+ setflags = (instr.name == 'ANDS') and a != PC
if c is None:
b, c = a, b
+ if c.is_op():
+ e, extra_ir = _shift_rotate_tpl(ir, instr, a, c, onlyCarry=setflags)
+ # get back the result
+ c = e.pop(0).src
+ else:
+ e = []
+ extra_ir = []
r = b & c
- if instr.name == 'ANDS' and a != PC:
+ if setflags:
e += [ExprAssign(zf, ExprOp('FLAG_EQ_AND', b, c))]
e += update_flag_nf(r)
@@ -436,8 +453,7 @@ def l_and(ir, instr, a, b, c=None):
dst = get_dst(a)
if dst is not None:
e.append(ExprAssign(ir.IRDst, r))
- return e, []
-
+ return e, extra_ir
def sub(ir, instr, a, b, c=None):
e = []
@@ -479,9 +495,16 @@ def eor(ir, instr, a, b, c=None):
def eors(ir, instr, a, b, c=None):
- e = []
+ setflags = a != PC
if c is None:
b, c = a, b
+ if c.is_op():
+ e, extra_ir = _shift_rotate_tpl(ir, instr, a, c, onlyCarry=setflags)
+ # get back the result
+ c = e.pop(0).src
+ else:
+ e = []
+ extra_ir = []
arg1, arg2 = b, c
r = arg1 ^ arg2
@@ -492,7 +515,7 @@ def eors(ir, instr, a, b, c=None):
dst = get_dst(a)
if dst is not None:
e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return e, extra_ir
def rsb(ir, instr, a, b, c=None):
@@ -585,18 +608,32 @@ def rscs(ir, instr, a, b, c=None):
def tst(ir, instr, a, b):
- e = []
+ setflags = a != PC
+ if b.is_op():
+ e, extra_ir = _shift_rotate_tpl(ir, instr, a, b, onlyCarry=setflags)
+ # get back the result
+ b = e.pop(0).src
+ else:
+ e = []
+ extra_ir = []
arg1, arg2 = a, b
r = arg1 & arg2
e += [ExprAssign(zf, ExprOp('FLAG_EQ_AND', arg1, arg2))]
e += update_flag_nf(r)
- return e, []
+ return e, extra_ir
def teq(ir, instr, a, b, c=None):
- e = []
+ setflags = a != PC
+ if b.is_op():
+ e, extra_ir = _shift_rotate_tpl(ir, instr, a, b, onlyCarry=setflags)
+ # get back the result
+ b = e.pop(0).src
+ else:
+ e = []
+ extra_ir = []
if c is None:
b, c = a, b
arg1, arg2 = b, c
@@ -605,7 +642,7 @@ def teq(ir, instr, a, b, c=None):
e += [ExprAssign(zf, ExprOp('FLAG_EQ_CMP', arg1, arg2))]
e += update_flag_nf(r)
- return e, []
+ return e, extra_ir
def l_cmp(ir, instr, a, b, c=None):
@@ -653,9 +690,16 @@ def orn(ir, instr, a, b, c=None):
def orrs(ir, instr, a, b, c=None):
- e = []
+ setflags = a != PC
if c is None:
b, c = a, b
+ if c.is_op():
+ e, extra_ir = _shift_rotate_tpl(ir, instr, a, c, onlyCarry=setflags)
+ # get back the result
+ c = e.pop(0).src
+ else:
+ e = []
+ extra_ir = []
arg1, arg2 = b, c
r = arg1 | arg2
@@ -666,10 +710,13 @@ def orrs(ir, instr, a, b, c=None):
dst = get_dst(a)
if dst is not None:
e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return e, extra_ir
def mov(ir, instr, a, b):
+ if b.is_op():
+ return _shift_rotate_tpl(ir, instr, a, b, setflags=False)
+ # TODO handle cf
e = [ExprAssign(a, b)]
dst = get_dst(a)
if dst is not None:
@@ -686,10 +733,78 @@ def movt(ir, instr, a, b):
return e, []
+def _shift_rotate_tpl(ir, instr, dst, shift_operation, setflags=False, is_not=False, onlyCarry=False):
+ """
+ Template to generate a shift/rotate
+ A temporary basic block is generated to handle 0-shift
+ @dst: destination
+ @shift_operation: the shift/rotate operation (ExprOp)
+ @setflags: (optional) if set, flags are updated (ZNC)
+ @onlyCarry: (optional) if set, Z and N flags won't be updated except if setflags is set.
+ @is_not: (optional) if set, behaves as MVN/MVNS
+ """
+ op = shift_operation.op
+ # Compute carry (+ result for rrx)
+ if op == 'rrx':
+ res, new_cf = compute_rrx_carry(shift_operation)
+ shifter = ExprInt(1, 8)
+ elif op in ['<<', '>>', 'a>>']:
+ shifter = shift_operation.args[1]
+ if setflags or onlyCarry:
+ new_cf = ExprOp(op, shift_operation.args[0], shifter - ExprInt(1, size=shifter.size))
+ left = op[-1] == '<'
+ new_cf = new_cf.msb() if left else new_cf[:1]
+ res = shift_operation
+ elif op == '>>>':
+ shifter = shift_operation.args[1]
+ if setflags or onlyCarry:
+ new_cf = shift_operation.msb()
+ res = shift_operation
+ else:
+ raise NotImplementedError(f"Unknown shift / rotate operation : {op}")
+
+ # NOT the result and use it for ZN flags computations
+ if is_not:
+ res ^= ExprInt(-1, res.size)
+ # Build basic blocks
+ e_do = []
+ e = [ExprAssign(dst, res)]
+ if setflags:
+ e += update_flag_zn(res)
+ if setflags or onlyCarry:
+ e_do += [ExprAssign(cf, expr_simp(new_cf))]
+ # Don't generate conditional shifter on constant
+ if shifter.is_int():
+ if shifter.is_int(0):
+ # assignement + flags if setflags except cf
+ return (e, [])
+ else:
+ # assignement + flags if setflags
+ return (e + e_do, [])
+
+ loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size)
+ loc_skip = ir.get_next_loc_key(instr)
+ loc_skip_expr = ExprLoc(loc_skip, ir.IRDst.size)
+ isPC = get_dst(dst)
+ if isPC is not None:
+ # Not really a Loc in this case
+ loc_skip_expr = res
+ e_do.append(ExprAssign(ir.IRDst, loc_skip_expr))
+ e.append(ExprAssign(
+ ir.IRDst, ExprCond(shifter, loc_do_expr, loc_skip_expr)))
+ return (e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])])
+
+
+
def movs(ir, instr, a, b):
e = []
+ # handle shift / rotate
+ if b.is_op():
+ return _shift_rotate_tpl(ir, instr, a, b, setflags=a != PC)
+
+
e.append(ExprAssign(a, b))
- # XXX TODO check
+ # TODO handle cf
e += [ExprAssign(zf, ExprOp('FLAG_EQ', b))]
e += update_flag_nf(b)
@@ -700,7 +815,10 @@ def movs(ir, instr, a, b):
def mvn(ir, instr, a, b):
+ if b.is_op():
+ return _shift_rotate_tpl(ir, instr, a, b, setflags=False, is_not=True)
r = b ^ ExprInt(-1, 32)
+ # TODO handle cf
e = [ExprAssign(a, r)]
dst = get_dst(a)
if dst is not None:
@@ -709,10 +827,12 @@ def mvn(ir, instr, a, b):
def mvns(ir, instr, a, b):
+ if b.is_op():
+ return _shift_rotate_tpl(ir, instr, a, b, setflags= a != PC, is_not=True)
e = []
r = b ^ ExprInt(-1, 32)
e.append(ExprAssign(a, r))
- # XXX TODO check
+ # TODO handle cf
e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))]
e += update_flag_nf(r)
@@ -774,9 +894,16 @@ def bic(ir, instr, a, b, c=None):
def bics(ir, instr, a, b, c=None):
- e = []
+ setflags = a != PC
if c is None:
b, c = a, b
+ if c.is_op():
+ e, extra_ir = _shift_rotate_tpl(ir, instr, a, c, onlyCarry=setflags)
+ # get back the result
+ c = e.pop(0).src
+ else:
+ e = []
+ extra_ir = []
tmp1, tmp2 = b, ~c
r = tmp1 & tmp2
@@ -787,7 +914,7 @@ def bics(ir, instr, a, b, c=None):
dst = get_dst(a)
if dst is not None:
e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return e, extra_ir
def sdiv(ir, instr, a, b, c=None):
@@ -1169,100 +1296,53 @@ def und(ir, instr, a, b):
e = []
return e, []
-# TODO XXX implement correct CF for shifters
def lsr(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
- r = b >> c
- e.append(ExprAssign(a, r))
- dst = get_dst(a)
- if dst is not None:
- e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return _shift_rotate_tpl(ir, instr, a, b >> c, setflags=False)
def lsrs(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
- r = b >> c
- e.append(ExprAssign(a, r))
-
- e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))]
- e += update_flag_nf(r)
-
- dst = get_dst(a)
- if dst is not None:
- e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return _shift_rotate_tpl(ir, instr, a, b >> c, setflags= a != PC)
def asr(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
r = ExprOp("a>>", b, c)
- e.append(ExprAssign(a, r))
- dst = get_dst(a)
- if dst is not None:
- e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return _shift_rotate_tpl(ir, instr, a, r, setflags=False)
def asrs(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
r = ExprOp("a>>", b, c)
- e.append(ExprAssign(a, r))
-
- e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))]
- e += update_flag_nf(r)
-
- dst = get_dst(a)
- if dst is not None:
- e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return _shift_rotate_tpl(ir, instr, a, r, setflags= a != PC)
def lsl(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
- r = b << c
- e.append(ExprAssign(a, r))
- dst = get_dst(a)
- if dst is not None:
- e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return _shift_rotate_tpl(ir, instr, a, b << c, setflags=False)
+
def lsls(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
- r = b << c
- e.append(ExprAssign(a, r))
-
- e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))]
- e += update_flag_nf(r)
-
- dst = get_dst(a)
- if dst is not None:
- e.append(ExprAssign(ir.IRDst, r))
- return e, []
+ return _shift_rotate_tpl(ir, instr, a, b << c, setflags= a != PC)
def rors(ir, instr, a, b):
e = []
r = ExprOp(">>>", a, b)
- e.append(ExprAssign(a, r))
-
- e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))]
- e += update_flag_nf(r)
+ return _shift_rotate_tpl(ir, instr, a, r, setflags= a != PC)
- dst = get_dst(a)
- if dst is not None:
- e.append(ExprAssign(ir.IRDst, r))
- return e, []
def push(ir, instr, a):
@@ -1962,9 +2042,7 @@ def get_ir(self, instr):
args = instr.args
# ir = get_mnemo_expr(self, self.name.lower(), *args)
if len(args) and isinstance(args[-1], ExprOp):
- if args[-1].op == 'rrx':
- args[-1] = ExprCompose(args[-1].args[0][1:], cf)
- elif (args[-1].op in ['<<', '>>', '<>', '<<<', '>>>'] and
+ if (args[-1].op in ['<<', '>>', '<>', '<<<', '>>>'] and
isinstance(args[-1].args[-1], ExprId)):
args[-1] = ExprOp(args[-1].op,
args[-1].args[0],
From bb53a4505ab43662d5ebb9349ecda93eacaa447c Mon Sep 17 00:00:00 2001
From: woni <81616747+W0ni@users.noreply.github.com>
Date: Wed, 6 Sep 2023 18:22:39 +0200
Subject: [PATCH 2/5] Add RRX support inside instructions
---
miasm/arch/arm/sem.py | 50 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py
index 0c6234751..156d8374f 100644
--- a/miasm/arch/arm/sem.py
+++ b/miasm/arch/arm/sem.py
@@ -405,6 +405,8 @@ def adc(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = b, c
r = b + c + cf.zeroExtend(32)
if instr.name == 'ADCS' and a != PC:
@@ -421,6 +423,8 @@ def add(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = b, c
r = b + c
if instr.name == 'ADDS' and a != PC:
@@ -459,6 +463,8 @@ def sub(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = b - c
e.append(ExprAssign(a, r))
dst = get_dst(a)
@@ -471,6 +477,8 @@ def subs(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = b, c
r = b - c
e += update_flag_arith_sub_zn(arg1, arg2)
@@ -486,6 +494,8 @@ def eor(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = b ^ c
e.append(ExprAssign(a, r))
dst = get_dst(a)
@@ -522,6 +532,8 @@ def rsb(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = c, b
r = arg1 - arg2
e.append(ExprAssign(a, r))
@@ -535,6 +547,8 @@ def rsbs(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = c, b
r = arg1 - arg2
e += update_flag_arith_sub_zn(arg1, arg2)
@@ -550,6 +564,8 @@ def sbc(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = b, c
r = arg1 - (arg2 + (~cf).zeroExtend(32))
e.append(ExprAssign(a, r))
@@ -563,6 +579,8 @@ def sbcs(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = b, c
r = arg1 - (arg2 + (~cf).zeroExtend(32))
@@ -580,6 +598,8 @@ def rsc(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = c, b
r = arg1 - (arg2 + (~cf).zeroExtend(32))
e.append(ExprAssign(a, r))
@@ -593,6 +613,8 @@ def rscs(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = c, b
r = arg1 - (arg2 + (~cf).zeroExtend(32))
@@ -659,6 +681,8 @@ def cmn(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
arg1, arg2 = b, c
e += update_flag_arith_add_zn(arg1, arg2)
e += update_flag_arith_add_co(arg1, arg2)
@@ -669,6 +693,8 @@ def orr(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = b | c
e.append(ExprAssign(a, r))
dst = get_dst(a)
@@ -681,6 +707,8 @@ def orn(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = ~(b | c)
e.append(ExprAssign(a, r))
dst = get_dst(a)
@@ -885,6 +913,8 @@ def bic(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = b & (c ^ ExprInt(-1, 32))
e.append(ExprAssign(a, r))
dst = get_dst(a)
@@ -921,6 +951,8 @@ def sdiv(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
loc_div = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
loc_except = ExprId(ir.loc_db.add_location(), ir.IRDst.size)
@@ -952,6 +984,8 @@ def udiv(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
@@ -1015,6 +1049,8 @@ def mul(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = b * c
e.append(ExprAssign(a, r))
dst = get_dst(a)
@@ -1027,6 +1063,8 @@ def muls(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = b * c
e += update_flag_zn(r)
e.append(ExprAssign(a, r))
@@ -1300,6 +1338,8 @@ def lsr(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
return _shift_rotate_tpl(ir, instr, a, b >> c, setflags=False)
@@ -1307,12 +1347,16 @@ def lsrs(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
return _shift_rotate_tpl(ir, instr, a, b >> c, setflags= a != PC)
def asr(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = ExprOp("a>>", b, c)
return _shift_rotate_tpl(ir, instr, a, r, setflags=False)
@@ -1320,6 +1364,8 @@ def asrs(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
r = ExprOp("a>>", b, c)
return _shift_rotate_tpl(ir, instr, a, r, setflags= a != PC)
@@ -1327,6 +1373,8 @@ def lsl(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
return _shift_rotate_tpl(ir, instr, a, b << c, setflags=False)
@@ -1335,6 +1383,8 @@ def lsls(ir, instr, a, b, c=None):
e = []
if c is None:
b, c = a, b
+ if c.is_op('rrx'):
+ c, _ = compute_rrx_carry(c)
return _shift_rotate_tpl(ir, instr, a, b << c, setflags= a != PC)
From 71e4e09da6816a72905adeea3c0864714353c406 Mon Sep 17 00:00:00 2001
From: woni <81616747+W0ni@users.noreply.github.com>
Date: Wed, 13 Sep 2023 10:34:16 +0200
Subject: [PATCH 3/5] Fix disassembly bug
---
miasm/arch/arm/arch.py | 4 ++++
test/arch/arm/sem.py | 4 ++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/miasm/arch/arm/arch.py b/miasm/arch/arm/arch.py
index 5ccf5ecab..91c22bd59 100644
--- a/miasm/arch/arm/arch.py
+++ b/miasm/arch/arm/arch.py
@@ -1148,8 +1148,12 @@ def decode(self, v):
shift_op = ExprInt(amount, 32)
a = regs_expr[rm]
if shift_op == ExprInt(0, 32):
+ #rrx
if shift_type == 3:
self.expr = ExprOp(allshifts[4], a)
+ #asr, lsr
+ elif shift_type == 1 or shift_type == 2:
+ self.expr = ExprOp(allshifts[shift_type], a, ExprInt(32, 32))
else:
self.expr = a
else:
diff --git a/test/arch/arm/sem.py b/test/arch/arm/sem.py
index a5b6d5eb7..c80b471d8 100755
--- a/test/arch/arm/sem.py
+++ b/test/arch/arm/sem.py
@@ -81,7 +81,7 @@ def test_shift(self):
self.assertEqual(
compute('MOV R4, R4 LSR 31', {R4: 0xDEADBEEF, }), {R4: 0x00000001, })
self.assertEqual(
- compute('MOV R4, R4 LSR 32', {R4: 0xDEADBEEF, }), {R4: 0xDEADBEEF, })
+ compute('MOV R4, R4 LSR 32', {R4: 0xDEADBEEF, }), {R4: 0x0, })
self.assertRaises(ValueError, compute, 'MOV R4, R4 LSR 33')
self.assertEqual(
compute('MOV R4, R4 LSR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0x6F56DF77, R5: 0xBADBAD01, })
@@ -93,7 +93,7 @@ def test_shift(self):
self.assertEqual(
compute('MOV R4, R4 ASR 31', {R4: 0xDEADBEEF, }), {R4: 0xFFFFFFFF, })
self.assertEqual(
- compute('MOV R4, R4 ASR 32', {R4: 0xDEADBEEF, }), {R4: 0xDEADBEEF, })
+ compute('MOV R4, R4 ASR 32', {R4: 0xDEADBEEF, }), {R4: 0xFFFFFFFF, })
self.assertRaises(ValueError, compute, 'MOV R4, R4 ASR 33')
self.assertEqual(
compute('MOV R4, R4 ASR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0xEF56DF77, R5: 0xBADBAD01, })
From 1885f3caa96cd953e6f90a33b5d3863808cbcf40 Mon Sep 17 00:00:00 2001
From: woni <81616747+W0ni@users.noreply.github.com>
Date: Wed, 13 Sep 2023 12:39:41 +0200
Subject: [PATCH 4/5] Add tests for MOVS and isThumb utility function
---
miasm/arch/arm/sem.py | 3 +++
test/arch/arm/sem.py | 51 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py
index 156d8374f..a138ef919 100644
--- a/miasm/arch/arm/sem.py
+++ b/miasm/arch/arm/sem.py
@@ -391,6 +391,9 @@ def update_flag_arith_subwc_co(arg1, arg2, arg3):
e += update_flag_subwc_of(arg1, arg2, arg3)
return e
+# Utility function for flag computation when it depends on the mode
+def isThumb(lifter):
+ return isinstance(lifter, (Lifter_Armtl, Lifter_Armtb))
def get_dst(a):
diff --git a/test/arch/arm/sem.py b/test/arch/arm/sem.py
index c80b471d8..343bc063f 100755
--- a/test/arch/arm/sem.py
+++ b/test/arch/arm/sem.py
@@ -111,6 +111,57 @@ def test_shift(self):
cf: 0, R4: 0x6F56DF77, })
self.assertEqual(compute('MOV R4, R4 RRX ', {cf: 1, R4: 0xDEADBEEF, }), {
cf: 1, R4: 0xEF56DF77, })
+ # S
+ self.assertEqual(
+ compute('MOVS R4, R4 ', {R4: 0xDEADBEEF, }), {R4: 0xDEADBEEF, nf: 1, zf: 0,})
+ self.assertRaises(ValueError, compute, 'MOVS R4, R4 LSL 0')
+ self.assertEqual(
+ compute('MOVS R4, R4 LSL 1', {R4: 0xDEADBEEF, }), {R4: 0xBD5B7DDE, nf: 1, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 LSL 16', {R4: 0xDEADBEEF, }), {R4: 0xBEEF0000, nf: 1, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 LSL 31', {R4: 0xDEADBEEF, }), {R4: 0x80000000, nf: 1, zf: 0, cf: 1,})
+ self.assertRaises(ValueError, compute, 'MOVS R4, R4 LSL 32')
+ self.assertEqual(
+ compute('MOVS R4, R4 LSL R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0xBD5B7DDE, R5: 0xBADBAD01, nf: 1, zf: 0, cf: 1,})
+ self.assertRaises(ValueError, compute, 'MOVS R4, R4 LSR 0')
+ self.assertEqual(
+ compute('MOVS R4, R4 LSR 1', {R4: 0xDEADBEEF, }), {R4: 0x6F56DF77, nf: 0, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 LSR 16', {R4: 0xDEADBEEF, }), {R4: 0x0000DEAD, nf: 0, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 LSR 31', {R4: 0xDEADBEEF, }), {R4: 0x00000001, nf: 0, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 LSR 32', {R4: 0xDEADBEEF, }), {R4: 0x0, nf: 0, zf: 1, cf: 1,})
+ self.assertRaises(ValueError, compute, 'MOVS R4, R4 LSR 33')
+ self.assertEqual(
+ compute('MOVS R4, R4 LSR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0x6F56DF77, R5: 0xBADBAD01, nf: 0, zf: 0, cf: 1,})
+ self.assertRaises(ValueError, compute, 'MOVS R4, R4 ASR 0')
+ self.assertEqual(
+ compute('MOVS R4, R4 ASR 1', {R4: 0xDEADBEEF, }), {R4: 0xEF56DF77, nf: 1, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 ASR 16', {R4: 0xDEADBEEF, }), {R4: 0xFFFFDEAD, nf: 1, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 ASR 31', {R4: 0xDEADBEEF, }), {R4: 0xFFFFFFFF, nf: 1, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 ASR 32', {R4: 0xDEADBEEF, }), {R4: 0xFFFFFFFF, nf: 1, zf: 0, cf: 1,})
+ self.assertRaises(ValueError, compute, 'MOVS R4, R4 ASR 33')
+ self.assertEqual(
+ compute('MOVS R4, R4 ASR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0xEF56DF77, R5: 0xBADBAD01, nf: 1, zf: 0, cf: 1,})
+ self.assertRaises(ValueError, compute, 'MOVS R4, R4 ROR 0')
+ self.assertEqual(
+ compute('MOVS R4, R4 ROR 1', {R4: 0xDEADBEEF, }), {R4: 0xEF56DF77, nf: 1, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 ROR 16', {R4: 0xDEADBEEF, }), {R4: 0xBEEFDEAD, nf: 1, zf: 0, cf: 1,})
+ self.assertEqual(
+ compute('MOVS R4, R4 ROR 31', {R4: 0xDEADBEEF, }), {R4: 0xBD5B7DDF, nf: 1, zf: 0, cf: 1,})
+ self.assertRaises(ValueError, compute, 'MOVS R4, R4 ROR 32')
+ self.assertEqual(
+ compute('MOVS R4, R4 ROR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0xEF56DF77, R5: 0xBADBAD01, nf: 1, zf: 0, cf: 1,})
+ self.assertEqual(compute('MOVS R4, R4 RRX ', {cf: 0, R4: 0xDEADBEEF, }), {
+ cf: 1, R4: 0x6F56DF77, zf: 0, nf: 0})
+ self.assertEqual(compute('MOVS R4, R4 RRX ', {cf: 1, R4: 0xDEADBEEF, }), {
+ cf: 1, R4: 0xEF56DF77, zf: 0, nf: 1})
def test_ADC(self):
# §A8.8.1: ADC{S}{}{} {,} , #
From 16cc7d3b374442808b1d653a0cc6c2477a4a750f Mon Sep 17 00:00:00 2001
From: woni <81616747+W0ni@users.noreply.github.com>
Date: Thu, 14 Mar 2024 18:20:58 +0100
Subject: [PATCH 5/5] Add MOV and MOVS tests for [AL]SR
---
test/arch/arm/arch.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/test/arch/arm/arch.py b/test/arch/arm/arch.py
index 42e807722..a3f3a9742 100644
--- a/test/arch/arm/arch.py
+++ b/test/arch/arm/arch.py
@@ -241,7 +241,12 @@ def u16swap(i):
'110f111e'),
('XXXXXXXX MCRCC p15, 0x0, R8, c2, c0, 0x1',
'308f023e'),
-
+ ('XXXXXXXX MOV R4, R4 ASR 0x20',
+ '4440a0e1'),
+ ('XXXXXXXX MOV R2, R5 LSR 0x20',
+ '2520a0e1'),
+ ('XXXXXXXX MOVS R2, R5 LSR 0x20',
+ '2520b0e1'),
]
ts = time.time()