about summary refs log tree commit diff stats
path: root/miasm2/arch/mips32
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/arch/mips32')
-rw-r--r--miasm2/arch/mips32/arch.py91
-rw-r--r--miasm2/arch/mips32/jit.py38
-rw-r--r--miasm2/arch/mips32/regs.py13
-rw-r--r--miasm2/arch/mips32/sem.py42
4 files changed, 133 insertions, 51 deletions
diff --git a/miasm2/arch/mips32/arch.py b/miasm2/arch/mips32/arch.py
index 3abdc053..15c59cf0 100644
--- a/miasm2/arch/mips32/arch.py
+++ b/miasm2/arch/mips32/arch.py
@@ -5,11 +5,13 @@ from collections import defaultdict
 
 from pyparsing import Literal, Group, Optional
 
-from miasm2.expression.expression import ExprMem, ExprInt, ExprId
+from miasm2.expression.expression import ExprMem, ExprInt, ExprId, ExprOp
 from miasm2.core.bin_stream import bin_stream
 import miasm2.arch.mips32.regs as regs
 import miasm2.core.cpu as cpu
 
+from miasm2.core.asm_ast import AstInt, AstId, AstMem, AstOp
+
 log = logging.getLogger("mips32dis")
 console_handler = logging.StreamHandler()
 console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
@@ -20,48 +22,26 @@ log.setLevel(logging.DEBUG)
 gpregs = cpu.reg_info(regs.regs32_str, regs.regs32_expr)
 
 
-
 LPARENTHESIS = Literal("(")
 RPARENTHESIS = Literal(")")
 
-def deref2expr(s, l, t):
-    t = t[0]
-    if len(t) != 4:
+def cb_deref(tokens):
+    if len(tokens) != 4:
         raise NotImplementedError("TODO")
+    return AstMem(tokens[2] + tokens[0], 32)
 
-    return ExprMem(t[2] + t[0], 32)
-
-def deref2expr_nooff(s, l, t):
-    t = t[0]
-    if len(t) != 3:
+def cb_deref_nooff(tokens):
+    if len(tokens) != 3:
         raise NotImplementedError("TODO")
-    return ExprMem(t[1], 32)
+    return AstMem(tokens[1], 32)
 
 base_expr = cpu.base_expr
 
-deref_off = Group(Optional(cpu.base_expr) + LPARENTHESIS + gpregs.parser + \
-                      RPARENTHESIS).setParseAction(deref2expr)
-deref_nooff = Group(LPARENTHESIS + gpregs.parser + \
-                        RPARENTHESIS).setParseAction(deref2expr_nooff)
+deref_off = (Optional(base_expr) + LPARENTHESIS + gpregs.parser + RPARENTHESIS).setParseAction(cb_deref)
+deref_nooff = (LPARENTHESIS + gpregs.parser + RPARENTHESIS).setParseAction(cb_deref_nooff)
 deref = deref_off | deref_nooff
 
 
-variable, operand, base_expr = cpu.gen_base_expr()
-
-int_or_expr = base_expr
-
-
-def ast_id2expr(t):
-    return mn_mips32.regs.all_regs_ids_byname.get(t, t)
-
-
-def ast_int2expr(a):
-    return ExprInt(a, 32)
-
-
-my_var_parser = cpu.ParseAst(ast_id2expr, ast_int2expr)
-base_expr.setParseAction(my_var_parser)
-
 class additional_info:
     def __init__(self):
         self.except_on_instr = False
@@ -274,8 +254,31 @@ def mips32op(name, fields, args=None, alias=False):
     type(name, (mn_mips32,), dct)
     #type(name, (mn_mips32b,), dct)
 
-
-class mips32_reg(cpu.reg_noarg, cpu.m_arg):
+class mips32_arg(cpu.m_arg):
+    def asm_ast_to_expr(self, arg, symbol_pool):
+        if isinstance(arg, AstId):
+            if isinstance(arg.name, ExprId):
+                return arg.name
+            if arg.name in gpregs.str:
+                return None
+            label = symbol_pool.getby_name_create(arg.name)
+            return ExprId(label, 32)
+        if isinstance(arg, AstOp):
+            args = [self.asm_ast_to_expr(tmp, symbol_pool) for tmp in arg.args]
+            if None in args:
+                return None
+            return ExprOp(arg.op, *args)
+        if isinstance(arg, AstInt):
+            return ExprInt(arg.value, 32)
+        if isinstance(arg, AstMem):
+            ptr = self.asm_ast_to_expr(arg.ptr, symbol_pool)
+            if ptr is None:
+                return None
+            return ExprMem(ptr, arg.size)
+        return None
+
+
+class mips32_reg(cpu.reg_noarg, mips32_arg):
     pass
 
 class mips32_gpreg(mips32_reg):
@@ -335,14 +338,14 @@ class mips32_soff_noarg(mips32_imm):
         return True
 
 
-class mips32_s16imm(mips32_s16imm_noarg, cpu.m_arg):
+class mips32_s16imm(mips32_s16imm_noarg, mips32_arg):
     pass
 
-class mips32_soff(mips32_soff_noarg, cpu.m_arg):
+class mips32_soff(mips32_soff_noarg, mips32_arg):
     pass
 
 
-class mips32_instr_index(mips32_imm, cpu.m_arg):
+class mips32_instr_index(mips32_imm, mips32_arg):
     def decode(self, v):
         v = v & self.lmask
         self.expr = ExprInt(v<<2, 32)
@@ -361,7 +364,7 @@ class mips32_instr_index(mips32_imm, cpu.m_arg):
         return True
 
 
-class mips32_u16imm(mips32_imm, cpu.m_arg):
+class mips32_u16imm(mips32_imm, mips32_arg):
     def decode(self, v):
         v = v & self.lmask
         self.expr = ExprInt(v, 32)
@@ -375,7 +378,7 @@ class mips32_u16imm(mips32_imm, cpu.m_arg):
         self.value = v
         return True
 
-class mips32_dreg_imm(cpu.m_arg):
+class mips32_dreg_imm(mips32_arg):
     parser = deref
     def decode(self, v):
         imm = self.parent.imm.expr
@@ -408,7 +411,7 @@ class mips32_dreg_imm(cpu.m_arg):
         assert(len(arg.args) == 2 and arg.op == '+')
         return "%s(%s)"%(arg.args[1], arg.args[0])
 
-class mips32_esize(mips32_imm, cpu.m_arg):
+class mips32_esize(mips32_imm, mips32_arg):
     def decode(self, v):
         v = v & self.lmask
         self.expr = ExprInt(v+1, 32)
@@ -422,7 +425,7 @@ class mips32_esize(mips32_imm, cpu.m_arg):
         self.value = v
         return True
 
-class mips32_eposh(mips32_imm, cpu.m_arg):
+class mips32_eposh(mips32_imm, mips32_arg):
     def decode(self, v):
         self.expr = ExprInt(v-int(self.parent.epos.expr)+1, 32)
         return True
@@ -437,7 +440,7 @@ class mips32_eposh(mips32_imm, cpu.m_arg):
 
 
 
-class mips32_cpr(cpu.m_arg):
+class mips32_cpr(mips32_arg):
     parser = regs.regs_cpr0_info.parser
     def decode(self, v):
         index = int(self.parent.cpr0.expr) << 3
@@ -605,6 +608,8 @@ bs_bcc = cpu.bs_name(l=5, name = {"BGEZ":    0b00001,
                                   })
 
 
+bs_code = cpu.bs(l=10)
+
 
 mips32op("addi",    [cpu.bs('001000'), rs, rt, s16imm], [rt, rs, s16imm])
 mips32op("addiu",   [cpu.bs('001001'), rs, rt, s16imm], [rt, rs, s16imm])
@@ -740,3 +745,7 @@ mips32op("tlbp",    [cpu.bs('010000'), cpu.bs('1'), cpu.bs('0'*19),
                      cpu.bs('001000')])
 mips32op("tlbwi",   [cpu.bs('010000'), cpu.bs('1'), cpu.bs('0'*19),
                      cpu.bs('000010')])
+
+
+mips32op("teq",     [cpu.bs('000000'), rs, rt, bs_code, cpu.bs('110100')],
+         [rs, rt])
diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py
index 1d2ec483..16d88067 100644
--- a/miasm2/arch/mips32/jit.py
+++ b/miasm2/arch/mips32/jit.py
@@ -1,6 +1,6 @@
 import logging
 
-from miasm2.jitter.jitload import jitter
+from miasm2.jitter.jitload import jitter, named_arguments
 from miasm2.core import asmblock
 from miasm2.core.utils import pck32, upck32
 from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b
@@ -104,6 +104,42 @@ class jitter_mips32l(jitter):
         jitter.init_run(self, *args, **kwargs)
         self.cpu.PC = self.pc
 
+    # calling conventions
+
+    @named_arguments
+    def func_args_stdcall(self, n_args):
+        args = [self.get_arg_n_stdcall(i) for i in xrange(n_args)]
+        ret_ad = self.cpu.RA
+        return ret_ad, args
+
+    def func_ret_stdcall(self, ret_addr, ret_value1=None, ret_value2=None):
+        self.pc = self.cpu.PC = ret_addr
+        if ret_value1 is not None:
+            self.cpu.V0 = ret_value1
+        if ret_value2 is not None:
+            self.cpu.V1 = ret_value2
+        return True
+
+    def func_prepare_stdcall(self, ret_addr, *args):
+        for index in xrange(min(len(args), 4)):
+            setattr(self.cpu, 'A%d' % index, args[index])
+        for index in xrange(4, len(args)):
+            self.vm.set_mem(self.cpu.SP + 4 * (index - 4), pck32(args[index]))
+        self.cpu.RA = ret_addr
+
+    def get_arg_n_stdcall(self, index):
+        if index < 4:
+            arg = getattr(self.cpu, 'A%d' % index)
+        else:
+            arg = self.get_stack_arg(index-4)
+        return arg
+
+
+    func_args_systemv = func_args_stdcall
+    func_ret_systemv = func_ret_stdcall
+    func_prepare_systemv = func_prepare_stdcall
+    get_arg_n_systemv = get_arg_n_stdcall
+
 
 class jitter_mips32b(jitter_mips32l):
 
diff --git a/miasm2/arch/mips32/regs.py b/miasm2/arch/mips32/regs.py
index afade869..7ff949f2 100644
--- a/miasm2/arch/mips32/regs.py
+++ b/miasm2/arch/mips32/regs.py
@@ -4,11 +4,11 @@ from miasm2.expression.expression import ExprId
 from miasm2.core.cpu import gen_reg, gen_regs
 
 
-gen_reg('PC', globals())
-gen_reg('PC_FETCH', globals())
+PC, _ = gen_reg('PC')
+PC_FETCH, _ = gen_reg('PC_FETCH')
 
-gen_reg('R_LO', globals())
-gen_reg('R_HI', globals())
+R_LO, _ = gen_reg('R_LO')
+R_HI, _ = gen_reg('R_HI')
 
 exception_flags = ExprId('exception_flags', 32)
 
@@ -55,11 +55,10 @@ regs_flt_expr, regs_flt_init, fltregs = gen_regs(regs_flt_str, globals(), sz=64)
 regs_fcc_expr, regs_fcc_init, fccregs = gen_regs(regs_fcc_str, globals())
 
 
-all_regs_ids = [PC, PC_FETCH, R_LO, R_HI] + gpregs_expr + regs_flt_expr + \
+all_regs_ids = [PC, PC_FETCH, R_LO, R_HI, exception_flags] + gpregs_expr + regs_flt_expr + \
     regs_fcc_expr + regs_cpr0_expr
 all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids])
-all_regs_ids_init = [PC_init, PC_FETCH_init, R_LO_init, R_HI_init] + \
-    gpregs_init + regs_flt_init + regs_fcc_init + regs_cpr0_init
+all_regs_ids_init = [ExprId("%s_init" % reg.name, reg.size) for reg in all_regs_ids]
 all_regs_ids_no_alias = all_regs_ids[:]
 
 attrib_to_regs = {
diff --git a/miasm2/arch/mips32/sem.py b/miasm2/arch/mips32/sem.py
index 789491f6..99c81a33 100644
--- a/miasm2/arch/mips32/sem.py
+++ b/miasm2/arch/mips32/sem.py
@@ -1,8 +1,9 @@
 import miasm2.expression.expression as m2_expr
-from miasm2.ir.ir import IntermediateRepresentation, IRBlock
+from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock
 from miasm2.arch.mips32.arch import mn_mips32
-from miasm2.arch.mips32.regs import R_LO, R_HI, PC, RA
+from miasm2.arch.mips32.regs import R_LO, R_HI, PC, RA, exception_flags
 from miasm2.core.sembuilder import SemBuilder
+from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO
 
 
 # SemBuilder context
@@ -377,6 +378,18 @@ def multu(arg1, arg2):
     R_HI = result[32:]
 
 @sbuild.parse
+def div(arg1, arg2):
+    """Divide (signed) @arg1 by @arg2 and stores the remaining/result in $R_HI/$R_LO"""
+    R_LO = ExprOp('idiv' ,arg1, arg2)
+    R_HI = ExprOp('imod', arg1, arg2)
+
+@sbuild.parse
+def divu(arg1, arg2):
+    """Divide (unsigned) @arg1 by @arg2 and stores the remaining/result in $R_HI/$R_LO"""
+    R_LO = ExprOp('udiv', arg1, arg2)
+    R_HI = ExprOp('umod', arg1, arg2)
+
+@sbuild.parse
 def mfhi(arg1):
     "The contents of register $R_HI are moved to the specified register @arg1."
     arg1 = R_HI
@@ -398,6 +411,30 @@ def ei(arg1):
 def ehb(arg1):
     "NOP"
 
+
+def teq(ir, instr, arg1, arg2):
+    e = []
+
+    lbl_except, lbl_except_expr = ir.gen_label_and_expr(ir.IRDst.size)
+    lbl_next = ir.get_next_label(instr)
+    lbl_next_expr = m2_expr.ExprId(lbl_next, ir.IRDst.size)
+
+    do_except = []
+    do_except.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(
+        EXCEPT_DIV_BY_ZERO, exception_flags.size)))
+    do_except.append(m2_expr.ExprAff(ir.IRDst, lbl_next_expr))
+    blk_except = IRBlock(lbl_except, [AssignBlock(do_except, instr)])
+
+    cond = arg1 - arg2
+
+
+    e = []
+    e.append(m2_expr.ExprAff(ir.IRDst,
+                             m2_expr.ExprCond(cond, lbl_next_expr, lbl_except_expr)))
+
+    return e, [blk_except]
+
+
 mnemo_func = sbuild.functions
 mnemo_func.update({
         'add.d': add_d,
@@ -423,6 +460,7 @@ mnemo_func.update({
         'subu': l_sub,
         'xor': l_xor,
         'xori': l_xor,
+        'teq': teq,
 })
 
 def get_mnemo_expr(ir, instr, *args):