Skip to content

Commit

Permalink
Arm: add parallel instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
serpilliere committed Mar 27, 2019
1 parent f54b2e4 commit f7b611a
Show file tree
Hide file tree
Showing 6 changed files with 680 additions and 1 deletion.
24 changes: 24 additions & 0 deletions miasm/arch/arm/arch.py
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,30 @@ def armtop(name, fields, args=None, alias=False):
armop("isb", [bs8(0xF5), bs8(0x7F), bs8(0xF0), bs8(0x6F)])
armop("nop", [bs8(0xE3), bs8(0x20), bs8(0xF0), bs8(0)])


parallel_arith_name = {
'Q': 0b01100010,
'S': 0b01100001,
'SH': 0b01100011,
'U': 0b01100101,
'UH': 0b01100111,
'UQ': 0b01100110,
}
bs_parallel_arith = bs_name(l=8, name=parallel_arith_name)

parallel_modarith_name = {
0b0001 : 'ADD16',
0b0011 : 'ADDSUBX',
0b0101 : 'SUBADDX',
0b0111 : 'SUB16',
0b1001 : 'ADD8',
0b1111 : 'SUB8',
}
bs_parallel_modarith = bs_mod_name(l=4, mn_mod=parallel_modarith_name)

armop("arith", [bs_parallel_arith, rn, rd, bs('1111'), bs_parallel_modarith, rm], [rd, rn, rm])


class arm_widthm1(arm_imm, m_arg):
def decode(self, v):
self.expr = ExprInt(v+1, 32)
Expand Down
147 changes: 147 additions & 0 deletions miasm/arch/arm/sem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1285,6 +1285,146 @@ def uadd8(ir, instr, a, b, c):
return e, []


def uadd16(ir, instr, a, b, c):
e = []
sums = []
ges = []
for i in range(0, 32, 16):
sums.append(b[i:i+16] + c[i:i+16])
ges.append((b[i:i+16].zeroExtend(17) + c[i:i+16].zeroExtend(17))[16:17])

e.append(ExprAssign(a, ExprCompose(*sums)))

for i, value in enumerate(ges):
e.append(ExprAssign(ge_regs[2 * i], value))
e.append(ExprAssign(ge_regs[2 * i + 1], value))
return e, []


def uaddsubx(ir, instr, a, b, c):
e = []
sums = []
ges = []


part1, part2 = b[16:32], c[0:16]
sums.append(part1 + part2)
ges.append((part1.zeroExtend(17) + part2.zeroExtend(17))[16:17])

part1, part2 = b[0:16], c[16:32]
sums.append(part1 - part2)
ges.append(ExprOp("FLAG_SIGN_SUB", part1, part2))

e.append(ExprAssign(a, ExprCompose(*sums[::-1])))

for i, value in enumerate(ges[::-1]):
e.append(ExprAssign(ge_regs[2 * i], value))
e.append(ExprAssign(ge_regs[2 * i + 1], value))
return e, []


def sadd8(ir, instr, a, b, c):
e = []
sums = []
ges = []
for i in range(0, 32, 8):
sums.append(b[i:i+8] + c[i:i+8])
ges.append(ExprOp("FLAG_SIGN_SUB", ExprInt(0, 9), b[i:i+8].signExtend(9) + c[i:i+8].signExtend(9)))

e.append(ExprAssign(a, ExprCompose(*sums)))

for i, value in enumerate(ges):
e.append(ExprAssign(ge_regs[i], value))
return e, []


def sadd16(ir, instr, a, b, c):
e = []
sums = []
ges = []
for i in range(0, 32, 16):
sums.append(b[i:i+16] + c[i:i+16])
ges.append(ExprOp("FLAG_SIGN_SUB", ExprInt(0, 17), b[i:i+16].signExtend(17) + c[i:i+16].signExtend(17)))

e.append(ExprAssign(a, ExprCompose(*sums)))

for i, value in enumerate(ges):
e.append(ExprAssign(ge_regs[2 * i], value))
e.append(ExprAssign(ge_regs[2 * i + 1], value))
return e, []


def saddsubx(ir, instr, a, b, c):
e = []
sums = []
ges = []


part1, part2 = b[16:32], c[0:16]
sums.append(part1 + part2)
ges.append(ExprOp("FLAG_SIGN_SUB", ExprInt(0, 17), part1.signExtend(17) + part2.signExtend(17)))

part1, part2 = b[0:16], c[16:32]
sums.append(part1 - part2)
ges.append(~ExprOp("FLAG_SIGN_SUB", part1, part2))

e.append(ExprAssign(a, ExprCompose(*sums[::-1])))

for i, value in enumerate(ges[::-1]):
e.append(ExprAssign(ge_regs[2 * i], value))
e.append(ExprAssign(ge_regs[2 * i + 1], value))
return e, []



def qadd_tpl(ir, instr, dst_size, a, b, c):
e = []
sums = []

median = 1 << (dst_size - 1)

min_int = ExprInt(- median, dst_size)
max_int = ExprInt(median - 1, dst_size)

test_min_int = min_int.signExtend(dst_size + 1)
test_max_int = max_int.signExtend(dst_size + 1)

for i in range(0, a.size, dst_size):
res = b[i:i+dst_size].signExtend(dst_size + 1) + c[i:i+dst_size].signExtend(dst_size + 1)
value = res[:dst_size]
res_sat = ExprCond(
ExprOp(
TOK_INF_EQUAL_SIGNED,
res,
test_min_int
),
min_int,
ExprCond(
ExprOp(
TOK_INF_SIGNED,
res,
test_max_int
),
value,
max_int
)
)
sums.append(res_sat)

e.append(ExprAssign(a, ExprCompose(*sums)))
return e, []


def qadd8(ir, instr, a, b, c):
e, blocks = qadd_tpl(ir, instr, 8, a, b, c)
return e, blocks


def qadd16(ir, instr, a, b, c):
e, blocks = qadd_tpl(ir, instr, 16, a, b, c)
return e, blocks


def sel(ir, instr, a, b, c):
e = []
cond = nf ^ of ^ ExprInt(1, 1)
Expand Down Expand Up @@ -1641,6 +1781,13 @@ def add_condition_expr(ir, instr, cond, instr_ir, extra_ir):
'smlatb': smlatb,
'smlatt': smlatt,
'uadd8': uadd8,
'uadd16': uadd16,
'uaddsubx': uaddsubx,
'sadd8': sadd8,
'sadd16': sadd16,
'saddsubx': saddsubx,
'qadd8': qadd8,
'qadd16': qadd16,
'sel': sel,
}

Expand Down
3 changes: 2 additions & 1 deletion test/arch/arm/arch.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ def u16swap(i):

('XXXXXXXX UXTAB R5, R2, R8 ROR 0x8',
'7854e2e6'),

('XXXXXXXX UADD8 R1, R2, R3',
'931f52e6'),

('XXXXXXXX PKHBT R1, R2, R3 LSL 0x8',
'131482e6'),
Expand Down
74 changes: 74 additions & 0 deletions test/arch/arm/unit/asm_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from builtins import str
from builtins import object
import sys
import os

from future.utils import viewitems

from miasm.arch.arm.arch import mn_arm, base_expr, variable
from miasm.core import parse_asm
from miasm.expression.expression import *
from miasm.core import asmblock
from miasm.loader.strpatchwork import StrPatchwork
from miasm.analysis.machine import Machine
from miasm.jitter.csts import *

reg_and_id = dict(mn_arm.regs.all_regs_ids_byname)

class Asm_Test(object):
run_addr = 0x0

def __init__(self, jitter_engine):
self.myjit = Machine(self.arch_name).jitter(jitter_engine)
self.myjit.init_stack()

def test_init(self):
pass

def prepare(self):
pass

def __call__(self):
self.prepare()
self.asm()
self.init_machine()
self.test_init()
self.run()
self.check()

def run(self):

self.myjit.init_run(self.run_addr)
self.myjit.continue_run()

assert(self.myjit.pc == self.ret_addr)

def asm(self):
blocks, loc_db = parse_asm.parse_txt(
mn_arm, self.arch_attrib, self.TXT,
loc_db = self.myjit.ir_arch.loc_db
)
# fix shellcode addr
loc_db.set_location_offset(loc_db.get_name_location("main"), 0x0)
s = StrPatchwork()
patches = asmblock.asm_resolve_final(mn_arm, blocks, loc_db)
for offset, raw in viewitems(patches):
s[offset] = raw

s = bytes(s)
self.assembly = s

def check(self):
raise NotImplementedError('abstract method')


class Asm_Test(Asm_Test):
arch_name = "arml"
arch_attrib = "l"
ret_addr = 0x1330

def init_machine(self):
self.myjit.vm.add_memory_page(self.run_addr, PAGE_READ | PAGE_WRITE, self.assembly)
self.myjit.push_uint32_t(self.ret_addr)
self.myjit.add_breakpoint(self.ret_addr, lambda x:False)

Loading

0 comments on commit f7b611a

Please sign in to comment.