about summary refs log tree commit diff stats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/miasm/arch/aarch64/arch.py2
-rw-r--r--src/miasm/arch/aarch64/sem.py55
-rw-r--r--test/arch/aarch64/arch.py3
3 files changed, 59 insertions, 1 deletions
diff --git a/src/miasm/arch/aarch64/arch.py b/src/miasm/arch/aarch64/arch.py
index ab6b7528..53de5633 100644
--- a/src/miasm/arch/aarch64/arch.py
+++ b/src/miasm/arch/aarch64/arch.py
@@ -2306,4 +2306,6 @@ ltacctype = bs_mod_name(l=1, fname='order', mn_mod=['', 'A'])
 
 
 aarch64op("casp",   [bs('0'), sf, bs('001000'), bs('0'), ltacctype, bs('1'), rs, stacctype, bs('11111'), rn64_deref_nooff, rt], [rs, rt, rn64_deref_nooff])
+aarch64op("ldsmax", [bs('1'), sf, bs('111000'), bs('0'), bs('0'), bs('1'), rs, bs('0'), bs('10000'), rn64_deref_nooff, rt], [rs, rt, rn64_deref_nooff])
+aarch64op("ldsmaxb",[bs('0'), bs('0'), bs('111000'), bs('0'), bs('0'), bs('1'), rs32, bs('0'), bs('10000'), rn64_deref_nooff, rt32], [rs32, rt32, rn64_deref_nooff])
 aarch64op("ldaxrb", [bs('00'),  bs('001000'), bs('0'), bs('1'), bs('0'), bs('11111'), bs('1'), bs('11111'), rn64_deref_nooff, rt32], [rt32, rn64_deref_nooff])
diff --git a/src/miasm/arch/aarch64/sem.py b/src/miasm/arch/aarch64/sem.py
index eaa01228..428ff771 100644
--- a/src/miasm/arch/aarch64/sem.py
+++ b/src/miasm/arch/aarch64/sem.py
@@ -2156,7 +2156,54 @@ def smulh(arg1, arg2, arg3):
 def smull(arg1, arg2, arg3):
     arg1 = (arg2.signExtend(64) * arg3.signExtend(64))[64:]
 
+def ldsmax(ir, instr, arg1, arg2, arg3):
+    # XXX TODO: memory barrier
+    # TODO: byte and halfword comparisons
+    e = []
+
+    if arg1.size == 32:
+        regs = gpregs32_expr
+        zero_reg = WZR
+    else:
+        regs = gpregs64_expr
+        zero_reg = XZR
+
+    # TODO endianness
+
+    # Label for path that updates memory value
+    # Jumps to loc_do after
+    loc_exchange = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
 
+    # Label for storing old value into destination register
+    loc_no_exchange = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
+
+    # Label for location after ldsmax instruction
+    loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size)
+
+    dest_reg = arg1
+    comp_value = arg2
+    mem_index = arg3.args[0]
+
+    data = ExprMem(mem_index, comp_value.size)
+    
+    subs(ir, instr, zero_reg, comp_value, data)
+    gt_cond = cond2expr['GT']
+
+    cond = ExprCond(gt_cond, loc_exchange, loc_no_exchange)
+    e.append(ExprAssign(ir.IRDst, cond))
+
+    e_exchange = []
+    e_exchange.append(ExprAssign(dest_reg, data))
+    e_exchange.append(ExprAssign(data, comp_value))
+    e_exchange.append(ExprAssign(ir.IRDst, loc_next))
+    blk_exchange = IRBlock(ir.loc_db, loc_exchange.loc_key, [AssignBlock(e_exchange, instr)])
+
+    e_no_exchange = []
+    e_exchange.append(ExprAssign(dest_reg, data))
+    e_no_exchange.append(ExprAssign(ir.IRDst, loc_next))
+    blk_no_exchange = IRBlock(ir.loc_db, loc_no_exchange.loc_key, [AssignBlock(e_no_exchange, instr)])
+
+    return e, [blk_exchange, blk_no_exchange]
 
 mnemo_func = sbuild.functions
 mnemo_func.update({
@@ -2274,7 +2321,13 @@ mnemo_func.update({
     'dmb': dmb,
     'tlbi': tlbi,
     'clrex': clrex,
-    'ic': ic
+    'ic': ic,
+
+    # TODO: other synchronization variants
+    'ldsmaxb': ldsmax,
+    'ldsmaxh': ldsmax,
+    'ldsmaxw': ldsmax,
+    'ldsmax': ldsmax,
 })
 
 
diff --git a/test/arch/aarch64/arch.py b/test/arch/aarch64/arch.py
index 7d81e45e..2f2657b8 100644
--- a/test/arch/aarch64/arch.py
+++ b/test/arch/aarch64/arch.py
@@ -1850,6 +1850,9 @@ reg_tests_aarch64 = [
 
     ("XXXXXXXX    ADR        X29, 0xFFFFFFFFFFFFFAC8",
      "5DD6FF10"),
+
+    ("XXXXXXXX    LDSMAX     X0, X2, X1",
+     "224020F8"),
 ]