about summary refs log tree commit diff stats
path: root/src/miasm/arch/mips32/jit.py
diff options
context:
space:
mode:
authorTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-10-14 09:09:29 +0000
committerTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-10-14 09:09:29 +0000
commit579cf1d03fb932083e6317967d1613d5c2587fb6 (patch)
tree629f039935382a2a7391bce9253f6c9968159049 /src/miasm/arch/mips32/jit.py
parent51c15d3ea2e16d4fc5f0f01a3b9befc66b1f982e (diff)
downloadmiasm-579cf1d03fb932083e6317967d1613d5c2587fb6.tar.gz
miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.zip
Convert to src-layout ta/nix
Diffstat (limited to 'src/miasm/arch/mips32/jit.py')
-rw-r--r--src/miasm/arch/mips32/jit.py160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/miasm/arch/mips32/jit.py b/src/miasm/arch/mips32/jit.py
new file mode 100644
index 00000000..a4d8a193
--- /dev/null
+++ b/src/miasm/arch/mips32/jit.py
@@ -0,0 +1,160 @@
+from builtins import range
+import logging
+
+from miasm.jitter.jitload import Jitter, named_arguments
+from miasm.core.locationdb import LocationDB
+from miasm.core.utils import pck32, upck32
+from miasm.arch.mips32.sem import Lifter_Mips32l, Lifter_Mips32b
+from miasm.jitter.codegen import CGen
+from miasm.ir.ir import AssignBlock, IRBlock
+import miasm.expression.expression as m2_expr
+
+log = logging.getLogger('jit_mips32')
+hnd = logging.StreamHandler()
+hnd.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s"))
+log.addHandler(hnd)
+log.setLevel(logging.CRITICAL)
+
+
+class mipsCGen(CGen):
+    CODE_INIT = CGen.CODE_INIT + r"""
+    unsigned int branch_dst_pc;
+    unsigned int branch_dst_irdst;
+    unsigned int branch_dst_set=0;
+    """
+
+    CODE_RETURN_NO_EXCEPTION = r"""
+    %s:
+    if (branch_dst_set) {
+        %s = %s;
+        BlockDst->address = %s;
+    } else {
+        BlockDst->address = %s;
+    }
+    return JIT_RET_NO_EXCEPTION;
+    """
+
+    def __init__(self, lifter):
+        super(mipsCGen, self).__init__(lifter)
+        self.delay_slot_dst = m2_expr.ExprId("branch_dst_irdst", 32)
+        self.delay_slot_set = m2_expr.ExprId("branch_dst_set", 32)
+
+    def block2assignblks(self, block):
+        irblocks_list = super(mipsCGen, self).block2assignblks(block)
+        for irblocks in irblocks_list:
+            for blk_idx, irblock in enumerate(irblocks):
+                has_breakflow = any(assignblock.instr.breakflow() for assignblock in irblock)
+                if not has_breakflow:
+                    continue
+
+                irs = []
+                for assignblock in irblock:
+                    if self.lifter.pc not in assignblock:
+                        irs.append(AssignBlock(assignments, assignblock.instr))
+                        continue
+                    assignments = dict(assignblock)
+                    # Add internal branch destination
+                    assignments[self.delay_slot_dst] = assignblock[
+                        self.lifter.pc]
+                    assignments[self.delay_slot_set] = m2_expr.ExprInt(1, 32)
+                    # Replace IRDst with next instruction
+                    dst_loc_key = self.lifter.get_next_instr(assignblock.instr)
+                    assignments[self.lifter.IRDst] = m2_expr.ExprLoc(dst_loc_key, 32)
+                    irs.append(AssignBlock(assignments, assignblock.instr))
+                irblocks[blk_idx] = IRBlock(irblock.loc_db, irblock.loc_key, irs)
+
+        return irblocks_list
+
+    def gen_finalize(self, block):
+        """
+        Generate the C code for the final block instruction
+        """
+
+        loc_key = self.get_block_post_label(block)
+        offset = self.lifter.loc_db.get_location_offset(loc_key)
+        out = (self.CODE_RETURN_NO_EXCEPTION % (loc_key,
+                                                self.C_PC,
+                                                m2_expr.ExprId('branch_dst_irdst', 32),
+                                                m2_expr.ExprId('branch_dst_irdst', 32),
+                                                self.id_to_c(m2_expr.ExprInt(offset, 32)))
+              ).split('\n')
+        return out
+
+
+class jitter_mips32l(Jitter):
+
+    C_Gen = mipsCGen
+
+    def __init__(self, loc_db, *args, **kwargs):
+        Jitter.__init__(self, Lifter_Mips32l(loc_db), *args, **kwargs)
+        self.vm.set_little_endian()
+
+    def push_uint32_t(self, value):
+        self.cpu.SP -= 4
+        self.vm.set_mem(self.cpu.SP, pck32(value))
+
+    def pop_uint32_t(self):
+        value = self.vm.get_u32(self.cpu.SP)
+        self.cpu.SP += 4
+        return value
+
+    def get_stack_arg(self, index):
+        return self.vm.get_u32(self.cpu.SP + 4 * index)
+
+    def init_run(self, *args, **kwargs):
+        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 range(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 range(min(len(args), 4)):
+            setattr(self.cpu, 'A%d' % index, args[index])
+        for index in range(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
+
+    def syscall_args_systemv(self, n_args):
+        # Documentation: http://man7.org/linux/man-pages/man2/syscall.2.html
+        # mips/o32      a0    a1    a2    a3    stack
+        args = [self.get_arg_n_stdcall(i) for i in range(n_args)]
+        return args
+
+    def syscall_ret_systemv(self, value1, value2, error):
+        # Documentation: http://man7.org/linux/man-pages/man2/syscall.2.html
+        self.cpu.V0 = value1
+        self.cpu.V1 = value2
+        self.cpu.A3 = error  # 0 -> no error, -1 -> error
+
+    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):
+
+    def __init__(self, loc_db, *args, **kwargs):
+        Jitter.__init__(self, Lifter_Mips32b(loc_db), *args, **kwargs)
+        self.vm.set_big_endian()