miasm2.arch.mep.sem module
# Toshiba MeP-c4 - miasm instructions side effects # Guillaume Valadon <guillaume@valadon.net> 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<Rm) R0<-1 else R0<-0 (Signed) # if (Rn<ZeroExt(imm5)) R0<-1 else R0<-0(Signed) r0 = i32(1) if compute_s_inf(rn, rm_or_imm5.signExtend(32)) else i32(0) if False: rm_ext = rm_or_imm5 # Mask sign bits sign_mask = i32(0x80000000) sign_rn = rn & sign_mask sign_rm = rm_ext & sign_mask # Check if both numbers are positive or negative are_both_neg = sign_rn & sign_rm are_both_pos = ~(sign_rn & sign_rm) >> 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<Rm) R0<-1 else R0<-0 (Unigned) # if (Rn<ZeroExt(imm5)) R0<-1 else R0<-0(Unsigned) r0 = i32(1) if compute_u_inf(rn, rm_or_imm5) else i32(0) @sbuild.parse def sl1ad3(r0, rn, rm): """SL1AD3 - Shift a register one bit left, then add another one.""" # R0 <- (Rn<<1) + Rm r0 = (rn << i32(1)) + rm @sbuild.parse def sl2ad3(r0, rn, rm): """SL2AD3 - Shift a register two bits left, then add another one.""" # R0 <- (Rn<<2) + Rm r0 = (rn << i32(2)) + rm ### Logical instructions @sbuild.parse def logical_or(rn, rm): """OR - Logical OR between two registers.""" # Rn <- Rn or Rm rn = rn | rm manual_functions["or"] = logical_or @sbuild.parse def logical_and(rn, rm): """AND - Logical AND between two registers.""" # Rn <- Rn and Rm rn = rn & rm manual_functions["and"] = logical_and @sbuild.parse def xor(rn, rm): """XOR - Logical XOR between two registers.""" # Rn <- Rn xor Rm rn = rn ^ rm @sbuild.parse def nor(rn, rm): """NOR - Logical NOR between two registers.""" # Rn <- Rn nor Rm rn = ~ (rn | rm) @sbuild.parse def or3(rn, rm, imm16): """OR3 - Logical OR between a register and an immediate""" # Rn <- Rm or ZeroExt(imm16) rn = rm | imm16 @sbuild.parse def and3(rn, rm, imm16): """AND3 - Logical AND between a register and an immediate""" # Rn <- Rm and ZeroExt(imm16) rn = rm & imm16 @sbuild.parse def xor3(rn, rm, imm16): """XOR3 - Logical XOR between a register and an immediate""" # Rn <- Rm xor ZeroExt(imm16) rn = rm ^ imm16 ### Shift instruction @sbuild.parse def sra(rn, rm_or_imm5): """SRA - Shift Right signed""" # Rn <- (Signed) 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)<<SAR5..0)63..32 # Note: lowest Rm bits are discarded sar = SAR[:5].zeroExtend(32) tmp_rn = rn << sar # Shift Rn tmp_rm = 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, i32(0)) else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if "-"(reg_test, i32(0)) 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<<imm3) mem8[rm_deref.arg] = ExprOp("|", mem8[rm_deref.arg], (i8(1) << imm3[:8])) @sbuild.parse def bclrm(rm_deref, imm3): """BCLRM - Bit Clear Memory""" # MemByte(Rm) <- MemByte(Rm) and ~(1<<imm3) shift = ExprOp("<<", i8(1), imm3[:8]) mem8[rm_deref.arg] = ExprOp("&", mem8[rm_deref.arg], shift.__invert__()) @sbuild.parse def bnotm(rm_deref, imm3): """BNOTM - Bit Not Memory""" # MemByte(Rm) <- MemByte(Rm) xor (1<<imm3) mem8[rm_deref.arg] = ExprOp("^", mem8[rm_deref.arg], (i8(1) << imm3[:8])) @sbuild.parse def btstm(r0, rm_deref, imm3): """BTSTM - Bit Test Memory""" # R0 <- ZeroExt( MemByte(Rm) and (1<<imm3) ) r0 = ExprOp("&", mem8[rm_deref.arg], i8(1) << imm3[:8]).zeroExtend(32) @sbuild.parse def tas(rn, rm_deref): """TAS - Load And Set""" # temp <- Rm; Rn <- ZeroExt(MemByte(temp)); MemByte(temp) <- 1 temp = rm_deref rn = mem8[temp.arg].zeroExtend(32) mem8[temp.arg] = i8(1) ### Data cache option # Note: the following instruction can't be implemented manual_functions["cache"] = mep_nop_2_args ### 32-bit multiply instruction option @sbuild.parse def mul(rn, rm): """MUL - Signed 32-bit multiplication""" # HI||LO <- Rn * Rm (Signed) result = rn.signExtend(64) * rm.signExtend(64) # expand registers size HI = result[32:64] LO = result[:32] @sbuild.parse def mulu(rn, rm): """MUL - Unsigned 32-bit multiplication""" # HI||LO <- Rn * Rm (Unsigned) result = rn.zeroExtend(64) * rm.zeroExtend(64) # expand registers size HI = result[32:64] LO = result[0:32] @sbuild.parse def mulr(rn, rm): """MULR - Signed 32-bit multiplication & store LO in Rn""" # HI||LO <- Rn * Rm; Rn <- LO (Signed) result = rn.signExtend(64) * rm.signExtend(64) # expand registers size HI = result[32:64] LO = result[:32] rn = result[:32] @sbuild.parse def mulru(rn, rm): """MULRU - Unsigned 32-bit multiplication & store LO in Rn""" # HI||LO <- Rn * Rm; Rn <- LO (Unsigned) result = rn.zeroExtend(64) * rm.zeroExtend(64) # expand registers size HI = result[32:64] LO = result[:32] rn = result[:32] @sbuild.parse def madd(rn, rm): """MADD - Signed 32-bit multiplication, adding results to HI & LO registers""" # HI||LO <- HI||LO + Rn*Rm (Signed) result = (HI << i32(32)).signExtend(64) + LO.signExtend(64) + rn.signExtend(64) * rm.signExtend(64) # expand registers size HI = result[32:64] LO = result[:32] @sbuild.parse def maddu(rn, rm): """MADDU - Unsigned 32-bit multiplication, adding results to HI & LO registers""" # HI||LO <- HI||LO + Rn*Rm (Unsigned) result = (HI << i32(32)).zeroExtend(64) + LO.zeroExtend(64) + rn.zeroExtend(64) * rm.zeroExtend(64) # expand registers size HI = result[32:64] LO = result[:32] @sbuild.parse def maddr(rn, rm): """MADDR - Signed 32-bit multiplication, adding results to HI & LO registers & storing LO in Rn""" # HI||LO <- HI||LO + Rn*Rm; Rn <- LO (Signed) result = (HI << i32(32)).signExtend(64) + LO.signExtend(64) + rn.signExtend(64) * rm.signExtend(64) # expand registers size HI = result[32:64] LO = result[:32] rn = result[:32] @sbuild.parse def maddru(rn, rm): """MADDRU - Unsigned 32-bit multiplication, adding results to HI & LO registers & storing LO in Rn""" # HI||LO <- HI||LO + Rn*Rm; Rn <- LO (Unsigned) result = (HI << i32(32)).zeroExtend(64) + LO.zeroExtend(64) + rn.zeroExtend(64) * rm.zeroExtend(64) # expand registers size HI = result[32:64] LO = result[:32] rn = result[:32] ### 32-bit divide instruction option @sbuild.parse def div(rn, rm): """DIV - Signed division""" # LO <- Rn / Rm, HI <- Rn % Rm (Signed) # Mask sign bits sign_mask = i32(0x80000000) sign_rn = rn & sign_mask sign_rm = rm & sign_mask # Check if both numbers are positive or negative are_both_neg = sign_rn & sign_rm are_both_pos = "=="(are_both_neg, sign_mask) # Invert both numbers rn_inv = ~rn + i32(1) rm_inv = ~rm + i32(1) # Used to delay the arithmetic computations tmp_rm = rm if rm else i32(1) tmp_rm_inv = rm_inv if rm_inv else i32(1) # Results if only rn, or rm is negative LO_rn_neg = (~(rn_inv / tmp_rm) + i32(1)) if sign_rn else (~(rn / tmp_rm_inv) + i32(1)) HI_rn_neg = (~(rn_inv % tmp_rm) + i32(1)) if sign_rn else (~(rn % tmp_rm_inv) + i32(1)) # Results if both numbers are positive LO_pos = rn / tmp_rm if are_both_pos else LO_rn_neg HI_pos = rn % tmp_rm if are_both_pos else HI_rn_neg # Results if both numbers are negative LO_neg = rn_inv / tmp_rm_inv if are_both_neg else LO_pos HI_neg = rn_inv % tmp_rm_inv if are_both_neg else HI_pos # Results if rm is equal to zero LO = LO_neg if rm else LO HI = HI_neg if rm else HI exception_flags = i32(0) if rm else i32(EXCEPT_DIV_BY_ZERO) @sbuild.parse def divu(rn, rm): """DIVU - Unsigned division""" # LO <- Rn / Rm, HI <- Rn % Rm (Unsigned) tmp_rm = rm if rm else i32(1) # used to delay the arithmetic computations LO = rn / tmp_rm if rm else LO HI = rn % tmp_rm if rm else HI exception_flags = i32(0) if rm else i32(EXCEPT_DIV_BY_ZERO) ### Debug function option @sbuild.parse def dret(): """DRET - Debug Exception Return""" # PC <- DEPC; DBG.DM <- 0 PC = DEPC DBG = DBG & i32(0xFFFFBFFF) # DBG.DM: bit 15 @sbuild.parse def dbreak(): """DBREAK - Debug break""" # The DBG.DBP bit becomes 1 DBG = DBG ^ i32(0b10) # DBG.DBP: bit 2 ### Leading zero instruction option @sbuild.parse def ldz(rn, rm): """LDZ - Count Leading Zeroes Note: this implementation is readable, yet slow. Each bit are tested individually, and the results are propagated to other bits. Here is the commented implementation for 4-bit integers: rm = 0b0001 # Invert the value reversed_rm = ~rm -> 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)
Module variables
var EXCEPT_DIV_BY_ZERO
var ctx
var manual_functions
var sbuild
Functions
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
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)], []
def compute_s_inf(
arg1, arg2)
Signed comparison operator
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
def compute_u_inf(x, y): """Unsigned comparison operator""" result = (((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y).msb() return result
def get_mnemo_expr(
ir, instr, *args)
Simplify getting the IR from a miasm instruction.
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
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
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)], []
def sbvck3(
ir, instr, r0, rn, rm)
SBVCK3 - Check substraction overflow
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)], []
Classes
class ir_mepb
Toshiba MeP miasm IR - Big Endian
It transforms an instructon into an 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
Ancestors (in MRO)
- ir_mepb
- miasm2.ir.ir.IntermediateRepresentation
- __builtin__.object
Class variables
var addrsize
Instance variables
var IRDst
var pc
var sp
Methods
def __init__(
self, loc_db=None)
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 add_asmblock_to_ircfg(
self, block, ircfg, gen_pc_updt=False)
Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions
def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): """ Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions """ loc_key = block.loc_key ir_blocks_all = [] assignments = [] for instr in block.lines: if loc_key is None: assignments = [] loc_key = self.get_loc_key_for_instr(instr) split = self.add_instr_to_current_state( instr, block, assignments, ir_blocks_all, gen_pc_updt ) if split: ir_blocks_all.append(IRBlock(loc_key, assignments)) loc_key = None assignments = [] if loc_key is not None: ir_blocks_all.append(IRBlock(loc_key, assignments)) new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all) for irblock in new_ir_blocks_all: ircfg.add_irblock(irblock) return new_ir_blocks_all
def add_bloc(
self, block, gen_pc_updt=False)
DEPRECATED function Use add_block instead of add_block
def add_bloc(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ self.add_block(block, gen_pc_updt)
def add_block(
self, block, gen_pc_updt=False)
DEPRECATED function Use add_block instead of add_block
def add_block(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ warnings.warn("""DEPRECATION WARNING ircfg is now out of IntermediateRepresentation Use: ircfg = ir_arch.new_ircfg() ir_arch.add_asmblock_to_ircfg(block, ircfg) """) raise RuntimeError("API Deprecated")
def add_instr_to_current_state(
self, instr, block, assignments, ir_blocks_all, gen_pc_updt)
Add the IR effects of an instruction to the current state.
Returns a bool: True if the current assignments list must be split False in other cases.
@instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt): """ Add the IR effects of an instruction to the current state. Returns a bool: * True if the current assignments list must be split * False in other cases. @instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions """ if gen_pc_updt is not False: self.gen_pc_update(assignments, instr) assignblk, ir_blocks_extra = self.instr2ir(instr) assignments.append(assignblk) ir_blocks_all += ir_blocks_extra if ir_blocks_extra: return True return False
def add_instr_to_ircfg(
self, instr, ircfg, loc_key=None, gen_pc_updt=False)
Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False): """ Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions """ if loc_key is None: offset = getattr(instr, "offset", None) loc_key = self.loc_db.add_location(offset=offset) block = AsmBlock(loc_key) block.lines = [instr] self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt) return loc_key
def expr_fix_regs_for_mode(
self, expr, *args, **kwargs)
def expr_fix_regs_for_mode(self, expr, *args, **kwargs): return expr
def expraff_fix_regs_for_mode(
self, expr, *args, **kwargs)
def expraff_fix_regs_for_mode(self, expr, *args, **kwargs): return expr
def gen_loc_key_and_expr(
self, size)
Return a loc_key and it's corresponding ExprLoc @size: size of expression
def gen_loc_key_and_expr(self, size): """ Return a loc_key and it's corresponding ExprLoc @size: size of expression """ loc_key = self.loc_db.add_location() return loc_key, m2_expr.ExprLoc(loc_key, size)
def gen_pc_update(
self, assignments, instr)
def gen_pc_update(self, assignments, instr): offset = m2_expr.ExprInt(instr.offset, self.pc.size) assignments.append(AssignBlock({self.pc:offset}, instr))
def get_ir(
self, instr)
Get the IR from a miasm instruction.
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_loc_key_for_instr(
self, instr)
Returns the loc_key associated to an instruction @instr: current instruction
def get_loc_key_for_instr(self, instr): """Returns the loc_key associated to an instruction @instr: current instruction""" return self.loc_db.get_or_create_offset_location(instr.offset)
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
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
def get_next_loc_key(
self, instr)
def get_next_loc_key(self, instr): loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) return loc_key
def instr2ir(
self, instr)
def instr2ir(self, instr): ir_bloc_cur, extra_irblocks = self.get_ir(instr) for index, irb in enumerate(extra_irblocks): irs = [] for assignblk in irb: irs.append(AssignBlock(assignblk, instr)) extra_irblocks[index] = IRBlock(irb.loc_key, irs) assignblk = AssignBlock(ir_bloc_cur, instr) return assignblk, extra_irblocks
def irbloc_fix_regs_for_mode(
self, irblock, *args, **kwargs)
def irbloc_fix_regs_for_mode(self, irblock, *args, **kwargs): return irblock
def is_pc_written(
self, block)
Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance
def is_pc_written(self, block): """Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance""" all_pc = self.arch.pc.values() for assignblk in block: if assignblk.dst in all_pc: return assignblk return None
def new_ircfg(
self, *args, **kwargs)
Return a new instance of IRCFG
def new_ircfg(self, *args, **kwargs): """ Return a new instance of IRCFG """ return IRCFG(self.IRDst, self.loc_db, *args, **kwargs)
def new_ircfg_from_asmcfg(
self, asmcfg, *args, **kwargs)
Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance
def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs): """ Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance """ ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs) for block in asmcfg.blocks: self.add_asmblock_to_ircfg(block, ircfg) return ircfg
def post_add_asmblock_to_ircfg(
self, block, ircfg, ir_blocks)
def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks): self.set_empty_dst_to_next(block, ir_blocks) new_irblocks = [] for irblock in ir_blocks: new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib) ircfg.add_irblock(new_irblock) new_irblocks.append(new_irblock) return new_irblocks
def set_empty_dst_to_next(
self, block, ir_blocks)
def set_empty_dst_to_next(self, block, ir_blocks): for index, irblock in enumerate(ir_blocks): if irblock.dst is not None: continue next_loc_key = block.get_next() if next_loc_key is None: loc_key = None if block.lines: line = block.lines[-1] if line.offset is not None: loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l) if loc_key is None: loc_key = self.loc_db.add_location() block.add_cst(loc_key, AsmConstraint.c_next) else: loc_key = next_loc_key dst = m2_expr.ExprLoc(loc_key, self.pc.size) if irblock.assignblks: instr = irblock.assignblks[-1].instr else: instr = None assignblk = AssignBlock({self.IRDst: dst}, instr) ir_blocks[index] = IRBlock(irblock.loc_key, list(irblock.assignblks) + [assignblk])
class ir_mepl
Toshiba MeP miasm IR - Little Endian
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)
Ancestors (in MRO)
Class variables
Instance variables
Methods
def __init__(
self, loc_db=None)
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)
def add_asmblock_to_ircfg(
self, block, ircfg, gen_pc_updt=False)
Inheritance:
ir_mepb
.add_asmblock_to_ircfg
Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions
def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): """ Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions """ loc_key = block.loc_key ir_blocks_all = [] assignments = [] for instr in block.lines: if loc_key is None: assignments = [] loc_key = self.get_loc_key_for_instr(instr) split = self.add_instr_to_current_state( instr, block, assignments, ir_blocks_all, gen_pc_updt ) if split: ir_blocks_all.append(IRBlock(loc_key, assignments)) loc_key = None assignments = [] if loc_key is not None: ir_blocks_all.append(IRBlock(loc_key, assignments)) new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all) for irblock in new_ir_blocks_all: ircfg.add_irblock(irblock) return new_ir_blocks_all
def add_bloc(
self, block, gen_pc_updt=False)
DEPRECATED function Use add_block instead of add_block
def add_bloc(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ self.add_block(block, gen_pc_updt)
def add_block(
self, block, gen_pc_updt=False)
Inheritance:
ir_mepb
.add_block
DEPRECATED function Use add_block instead of add_block
def add_block(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ warnings.warn("""DEPRECATION WARNING ircfg is now out of IntermediateRepresentation Use: ircfg = ir_arch.new_ircfg() ir_arch.add_asmblock_to_ircfg(block, ircfg) """) raise RuntimeError("API Deprecated")
def add_instr_to_current_state(
self, instr, block, assignments, ir_blocks_all, gen_pc_updt)
Inheritance:
ir_mepb
.add_instr_to_current_state
Add the IR effects of an instruction to the current state.
Returns a bool: True if the current assignments list must be split False in other cases.
@instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt): """ Add the IR effects of an instruction to the current state. Returns a bool: * True if the current assignments list must be split * False in other cases. @instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions """ if gen_pc_updt is not False: self.gen_pc_update(assignments, instr) assignblk, ir_blocks_extra = self.instr2ir(instr) assignments.append(assignblk) ir_blocks_all += ir_blocks_extra if ir_blocks_extra: return True return False
def add_instr_to_ircfg(
self, instr, ircfg, loc_key=None, gen_pc_updt=False)
Inheritance:
ir_mepb
.add_instr_to_ircfg
Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False): """ Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions """ if loc_key is None: offset = getattr(instr, "offset", None) loc_key = self.loc_db.add_location(offset=offset) block = AsmBlock(loc_key) block.lines = [instr] self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt) return loc_key
def expr_fix_regs_for_mode(
self, expr, *args, **kwargs)
Inheritance:
ir_mepb
.expr_fix_regs_for_mode
def expr_fix_regs_for_mode(self, expr, *args, **kwargs): return expr
def expraff_fix_regs_for_mode(
self, expr, *args, **kwargs)
Inheritance:
ir_mepb
.expraff_fix_regs_for_mode
def expraff_fix_regs_for_mode(self, expr, *args, **kwargs): return expr
def gen_loc_key_and_expr(
self, size)
Inheritance:
ir_mepb
.gen_loc_key_and_expr
Return a loc_key and it's corresponding ExprLoc @size: size of expression
def gen_loc_key_and_expr(self, size): """ Return a loc_key and it's corresponding ExprLoc @size: size of expression """ loc_key = self.loc_db.add_location() return loc_key, m2_expr.ExprLoc(loc_key, size)
def gen_pc_update(
self, assignments, instr)
Inheritance:
ir_mepb
.gen_pc_update
def gen_pc_update(self, assignments, instr): offset = m2_expr.ExprInt(instr.offset, self.pc.size) assignments.append(AssignBlock({self.pc:offset}, instr))
def get_ir(
self, instr)
Get the IR from a miasm instruction.
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_loc_key_for_instr(
self, instr)
Inheritance:
ir_mepb
.get_loc_key_for_instr
Returns the loc_key associated to an instruction @instr: current instruction
def get_loc_key_for_instr(self, instr): """Returns the loc_key associated to an instruction @instr: current instruction""" return self.loc_db.get_or_create_offset_location(instr.offset)
def get_next_break_loc_key(
self, instr)
Inheritance:
ir_mepb
.get_next_break_loc_key
Returns a new label that identifies where the instuction is going.
Note: it eases linking IR blocs
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
def get_next_loc_key(
self, instr)
Inheritance:
ir_mepb
.get_next_loc_key
def get_next_loc_key(self, instr): loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) return loc_key
def instr2ir(
self, instr)
def instr2ir(self, instr): ir_bloc_cur, extra_irblocks = self.get_ir(instr) for index, irb in enumerate(extra_irblocks): irs = [] for assignblk in irb: irs.append(AssignBlock(assignblk, instr)) extra_irblocks[index] = IRBlock(irb.loc_key, irs) assignblk = AssignBlock(ir_bloc_cur, instr) return assignblk, extra_irblocks
def irbloc_fix_regs_for_mode(
self, irblock, *args, **kwargs)
Inheritance:
ir_mepb
.irbloc_fix_regs_for_mode
def irbloc_fix_regs_for_mode(self, irblock, *args, **kwargs): return irblock
def is_pc_written(
self, block)
Inheritance:
ir_mepb
.is_pc_written
Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance
def is_pc_written(self, block): """Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance""" all_pc = self.arch.pc.values() for assignblk in block: if assignblk.dst in all_pc: return assignblk return None
def new_ircfg(
self, *args, **kwargs)
Inheritance:
ir_mepb
.new_ircfg
Return a new instance of IRCFG
def new_ircfg(self, *args, **kwargs): """ Return a new instance of IRCFG """ return IRCFG(self.IRDst, self.loc_db, *args, **kwargs)
def new_ircfg_from_asmcfg(
self, asmcfg, *args, **kwargs)
Inheritance:
ir_mepb
.new_ircfg_from_asmcfg
Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance
def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs): """ Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance """ ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs) for block in asmcfg.blocks: self.add_asmblock_to_ircfg(block, ircfg) return ircfg
def post_add_asmblock_to_ircfg(
self, block, ircfg, ir_blocks)
Inheritance:
ir_mepb
.post_add_asmblock_to_ircfg
def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks): self.set_empty_dst_to_next(block, ir_blocks) new_irblocks = [] for irblock in ir_blocks: new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib) ircfg.add_irblock(new_irblock) new_irblocks.append(new_irblock) return new_irblocks
def set_empty_dst_to_next(
self, block, ir_blocks)
Inheritance:
ir_mepb
.set_empty_dst_to_next
def set_empty_dst_to_next(self, block, ir_blocks): for index, irblock in enumerate(ir_blocks): if irblock.dst is not None: continue next_loc_key = block.get_next() if next_loc_key is None: loc_key = None if block.lines: line = block.lines[-1] if line.offset is not None: loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l) if loc_key is None: loc_key = self.loc_db.add_location() block.add_cst(loc_key, AsmConstraint.c_next) else: loc_key = next_loc_key dst = m2_expr.ExprLoc(loc_key, self.pc.size) if irblock.assignblks: instr = irblock.assignblks[-1].instr else: instr = None assignblk = AssignBlock({self.IRDst: dst}, instr) ir_blocks[index] = IRBlock(irblock.loc_key, list(irblock.assignblks) + [assignblk])