Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arm: add parallel instructions #1005

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
163 changes: 163 additions & 0 deletions miasm/arch/arm/sem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1285,6 +1285,160 @@ 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)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double checking: is using _sub on purpose? (because it seems to be an addition)


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 q_tpl(ir, instr, is_sub, 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):
src1 = b[i:i+dst_size].signExtend(dst_size + 1)
src2 = c[i:i+dst_size].signExtend(dst_size + 1)
if is_sub:
src2 = -src2
res = src1 + src2
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 = q_tpl(ir, instr, False, 8, a, b, c)
return e, blocks


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


def qsub8(ir, instr, a, b, c):
e, blocks = q_tpl(ir, instr, True, 8, a, b, c)
return e, blocks


def qsub16(ir, instr, a, b, c):
e, blocks = q_tpl(ir, instr, True, 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 +1795,15 @@ 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,
'qsub8': qsub8,
'qsub16': qsub16,
'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