diff options
| author | Aymeric Vincent <aymeric.vincent@cea.fr> | 2018-02-22 16:02:57 +0100 |
|---|---|---|
| committer | Aymeric Vincent <aymeric.vincent@cea.fr> | 2018-02-26 11:34:41 +0100 |
| commit | cc2ee2c61dd4719bd7f9a85193590dffcda46991 (patch) | |
| tree | 8d6b3e6077c97f368dab884b8a889bba75e74f5a | |
| parent | 0606dd974a5ff0c3d6fb58e002b9319235a2dfbd (diff) | |
| download | miasm-cc2ee2c61dd4719bd7f9a85193590dffcda46991.tar.gz miasm-cc2ee2c61dd4719bd7f9a85193590dffcda46991.zip | |
Add support for PowerPC 32bit big-endian processors: "ppc32b"
| -rw-r--r-- | example/jitter/sandbox_elf_ppc32.py | 25 | ||||
| -rw-r--r-- | miasm2/analysis/machine.py | 13 | ||||
| -rw-r--r-- | miasm2/analysis/sandbox.py | 85 | ||||
| -rw-r--r-- | miasm2/arch/ppc/__init__.py | 1 | ||||
| -rw-r--r-- | miasm2/arch/ppc/arch.py | 759 | ||||
| -rw-r--r-- | miasm2/arch/ppc/disasm.py | 7 | ||||
| -rw-r--r-- | miasm2/arch/ppc/ira.py | 47 | ||||
| -rw-r--r-- | miasm2/arch/ppc/jit.py | 70 | ||||
| -rw-r--r-- | miasm2/arch/ppc/regs.py | 59 | ||||
| -rw-r--r-- | miasm2/arch/ppc/sem.py | 921 | ||||
| -rw-r--r-- | miasm2/jitter/Makefile | 7 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_ppc32.c | 373 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_ppc32.h | 24 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_ppc32_regs.h | 89 | ||||
| -rw-r--r-- | miasm2/jitter/csts.py | 1 | ||||
| -rw-r--r-- | miasm2/jitter/jitload.py | 4 | ||||
| -rwxr-xr-x | setup.py | 13 |
17 files changed, 2494 insertions, 4 deletions
diff --git a/example/jitter/sandbox_elf_ppc32.py b/example/jitter/sandbox_elf_ppc32.py new file mode 100644 index 00000000..c5960e8e --- /dev/null +++ b/example/jitter/sandbox_elf_ppc32.py @@ -0,0 +1,25 @@ +import os +from pdb import pm +from miasm2.analysis.sandbox import Sandbox_Linux_ppc32b +from miasm2.jitter.csts import * +from miasm2.jitter.jitload import log_func +import logging + + +# Python auto completion +filename = os.environ.get('PYTHONSTARTUP') +if filename and os.path.isfile(filename): + execfile(filename) + +# Insert here user defined methods + +# Parse arguments +parser = Sandbox_Linux_ppc32b.parser(description="ELF sandboxer") +parser.add_argument("filename", help="ELF Filename") +options = parser.parse_args() + +# Create sandbox +sb = Sandbox_Linux_ppc32b(options.filename, options, globals()) +log_func.setLevel(logging.ERROR) + +sb.run() diff --git a/miasm2/analysis/machine.py b/miasm2/analysis/machine.py index 7a6069c0..f361b412 100644 --- a/miasm2/analysis/machine.py +++ b/miasm2/analysis/machine.py @@ -12,7 +12,7 @@ class Machine(object): __available = ["arml", "armb", "armtl", "armtb", "sh4", "x86_16", "x86_32", "x86_64", "msp430", "mips32b", "mips32l", - "aarch64l", "aarch64b"] + "aarch64l", "aarch64b", "ppc32b"] def __init__(self, machine_name): @@ -162,6 +162,17 @@ class Machine(object): mn = arch.mn_mips32 from miasm2.arch.mips32.ira import ir_a_mips32l as ira from miasm2.arch.mips32.sem import ir_mips32l as ir + elif machine_name == "ppc32b": + from miasm2.arch.ppc.disasm import dis_ppc32b as dis_engine + from miasm2.arch.ppc import arch + try: + from miasm2.arch.ppc import jit + jitter = jit.jitter_ppc32b + except ImportError: + pass + mn = arch.mn_ppc + from miasm2.arch.ppc.ira import ir_a_ppc32b as ira + from miasm2.arch.ppc.sem import ir_ppc32b as ir else: raise ValueError('Unknown machine: %s' % machine_name) diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py index 086473b0..5bdccddd 100644 --- a/miasm2/analysis/sandbox.py +++ b/miasm2/analysis/sandbox.py @@ -440,6 +440,14 @@ class Arch_aarch64b(Arch): self.jitter.stack_base = self.STACK_BASE self.jitter.init_stack() +class Arch_ppc(Arch): + _ARCH_ = None + +class Arch_ppc32(Arch): + _ARCH_ = None + +class Arch_ppc32b(Arch_ppc32): + _ARCH_ = "ppc32b" class Sandbox_Win_x86_32(Sandbox, Arch_x86_32, OS_Win): @@ -745,3 +753,80 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux): """ prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) super(self.__class__, self).call(prepare_cb, addr, *args) + +class Sandbox_Linux_ppc32b(Sandbox, Arch_ppc32b, OS_Linux): + + STACK_SIZE = 0x10000 + STACK_BASE = 0xbfce0000 + + # The glue between the kernel and the ELF ABI on Linux/PowerPC is + # implemented in glibc/sysdeps/powerpc/powerpc32/dl-start.S, so we + # have to play the role of ld.so here. + def __init__(self, *args, **kwargs): + super(Sandbox_Linux_ppc32b, self).__init__(*args, **kwargs) + + # Init stack + self.jitter.stack_size = self.STACK_SIZE + self.jitter.stack_base = self.STACK_BASE + self.jitter.init_stack() + self.jitter.cpu.R1 -= 8 + + # Pre-stack some arguments + if self.options.mimic_env: + env_ptrs = [] + for env in self.envp: + env += "\x00" + self.jitter.cpu.R1 -= len(env) + ptr = self.jitter.cpu.R1 + self.jitter.vm.set_mem(ptr, env) + env_ptrs.append(ptr) + argv_ptrs = [] + for arg in self.argv: + arg += "\x00" + self.jitter.cpu.R1 -= len(arg) + ptr = self.jitter.cpu.R1 + self.jitter.vm.set_mem(ptr, arg) + argv_ptrs.append(ptr) + + self.jitter.push_uint32_t(0) + for ptr in reversed(env_ptrs): + self.jitter.push_uint32_t(ptr) + self.jitter.cpu.R5 = self.jitter.cpu.R1 # envp + self.jitter.push_uint32_t(0) + for ptr in reversed(argv_ptrs): + self.jitter.push_uint32_t(ptr) + self.jitter.cpu.R4 = self.jitter.cpu.R1 # argv + self.jitter.cpu.R3 = len(self.argv) # argc + self.jitter.push_uint32_t(self.jitter.cpu.R3) + + self.jitter.cpu.R6 = 0 # auxp + self.jitter.cpu.R7 = 0 # termination function + + # From the glibc, we should push a 0 here to distinguish a + # dynamically linked executable from a statically linked one. + # We actually do not do it and attempt to be somehow compatible + # with both types of executables. + #self.jitter.push_uint32_t(0) + + self.jitter.cpu.LR = self.CALL_FINISH_ADDR + + # Set the runtime guard + self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, + self.__class__.code_sentinelle) + + def run(self, addr=None): + """ + If addr is not set, use entrypoint + """ + if addr is None and self.options.address is None: + addr = self.entry_point + super(Sandbox_Linux_ppc32b, self).run(addr) + + def call(self, addr, *args, **kwargs): + """ + Direct call of the function at @addr, with arguments @args + @addr: address of the target function + @args: arguments + """ + prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) + super(self.__class__, self).call(prepare_cb, addr, *args) diff --git a/miasm2/arch/ppc/__init__.py b/miasm2/arch/ppc/__init__.py new file mode 100644 index 00000000..bbad893b --- /dev/null +++ b/miasm2/arch/ppc/__init__.py @@ -0,0 +1 @@ +__all__ = ["arch", "disasm", "regs", "sem"] diff --git a/miasm2/arch/ppc/arch.py b/miasm2/arch/ppc/arch.py new file mode 100644 index 00000000..d47c2aad --- /dev/null +++ b/miasm2/arch/ppc/arch.py @@ -0,0 +1,759 @@ + +import logging +from pyparsing import * +from miasm2.expression.expression import * +from miasm2.core.cpu import * +from collections import defaultdict +from miasm2.core.bin_stream import bin_stream +from miasm2.core.asmblock import asm_label +import miasm2.arch.ppc.regs as regs_module +from miasm2.arch.ppc.regs import * +from pdb import pm + +log = logging.getLogger("ppcdis") +console_handler = logging.StreamHandler() +console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) +log.addHandler(console_handler) +log.setLevel(logging.DEBUG) + +LPARENTHESIS = Suppress(Literal("(")) +RPARENTHESIS = Suppress(Literal(")")) + +def deref2expr_imm_reg(s, l, t): + t = t[0] + if len(t) == 1: + return ExprMem(t[0]) + elif len(t) == 2: + return ExprMem(t[1] + t[0]) + else: + raise NotImplementedError('len(t) > 2') + +variable, operand, base_expr = gen_base_expr() + +int_or_expr = base_expr + + +def ast_id2expr(t): + if not t in mn_ppc.regs.all_regs_ids_byname: + r = ExprId(asm_label(t)) + else: + r = mn_ppc.regs.all_regs_ids_byname[t] + return r + +def ast_int2expr(a): + return ExprInt(a, 32) + +deref_reg_disp = Group(Optional(int_or_expr) + LPARENTHESIS + gpregs.parser + RPARENTHESIS).setParseAction(deref2expr_imm_reg) +deref_reg = Group(LPARENTHESIS + gpregs.parser + RPARENTHESIS).setParseAction(deref2expr_imm_reg) + +deref = deref_reg | deref_reg_disp + +my_var_parser = ParseAst(ast_id2expr, ast_int2expr) +base_expr.setParseAction(my_var_parser) + + +class additional_info: + + def __init__(self): + self.except_on_instr = False + self.bo_bi_are_defined = False + self.bi = 0 + self.bo = 0 + + +class instruction_ppc(instruction): + delayslot = 0 + + def __init__(self, *args, **kargs): + super(instruction_ppc, self).__init__(*args, **kargs) + + @staticmethod + def arg2str(e, pos = None): + if isinstance(e, ExprId) or isinstance(e, ExprInt): + return str(e) + elif isinstance(e, ExprMem): + addr = e.arg + if isinstance(addr, ExprInt) or isinstance(addr, ExprId): + out = '(%s)'%addr + elif isinstance(addr, ExprOp): + if len(addr.args) == 1: + out = '(%s)'%addr + elif len(addr.args) == 2: + out = '%s(%s)'%(addr.args[1], addr.args[0]) + else: + raise NotImplementedError('More than two args to ExprOp of address') + else: + raise NotImplementedError('Invalid memory expression') + return out + + return str(e) + + @staticmethod + def is_conditional_jump(s): + return (s[0] == 'B' and + s[1:3] in { 'DN', 'DZ', 'LT', 'GT', 'EQ', 'SO', + 'GE', 'LE', 'NE', 'NS' }) + + def dstflow(self): + name = self.name + if name[-1] == '+' or name[-1] == '-': + name = name[:-1] + return (name[0] == 'B' and + name[-2:] != 'LR' and + name[-3:] != 'LRL' and + name[-3:] != 'CTR' and + name[-4:] != 'CTRL') + + def dstflow2label(self, symbol_pool): + name = self.name + if name[-1] == '+' or name[-1] == '-': + name = name[:-1] + + if name[-1] == 'L': + name = name[:-1] + elif name[-2:] == 'LA': + name = name[:-2] + 'A' + + if name[-2:] != 'LR' and name[-3:] != 'CTR': + if self.is_conditional_jump(name): + address_index = 1 + else: + address_index = 0 + e = self.args[address_index] + if not isinstance(e, ExprInt): + return + if name[-1] != 'A': + ad = e.arg + self.offset + else: + ad = e.arg + l = symbol_pool.getby_offset_create(ad) + s = ExprId(l, e.size) + self.args[address_index] = s + + def breakflow(self): + return self.name[0] == 'B' + + def is_subcall(self): + name = self.name + if name[-1] == '+' or name[-1] == '-': + name = name[0:-1] + return name[0] == 'B' and (name[-1] == 'L' or name[-2:-1] == 'LA') + + def getdstflow(self, symbol_pool): + if 'LR' in self.name: + return [ LR ] + elif 'CTR' in self.name: + return [ CTR ] + elif self.is_conditional_jump(self.name): + address_index = 1 + else: + address_index = 0 + return [ self.args[address_index] ] + + def splitflow(self): + ret = False + if self.is_conditional_jump(self.name): + if self.additional_info.bo & 0b10100 != 0b10100: + ret = True + ret = ret or self.is_subcall() + return ret + + def get_symbol_size(self, symbol, symbol_pool): + return 32 + + def fixDstOffset(self): + e = self.args[0] + if not isinstance(e, ExprInt): + log.debug('Dynamic destination offset %r' % e) + return + if self.name[-1] != 'A': + if self.offset is None: + raise ValueError('symbol not resolved %s' % self.l) + off = e.arg - (self.offset + self.l) + if int(off % 4): + raise ValueError('Offset %r must be a multiple of four' % off) + else: + off = e.arg + self.args[0] = ExprInt(off, 32) + + def get_args_expr(self): + args = [a for a in self.args] + return args + + def get_asm_offset(self, x): + return ExprInt_from(x, self.offset) + + +class mn_ppc(cls_mn): + delayslot = 0 + name = "ppc32" + regs = regs_module + bintree = {} + num = 0 + all_mn = [] + all_mn_mode = defaultdict(list) + all_mn_name = defaultdict(list) + all_mn_inst = defaultdict(list) + instruction = instruction_ppc + max_instruction_len = 4 + + @classmethod + def getpc(cls, attrib = None): + return PC + + @classmethod + def getsp(cls, attrib = None): + return R1 + + def additional_info(self): + info = additional_info() + info.bo_bi_are_defined = False + if hasattr(self, "bo"): + info.bo_bi_are_defined = True + info.bi = int(self.bi.strbits, 2) + info.bo = int(self.bo.strbits, 2) + return info + + @classmethod + def getbits(cls, bs, attrib, start, n): + if not n: + return 0 + o = 0 + if n > bs.getlen() * 8: + raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8)) + while n: + offset = start / 8 + n_offset = cls.endian_offset(attrib, offset) + c = cls.getbytes(bs, n_offset, 1) + if not c: + raise IOError + c = ord(c) + r = 8 - start % 8 + c &= (1 << r) - 1 + l = min(r, n) + c >>= (r - l) + o <<= l + o |= c + n -= l + start += l + return o + + @classmethod + def endian_offset(cls, attrib, offset): + if attrib == "b": + return offset + else: + raise NotImplementedError("bad attrib") + + @classmethod + def check_mnemo(cls, fields): + l = sum([x.l for x in fields]) + assert l == 32, "len %r" % l + + @classmethod + def getmn(cls, name): + return name.upper() + + @classmethod + def mod_fields(cls, fields): + l = sum([x.l for x in fields]) + return fields + + @classmethod + def gen_modes(cls, subcls, name, bases, dct, fields): + dct['mode'] = None + return [(subcls, name, bases, dct, fields)] + + def post_dis(self): + return self + + def value(self, mode): + v = super(mn_ppc, self).value(mode) + if mode == 'b': + return [x for x in v] + else: + raise NotImplementedError("bad attrib") + + def get_symbol_size(self, symbol, symbol_pool, mode): + return 32 + + +class ppc_reg(reg_noarg, m_arg): + pass + + +class ppc_gpreg_noarg(reg_noarg): + reg_info = gpregs + parser = reg_info.parser + +class ppc_gpreg_or_0_noarg(reg_noarg): + reg_info = gpregs + parser = reg_info.parser + + def decode(self, v): + ret = super(ppc_gpreg_or_0_noarg, self).decode(v) + if ret == False: + return False + reg = self.expr + if reg == R0: + self.expr = ExprInt(0, 32) + return ret + +class ppc_gpreg(ppc_reg): + reg_info = gpregs + parser = reg_info.parser + +class ppc_gpreg_or_0(ppc_reg): + reg_info = gpregs + parser = reg_info.parser + + def decode(self, v): + ret = super(ppc_reg, self).decode(v) + if ret == False: + return False + reg = self.expr + if reg == R0: + self.expr = ExprInt(0, 32) + return ret + +class ppc_crfreg_noarg(reg_noarg): + reg_info = crfregs + parser = reg_info.parser + +class ppc_crfreg(ppc_reg): + reg_info = crfregs + parser = reg_info.parser + +class ppc_imm(imm_noarg, m_arg): + parser = base_expr + +class ppc_s14imm_branch(ppc_imm): + + def decode(self, v): + v = sign_ext(v << 2, 16, 32) + self.expr = ExprInt(v, 32) + return True + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = self.expr.arg.arg + if v & 0x3: + return False + v = v >> 2 + if sign_ext(v & self.lmask, 14, 32) != v: + return False + self.value = v & self.lmask + return True + +class ppc_s24imm_branch(ppc_imm): + + def decode(self, v): + v = sign_ext(v << 2, 26, 32) + self.expr = ExprInt(v, 32) + return True + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = self.expr.arg.arg + if v & 0x3: + return False + v = v >> 2 + if sign_ext(v & self.lmask, 24, 32) != v: + return False + self.value = v & self.lmask + return True + +class ppc_s16imm(ppc_imm): + + def decode(self, v): + v = sign_ext(v, 16, 32) + self.expr = ExprInt(v, 32) + return True + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = self.expr.arg.arg + if sign_ext(v & self.lmask, 16, 32) != v: + return False + self.value = v & self.lmask + return True + +class ppc_u16imm(ppc_imm): + + def decode(self, v): + if v & self.lmask != v: + return False + self.expr = ExprInt(v, 32) + return True + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = self.expr.arg.arg + if v & self.lmask != v: + return False + self.value = v & self.lmask + return True + +def ppc_swap_10(v): + return ((v & 0b11111) << 5) | ((v & 0b1111100000) >> 5) + +class ppc_spr(ppc_imm): + + def decode(self, v): + self.expr = ExprInt(ppc_swap_10(v), 32) + return True + + def encode(self, e): + if not isinstance(e, ExprInt): + return False + self.value = ppc_swap_10(e.arg) + return True + +class ppc_tbr(ppc_imm): + + def decode(self, v): + self.expr = ExprInt(ppc_swap_10(v), 32) + return True + + def encode(self, e): + if not isinstance(e, ExprInt): + return False + self.value = ppc_swap_10(e.arg) + return True + +class ppc_u08imm(ppc_u16imm): + pass + +class ppc_u05imm(ppc_u16imm): + pass + +class ppc_u04imm(ppc_u16imm): + pass + +class ppc_u02imm_noarg(imm_noarg): + pass + + +def ppc_bo_bi_to_mnemo(bo, bi, prefer_taken=True, default_taken=True): + bo2mnemo = { 0: 'DNZF', 2: 'DZF', 4: 'F', 8: 'DNZT', + 10: 'DZT', 12: 'T', 16: 'DNZ', 18: 'DZ', + 20: '' } + bi2cond = { 0b00: 'LT', 0b01: 'GT', 0b10: 'EQ', 0b11: 'SO' } + bi2ncond = { 0b00: 'GE', 0b01: 'LE', 0b10: 'NE', 0b11: 'NS' } + n = bo & 0b11110 + if not n in bo2mnemo: + raise NotImplementedError("Unknown BO field") + mnem = 'B' + bo2mnemo[n] + if mnem[-1] == 'T': + mnem = mnem[:-1] + bi2cond[bi & 0b11] + if mnem[-1] == 'F': + mnem = mnem[:-1] + bi2ncond[bi & 0b11] + + if prefer_taken != default_taken: + if prefer_taken: + mnem += '+' + else: + mnem += '-' + + return mnem + +def ppc_all_bo_bi(): + yield 20, 0 + + for bo in [0, 2, 4, 8, 10, 12, 16, 18]: + for bi in xrange(4): + yield bo, bi + +class ppc_divert_conditional_branch(bs_divert): + prio=3 + def divert(self, i, candidates): + out = [] + for cls, _, bases, dct, fields in candidates: + bi_i = getfieldindexby_name(fields, 'bi')[1] + bo_i = getfieldindexby_name(fields, 'bo')[1] + + for bo, bi in ppc_all_bo_bi(): + nfields = fields[:] + nfields[bi_i] = bs(int2bin(bi, 2), fname="bi") + nfields[bo_i] = bs(int2bin(bo, 5), fname="bo") + ndct = dict(dct) + ndct['name'] = ppc_bo_bi_to_mnemo(bo, bi) + out.append((cls, ndct['name'], bases, ndct, nfields)) + + nfields = fields[:] + nfields[bi_i] = bs(int2bin(bi, 2), fname="bi") + nfields[bo_i] = bs(int2bin(bo+1, 5), fname="bo") + ndct = dict(dct) + ndct['name'] = ppc_bo_bi_to_mnemo(bo, bi) + out.append((cls, ndct['name'], bases, ndct, nfields)) + + return out + +class ppc_deref32(m_arg): + parser = deref + + def decode(self, v): + v = sign_ext(v, 16, 32) + e = self.parent.ra.expr + ExprInt(v, 32) + self.expr = ExprMem(e, size=32) + return True + + def encode(self): + e = self.expr + if not isinstance(e, ExprMem): + return False + addr = e.arg + if isinstance(addr, ExprId) or isinstance(addr, ExprInt): + addr = addr + ExprInt(0, 32) + elif not isinstance(addr, ExprOp): + return False + if addr.op != '+': + return False + if len(addr.args) != 2: + return False + reg, disp = addr.args[0], addr.args[1] + v = int(disp.arg) + if sign_ext(v & 0xFFFF, 16, 32) != v: + return False + v &= 0xFFFF + self.value = v + self.parent.ra.expr = reg + return True + + +def ppcop(name, fields, args=None, alias=False): + dct = {"fields": fields} + dct["alias"] = alias + if args is not None: + dct['args'] = args + type(name, (mn_ppc,), dct) + +rd = bs(l=5, cls=(ppc_gpreg,)) +ra = bs(l=5, cls=(ppc_gpreg,)) +ra_or_0 = bs(l=5, cls=(ppc_gpreg_or_0,)) +rb = bs(l=5, cls=(ppc_gpreg,)) +rs = bs(l=5, cls=(ppc_gpreg,)) +crfd = bs(l=3, cls=(ppc_crfreg,)) +crfs = bs(l=3, cls=(ppc_crfreg,)) +sh = bs(l=5, cls=(ppc_u05imm,)) +mb = bs(l=5, cls=(ppc_u05imm,)) +me = bs(l=5, cls=(ppc_u05imm,)) +nb = bs(l=5, cls=(ppc_u05imm,)) +crm = bs(l=8, cls=(ppc_u08imm,)) +sr = bs(l=4, cls=(ppc_u04imm,)) +spr = bs(l=10, cls=(ppc_spr,)) +tbr = bs(l=10, cls=(ppc_tbr,)) +u05imm = bs(l=5, cls=(ppc_u05imm,)) + +s24imm_branch = bs(l=24, cls=(ppc_s24imm_branch,), fname="imm") +s14imm_branch = bs(l=14, cls=(ppc_s14imm_branch,), fname="imm") +s16imm = bs(l=16, cls=(ppc_s16imm,), fname="imm") +u16imm = bs(l=16, cls=(ppc_u16imm,), fname="imm") +u08imm = bs(l=5, cls=(ppc_u08imm,), fname="imm") +u02imm_noarg = bs(l=2, cls=(ppc_u02imm_noarg,), fname="imm") + +ra_noarg = bs(l=5, cls=(ppc_gpreg_noarg,), fname="ra") +ra_or_0_noarg = bs(l=5, cls=(ppc_gpreg_or_0_noarg,), fname="ra") +dregimm = bs(l=16, cls=(ppc_deref32,)) + +rc_mod = bs_mod_name(l=1, mn_mod=['', '.'], fname='rc') + +arith1_name = {"MULLI": 0b000111, "SUBFIC": 0b001000, "ADDIC": 0b001100, + "ADDIC.": 0b001101 } + +logic2_name = {"ORI": 0b011000, "XORI": 0b011010, "ANDI.": 0b011100 } +slogic2_name = {"ORIS": 0b011001, "XORIS": 0b011011, "ANDIS.": 0b011101 } + +arith3_name = {"SUBFC": 0b0000001000, "ADDC": 0b0000001010, + "MULHWU": 0b0000001011, "SUBF": 0b0000101000, + "MULHW": 0b0001001011, "SUBFE": 0b0010001000, + "ADDE": 0b0010001010, "MULLW": 0b0011101011, + "ADD": 0b0100001010, "DIVWU": 0b0111001011, + "DIVW": 0b0111101011, "SUBFCO": 0b1000001000, + "ADDCO": 0b1000001010, "SUBFO": 0b1000101000, + "SUBFEO": 0b1010001000, "ADDEO": 0b1010001010, + "MULLWO": 0b1011101011, "ADDO": 0b1100001010, + "DIVWUO": 0b1111001011, "DIVWO": 0b1111101011 } + +xor_name = { "EQV": 0b0100011100, "XOR": 0b0100111100 } + +arith4_name = {"NEG": 0b0001101000, "SUBFZE": 0b0011001000, + "ADDZE": 0b0011001010, "SUBFME": 0b0011101000, + "ADDME": 0b0011101010, "NEGO": 0b1001101000, + "SUBFZEO": 0b1011001000, "ADDZEO": 0b1011001010, + "SUBFMEO": 0b1011101000, "ADDMEO": 0b1011101010 } + +arith5_name = {"CNTLZW": 0b00000, "EXTSH": 0b11100, "EXTSB": 0b11101 } + +crlogic_name = {"CRAND": 0b1000, "CRANDC": 0b0100, "CREQV": 0b1001, + "CRNAND": 0b0111, "CRNOR": 0b0001, "CROR": 0b1110, + "CRORC": 0b1101, "CRXOR": 0b0110 } + +rotins_name = {"RLWIMI": 0b010100, "RLWINM": 0b010101 } + +bs_arith1_name = bs_name(l=6, name=arith1_name) + +load1_name = {"LWARX": 0b0000010100, "LWZX": 0b0000010111, + "LBZX": 0b0001010111, "LHZX": 0b0100010111, + "ECIWX": 0b0100110110, "LHAX": 0b0101010111, + "LSWX": 0b1000010101, "LWBRX": 0b1000010110, + "LHBRX": 0b1100010110 } + +load1_name_u = {"LWZUX": 0b0000110111, "LBZUX": 0b0001110111, + "LHZUX": 0b0100110111, "LHAUX": 0b0101110111 } + +load2_name = {"LWZ": 0b0000, "LBZ": 0b0010, "LHZ": 0b1000, "LHA": 0b1010, + "LMW": 0b1110 } + +load2_name_u = {"LWZU": 0b0001, "LBZU": 0b0011, "LHZU": 0b1001, "LHAU": 0b1011} + +store1_name = { "STWCX.": 0b00100101101, "STWX": 0b00100101110, + "STBX": 0b00110101110, "STHX": 0b01100101110, + "ECOWX": 0b01101101100, "STSWX": 0b10100101010, + "STWBRX": 0b10100101100, "STHBRX": 0b11100101100 } +store1_name_u = { "STWUX": 0b00101101110, "STBUX": 0b00111101110, + "STHUX": 0b01101101110 } + +store2_name = { "STW": 0b0100, "STB": 0b0110, "STH": 0b1100, "STMW": 0b1111 } +store2_name_u = { "STWU": 0b0101, "STBU": 0b0111, "STHU": 0b1101 } + +logic1_name = {"SLW": 0b0000011000, "AND": 0b0000011100, + "ANDC": 0b0000111100, "NOR": 0b0001111100, + "ORC": 0b0110011100, "OR": 0b0110111100, + "NAND": 0b0111011100, "SRW": 0b1000011000, + "SRAW": 0b1100011000 } + +dcb_name = {"DCBST": 0b00001, "DCBF": 0b00010, + "DCBTST": 0b00111, "DCBT": 0b01000, + "DCBI": 0b01110, "DCBA": 0b10111, + "ICBI": 0b11110, "DCBZ": 0b11111 } + +class bs_mod_name_prio4(bs_mod_name): + prio = 4 + +class bs_mod_name_prio5(bs_mod_name): + prio = 5 + +class bs_mod_name_prio6(bs_mod_name): + prio = 6 + +branch_to_reg = bs_mod_name_prio4(l=1, mn_mod=['LR', 'CTR'], fname='btoreg') +branch_lk = bs_mod_name_prio5(l=1, mn_mod=['', 'L'], fname='lk') +branch_aa = bs_mod_name_prio6(l=1, mn_mod=['', 'A'], fname='aa') + +ppcop("arith1", [bs_arith1_name, rd, ra, s16imm]) +ppcop("ADDIS", [bs('001111'), rd, ra_or_0, u16imm]) +ppcop("ADDI", [bs('001110'), rd, ra_or_0, s16imm]) + +ppcop("logic2", [bs_name(l=6, name=logic2_name), rs, ra, u16imm], + [ra, rs, u16imm]) +ppcop("slogic2", [bs_name(l=6, name=slogic2_name), rs, ra, u16imm], + [ra, rs, u16imm]) + +ppcop("store1", [bs('011111'), rs, ra_or_0, rb, + bs_name(l=11, name=store1_name_u)]) +ppcop("store1u", [bs('011111'), rs, ra, rb, bs_name(l=11, name=store1_name)]) + +ppcop("store2", [bs('10'), bs_name(l=4, name=store2_name), rs, + ra_noarg, dregimm]) +ppcop("store2u", [bs('10'), bs_name(l=4, name=store2_name_u), rs, + ra_or_0_noarg, dregimm]) + +ppcop("arith3", [bs('011111'), rd, ra, rb, bs_name(l=10, name=arith3_name), + rc_mod]) + +ppcop("xor", [bs('011111'), rs, ra, rb, bs_name(l=10, name=xor_name), + rc_mod], [ra, rs, rb]) + +ppcop("arith4", [bs('011111'), rd, ra, bs('00000'), + bs_name(l=10, name=arith4_name), rc_mod]) + +ppcop("arith5", [bs('011111'), rs, ra, bs('00000'), + bs_name(l=5, name=arith5_name), + bs('11010'), rc_mod], [ra, rs]) + +ppcop("load1", [bs('011111'), rd, ra_or_0, rb, + bs_name(l=10, name=load1_name), bs('0')]) +ppcop("load1u", [bs('011111'), rd, ra, rb, + bs_name(l=10, name=load1_name_u), bs('0')]) +ppcop("load2", [bs('10'), bs_name(l=4, name=load2_name), + rd, ra_or_0_noarg, dregimm]) +ppcop("load2u", [bs('10'), bs_name(l=4, name=load2_name_u), + rd, ra_noarg, dregimm]) + +ppcop("logic1", [bs('011111'), rs, ra, rb, bs_name(l=10, name=logic1_name), + rc_mod], + [ra, rs, rb]) + +ppcop("TWI", [bs('000011'), u05imm, ra, s16imm]) +ppcop("TW", [bs('011111'), u05imm, ra, rb, bs('00000001000')]) + +ppcop("CMPW", [bs('011111'), crfd, bs('00'), ra, rb, bs('00000000000')]) +ppcop("CMPLW", [bs('011111'), crfd, bs('00'), ra, rb, bs('00001000000')]) +ppcop("CMPLWI", [bs('001010'), crfd, bs('00'), ra, u16imm]) +ppcop("CMPWI", [bs('001011'), crfd, bs('00'), ra, s16imm]) + +ppcop("BC", [bs('010000'), bs(l=5, cls=(ppc_u05imm,), fname='bo'), + crfs, + ppc_divert_conditional_branch(l=2, fname='bi'), + s14imm_branch, branch_aa, branch_lk]) +ppcop("SC", [bs('01000100000000000000000000000010')]) +ppcop("B", [bs('010010'), s24imm_branch, branch_aa, branch_lk]) +ppcop("MCRF", [bs('010011'), crfd, bs('00'), crfs, bs('000000000000000000')]) + +ppcop("BCXXX", [bs('010011'), bs(l=5, cls=(ppc_u05imm,), fname='bo'), + crfs, + ppc_divert_conditional_branch(l=2, fname='bi'), + bs('00000'), branch_to_reg, + bs('000010000'), branch_lk]) + +ppcop("crlogic", [bs('010011'), + bs(l=5, cls=(ppc_u05imm,), fname='crbd'), + bs(l=5, cls=(ppc_u05imm,), fname='crba'), + bs(l=5, cls=(ppc_u05imm,), fname='crbb'), + bs('0'), + bs_name(l=4, name=crlogic_name), + bs('000010')]) + +ppcop("rotins", [bs_name(l=6, name=rotins_name), + rs, ra, sh, mb, me, rc_mod], + [ ra, rs, sh, mb, me ]) +ppcop("RLWNM", [bs('010111'), rs, ra, rb, mb, me, rc_mod], + [ ra, rs, rb, mb, me ]) +ppcop("MFXXX", [bs('011111'), rd, bs('0000000000'), + bs('000'), + bs_name(l=1, name={'MFCR':0, 'MFMSR':1}), + bs('0100110')]) + +ppcop("dcb", [bs('01111100000'), ra, rb, bs_name(l=5, name=dcb_name), + bs('101100')]) + +ppcop("MTCRF", [bs('011111'), rs, bs('0'), crm, bs('000100100000')], [crm, rs]) +ppcop("MTMSR", [bs('011111'), rs, bs('0000000000'), bs('00100100100')]) +ppcop("MTSR", [bs('011111'), rs, bs('0'), sr, bs('0000000110100100')], [sr, rs]) +ppcop("MTSRIN", [bs('011111'), rs, bs('00000'), rb, bs('00111100100')]) + +ppcop("TLBIE", [bs('011111'), bs('0000000000'), rb, bs('01001100100')]) +ppcop("MFSPR", [bs('011111'), rd, spr, bs('01010100110')]) +ppcop("TLBIA", [bs('01111100000000000000001011100100')]) +ppcop("MFTB", [bs('011111'), rd, tbr, bs('01011100110')]) +ppcop("RFI", [bs('01001100000000000000000001100100')]) +ppcop("ISYNC", [bs('01001100000000000000000100101100')]) +ppcop("MTSPR", [bs('011111'), rs, spr, bs('01110100110')], [spr, rs]) +ppcop("MCRXR", [bs('011111'), crfd, bs('000000000000'), + bs('10000000000')]) +ppcop("TLBSYNC", [bs('01111100000000000000010001101100')]) +ppcop("MFSR", [bs('011111'), rd, bs('0'), sr, bs('00000'), bs('10010100110')]) +ppcop("LSWI", [bs('011111'), rd, ra, nb, bs('10010101010')]) +ppcop("STSWI", [bs('011111'), rs, ra, nb, bs('10110101010')]) +ppcop("SYNC", [bs('011111'), bs('000000000000000'), bs('10010101100')]) +ppcop("MFSRIN", [bs('011111'), rd, bs('00000'), rb, bs('10100100110')]) + +ppcop("SRAWI", [bs('011111'), rs, ra, sh, bs('1100111000'), rc_mod], + [ra, rs, sh]) + +ppcop("EIEIO", [bs('011111'), bs('000000000000000'), bs('11010101100')]) diff --git a/miasm2/arch/ppc/disasm.py b/miasm2/arch/ppc/disasm.py new file mode 100644 index 00000000..9fe3d886 --- /dev/null +++ b/miasm2/arch/ppc/disasm.py @@ -0,0 +1,7 @@ +from miasm2.arch.ppc.arch import mn_ppc +from miasm2.core.asmblock import disasmEngine + +class dis_ppc32b(disasmEngine): + def __init__(self, bs=None, **kwargs): + super(dis_ppc32b, self).__init__(mn_ppc, None, bs, **kwargs) + self.attrib = 'b' diff --git a/miasm2/arch/ppc/ira.py b/miasm2/arch/ppc/ira.py new file mode 100644 index 00000000..2459c0e4 --- /dev/null +++ b/miasm2/arch/ppc/ira.py @@ -0,0 +1,47 @@ +from miasm2.expression.expression import ExprAff, ExprOp +from miasm2.ir.ir import AssignBlock +from miasm2.ir.analysis import ira +from miasm2.arch.ppc.sem import ir_ppc32b + + +class ir_a_ppc32b(ir_ppc32b, ira): + + def __init__(self, *args): + super(ir_a_ppc32b, self).__init__(*args) + self.ret_reg = self.arch.regs.R3 + + # for test XXX TODO + def set_dead_regs(self, irblock): + pass + + def get_out_regs(self, _): + return set([self.ret_reg, self.sp]) + + def add_unused_regs(self): + leaves = [self.blocks[label] for label in self.g.leafs()] + for irblock in leaves: + self.set_dead_regs(irblock) + + def pre_add_instr(self, block, instr, assignments, ir_blocks_all, gen_pc_update): + """Replace function call with corresponding call effects, + inside the IR block""" + if not instr.is_subcall(): + return False + call_effects = self.call_effects(instr.getdstflow(None)[0], instr) + assignments+= call_effects + return True + + def sizeof_char(self): + return 8 + + def sizeof_short(self): + return 16 + + def sizeof_int(self): + return 32 + + def sizeof_long(self): + return 32 + + def sizeof_pointer(self): + return 32 diff --git a/miasm2/arch/ppc/jit.py b/miasm2/arch/ppc/jit.py new file mode 100644 index 00000000..9134e032 --- /dev/null +++ b/miasm2/arch/ppc/jit.py @@ -0,0 +1,70 @@ +from miasm2.jitter.jitload import jitter, named_arguments +from miasm2.core import asmblock +from miasm2.arch.ppc.sem import ir_ppc32b +import struct + +import logging + +log = logging.getLogger('jit_ppc') +hnd = logging.StreamHandler() +hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s")) +log.addHandler(hnd) +log.setLevel(logging.CRITICAL) + +class jitter_ppc32b(jitter): + max_reg_arg = 8 + + def __init__(self, *args, **kwargs): + super(jitter_ppc32b, self).__init__(ir_ppc32b(asmblock.AsmSymbolPool()), + *args, **kwargs) + self.vm.set_big_endian() + + def push_uint32_t(self, v): + self.cpu.R1 -= 4 + self.vm.set_mem(self.cpu.R1, struct.pack(">I", v)) + + def pop_uint32_t(self): + x = struct.unpack(">I", self.vm.get_mem(self.cpu.R1, 4))[0] + self.cpu.R1 += 4 + return x + + def get_stack_arg(self, n): + x = struct.unpack(">I", self.vm.get_mem(self.cpu.R1 + 8 + 4 * n, 4))[0] + return x + + @named_arguments + def func_args_systemv(self, n_args): + args = [self.get_arg_n_systemv(i) for i in xrange(n_args)] + ret_ad = self.cpu.LR + return ret_ad, args + + def func_ret_systemv(self, ret_addr, ret_value1=None, ret_value2=None): + self.pc = self.cpu.PC = ret_addr + if ret_value1 is not None: + self.cpu.R3 = ret_value1 + if ret_value2 is not None: + self.cpu.R4 = ret_value2 + return True + + def func_prepare_systemv(self, ret_addr, *args): + for index in xrange(min(len(args), self.max_reg_arg)): + setattr(self.cpu, 'R%d' % (index + 3), args[index]) + for index in xrange(len(args) - 1, self.max_reg_arg - 1, -1): + self.push_uint32_t(args[index]) + + # reserve room for LR save word and backchain + self.cpu.R1 -= 8 + + self.cpu.LR = ret_addr + + def get_arg_n_systemv(self, index): + if index < self.max_reg_arg: + arg = getattr(self.cpu, 'R%d' % (index + 3)) + else: + arg = self.get_stack_arg(index - self.max_reg_arg) + return arg + + + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.PC = self.pc diff --git a/miasm2/arch/ppc/regs.py b/miasm2/arch/ppc/regs.py new file mode 100644 index 00000000..70b49f82 --- /dev/null +++ b/miasm2/arch/ppc/regs.py @@ -0,0 +1,59 @@ + +from miasm2.expression.expression import * +from miasm2.core.cpu import gen_reg, gen_regs + +exception_flags = ExprId('exception_flags', 32) +spr_access = ExprId('spr_access', 32) + +reserve = ExprId('reserve', 1) +reserve_address = ExprId('reserve_address', 32) + +SPR_ACCESS_IS_WRITE = 0x80000000 +SPR_ACCESS_SPR_MASK = 0x000003FF +SPR_ACCESS_SPR_OFF = 0 +SPR_ACCESS_GPR_MASK = 0x0001F000 +SPR_ACCESS_GPR_OFF = 12 + +gpregs_str = ["R%d" % i for i in xrange(32)] +gpregs_expr, gpregs_init, gpregs = gen_regs(gpregs_str, globals(), 32) + +crfregs_str = ["CR%d" % i for i in xrange(8)] +crfregs_expr, crfregs_init, crfregs = gen_regs(crfregs_str, globals(), 4) + +crfbitregs_str = ["CR%d_%s" % (i, flag) for i in xrange(8) + for flag in ['LT', 'GT', 'EQ', 'SO'] ] +crfbitregs_expr, crfbitregs_init, crfbitregs = gen_regs(crfbitregs_str, + globals(), 1) + +xerbitregs_str = ["XER_%s" % field for field in ['SO', 'OV', 'CA'] ] +xerbitregs_expr, xerbitregs_init, xerbitregs = gen_regs(xerbitregs_str, + globals(), 1) + +xerbcreg_str = ["XER_BC"] +xerbcreg_expr, xerbcreg_init, xerbcreg = gen_regs(xerbcreg_str, + globals(), 7) + + +otherregs_str = ["PC", "CTR", "LR" ] +otherregs_expr, otherregs_init, otherregs = gen_regs(otherregs_str, + globals(), 32) + +superregs_str = (["SPRG%d" % i for i in xrange(4)] + + ["SRR%d" % i for i in xrange(2)] + + ["DAR", "DSISR", "MSR", "PIR", "PVR", + "DEC", "TBL", "TBU"]) +superregs_expr, superregs_init, superregs = gen_regs(superregs_str, + globals(), 32) + +regs_flt_expr = [] + +all_regs_ids = (gpregs_expr + crfbitregs_expr + xerbitregs_expr + + xerbcreg_expr + otherregs_expr + superregs_expr + + [ exception_flags, spr_access, reserve, reserve_address ]) +all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids]) +all_regs_ids_init = [ExprId("%s_init" % x.name, x.size) for x in all_regs_ids] +all_regs_ids_no_alias = all_regs_ids[:] + +regs_init = {} +for i, r in enumerate(all_regs_ids): + regs_init[r] = all_regs_ids_init[i] diff --git a/miasm2/arch/ppc/sem.py b/miasm2/arch/ppc/sem.py new file mode 100644 index 00000000..76a1a27e --- /dev/null +++ b/miasm2/arch/ppc/sem.py @@ -0,0 +1,921 @@ +import miasm2.expression.expression as expr +from miasm2.ir.ir import AssignBlock, IntermediateRepresentation, IRBlock +from miasm2.arch.ppc.arch import mn_ppc +from miasm2.arch.ppc.regs import * +from miasm2.core.sembuilder import SemBuilder +from miasm2.jitter.csts import * + +spr_dict = { + 8: LR, 9: CTR, 18: DSISR, 19: DAR, + 22: DEC, 26: SRR0, 27: SRR1, + 272: SPRG0, 273: SPRG0, 274: SPRG1, 275: SPRG2, 276: SPRG3, + 284: TBL, 285: TBU, 287: PVR, 1023: PIR +} + +crf_dict = dict((ExprId("CR%d" % i, 4), + dict( (bit, ExprId("CR%d_%s" % (i, bit), 1)) + for bit in ['LT', 'GT', 'EQ', 'SO' ] )) + for i in xrange(8) ) + +ctx = { 'crf_dict': crf_dict, 'spr_dict': spr_dict } +ctx.update(all_regs_ids_byname) +sbuild = SemBuilder(ctx) + +def mn_compute_flags(rvalue, overflow_expr=None): + ret = [] + ret.append(ExprAff(CR0_LT, rvalue.msb())) + ret.append(ExprAff(CR0_GT, (ExprCond(rvalue, ExprInt(1, 1), + ExprInt(0, 1)) & ~rvalue.msb()))) + ret.append(ExprAff(CR0_EQ, ExprCond(rvalue, ExprInt(0, 1), + ExprInt(1, 1)))) + if overflow_expr != None: + ret.append(ExprAff(CR0_SO, XER_SO | overflow_expr)) + else: + ret.append(ExprAff(CR0_SO, XER_SO)) + + return ret + +def mn_do_add(ir, instr, arg1, arg2, arg3): + assert instr.name[0:3] == 'ADD' + + flags_update = [] + + has_dot = False + has_c = False + has_e = False + has_o = False + + for l in instr.name[3:]: + if l == '.': + has_dot = True + elif l == 'C': + has_c = True + elif l == 'E': + has_e = True + elif l == 'O': + has_o = True + elif l == 'I' or l == 'M' or l == 'S' or l == 'Z': + pass # Taken care of earlier + else: + assert False + + rvalue = arg2 + arg3 + + if has_e: + rvalue = rvalue + XER_CA.zeroExtend(32) + + over_expr = None + if has_o: + msb1 = arg2.msb() + msb2 = arg3.msb() + msba = rvalue.msb() + over_expr = ~(msb1 ^ msb2) & (msb1 ^ msba) + flags_update.append(ExprAff(XER_OV, over_expr)) + flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) + + if has_dot: + flags_update += mn_compute_flags(rvalue, over_expr) + + if has_c or has_e: + carry_expr = (((arg2 ^ arg3) ^ rvalue) ^ + ((arg2 ^ rvalue) & (~(arg2 ^ arg3)))).msb() + flags_update.append(ExprAff(XER_CA, carry_expr)) + + return ([ ExprAff(arg1, rvalue) ] + flags_update), [] + +def mn_do_and(ir, instr, ra, rs, arg2): + if len(instr.name) > 3 and instr.name[3] == 'C': + oarg = ~arg2 + else: + oarg = arg2 + + rvalue = rs & oarg + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_cntlzw(ir, instr, ra, rs): + rvalue = ExprCond(rs, ExprInt(31, 32) - ExprOp('bsr', rs), ExprInt(32, 32)) + + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def crbit_to_reg(bit): + bit = bit.arg.arg + crid = bit / 4 + bitname = [ 'LT', 'GT', 'EQ', 'SO' ][bit % 4] + return all_regs_ids_byname["CR%d_%s" % (crid, bitname)] + +def mn_do_cr(ir, instr, crd, cra, crb): + a = crbit_to_reg(cra) + b = crbit_to_reg(crb) + d = crbit_to_reg(crd) + + op = instr.name[2:] + + if op == 'AND': + r = a & b + elif op == 'ANDC': + r = a & ~b + elif op == 'EQV': + r = ~(a ^ b) + elif op == 'NAND': + r = ~(a & b) + elif op == 'NOR': + r = ~(a | b) + elif op == 'OR': + r = a | b + elif op == 'ORC': + r = a | ~b + elif op == 'XOR': + r = a ^ b + else: + raise "Unknown operation on CR" + return [ ExprAff(d, r) ], [] + +def mn_do_div(ir, instr, rd, ra, rb): + assert instr.name[0:4] == 'DIVW' + + flags_update = [] + + has_dot = False + has_c = False + has_o = False + has_u = False + + for l in instr.name[3:]: + if l == '.': + has_dot = True + elif l == 'C': + has_c = True + elif l == 'O': + has_o = True + elif l == 'U': + has_u = True + elif l == 'W': + pass + else: + assert False + + if has_u: + op = 'udiv' + else: + op = 'idiv' + + rvalue = ExprOp(op, ra, rb) + + over_expr = None + if has_o: + over_expr = ExprCond(rb, ExprInt(0, 1), ExprInt(1, 1)) + if not has_u: + over_expr = over_expr | (ExprCond(ra ^ 0x80000000, ExprInt(0, 1), + ExprInt(1, 1)) & + ExprCond(rb ^ 0xFFFFFFFF, ExprInt(0, 1), + ExprInt(1, 1))) + flags_update.append(ExprAff(XER_OV, over_expr)) + flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) + + if has_dot: + flags_update += mn_compute_flags(rvalue, over_expr) + + return ([ ExprAff(rd, rvalue) ] + flags_update), [] + + +def mn_do_eqv(ir, instr, ra, rs, rb): + rvalue = ~(rs ^ rb) + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_exts(ir, instr, ra, rs): + if instr.name[4] == 'B': + size = 8 + elif instr.name[4] == 'H': + size = 16 + else: + assert False + + rvalue = rs[0:size].signExtend(32) + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def byte_swap(expr): + nbytes = expr.size / 8 + bytes = [ expr[i*8:i*8+8] for i in xrange(nbytes - 1, -1, -1) ] + return ExprCompose(bytes) + +def mn_do_load(ir, instr, arg1, arg2, arg3=None): + assert instr.name[0] == 'L' + + ret = [] + + if instr.name[1] == 'M': + return mn_do_lmw(ir, instr, arg1, arg2) + elif instr.name[1] == 'S': + raise RuntimeError("LSWI, and LSWX need implementing") + pass # XXX + + size = {'B': 8, 'H': 16, 'W': 32}[instr.name[1]] + + has_a = False + has_b = False + has_u = False + is_lwarx = False + + for l in instr.name[2:]: + if l == 'A': + has_a = True + elif l == 'B': + has_b = True + elif l == 'U': + has_u = True + elif l == 'X' or l == 'Z': + pass # Taken care of earlier + elif l == 'R' and not has_b: + is_lwarx = True + else: + assert False + + if arg3 is None: + assert isinstance(arg2, ExprMem) + + address = arg2.arg + else: + address = arg2 + arg3 + + src = ExprMem(address, size) + + if has_b: + src = byte_swap(src) + + if has_a: + src = src.signExtend(32) + else: + src = src.zeroExtend(32) + + ret.append(ExprAff(arg1, src)) + if has_u: + if arg3 is None: + ret.append(ExprAff(arg2.arg.args[0], address)) + else: + ret.append(ExprAff(arg2, address)) + + if is_lwarx: + ret.append(ExprAff(reserve, ExprInt(1, 1))) + ret.append(ExprAff(reserve_address, address)) # XXX should be the PA + + return ret, [] + +def mn_do_lmw(ir, instr, rd, src): + ret = [] + address = src.arg + ri = int(rd.name[1:],10) + i = 0 + while ri <= 31: + ret.append(ExprAff(all_regs_ids_byname["R%d" % ri], + ExprMem(address + ExprInt(i, 32), 32))) + ri += 1 + i += 4 + + return ret, [] + +def mn_do_lswi(ir, instr, rd, ra, nb): + if nb == 0: + nb = 32 + i = 32 + raise "%r not implemented" % instr + +def mn_do_lswx(ir, instr, rd, ra, nb): + raise "%r not implemented" % instr + +def mn_do_mcrf(ir, instr, crfd, crfs): + ret = [] + + for bit in [ 'LT', 'GT', 'EQ', 'SO' ]: + d = all_regs_ids_byname["%s_%s" % (crfd, bit)] + s = all_regs_ids_byname["%s_%s" % (crfs, bit)] + ret.append(ExprAff(d, s)) + + return ret, [] + +def mn_do_mcrxr(ir, instr, crfd): + ret = [] + + for (bit, val) in [ ('LT', XER_SO), ('GT', XER_OV), ('EQ', XER_CA), + ('SO', ExprInt(0, 1)) ]: + ret.append(ExprAff(all_regs_ids_byname["%s_%s" % (crfd, bit)], val)) + + return ret, [] + +def mn_do_mfcr(ir, instr, rd): + return ([ ExprAff(rd, ExprCompose(*[ all_regs_ids_byname["CR%d_%s" % (i, b)] + for i in xrange(7, -1, -1) + for b in ['SO', 'EQ', 'GT', 'LT']]))], + []) + +@sbuild.parse +def mn_mfmsr(rd): + rd = MSR + +def mn_mfspr(ir, instr, arg1, arg2): + sprid = arg2.arg.arg + gprid = int(arg1.name[1:]) + if sprid in spr_dict: + return [ ExprAff(arg1, spr_dict[sprid]) ], [] + elif sprid == 1: # XER + return [ ExprAff(arg1, ExprCompose(XER_BC, ExprInt(0, 22), + XER_CA, XER_OV, XER_SO)) ], [] + else: + return [ ExprAff(spr_access, + ExprInt(((sprid << SPR_ACCESS_SPR_OFF) | + (gprid << SPR_ACCESS_GPR_OFF)), 32)), + ExprAff(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], [] + +def mn_mtcrf(ir, instr, crm, rs): + ret = [] + + for i in xrange(8): + if crm.arg.arg & (1 << (7 - i)): + j = (28 - 4 * i) + 3 + for b in ['LT', 'GT', 'EQ', 'SO']: + ret.append(ExprAff(all_regs_ids_byname["CR%d_%s" % (i, b)], + rs[j:j+1])) + j -= 1 + + return ret, [] + +def mn_mtmsr(ir, instr, rs): + print "%08x: MSR assigned" % instr.offset + return [ ExprAff(MSR, rs) ], [] + +def mn_mtspr(ir, instr, arg1, arg2): + sprid = arg1.arg.arg + gprid = int(arg2.name[1:]) + if sprid in spr_dict: + return [ ExprAff(spr_dict[sprid], arg2) ], [] + elif sprid == 1: # XER + return [ ExprAff(XER_SO, arg2[31:32]), + ExprAff(XER_OV, arg2[30:31]), + ExprAff(XER_CA, arg2[29:30]), + ExprAff(XER_BC, arg2[0:7]) ], [] + else: + return [ ExprAff(spr_access, + ExprInt(((sprid << SPR_ACCESS_SPR_OFF) | + (gprid << SPR_ACCESS_GPR_OFF) | + SPR_ACCESS_IS_WRITE), 32)), + ExprAff(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], [] + +def mn_do_mul(ir, instr, rd, ra, arg2): + variant = instr.name[3:] + if variant[-1] == '.': + variant = variant[:-2] + + if variant == 'HW': + v1 = ra.signExtend(64) + v2 = arg2.signExtend(64) + shift = 32 + elif variant == 'HWU': + v1 = ra.zeroExtend(64) + v2 = arg2.zeroExtend(64) + shift = 32 + else: + v1 = ra + v2 = arg2 + shift = 0 + + rvalue = ExprOp('*', v1, v2) + if shift != 0: + rvalue = rvalue[shift : shift + 32] + + ret = [ ExprAff(rd, rvalue) ] + + over_expr = None + if variant[-1] == 'O': + over_expr = ExprCond((rvalue.signExtend(64) ^ + ExprOp('*', v1.signExtend(64), + v2.signExtend(64))), + ExprInt(1, 1), ExprInt(0, 1)) + ret.append(ExprAff(XER_OV, over_expr)) + ret.append(ExprAff(XER_SO, XER_SO | over_expr)) + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue, over_expr) + + return ret, [] + +def mn_do_nand(ir, instr, ra, rs, rb): + rvalue = ~(rs & rb) + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_neg(ir, instr, rd, ra): + rvalue = -ra + ret = [ ExprAff(ra, rvalue) ] + has_o = False + + over_expr = None + if instr.name[-1] == 'O' or instr.name[-2] == 'O': + has_o = True + over_expr = ExprCond(ra ^ ExprInt(0x80000000, 32), + ExprInt(0, 1), ExprInt(1, 1)) + ret.append(ExprAff(XER_OV, over_expr)) + ret.append(ExprAff(XER_SO, XER_SO | over_expr)) + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue, over_expr) + + return ret, [] + +def mn_do_nor(ir, instr, ra, rs, rb): + + rvalue = ~(rs | rb) + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_or(ir, instr, ra, rs, arg2): + if len(instr.name) > 2 and instr.name[2] == 'C': + oarg = ~arg2 + else: + oarg = arg2 + + rvalue = rs | oarg + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_rfi(ir, instr): + dest = ExprCompose(ExprInt(0, 2), SRR0[2:32]) + ret = [ ExprAff(MSR, (MSR & + ~ExprInt(0b1111111101110011, 32) | + ExprCompose(SRR1[0:2], ExprInt(0, 2), + SRR1[4:7], ExprInt(0, 1), + SRR1[8:16], ExprInt(0, 16)))), + ExprAff(PC, dest), + ExprAff(ir.IRDst, dest) ] + return ret, [] + +def mn_do_rotate(ir, instr, ra, rs, shift, mb, me): + r = ExprOp('<<<', rs, shift) + if mb <= me: + m = ExprInt(((1 << (32 - mb)) - 1) & ~((1 << (32 - me - 1)) - 1), 32) + else: + m = ExprInt(((1 << (32 - mb)) - 1) | ~((1 << (32 - me - 1)) - 1), 32) + rvalue = r & m + if instr.name[0:6] == 'RLWIMI': + rvalue = rvalue | (ra & ~m) + + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_slw(ir, instr, ra, rs, rb): + + rvalue = ExprCond(rb[5:6], ExprInt(0, 32), + ExprOp('<<', rs, rb & ExprInt(0b11111, 32))) + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_sraw(ir, instr, ra, rs, rb): + rvalue = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), + ExprOp('a>>', rs, rb & ExprInt(0b11111, 32))) + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + mask = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), + (ExprInt(0xFFFFFFFF, 32) >> + (ExprInt(32, 32) - (rb & ExprInt(0b11111, 32))))) + ret.append(ExprAff(XER_CA, rs.msb() & + ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) + + return ret, [] + +def mn_do_srawi(ir, instr, ra, rs, imm): + rvalue = ExprOp('a>>', rs, imm) + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + mask = ExprInt(0xFFFFFFFF >> (32 - imm.arg.arg), 32) + + ret.append(ExprAff(XER_CA, rs.msb() & + ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) + + return ret, [] + +def mn_do_srw(ir, instr, ra, rs, rb): + rvalue = rs >> (rb & ExprInt(0b11111, 32)) + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +def mn_do_stmw(ir, instr, rs, dest): + ret = [] + address = dest.arg + ri = int(rs.name[1:],10) + i = 0 + while ri <= 31: + ret.append(ExprAff(ExprMem(address + ExprInt(i,32), 32), + all_regs_ids_byname["R%d" % ri])) + ri += 1 + i += 4 + + return ret, [] + +def mn_do_store(ir, instr, arg1, arg2, arg3=None): + assert instr.name[0:2] == 'ST' + + ret = [] + additional_ir = [] + + if instr.name[2] == 'S': + raise RuntimeError("STSWI, and STSWX need implementing") + pass # XXX + + size = {'B': 8, 'H': 16, 'W': 32}[instr.name[2]] + + has_b = False + has_u = False + is_stwcx = False + + for l in instr.name[3:]: + if l == 'B' or l == 'R': + has_b = True + elif l == 'U': + has_u = True + elif l == 'X' or l == 'Z': + pass # Taken care of earlier + elif l == 'C' or l == '.': + is_stwcx = True + else: + assert False + + if arg3 is None: + assert isinstance(arg2, ExprMem) + + address = arg2.arg + else: + address = arg2 + arg3 + + dest = ExprMem(address, size) + + src = arg1[0:size] + if has_b: + src = byte_swap(src) + + ret.append(ExprAff(dest, src)) + if has_u: + if arg3 is None: + ret.append(ExprAff(arg2.arg.args[0], address)) + else: + ret.append(ExprAff(arg2, address)) + + if is_stwcx: + lbl_do = ExprId(ir.gen_label(), ir.IRDst.size) + lbl_dont = ExprId(ir.gen_label(), ir.IRDst.size) + lbl_next = ExprId(ir.get_next_label(instr), ir.IRDst.size) + flags = [ ExprAff(CR0_LT, ExprInt(0,1)), + ExprAff(CR0_GT, ExprInt(0,1)), + ExprAff(CR0_SO, XER_SO)] + ret += flags + ret.append(ExprAff(CR0_EQ, ExprInt(1,1))) + ret.append(ExprAff(ir.IRDst, lbl_next)) + dont = flags + [ ExprAff(CR0_EQ, ExprInt(0,1)), + ExprAff(ir.IRDst, lbl_next) ] + additional_ir = [ IRBlock(lbl_do.name, [ AssignBlock(ret) ]), + IRBlock(lbl_dont.name, [ AssignBlock(dont) ]) ] + ret = [ ExprAff(reserve, ExprInt(0, 1)), + ExprAff(ir.IRDst, ExprCond(reserve, lbl_do, lbl_dont)) ] + + return ret, additional_ir + +def mn_do_sub(ir, instr, arg1, arg2, arg3): + assert instr.name[0:4] == 'SUBF' + + flags_update = [] + + has_dot = False + has_c = False + has_e = False + has_o = False + + for l in instr.name[4:]: + if l == '.': + has_dot = True + elif l == 'C': + has_c = True + elif l == 'E': + has_e = True + elif l == 'O': + has_o = True + elif l == 'I' or l == 'M' or l == 'S' or l == 'Z': + pass # Taken care of earlier + else: + assert False + + if has_e: + arg3 = arg3 + XER_CA.zeroExtend(32) + arg2 = arg2 + ExprInt(1, 32) + + rvalue = arg3 - arg2 + + over_expr = None + if has_o: + msb1 = arg2.msb() + msb2 = arg3.msb() + msba = rvalue.msb() + over_expr = (msb1 ^ msb2) & (msb1 ^ msba) + flags_update.append(ExprAff(XER_OV, over_expr)) + flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) + + if has_dot: + flags_update += mn_compute_flags(rvalue, over_expr) + + if has_c or has_e: + carry_expr = ((((arg3 ^ arg2) ^ rvalue) ^ + ((arg3 ^ rvalue) & (arg3 ^ arg2))).msb()) + flags_update.append(ExprAff(XER_CA, ~carry_expr)) + + return ([ ExprAff(arg1, rvalue) ] + flags_update), [] + +def mn_do_xor(ir, instr, ra, rs, rb): + rvalue = rs ^ rb + ret = [ ExprAff(ra, rvalue) ] + + if instr.name[-1] == '.': + ret += mn_compute_flags(rvalue) + + return ret, [] + +@sbuild.parse +def mn_b(arg1): + PC = arg1 + ir.IRDst = arg1 + +@sbuild.parse +def mn_bl(arg1): + LR = ExprId(ir.get_next_instr(instr), 32) + PC = arg1 + ir.IRDst = arg1 + +def mn_get_condition(instr): + bit = instr.additional_info.bi & 0b11 + cr = instr.args[0].name + return all_regs_ids_byname[cr + '_' + ['LT', 'GT', 'EQ', 'SO'][bit]] + +def mn_do_cond_branch(ir, instr, dest): + bo = instr.additional_info.bo + bi = instr.additional_info.bi + ret = [] + if not (bo & 0b00100): + ret.append(ExprAff(CTR, CTR - ExprInt(1, 32))) + if (bo & 0b10100) == 0b10100: + ctr_cond = True + else: + ctr_cond = ExprCond(CTR ^ ExprInt(1, 32), ExprInt(1, 1), ExprInt(0, 1)) + if bo & 0b00010: + ctr_cond = ~ctr_cond + + if (bo & 0b10000): + cond_cond = True + else: + cond_cond = mn_get_condition(instr) + if not (bo & 0b01000): + cond_cond = ~cond_cond + + if ctr_cond != True or cond_cond != True: + if ctr_cond != True: + condition = ctr_cond + if cond_cond != True: + condition = condition & cond_cond + else: + condition = cond_cond + dest_expr = ExprCond(condition, dest, + ExprId(ir.get_next_instr(instr), 32)) + else: + dest_expr = dest + + if instr.name[-1] == 'L' or instr.name[-2:-1] == 'LA': + ret.append(ExprAff(LR, ExprId(ir.get_next_instr(instr), 32))) + + ret.append(ExprAff(PC, dest_expr)) + ret.append(ExprAff(ir.IRDst, dest_expr)) + + return ret, [] + +def mn_do_nop_warn(ir, instr, *args): + print "Warning, instruction %s implemented as NOP" % instr + return [], [] + +@sbuild.parse +def mn_cmp_signed(arg1, arg2, arg3): + crf_dict[arg1]['LT'] = ((arg2 - arg3) ^ + ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))).msb() + crf_dict[arg1]['GT'] = ((arg3 - arg2) ^ + ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))).msb() + crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1) + crf_dict[arg1]['SO'] = XER_SO + +@sbuild.parse +def mn_cmp_unsigned(arg1, arg2, arg3): + crf_dict[arg1]['LT'] = (((arg2 - arg3) ^ + ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))) ^ + arg2 ^ arg3).msb() + crf_dict[arg1]['GT'] = (((arg3 - arg2) ^ + ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))) ^ + arg2 ^ arg3).msb() + crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1) + crf_dict[arg1]['SO'] = XER_SO + +def mn_nop(ir, instr, *args): + return [], [] + +@sbuild.parse +def mn_or(arg1, arg2, arg3): + arg1 = arg2 | arg3 + +@sbuild.parse +def mn_assign(arg1, arg2): + arg2 = arg1 + +def mn_stb(ir, instr, arg1, arg2): + dest = ExprMem(arg2.arg, 8) + return [ExprAff(dest, ExprSlice(arg1, 0, 8))], [] + +@sbuild.parse +def mn_stwu(arg1, arg2): + arg2 = arg1 + arg1 = arg2.arg + +sem_dir = { + 'B': mn_b, + 'BA': mn_b, + 'BL': mn_bl, + 'BLA': mn_bl, + 'CMPLW': mn_cmp_unsigned, + 'CMPLWI': mn_cmp_unsigned, + 'CMPW': mn_cmp_signed, + 'CMPWI': mn_cmp_signed, + 'CNTLZW': mn_do_cntlzw, + 'CNTLZW.': mn_do_cntlzw, + 'ECIWX': mn_do_nop_warn, + 'ECOWX': mn_do_nop_warn, + 'EIEIO': mn_do_nop_warn, + 'EQV': mn_do_eqv, + 'EQV.': mn_do_eqv, + 'ICBI': mn_do_nop_warn, + 'ISYNC': mn_do_nop_warn, + 'MCRF': mn_do_mcrf, + 'MCRXR': mn_do_mcrxr, + 'MFCR': mn_do_mfcr, + 'MFMSR': mn_mfmsr, + 'MFSPR': mn_mfspr, + 'MFSR': mn_do_nop_warn, + 'MFSRIN': mn_do_nop_warn, + 'MFTB': mn_mfmsr, + 'MTCRF': mn_mtcrf, + 'MTMSR': mn_mtmsr, + 'MTSPR': mn_mtspr, + 'MTSR': mn_do_nop_warn, + 'MTSRIN': mn_do_nop_warn, + 'NAND': mn_do_nand, + 'NAND.': mn_do_nand, + 'NOR': mn_do_nor, + 'NOR.': mn_do_nor, + 'RFI': mn_do_rfi, + 'SC': mn_do_nop_warn, + 'SLW': mn_do_slw, + 'SLW.': mn_do_slw, + 'SRAW': mn_do_sraw, + 'SRAW.': mn_do_sraw, + 'SRAWI': mn_do_srawi, + 'SRAWI.': mn_do_srawi, + 'SRW': mn_do_srw, + 'SRW.': mn_do_srw, + 'SYNC': mn_do_nop_warn, + 'TLBIA': mn_do_nop_warn, + 'TLBIE': mn_do_nop_warn, + 'TLBSYNC': mn_do_nop_warn, + 'TW': mn_do_nop_warn, + 'TWI': mn_do_nop_warn, +} + + +class ir_ppc32b(IntermediateRepresentation): + + def __init__(self, symbol_pool=None): + super(ir_ppc32b, self).__init__(mn_ppc, 'b', symbol_pool) + self.pc = mn_ppc.getpc() + self.sp = mn_ppc.getsp() + self.IRDst = expr.ExprId('IRDst', 32) + + def get_ir(self, instr): + args = instr.args[:] + if instr.name[0:5] in [ 'ADDIS', 'ORIS', 'XORIS', 'ANDIS' ]: + args[2] = ExprInt(args[2].arg << 16, 32) + if instr.name[0:3] == 'ADD': + if instr.name[0:4] == 'ADDZ': + last_arg = ExprInt(0, 32) + elif instr.name[0:4] == 'ADDM': + last_arg = ExprInt(0xFFFFFFFF, 32) + else: + last_arg = args[2] + instr_ir, extra_ir = mn_do_add(self, instr, args[0], args[1], + last_arg) + elif instr.name[0:3] == 'AND': + instr_ir, extra_ir = mn_do_and(self, instr, *args) + elif instr.additional_info.bo_bi_are_defined: + name = instr.name + if name[-1] == '+' or name[-1] == '-': + name = name[0:-1] + if name[-3:] == 'CTR' or name[-4:] == 'CTRL': + arg1 = ExprCompose(ExprInt(0, 2), CTR[2:32]) + elif name[-2:] == 'LR' or name[-3:] == 'LRL': + arg1 = ExprCompose(ExprInt(0, 2), LR[2:32]) + else: + arg1 = args[1] + instr_ir, extra_ir = mn_do_cond_branch(self, instr, arg1) + elif instr.name[0:2] == 'CR': + instr_ir, extra_ir = mn_do_cr(self, instr, *args) + elif instr.name[0:3] == 'DCB': + instr_ir, extra_ir = mn_do_nop_warn(self, instr, *args) + elif instr.name[0:3] == 'DIV': + instr_ir, extra_ir = mn_do_div(self, instr, *args) + elif instr.name[0:4] == 'EXTS': + instr_ir, extra_ir = mn_do_exts(self, instr, *args) + elif instr.name[0] == 'L': + instr_ir, extra_ir = mn_do_load(self, instr, *args) + elif instr.name[0:3] == 'MUL': + instr_ir, extra_ir = mn_do_mul(self, instr, *args) + elif instr.name[0:3] == 'NEG': + instr_ir, extra_ir = mn_do_neg(self, instr, *args) + elif instr.name[0:2] == 'OR': + instr_ir, extra_ir = mn_do_or(self, instr, *args) + elif instr.name[0:2] == 'RL': + instr_ir, extra_ir = mn_do_rotate(self, instr, args[0], args[1], + args[2], args[3].arg.arg, + args[4].arg.arg) + elif instr.name == 'STMW': + instr_ir, extra_ir = mn_do_stmw(self, instr, *args) + elif instr.name[0:2] == 'ST': + instr_ir, extra_ir = mn_do_store(self, instr, *args) + elif instr.name[0:4] == 'SUBF': + if instr.name[0:5] == 'SUBFZ': + last_arg = ExprInt(0) + elif instr.name[0:5] == 'SUBFM': + last_arg = ExprInt(0xFFFFFFFF) + else: + last_arg = args[2] + instr_ir, extra_ir = mn_do_sub(self, instr, args[0], args[1], + last_arg) + elif instr.name[0:3] == 'XOR': + instr_ir, extra_ir = mn_do_xor(self, instr, *args) + else: + instr_ir, extra_ir = sem_dir[instr.name](self, instr, *args) + + return instr_ir, extra_ir + + def get_next_instr(self, instr): + l = self.symbol_pool.getby_offset_create(instr.offset + 4) + return l + + def get_next_break_label(self, instr): + l = self.symbol_pool.getby_offset_create(instr.offset + 4) + return l diff --git a/miasm2/jitter/Makefile b/miasm2/jitter/Makefile index 7d43f28c..4bc96b0f 100644 --- a/miasm2/jitter/Makefile +++ b/miasm2/jitter/Makefile @@ -1,5 +1,5 @@ all: vm_mngr.so Jit_x86.so Jittcc.so - + vm_mngr.so: vm_mngr.c vm_mngr.h vm_mngr_py.c gcc -I /usr/include/python2.7 -shared -fPIC vm_mngr.c vm_mngr_py.c -o vm_mngr.so @@ -10,8 +10,11 @@ Jit_x86.so: arch/Jit_x86.c Jit_arm.so: arch/Jit_arm.c gcc -I /usr/include/python2.7 -shared -fPIC arch/Jit_arm.c -o arch/Jit_arm.so +Jit_ppc.so: arch/Jit_ppc.c + gcc -I /usr/include/python2.7 -shared -fPIC arch/Jit_ppc.c -o arch/Jit_ppc.so + Jittcc.so: Jittcc.c gcc -I /usr/include/python2.7 -shared -fPIC Jittcc.c -o Jittcc.so -ltcc clean: - rm vm_mngr.so Jittcc.so arch/Jit_x86.so \ No newline at end of file + rm vm_mngr.so Jittcc.so arch/Jit_x86.so arch/Jit_arm.so arch/Jit_ppc.so diff --git a/miasm2/jitter/arch/JitCore_ppc32.c b/miasm2/jitter/arch/JitCore_ppc32.c new file mode 100644 index 00000000..7ea5e88f --- /dev/null +++ b/miasm2/jitter/arch/JitCore_ppc32.c @@ -0,0 +1,373 @@ +#include <Python.h> +#include "structmember.h" +#include <stdint.h> +#include <inttypes.h> +#include "../queue.h" +#include "../vm_mngr.h" +#include "../vm_mngr_py.h" +#include "../JitCore.h" +#include "JitCore_ppc32.h" + +reg_dict gpreg_dict[] = { +#define JITCORE_PPC_REG_EXPAND(_name, _size) \ + { .name = #_name, .offset = offsetof(struct vm_cpu, _name) }, +#include "JitCore_ppc32_regs.h" +#undef JITCORE_PPC_REG_EXPAND +}; + +PyObject* cpu_get_gpreg(JitCpu* self) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + +#define JITCORE_PPC_REG_EXPAND(_name, _size) \ + get_reg(_name); +#include "JitCore_ppc32_regs.h" +#undef JITCORE_PPC_REG_EXPAND + + return dict; +} + + + +PyObject * +cpu_set_gpreg(JitCpu *self, PyObject *args) { + PyObject *dict; + PyObject *d_key, *d_value = NULL; + Py_ssize_t pos = 0; + uint64_t val; + unsigned int i; + + if (!PyArg_ParseTuple(args, "O", &dict)) + return NULL; + if(!PyDict_Check(dict)) + RAISE(PyExc_TypeError, "arg must be dict"); + + while(PyDict_Next(dict, &pos, &d_key, &d_value)) { + int found = 0; + + if(!PyString_Check(d_key)) + RAISE(PyExc_TypeError, "key must be str"); + + PyGetInt(d_value, val); + + for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ + if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name)) + continue; + *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; + found = 1; + break; + } + + if (found) + continue; + fprintf(stderr, "unknown key: %s\n", PyString_AsString(d_key)); + RAISE(PyExc_ValueError, "unknown reg"); + } + + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject * +cpu_init_regs(JitCpu *self) { + memset(self->cpu, 0, sizeof(struct vm_cpu)); + + Py_INCREF(Py_None); + return Py_None; +} + +static void +dump_gpreg(const char *name, uint32_t val, int *n) { + printf("%6s %.8" PRIX32"%c", name, val, (*n + 1) % 4 == 0? '\n':' '); + *n = (*n + 1) % 4; +} + +void +dump_gpregs(struct vm_cpu *vmcpu) { + int reg_num = 0; + +#define JITCORE_PPC_REG_EXPAND(_name, _size) \ + dump_gpreg(#_name, vmcpu->_name, ®_num); +#include "JitCore_ppc32_regs.h" +#undef JITCORE_PPC_REG_EXPAND + + if ((reg_num % 4) != 0) + putchar('\n'); +} + + +PyObject * +cpu_dump_gpregs(JitCpu *self, PyObject *args) { + + dump_gpregs(self->cpu); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject * +cpu_set_exception(JitCpu *self, PyObject *args) { + PyObject *item1; + uint64_t i; + + if (!PyArg_ParseTuple(args, "O", &item1)) + return NULL; + + PyGetInt(item1, i); + + ((struct vm_cpu *)self->cpu)->exception_flags = i; + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject * +cpu_get_exception(JitCpu *self, PyObject *args) { + return PyLong_FromUnsignedLongLong(((struct vm_cpu *)self->cpu)->exception_flags); +} + +static PyObject * +cpu_get_spr_access(JitCpu *self, PyObject *args) { + return PyLong_FromUnsignedLongLong(((struct vm_cpu *) self->cpu)->spr_access); +} + +void +check_automod(JitCpu *jitcpu, uint64_t addr, uint64_t size) { + PyObject *result; + + if (!(((VmMngr*)jitcpu->pyvm)->vm_mngr.exception_flags & EXCEPT_CODE_AUTOMOD)) + return; + result = PyObject_CallMethod(jitcpu->jitter, "automod_cb", "LL", addr, size); + Py_DECREF(result); +} + +void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) +{ + vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 8); +} + +void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) +{ + vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 16); +} + +void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) +{ + vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 32); +} + +void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) +{ + vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 64); +} + + + +PyObject * +vm_set_mem(JitCpu *self, PyObject *args) { + PyObject *py_addr; + PyObject *py_buffer; + Py_ssize_t py_length; + + char *buffer; + uint64_t size; + uint64_t addr; + int ret = 0x1337; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_buffer)) + return NULL; + + PyGetInt(py_addr, addr); + + if(!PyString_Check(py_buffer)) + RAISE(PyExc_TypeError,"arg must be str"); + + size = PyString_Size(py_buffer); + PyString_AsStringAndSize(py_buffer, &buffer, &py_length); + + ret = vm_write_mem(&(((VmMngr*)self->pyvm)->vm_mngr), addr, buffer, size); + if (ret < 0) + RAISE(PyExc_TypeError,"arg must be str"); + check_automod(self, addr, size*8); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyMemberDef JitCpu_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef JitCpu_methods[] = { + {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"}, + {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, + {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, + {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"}, + {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"}, + {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, "X"}, + {"get_spr_access", (PyCFunction)cpu_get_spr_access, METH_VARARGS, "X"}, + {"set_mem", (PyCFunction)vm_set_mem, METH_VARARGS, "X"}, + {"get_mem", (PyCFunction)vm_get_mem, METH_VARARGS, "X"}, + {NULL} /* Sentinel */ +}; + +static int +JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) { + self->cpu = malloc(sizeof(struct vm_cpu)); + if (self->cpu == NULL) { + fprintf(stderr, "cannot alloc struct vm_cpu\n"); + exit(1); + } + return 0; +} + + +#define JITCORE_PPC_REG_EXPAND(_name, _size) \ +getset_reg_u32(_name); +#include "JitCore_ppc32_regs.h" +#undef JITCORE_PPC_REG_EXPAND + +PyObject * +get_gpreg_offset_all(void) { + PyObject *dict = PyDict_New(); + PyObject *o; + +#define JITCORE_PPC_REG_EXPAND(_name, _size) \ + get_reg_off(_name); +#include "JitCore_ppc32_regs.h" +#undef JITCORE_PPC_REG_EXPAND + + return dict; +} + +int32_t +idiv32(struct vm_cpu *cpu, int32_t a, int32_t b) { + if (b == 0) + return 0; + + return a / b; +} + +uint32_t +udiv32(struct vm_cpu *cpu, uint32_t a, uint32_t b) { + if (b == 0) + return 0; + + return a / b; +} + +int32_t +imod32(struct vm_cpu *cpu, int32_t a, int32_t b) { + if (b == 0) + return 0; + + return a % b; +} + +uint32_t +umod32(struct vm_cpu *cpu, uint32_t a, uint32_t b) { + if (b == 0) + return 0; + + return a % b; +} + +static PyGetSetDef JitCpu_getseters[] = { + {"vmmngr", + (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, + "vmmngr", + NULL}, + + {"jitter", + (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, + "jitter", + NULL}, + +#define JITCORE_PPC_REG_EXPAND(_name, _size) \ + { #_name, (getter) JitCpu_get_ ## _name , \ + (setter) JitCpu_set_ ## _name , #_name , NULL}, +#include "JitCore_ppc32_regs.h" +#undef JITCORE_PPC_REG_EXPAND + + {NULL} /* Sentinel */ +}; + + +static PyTypeObject JitCpuType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "JitCore_ppc.JitCpu", /*tp_name*/ + sizeof(JitCpu), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)JitCpu_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "JitCpu objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + JitCpu_methods, /* tp_methods */ + JitCpu_members, /* tp_members */ + JitCpu_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)JitCpu_init, /* tp_init */ + 0, /* tp_alloc */ + JitCpu_new, /* tp_new */ +}; + + + +static PyMethodDef JitCore_ppc_Methods[] = { + {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +static PyObject *JitCore_ppc32_Error; + +PyMODINIT_FUNC +initJitCore_ppc32(void) +{ + PyObject *m; + + if (PyType_Ready(&JitCpuType) < 0) + return; + + m = Py_InitModule("JitCore_ppc32", JitCore_ppc_Methods); + if (m == NULL) + return; + + JitCore_ppc32_Error = PyErr_NewException("JitCore_ppc32.error", NULL, NULL); + Py_INCREF(JitCore_ppc32_Error); + PyModule_AddObject(m, "error", JitCore_ppc32_Error); + + Py_INCREF(&JitCpuType); + PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType); + +} + diff --git a/miasm2/jitter/arch/JitCore_ppc32.h b/miasm2/jitter/arch/JitCore_ppc32.h new file mode 100644 index 00000000..18cee358 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_ppc32.h @@ -0,0 +1,24 @@ +/* + * _size can't be used yet because all register accesses are homogeneously + * 32-bit + */ +struct vm_cpu { +#define JITCORE_PPC_REG_EXPAND(_name, _size) \ + uint32_t _name; +#include "JitCore_ppc32_regs.h" +#undef JITCORE_PPC_REG_EXPAND + + uint64_t exception_flags; + uint32_t spr_access; + uint32_t reserve; + uint32_t reserve_address; +}; + +int32_t idiv32(struct vm_cpu *, int32_t, int32_t); +uint32_t udiv32(struct vm_cpu *, uint32_t, uint32_t); +int32_t imod32(struct vm_cpu *, int32_t, int32_t); +uint32_t umod32(struct vm_cpu *, uint32_t, uint32_t); + +void dump_gpregs(struct vm_cpu *); + +typedef struct vm_cpu vm_cpu_t; diff --git a/miasm2/jitter/arch/JitCore_ppc32_regs.h b/miasm2/jitter/arch/JitCore_ppc32_regs.h new file mode 100644 index 00000000..d15b5e51 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_ppc32_regs.h @@ -0,0 +1,89 @@ +JITCORE_PPC_REG_EXPAND(R0, 32) +JITCORE_PPC_REG_EXPAND(R1, 32) +JITCORE_PPC_REG_EXPAND(R2, 32) +JITCORE_PPC_REG_EXPAND(R3, 32) +JITCORE_PPC_REG_EXPAND(R4, 32) +JITCORE_PPC_REG_EXPAND(R5, 32) +JITCORE_PPC_REG_EXPAND(R6, 32) +JITCORE_PPC_REG_EXPAND(R7, 32) +JITCORE_PPC_REG_EXPAND(R8, 32) +JITCORE_PPC_REG_EXPAND(R9, 32) +JITCORE_PPC_REG_EXPAND(R10, 32) +JITCORE_PPC_REG_EXPAND(R11, 32) +JITCORE_PPC_REG_EXPAND(R12, 32) +JITCORE_PPC_REG_EXPAND(R13, 32) +JITCORE_PPC_REG_EXPAND(R14, 32) +JITCORE_PPC_REG_EXPAND(R15, 32) +JITCORE_PPC_REG_EXPAND(R16, 32) +JITCORE_PPC_REG_EXPAND(R17, 32) +JITCORE_PPC_REG_EXPAND(R18, 32) +JITCORE_PPC_REG_EXPAND(R19, 32) +JITCORE_PPC_REG_EXPAND(R20, 32) +JITCORE_PPC_REG_EXPAND(R21, 32) +JITCORE_PPC_REG_EXPAND(R22, 32) +JITCORE_PPC_REG_EXPAND(R23, 32) +JITCORE_PPC_REG_EXPAND(R24, 32) +JITCORE_PPC_REG_EXPAND(R25, 32) +JITCORE_PPC_REG_EXPAND(R26, 32) +JITCORE_PPC_REG_EXPAND(R27, 32) +JITCORE_PPC_REG_EXPAND(R28, 32) +JITCORE_PPC_REG_EXPAND(R29, 32) +JITCORE_PPC_REG_EXPAND(R30, 32) +JITCORE_PPC_REG_EXPAND(R31, 32) + +JITCORE_PPC_REG_EXPAND(PC, 32) +JITCORE_PPC_REG_EXPAND(LR, 32) +JITCORE_PPC_REG_EXPAND(CTR, 32) +JITCORE_PPC_REG_EXPAND(MSR, 32) + +JITCORE_PPC_REG_EXPAND(XER_SO, 32) +JITCORE_PPC_REG_EXPAND(XER_OV, 32) +JITCORE_PPC_REG_EXPAND(XER_CA, 32) +JITCORE_PPC_REG_EXPAND(XER_BC, 32) + +JITCORE_PPC_REG_EXPAND(CR0_LT, 8) +JITCORE_PPC_REG_EXPAND(CR0_GT, 8) +JITCORE_PPC_REG_EXPAND(CR0_EQ, 8) +JITCORE_PPC_REG_EXPAND(CR0_SO, 8) +JITCORE_PPC_REG_EXPAND(CR1_LT, 8) +JITCORE_PPC_REG_EXPAND(CR1_GT, 8) +JITCORE_PPC_REG_EXPAND(CR1_EQ, 8) +JITCORE_PPC_REG_EXPAND(CR1_SO, 8) +JITCORE_PPC_REG_EXPAND(CR2_LT, 8) +JITCORE_PPC_REG_EXPAND(CR2_GT, 8) +JITCORE_PPC_REG_EXPAND(CR2_EQ, 8) +JITCORE_PPC_REG_EXPAND(CR2_SO, 8) +JITCORE_PPC_REG_EXPAND(CR3_LT, 8) +JITCORE_PPC_REG_EXPAND(CR3_GT, 8) +JITCORE_PPC_REG_EXPAND(CR3_EQ, 8) +JITCORE_PPC_REG_EXPAND(CR3_SO, 8) +JITCORE_PPC_REG_EXPAND(CR4_LT, 8) +JITCORE_PPC_REG_EXPAND(CR4_GT, 8) +JITCORE_PPC_REG_EXPAND(CR4_EQ, 8) +JITCORE_PPC_REG_EXPAND(CR4_SO, 8) +JITCORE_PPC_REG_EXPAND(CR5_LT, 8) +JITCORE_PPC_REG_EXPAND(CR5_GT, 8) +JITCORE_PPC_REG_EXPAND(CR5_EQ, 8) +JITCORE_PPC_REG_EXPAND(CR5_SO, 8) +JITCORE_PPC_REG_EXPAND(CR6_LT, 8) +JITCORE_PPC_REG_EXPAND(CR6_GT, 8) +JITCORE_PPC_REG_EXPAND(CR6_EQ, 8) +JITCORE_PPC_REG_EXPAND(CR6_SO, 8) +JITCORE_PPC_REG_EXPAND(CR7_LT, 8) +JITCORE_PPC_REG_EXPAND(CR7_GT, 8) +JITCORE_PPC_REG_EXPAND(CR7_EQ, 8) +JITCORE_PPC_REG_EXPAND(CR7_SO, 8) + +JITCORE_PPC_REG_EXPAND(SPRG0, 32) +JITCORE_PPC_REG_EXPAND(SPRG1, 32) +JITCORE_PPC_REG_EXPAND(SPRG2, 32) +JITCORE_PPC_REG_EXPAND(SPRG3, 32) +JITCORE_PPC_REG_EXPAND(SRR0, 32) +JITCORE_PPC_REG_EXPAND(SRR1, 32) +JITCORE_PPC_REG_EXPAND(DAR, 32) +JITCORE_PPC_REG_EXPAND(DSISR, 32) +JITCORE_PPC_REG_EXPAND(PIR, 32) +JITCORE_PPC_REG_EXPAND(PVR, 32) +JITCORE_PPC_REG_EXPAND(DEC, 32) +JITCORE_PPC_REG_EXPAND(TBL, 32) +JITCORE_PPC_REG_EXPAND(TBU, 32) diff --git a/miasm2/jitter/csts.py b/miasm2/jitter/csts.py index 8efd5626..56179c92 100644 --- a/miasm2/jitter/csts.py +++ b/miasm2/jitter/csts.py @@ -8,6 +8,7 @@ EXCEPT_NUM_UPDT_EIP = (1<<11) EXCEPT_CODE_AUTOMOD = (1 << 0) EXCEPT_SOFT_BP = (1 << 1) EXCEPT_INT_XX = (1 << 2) +EXCEPT_SPR_ACCESS = (1 << 3) EXCEPT_BREAKPOINT_INTERN = (1 << 10) EXCEPT_ACCESS_VIOL = ((1 << 14) | EXCEPT_DO_NOT_UPDATE_PC) diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index ff7ba215..7a3acb2c 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -157,7 +157,7 @@ class ExceptionHandle(): return (self.except_flag == to_cmp.except_flag) -class jitter: +class jitter(object): "Main class for JIT handling" @@ -188,6 +188,8 @@ class jitter: from miasm2.jitter.arch import JitCore_msp430 as jcore elif arch_name == "mips32": from miasm2.jitter.arch import JitCore_mips32 as jcore + elif arch_name == "ppc32": + from miasm2.jitter.arch import JitCore_ppc32 as jcore else: raise ValueError("unknown jit arch: %s" % arch_name) except ImportError: diff --git a/setup.py b/setup.py index 03999108..e6851364 100755 --- a/setup.py +++ b/setup.py @@ -14,6 +14,7 @@ def buil_all(): 'miasm2/arch/msp430', 'miasm2/arch/sh4', 'miasm2/arch/mips32', + 'miasm2/arch/ppc', 'miasm2/core', 'miasm2/expression', 'miasm2/ir', @@ -48,6 +49,12 @@ def buil_all(): ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/arch/JitCore_mips32.c"]), + Extension("miasm2.jitter.arch.JitCore_ppc32", + ["miasm2/jitter/JitCore.c", + "miasm2/jitter/vm_mngr.c", + "miasm2/jitter/arch/JitCore_ppc32.c"], + depends=["miasm2/jitter/arch/JitCore_ppc32.h", + "miasm2/jitter/arch/JitCore_ppc32_regs.h"]), Extension("miasm2.jitter.Jitgcc", ["miasm2/jitter/Jitgcc.c"]), Extension("miasm2.jitter.Jitllvm", @@ -78,6 +85,12 @@ def buil_all(): ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/arch/JitCore_mips32.c"]), + Extension("miasm2.jitter.arch.JitCore_ppc32", + ["miasm2/jitter/JitCore.c", + "miasm2/jitter/vm_mngr.c", + "miasm2/jitter/arch/JitCore_ppc32.c"], + depends=["miasm2/jitter/arch/JitCore_ppc32.h", + "miasm2/jitter/arch/JitCore_ppc32_regs.h"]), Extension("miasm2.jitter.Jitllvm", ["miasm2/jitter/Jitllvm.c"]), Extension("miasm2.jitter.Jitgcc", |