# Toshiba MeP-c4 - miasm instructions side effects # Guillaume Valadon from miasm2.core.sembuilder import SemBuilder from miasm2.ir.ir import IntermediateRepresentation from miasm2.arch.mep.arch import mn_mep from miasm2.arch.mep.regs import PC, SP, LP, SAR, TP, RPB, RPE, RPC, EPC, NPC, \ take_jmp, in_erepeat from miasm2.arch.mep.regs import EXC, HI, LO, PSW, DEPC, DBG from miasm2.expression.expression import ExprId, ExprInt, ExprOp from miasm2.expression.expression import ExprAff, ExprCond, ExprMem from miasm2.core.cpu import sign_ext from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO from miasm2.arch.mep.regs import exception_flags def compute_s_inf(arg1, arg2): """Signed comparison operator""" return ((arg1 - arg2) ^ ((arg1 ^ arg2) & ((arg1 - arg2) ^ arg1))).msb() def compute_u_inf(x, y): """Unsigned comparison operator""" result = (((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y).msb() return result # SemBuilder context ctx = {"PC": PC, "SP": SP, "LP": LP, "SAR": SAR, "TP": TP, "RPB": RPB, "RPE": RPE, "RPC": RPC, "EPC": EPC, "NPC": NPC, "EXC": EXC, "HI": HI, "LO": LO, "PSW": PSW, "DEPC": DEPC, "DBG": DBG, "exception_flags": exception_flags, "compute_s_inf": compute_s_inf, "compute_u_inf": compute_u_inf, "take_jmp": take_jmp, "in_erepeat": in_erepeat, "EXCEPT_DIV_BY_ZERO": EXCEPT_DIV_BY_ZERO} sbuild = SemBuilder(ctx) # Functions used to get an instruction IR manual_functions = dict() @sbuild.parse def mep_nop(): """Dummy instruction""" @sbuild.parse def mep_nop_2_args(arg1, arg2): """Dummy instruction with two arguments""" ### Load/Store instructions # Register indirect addressing mode @sbuild.parse def sb(reg_src, deref_dst): """SB - Store Byte into memory""" # MemByte(Rm31..0) <- Rn7..0 # MemByte((ZeroExt(disp7)+TP)31..0)) <- Rn7..0 # MemByte((SignExt(disp16)+Rm)31..0) <- Rn7..0 mem8[deref_dst.arg] = reg_src[:8] @sbuild.parse def sh(reg_src, deref_dst): """SH - Store Halfword into memory""" # MemHword(Rm31..1||0) <- Rn15..0 # MemHword((ZeroExt((disp7)6..1||0)+TP)31..1||0)) <- Rn15..0 # MemHword((SignExt(disp16)+Rm)31..1||0) <- Rn15..0 mem16[deref_dst.arg & i32(0xFFFFFFFE)] = reg_src[:16] @sbuild.parse def sw(reg_src, deref_dst): """SW - Store Word into memory""" # MemWord(Rm31..2||00) <- Rn31..0 # MemWord((ZeroExt((disp7)6..2||00)+SP)31..2||00)) <- Rn31..0 # MemWord((ZeroExt((disp7)6..2||00)+TP)31..2||00)) <- Rn31..0 # MemWord((SignExt(disp16)+Rm)31..2||00) <- Rn31..0 # MemWord(ZeroExt((abs24)23..2||00)) - Rn31..0 mem32[deref_dst.arg & i32(0xFFFFFFFC)] = reg_src # Without the sembuilder #def sw(ir, instr, reg_src, deref_reg_or_imm, deref_reg=None): # """SW - store Word into memory. # # Note: there are three variants to get the memory address: # - from a register # - relatively to SP # - relatively to TP""" # # if isinstance(deref_reg_or_imm, ExprMem): # # MemWord(Rm31..2||00) <- Rn31..0 # dst = deref_reg_or_imm # # elif isinstance(deref_reg_or_imm, ExprInt) and deref_reg: # # MemWord((ZeroExt((disp7)6..2||00)+SP)31..2||00)) <- Rn31..0 # # MemWord((ZeroExt((disp7)6..2||00)+TP)31..2||00)) <- Rn31..0 # # imm = deref_reg_or_imm.zeroExtend(32) # dst = ExprMem(ExprOp("+", imm, deref_reg.arg)) # # return [ExprAff(dst, reg_src)], [] @sbuild.parse def lb(reg_dst, deref_dst): """LB - Load Byte from memory""" # Rn <- SignExt(MemByte(Rm31..0)) # Rn <- SignExt(MemByte((ZeroExt(disp7)+TP)31..0)) # Rn <- SignExt(MemByte((SignExt(disp16)+Rm)31..0) reg_dst = mem8[deref_dst.arg].signExtend(32) @sbuild.parse def lh(reg_dst, deref_dst): """LH - Load Halfword from memory""" # Rn <- SignExt(MemHword(Rm31..1||0)) # Rn <- SignExt(MemHword((ZeroExt((disp7)6..1||0)+TP)31..1||0) # Rn <- SignExt(MemHword((SignExt(disp16)+Rm)31..1||0)) reg_dst = mem16[deref_dst.arg & i32(0xFFFFFFFE)].signExtend(32) @sbuild.parse def lw(reg_dst, deref_dst): """LW - Load Word from memory""" # Rn <- MemWord(Rm31..2||00) # Rn <- MemWord((ZeroExt((disp7)6..2||00)+TP)31..2||00) # Rn <- MemWord((SignExt(disp16)+Rm)31..2||00) # Rn <- MemWord(ZeroExt((abs24)23..2||00)) reg_dst = mem32[deref_dst.arg & i32(0xFFFFFFFC)] @sbuild.parse def lbu(reg_dst, deref_dst): """LBU - Load an unsigned Byte from memory""" # Rn <- ZeroExt(MemByte(Rm31..0)) # Rn <- ZeroExt(MemByte((ZeroExt(disp7)+TP)31..0)) # Rn <- ZeroExt(MemByte((SignExt(disp16)+Rm)31..0)) reg_dst = mem8[deref_dst.arg].zeroExtend(32) @sbuild.parse def lhu(reg_dst, deref_dst): """LHU - Load an unsigned Halfword from memory""" # Rn <- ZeroExt(MemHword(Rm31..1||0)) # Rn <- ZeroExt(MemHword((SignExt(disp16)+Rm)31..1||0)) # Rn <- ZeroExt(MemHword((ZeroExt((disp7)6..1||0)+TP)31..1||0)) reg_dst = mem16[deref_dst.arg & i32(0xFFFFFFFE)].zeroExtend(32) ### Byte/Halfword extension instructions @sbuild.parse def extb(reg): """EXTB - Sign extend a byte""" # Rn <- SignExt(Rn7..0) reg = reg[:8].signExtend(32) @sbuild.parse def exth(reg): """EXTH - Sign extend a word""" # Rn <- ZeroExt(Rn15..0) reg = reg[:16].signExtend(32) @sbuild.parse def extub(reg): """EXUTB - Zero extend a byte""" # Rn <- SignExt(Rn7..0) reg = reg[:8].zeroExtend(32) @sbuild.parse def extuh(reg): """EXTUH - Zero extend a word""" # Rn <- ZeroExt(Rn15..0) reg = reg[:16].zeroExtend(32) ### Shift amount manipulation instructions #@sbuild.parse #def ssarb(deref_reg): ### Move instructions @sbuild.parse def mov(reg, value): """MOV - Copy 'value' to a register. The three alternatives are handled.""" # Rn <- Rm # Rn <- SignExt(imm8) # Rn <- SignExt(imm16) reg = value.signExtend(32) @sbuild.parse def movu(reg, value): """MOV - Copy 'value' to a register. The two alternatives are handled.""" # Rn[0-7] <- ZeroExt(imm24) # Rn <- ZeroExt(imm16) reg = value.zeroExtend(32) @sbuild.parse def movh(reg, imm16): """MOVH - Copy a shifted imm16 to a register.""" # Rn <- imm16 <<16 reg = imm16.zeroExtend(32) << i32(16) ### Arithmetic instructions def add3(ir, instr, reg_dst, reg_src, reg_or_imm): """ADD3 - Add two register and store the result to a register, or add a register and an immediate and store the result to a register""" if isinstance(reg_or_imm, ExprId): # Rl <- Rn + Rm result = ExprOp("+", reg_src, reg_or_imm) else: # Rn <- Rm + SignExt(imm16) value = int(reg_or_imm.arg) result = ExprOp("+", reg_src, ExprInt(value, 32)) return [ExprAff(reg_dst, result)], [] manual_functions["add3"] = add3 @sbuild.parse def add(arg1, arg2): """ADD - Add a register and an immediate.""" # Rn <- Rn + SignExt(imm6) arg1 = arg1 + arg2.signExtend(32) @sbuild.parse def advck3(r0, rn, rm): """ADVCK3 - Check addition overflow.""" # if(Overflow(Rn+Rm)) R0<-1 else R0<-0 (Signed) r0 = i32(1) if compute_u_inf(i64(0xFFFFFFFF), rn.zeroExtend(64) + rm.zeroExtend(64)) else i32(0) @sbuild.parse def sub(reg1, reg2): """SUB - Substract one register to another.""" # Rn <- Rn - Rm reg1 = reg1 - reg2 def sbvck3(ir, instr, r0, rn, rm): """SBVCK3 - Check substraction overflow""" # if(Overflow(Rn-Rm)) R0<-1 else R0<-0 (Signed) # Substract registers reg_sub = ExprOp("+", rn, rm) # Get the register storing the highest value max_rn_rm = ExprCond(ExprOp(">", rn, rm), rn, rm) # Check for an overflow overflow_test = ExprOp(">", reg_sub, max_rn_rm) # Return the result condition = ExprCond(overflow_test, ExprInt(1, 32), ExprInt(0, 32)) return [ExprAff(r0, condition)], [] manual_functions["sbvck3"] = sbvck3 @sbuild.parse def neg(reg1, reg2): """NEG - Negate one register.""" # Rn <- - Rm reg1 = - reg2 @sbuild.parse def slt3(r0, rn, rm_or_imm5): """SLT3 - Set on less than (signed).""" # if (Rn> i32(31) # rn is positive and rm negative, return 1 r0_mixed = i32(1) if sign_rn else i32(0) # rn & rm are both positives, test and return 1 or 0 r0_pos = (i32(1) if "<"(rn, rm_ext) else i32(0)) if are_both_pos else r0_mixed # rn & rm are both negatives, test and return 0 or 1 r0 = (i32(0) if "<"(rn, rm_ext) else i32(1)) if are_both_neg else r0_pos @sbuild.parse def sltu3(r0, rn, rm_or_imm5): """SLTU3 - Set on less than (unsigned).""" # if (Rn> Rm4..0 # Rn <- (Signed) Rn >> imm5 # Unsigned result shift_u = rn >> rm_or_imm5 # Signed result shift_mask = i32(32) - rm_or_imm5 mask = (i32(0xFFFFFFFF) >> shift_mask) << shift_mask shift_s = shift_u | mask rn = shift_s if rn.msb() else shift_u @sbuild.parse def srl(rn, rm_or_imm5): """SRL - Shift Right unsigned.""" # Rn <- (Unsigned) Rn >> Rm4..0 # Rn <- (Unsigned) Rn >> imm5 rn = rn >> rm_or_imm5 @sbuild.parse def sll(rn, rm_or_imm5): """SLL - Shift Left unsigned.""" # Rn <- (Unsigned) Rn >> Rm4..0 # Rn <- (Unsigned) Rn << imm5 rn = rn << rm_or_imm5 @sbuild.parse def sll3(r0, rn, imm5): """SLL3 - Shift Left unsigned, with 3 arguments.""" # R0 <- (Unsigned) Rn << imm5 r0 = rn << imm5 @sbuild.parse def fsft(rn, rm): "FSFT - Funnel shift.""" # Rn <- ((Rn||Rm)<> (i32(32) - sar) # Shift Rm in the reverse order rn = tmp_rn | tmp_rm # Concatenate registers ## Branch/Jump instructions @sbuild.parse def bra(disp12): """BRA - Branch to an address.""" # PC <- PC + SignExt((disp12)11..1||0) dst = disp12 PC = dst take_jmp = ExprInt(1, 32) ir.IRDst = dst @sbuild.parse def beqz(reg_test, disp8): """BEQZ - Branch if the register stores zero.""" # if(Rn==0) PC <- PC +SignExt((disp8)7..1||0) dst = ExprLoc(ir.get_next_break_loc_key(instr), 32) if reg_test else disp8 take_jmp = ExprInt(0, 32) if reg_test else ExprInt(1, 32) PC = dst ir.IRDst = dst @sbuild.parse def bnez(reg_test, disp8): """BNEZ - Branch if the register does not store zero.""" # if(Rn!=0) PC <- PC + SignExt((disp8)7..1||0) dst = disp8 if reg_test else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if reg_test else ExprInt(0, 32) PC = dst ir.IRDst = dst @sbuild.parse def beqi(reg_test, imm4, disp16): """BEQI - Branch if the register stores imm4.""" # if(Rn==ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) dst = ExprLoc(ir.get_next_break_loc_key(instr), 32) if (reg_test - imm4) else disp16 take_jmp = ExprInt(0, 32) if (reg_test - imm4) else ExprInt(1, 32) PC = dst ir.IRDst = dst @sbuild.parse def bnei(reg_test, imm4, disp16): """BNEI - Branch if the register does not store imm4.""" # if(Rn!=ZeroExt(imm4)) PC <- PC+SignExt((disp17)16..1||0) dst = disp16 if (reg_test - imm4) else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if (reg_test - imm4) else ExprInt(0, 32) PC = dst ir.IRDst = dst @sbuild.parse def blti(reg_test, imm4, disp16): """BLTI - Branch if the register is lower than imm4.""" # if(Rn< ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) - (Signed comparison) dst = disp16 if compute_s_inf(reg_test, imm4) else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if compute_s_inf(reg_test, imm4) else ExprInt(0, 32) PC = dst ir.IRDst = dst @sbuild.parse def bgei(reg_test, imm4, disp16): """BGEI - Branch if the register is greater or equal to imm4.""" # if(Rn>=ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) - (Signed comparison) dst = disp16 if ">="(reg_test, imm4) else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if ">="(reg_test, imm4) else ExprInt(0, 32) PC = dst ir.IRDst = dst @sbuild.parse def beq(rn, rm, disp16): """BEQ - Branch if the two registers are equal.""" # if(Rn==Rm) PC <- PC +SignExt((disp17)16..1||0) dst = ExprLoc(ir.get_next_break_loc_key(instr), 32) if (rn - rm) else disp16 take_jmp = ExprInt(0, 32) if (rn - rm) else ExprInt(1, 32) PC = dst ir.IRDst = dst @sbuild.parse def bne(rn, rm, disp16): """BNE - Branch if the two registers are not equal.""" # if(Rn!=Rm) PC <- PC +SignExt((disp17)16..1||0) dst = disp16 if (rn - rm) else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if (rn - rm) else ExprInt(0, 32) PC = dst ir.IRDst = dst @sbuild.parse def bsr(disp): """BSR - Branch to an address, and store the return address.""" # 16-bit variant: LP <- PC + 2; PC <- PC +SignExt((disp12)11..1||0) # 32-bit variant: LP <- PC + 4; PC <- PC +SignExt((disp24)23..1||0) # Set LP LP = ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) # Set PC according to the immediate size dst = disp PC = dst ir.IRDst = dst def jmp(ir, instr, reg_or_imm): """JMP - Change PC to a register content or an immediate. Note: the behavior in VLIW mode is not implemented""" take_jmp = ExprInt(1, 32) if isinstance(reg_or_imm, ExprId): # PC <- Rm31..1||0 new_PC = ExprAff(PC, reg_or_imm) else: # PC <- PC31..28||0000||(target24)23..1||0 new_PC = ExprAff(PC, ExprOp("+", ExprOp("&", PC, ExprInt(0xF0000000, 32)), reg_or_imm)) return [new_PC, ExprAff(ir.IRDst, new_PC)], [] manual_functions["jmp"] = jmp @sbuild.parse def jsr(reg): """JSR - Jump to the register, and store the return address.""" # LP <- PC + 2; PC <- Rm31..1||0 LP = ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) PC = reg ir.IRDst = reg @sbuild.parse def ret(): """RET - Return from a function call. Note: the behavior in VLIW mode is not implemented""" # PC <- LP31..1||0 dst = LP PC = dst ir.IRDst = dst # Repeat instructions @sbuild.parse def repeat(rn, disp17): """REPEAT - This instruction repeats an instruction block. It sets the RPB, RPE and RPC control registers.""" # RPB <- pc+4 // Repeat Begin RPB = PC + i32(4) # RPE <- pc+SignExt((disp17)16..1||0)) // Repeat End RPE = PC + i32(disp17.arg & 0xFFFFFFFE) # RPC <- Rn RPC = rn in_erepeat = ExprInt(0, 32) @sbuild.parse def erepeat(disp17): """EREPEAT - This instruction repeats an instruction block. It sets the RPB and RPE control registers. To distinguish from the repeat instruction, the least significant bit in the RPE register (ELR) is set to 1.""" # RPB <- pc+4 // Repeat Begin RPB = PC + i32(4) # RPE <- pc+SignExt((disp17)16..1||1)) (EREPEAT) RPE = PC + i32(disp17.arg + 1) # RPC <- undefined in_erepeat = ExprInt(1, 32) ## Control Instructions @sbuild.parse def stc(reg, control_reg): """STC - Copy a general-purpose register into a control register.""" # ControlReg(imm5) <- Rn control_reg = reg @sbuild.parse def ldc(reg, control_reg): """LDC - Copy a control register into a general-purpose register.""" # Rn <- ControlReg(imm5) reg = control_reg @sbuild.parse def di(): """DI - Disable Interrupt""" # PSW.IEC<-0 PSW = PSW & i32(0xFFFFFFFE) # PSW.IEC: bit 0 @sbuild.parse def ei(): """EI - Enable Interrupt""" # PSW.IEC<-1 PSW = PSW ^ i32(0b1) # PSW.IEC: bit 0 @sbuild.parse def reti(): """RETI - Return from the exception/interrupt handler. Note: the behavior in VLIW mode is not implemented""" #if (PSW.NMI==1) { # PC <- NPC31..1 || 0; PSW.NMI<-0; #} else { # PC <- EPC31..1 || 0; # PSW.UMC <- PSW.UMP; PSW.IEC <- PSW.IEP #} # PSW.NMI == bit 9 NMI_mask = i32(1 << 9) # PSW.UMP == bit 3 # PSW.IEP == bit 1 UMP_IEP_mask = i32((1 << 3) ^ (1 << 1)) # PSW.UMC == bit 2 # PSW.IEC == bit 0 UMC_IEC_mask = (PSW & UMP_IEP_mask) >> i32(1) # Get PSW.NMI PSW_NMI = (PSW & NMI_mask) >> i32(9) # Set PC dst = NPC & i32(0xFFFFFFFE) if PSW_NMI else EPC & i32(0xFFFFFFFE) PC = dst # Set flags PSW = PSW ^ NMI_mask if PSW_NMI else PSW ^ UMC_IEC_mask ir.IRDst = dst @sbuild.parse def swi(imm2): """SWI - Software Interrupt""" # if(imm2==0) EXC.SIP0 <- 1 # else if (imm2==1) EXC.SIP1 <- 1 # else if (imm2==2) EXC.SIP2 <- 1 # else if (imm2==3) EXC.SIP3 <- 1 # EXC.SIP0 == bit 4 # EXC.SIP1 == bit 5 # EXC.SIP2 == bit 6 # EXC.SIP3 == bit 7 EXC = EXC ^ (i32(1) << (i32(4) + imm2)) # Note: the following instructions can't be implemented manual_functions["halt"] = mep_nop manual_functions["sleep"] = mep_nop manual_functions["break"] = mep_nop manual_functions["syncm"] = mep_nop manual_functions["stcb"] = mep_nop_2_args manual_functions["ldcb"] = mep_nop_2_args ### Bit manipulation instruction option @sbuild.parse def bsetm(rm_deref, imm3): """BSETM - Bit Set Memory""" # MemByte(Rm) <- MemByte(Rm) or (1< reversed_rm = 0b1110 # Test bits individually b3 = (reversed_rm & i32(2**3)) >> i32(3) if reversed_rm else i32(0) -> b3 = (0b1110 & 0b1000 >> 3) = 1 b2 = (reversed_rm & i32(2**2)) >> i32(2) if b3 else i32(0) -> b2 = (0b1110 & 0b0100 >> 2) = 1 b1 = (reversed_rm & i32(2**1)) >> i32(1) if b2 else i32(0) -> b1 = (0b1110 & 0b0010 >> 1) = 1 b0 = (reversed_rm & i32(2**0)) >> i32(0) if b1 else i32(0) -> b0 = (0b1110 & 0b0001 >> 0) = 0 # Sum all partial results rn = b3 + b2 + b1 + b0 -> rn = 1 + 1 + 1 + 0 = 3 """ # Rn <- LeadingZeroDetect(Rm) # Invert the value reversed_rm = ~rm # Test bits individually b31 = (reversed_rm & i32(2**31)) >> i32(31) if reversed_rm else i32(0) b30 = (reversed_rm & i32(2**30)) >> i32(30) if b31 else i32(0) b29 = (reversed_rm & i32(2**29)) >> i32(29) if b30 else i32(0) b28 = (reversed_rm & i32(2**28)) >> i32(28) if b29 else i32(0) b27 = (reversed_rm & i32(2**27)) >> i32(27) if b28 else i32(0) b26 = (reversed_rm & i32(2**26)) >> i32(26) if b27 else i32(0) b25 = (reversed_rm & i32(2**25)) >> i32(25) if b26 else i32(0) b24 = (reversed_rm & i32(2**24)) >> i32(24) if b25 else i32(0) b23 = (reversed_rm & i32(2**23)) >> i32(23) if b24 else i32(0) b22 = (reversed_rm & i32(2**22)) >> i32(22) if b23 else i32(0) b21 = (reversed_rm & i32(2**21)) >> i32(21) if b22 else i32(0) b20 = (reversed_rm & i32(2**20)) >> i32(20) if b21 else i32(0) b19 = (reversed_rm & i32(2**19)) >> i32(19) if b20 else i32(0) b18 = (reversed_rm & i32(2**18)) >> i32(18) if b19 else i32(0) b17 = (reversed_rm & i32(2**17)) >> i32(17) if b18 else i32(0) b16 = (reversed_rm & i32(2**16)) >> i32(16) if b17 else i32(0) b15 = (reversed_rm & i32(2**15)) >> i32(15) if b16 else i32(0) b14 = (reversed_rm & i32(2**14)) >> i32(14) if b15 else i32(0) b13 = (reversed_rm & i32(2**13)) >> i32(13) if b14 else i32(0) b12 = (reversed_rm & i32(2**12)) >> i32(12) if b13 else i32(0) b11 = (reversed_rm & i32(2**11)) >> i32(11) if b12 else i32(0) b10 = (reversed_rm & i32(2**10)) >> i32(10) if b11 else i32(0) b09 = (reversed_rm & i32(2 ** 9)) >> i32(9) if b10 else i32(0) b08 = (reversed_rm & i32(2 ** 8)) >> i32(8) if b09 else i32(0) b07 = (reversed_rm & i32(2 ** 7)) >> i32(7) if b08 else i32(0) b06 = (reversed_rm & i32(2 ** 6)) >> i32(6) if b07 else i32(0) b05 = (reversed_rm & i32(2 ** 5)) >> i32(5) if b06 else i32(0) b04 = (reversed_rm & i32(2 ** 4)) >> i32(4) if b05 else i32(0) b03 = (reversed_rm & i32(2 ** 3)) >> i32(3) if b04 else i32(0) b02 = (reversed_rm & i32(2 ** 2)) >> i32(2) if b03 else i32(0) b01 = (reversed_rm & i32(2 ** 1)) >> i32(1) if b02 else i32(0) b00 = (reversed_rm & i32(2 ** 0)) >> i32(0) if b01 else i32(0) # Sum all partial results rn = b31 + b30 + b29 + b28 + b27 + b26 + b25 + b24 + b23 + b22 + b21 + b20 \ + b19 + b18 + b17 + b16 + b15 + b14 + b13 + b12 + b11 + b10 + b09 + b08 \ + b07 + b06 + b05 + b04 + b03 + b02 + b01 + b00 ### Coprocessor option # Note: these instructions are implemented when needed # SWCP - Store Word to memory from a coprocessor register # MemWord(Rm31..2||00) <- CRn 31..0 manual_functions["swcp"] = sw # LWCP - Load Word from memory to a coprocessor register # CRn <- MemWord(Rm31..2||00) manual_functions["lwcp"] = lw @sbuild.parse def smcp(reg_src, deref_dst): """SMCP - Store Word to memory from a coprocessor register""" # MemDword(Rm31..3||000) <- CRn mem32[deref_dst.arg & i32(0xFFFFFFF8)] = reg_src @sbuild.parse def lmcp(reg_dst, deref_src): """LMCP - Load Word from memory to a coprocessor register""" # CRn <- MemDword(Rm31..3||000) reg_dst = mem32[deref_src.arg & i32(0xFFFFFFF8)] @sbuild.parse def swcpi(reg_src, deref_dst): """SWCPI - Store Word to memory, and increment the address""" # MemWord(Rm31..2||00) <- CRn 31..0; Rm<-Rm+4 mem32[deref_dst.arg & i32(0xFFFFFFFC)] = reg_src deref_dst.arg = deref_dst.arg + i32(4) @sbuild.parse def lwcpi(reg_dst, deref_src): """LWCPI - Load Word from memory, and increment the address""" # CRn <- MemWord(Rm31..2||00); Rm<-Rm+4 reg_dst = mem32[deref_src.arg & i32(0xFFFFFFFC)] deref_src.arg = deref_src.arg + i32(4) @sbuild.parse def smcpi(reg_src, deref_dst): """SMCPI - Store Word to memory, and increment the address""" # MemDword(Rm31..3||000) <- CRn; Rm<-Rm+8 mem32[deref_dst.arg & i32(0xFFFFFFF8)] = reg_src deref_dst.arg = deref_dst.arg + i32(8) @sbuild.parse def lmcpi(reg_dst, deref_src): """LMCPI - Load Word from memory, and increment the address""" # CRn <- MemDword(Rm31..3||000); Rm<-Rm+8 reg_dst = mem32[deref_src.arg & i32(0xFFFFFFFC)] deref_src.arg = deref_src.arg + i32(8) ### IR MeP definitions def get_mnemo_expr(ir, instr, *args): """Simplify getting the IR from a miasm instruction.""" if instr.name.lower() in sbuild.functions: mnemo_func = sbuild.functions[instr.name.lower()] else: mnemo_func = manual_functions[instr.name.lower()] ir, extra_ir = mnemo_func(ir, instr, *args) return ir, extra_ir class ir_mepb(IntermediateRepresentation): """Toshiba MeP miasm IR - Big Endian It transforms an instructon into an IR. """ addrsize = 32 def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_mep, "b", loc_db) self.pc = mn_mep.getpc() self.sp = mn_mep.getsp() self.IRDst = ExprId("IRDst", 32) def get_ir(self, instr): """Get the IR from a miasm instruction.""" instr_ir, extra_ir = get_mnemo_expr(self, instr, *instr.args) return instr_ir, extra_ir def get_next_break_loc_key(self, instr): """Returns a new label that identifies where the instuction is going. Note: it eases linking IR blocs """ l = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) return l class ir_mepl(ir_mepb): """Toshiba MeP miasm IR - Little Endian""" def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_mep, "l", loc_db) self.pc = mn_mep.getpc() self.sp = mn_mep.getsp() self.IRDst = ExprId("IRDst", 32)