📄 toir.c
字号:
case ARMCondHS: return "{hs}"; // or 'cs' case ARMCondLO: return "{lo}"; // or 'cc' case ARMCondMI: return "{mi}"; case ARMCondPL: return "{pl}"; case ARMCondVS: return "{vs}"; case ARMCondVC: return "{vc}"; case ARMCondHI: return "{hi}"; case ARMCondLS: return "{ls}"; case ARMCondGE: return "{ge}"; case ARMCondLT: return "{lt}"; case ARMCondGT: return "{gt}"; case ARMCondLE: return "{le}"; case ARMCondAL: return ""; // {al}: default, doesn't need specifying case ARMCondNV: return "{nv}"; default: vpanic("name_ARMCondcode"); }}#if 0static ARMCondcode positiveIse_ARMCondcode ( ARMCondcode cond, Bool* needInvert ){ vassert(cond >= ARMCondEQ && cond <= ARMCondNV); if (cond & 1) { *needInvert = True; return cond-1; } else { *needInvert = False; return cond; }}#endif/* Addressing Mode 1 - DP ops Addressing Mode 2 - Load/Store word/ubyte (scaled) */static HChar* name_ARMShiftOp ( UChar shift_op, UChar imm_val ){ switch (shift_op) { case 0x0: case 0x1: case 0x8: return "lsl"; case 0x2: case 0x3: case 0xA: return "lsr"; case 0x4: case 0x5: case 0xC: return "asr"; case 0x6: return (imm_val==0) ? "rrx" : "ror"; case 0x7: case 0xE: return "ror"; default: vpanic("name_ARMShiftcode"); }}/* Addressing Mode 4 - Load/Store Multiple */static HChar* name_ARMAddrMode4 ( UChar mode ){ /* See ARM ARM A5-55 for alternative names for stack operations ldmfa (full ascending), etc. */ switch (mode) { case 0x0: return "da"; // Decrement after case 0x1: return "ia"; // Increment after case 0x2: return "db"; // Decrement before case 0x3: return "ib"; // Increment before default: vpanic("name_ARMAddrMode4"); }}/* Data Processing ops */static HChar* name_ARMDataProcOp ( UChar opc ){ switch (opc) { case 0x0: return "and"; case 0x1: return "eor"; case 0x2: return "sub"; case 0x3: return "rsb"; case 0x4: return "add"; case 0x5: return "adc"; case 0x6: return "sbc"; case 0x7: return "rsc"; case 0x8: return "tst"; case 0x9: return "teq"; case 0xA: return "cmp"; case 0xB: return "cmn"; case 0xC: return "orr"; case 0xD: return "mov"; case 0xE: return "bic"; case 0xF: return "mvn"; default: vpanic("name_ARMDataProcOp"); }}/* Addressing mode 4 - LOAD/STORE multiple, LDM|STM ARM ARM A5-48*/staticBool dis_loadstore_mult ( UInt theInstr ){ UChar flags = toUChar((theInstr >> 20) & 0x1F); // theInstr[24:20] UChar Rn_addr = toUChar((theInstr >> 16) & 0xF); IRTemp Rn = newTemp(Ity_I32); IRTemp Rn_orig = newTemp(Ity_I32); UInt reg_list = theInstr & 0xFFFF; // each bit addresses a register: R15 to R0 // Load(1) | Store(0) UChar L = toUChar((flags >> 0) & 1); // (W)riteback Rn (incr(U=1) | decr(U=0) by n_bytes) UChar W = toUChar((flags >> 1) & 1); // Priviledged mode flag - *** CAB TODO *** UChar S = toUChar((flags >> 2) & 1); // Txfr ctl: Direction = upwards(1) | downwards(0) UChar U = toUChar((flags >> 3) & 1); // Txfr ctl: Rn within(P=1) | outside(P=0) accessed mem UChar PU = toUChar((flags >> 3) & 3); IRTemp start_addr = newTemp(Ity_I32); IRTemp end_addr = newTemp(Ity_I32); IRTemp data=0; UInt n_bytes=0; UInt tmp_reg = reg_list; UInt reg_idx, offset; Bool decode_ok = True; HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); HChar reg_names[70]; UInt buf_offset; while (tmp_reg > 0) { // Count num bits in reg_list => num_bytes if (tmp_reg & 1) { n_bytes += 4; } tmp_reg = tmp_reg >> 1; } assign( Rn, getIReg(Rn_addr) ); assign( Rn_orig, mkexpr(Rn) ); switch (PU) { // <addressing_mode> case 0x0: // Decrement after (DA) assign( start_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes + 4) ) ); assign( end_addr, mkexpr(Rn) ); break; case 0x1: // Increment after (IA) assign( start_addr, mkexpr(Rn) ); assign( end_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes - 4) ) ); break; case 0x2: // Decrement before (DB) assign( start_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(n_bytes) ) ); assign( end_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(4) ) ); break; case 0x3: // Increment before (IB) assign( start_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(4) ) ); assign( end_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes) ) ); break; default: vex_printf("dis_loadstore_mult(ARM): No such case: 0x%x", PU); return False; } if (W==1) { if (U==1) { // upwards putIReg( Rn_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes) ) ); } else { // downwards putIReg( Rn_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(n_bytes) ) ); } } /* Loop through register list, LOAD/STORE indicated registers Lowest numbered reg -> lowest address, so start with lowest register reg_idx: guest register address offset : current mem offset from start_addr */ reg_names[0] = '\0'; buf_offset=0; offset=0; for (reg_idx=0; reg_idx < 16; reg_idx++) { if (( reg_list >> reg_idx ) & 1) { // reg_list[i] == 1? if (L==1) { // LOAD Ri, (start_addr + offset) if (Rn_addr == reg_idx && W==1) { // Undefined - ARM ARM A4-31 decode_ok=False; break; } assign( data, loadLE(Ity_I32, binop(Iop_Add32, mkexpr(start_addr), mkU32(offset))) ); if (reg_idx == 15) { // assuming architecture < 5: See ARM ARM A4-31 putIReg( reg_idx, binop(Iop_And32, mkexpr(data), mkU32(0xFFFFFFFC)) ); } else { putIReg( reg_idx, mkexpr(data) ); } } else { // STORE Ri, (start_addr + offset) // ARM ARM A4-85 (Operand restrictions) if (reg_idx == Rn_addr && W==1) { // Rn in reg_list && writeback if (offset != 0) { // Undefined - See ARM ARM A4-85 decode_ok=False; break; } // is lowest reg in reg_list: store Rn_orig storeLE( mkexpr(start_addr), mkexpr(Rn_orig) ); } else { storeLE( binop(Iop_Add32, mkexpr(start_addr), mkU32(offset) ), getIReg(reg_idx) ); } } offset += 4; reg_names[buf_offset++] = 'R'; if (reg_idx > 9) { reg_names[buf_offset++] = '1'; reg_names[buf_offset++] = (HChar)toUChar(38 + reg_idx); } else { reg_names[buf_offset++] = (HChar)toUChar(48 + reg_idx); } reg_names[buf_offset++] = ','; // CAB: Eugh! Where's strcpy?! } } if (buf_offset > 0) { reg_names[buf_offset-1] = '\0'; } DIP("%s%s%s R%d%s, {%s}%s\n", (L==1) ? "ldm":"stm", cond_name, name_ARMAddrMode4( PU ), Rn_addr, (W==1) ? "!" : "", reg_names, (S==1) ? "^" : ""); // CAB TODO: // IR assert( end_addr == (start_addr + offset) - 8 ) if (offset == 0) { // Unpredictable - ARM ARM A5-21 vex_printf("dis_loadstore_mult(arm): Unpredictable - offset==0\n"); decode_ok = False; } return decode_ok;}staticBool dis_loadstore_w_ub_address ( UInt theInstr, IRTemp* address, HChar* buf ){ UChar is_reg = toUChar((theInstr >> 25) & 0x1); // immediate | register offset/index UInt flags = (theInstr >> 20) & 0x3F; // theInstr[25:20] UChar Rn_addr = toUChar((theInstr >> 16) & 0xF); UChar Rm_addr = toUChar((theInstr >> 00) & 0xF); UChar shift_op = toUChar((theInstr >> 04) & 0xFF); UInt offset_12 = (theInstr >> 00) & 0xFFF; IRTemp Rn = newTemp(Ity_I32); IRTemp Rm = newTemp(Ity_I32); UChar shift_imm, shift; UChar W = toUChar((flags >> 1) & 1); // base register writeback flag - See *Note UChar U = toUChar((flags >> 3) & 1); // offset is added(1)|subtracted(0) from the base UChar P = toUChar((flags >> 4) & 1); // addressing mode flag - See *Note /* *Note P==0: post-indexed addressing: addr -> Rn W==0: normal mem access W==1: unprivileged mem access P==1: W==0: offset addressing: Rn not updated - ARM ARM A5-20 W==1: pre-indexed addressing: addr -> Rn */ IRTemp scaled_index = newTemp(Ity_I32); IRTemp reg_offset = newTemp(Ity_I32); IRTemp oldFlagC = newTemp(Ity_I32); HChar buf2[30]; HChar buf3[20]; buf3[0] = '\0'; if (Rn_addr == 15) { if (P==1 && W==0) { // offset addressing // CAB: This right? assign( Rn, binop(Iop_And32, getIReg(15), mkU32(8)) ); } else { // Unpredictable - ARM ARM A5-25,29... vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rn_addr==15\n"); return False; } } else { assign( Rn, getIReg(Rn_addr) ); } /* Retrieve / Calculate reg_offset */ if (is_reg) { if (Rm_addr == 15) { // Unpredictable - ARM ARM A5-21 vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rm_addr==15\n"); return False; } if (P==0 || W==1) { // pre|post-indexed addressing if (Rm_addr == Rn_addr) { // Unpredictable - ARM ARM A5-25 vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rm_addr==Rn_addr\n"); return False; } } assign( Rm, getIReg(Rm_addr) ); if (shift_op == 0) { // Register addressing assign( reg_offset, mkexpr(Rm) ); } else { // Scaled Register addressing shift_imm = toUChar((shift_op >> 3) & 0x1F); shift = toUChar((shift_op >> 1) & 0x3); switch (shift) { case 0x0: // LSL assign( scaled_index, binop(Iop_Shl32, mkexpr(Rm), mkU8(shift_imm)) ); break; case 0x1: // LSR if (shift_imm) { assign( scaled_index, binop(Iop_Shr32, mkexpr(Rm), mkU8(shift_imm)) ); } else { assign( scaled_index, mkU32(0) ); } break; case 0x2: // ASR if (shift_imm) { assign( scaled_index, binop(Iop_Sar32, mkexpr(Rm), mkU32(shift_imm)) ); } else { assign( scaled_index, // Rm[31] ? 0xFFFFFFFF : 0x0 IRExpr_Mux0X(binop(Iop_And32, mkexpr(Rm), mkU32(0x8FFFFFFF)), mkexpr(0x0), mkexpr(0xFFFFFFFF)) ); } break; case 0x3: // ROR|RRX assign( oldFlagC, binop(Iop_Shr32, mk_armg_calculate_flags_c(), mkU8(ARMG_CC_SHIFT_C)) ); if (shift_imm == 0) { // RRX (ARM ARM A5-17) // 33 bit ROR using carry flag as the 33rd bit // op = Rm >> 1, carry flag replacing vacated bit position. // scaled_index = (c_flag << 31) | (Rm >> 1) assign( scaled_index, binop(Iop_Or32, binop(Iop_Shl32, mkexpr(oldFlagC), mkU32(31)), binop(Iop_Shr32, mkexpr(Rm), mkU8(1))) ); } else { // ROR // scaled_index = Rm ROR shift_imm // = (Rm >> shift_imm) | (Rm << (32-shift_imm)) assign( scaled_index, binop(Iop_Or32, binop(Iop_Shr32, mkexpr(Rm), mkU8(shift_imm)), binop(Iop_Shl32, mkexpr(Rm), binop(Iop_Sub8, mkU8(32), mkU32(shift_imm)))) ); } break; default: vex_printf("dis_loadstore_w_ub(ARM): No such case: 0x%x", shift); return False; } assign( reg_offset, mkexpr(scaled_index) ); if (shift == 0x3 && shift_imm == 0) { DIS(buf3, ", %s", name_ARMShiftOp(toUChar(shift_op * 2), shift_imm)); } else { DIS(buf3, ", %s #%d", name_ARMShiftOp(toUChar(shift_op * 2), shift_imm), shift_imm); } } DIS(buf2, "%cR%d%s", (U==1) ? '+' : '-', Rm_addr, buf3); } else { // immediate assign( reg_offset, mkU32(offset_12) ); DIS(buf2, "#%c%u", (U==1) ? '+' : '-', offset_12); } DIS(buf, "[R%d%s, %s%s", Rn_addr, (P==0) ? "]" : "", buf2, (P==1) ? ((W==1) ? "]!" : "]") : ""); /* Depending on P,U,W, write to Rn and set address to load/store */ if (P==1) { // offset | pre-indexed addressing if (U == 1) { // - increment assign( *address, binop(Iop_Add32, mkexpr(Rn), mkexpr(reg_offset)) ); } else { // - decrement assign( *address, binop(Iop_Sub32, mkexpr(Rn), mkexpr(reg_offset)) ); } if (W == 1) { // pre-indexed addressing, base register writeback putIReg( Rn_addr, mkexpr(*address) ); } } else { // post-indexed addressing assign( *address, mkexpr(Rn) ); if (U == 1) { // - increment putIReg( Rn_addr, binop( Iop_Add32, mkexpr(Rn), mkexpr(reg_offset) ) ); } else { // - decrement putIReg( Rn_addr, binop( Iop_Sub32, mkexpr(Rn), mkexpr(reg_offset) ) ); } } return True;}/* Addressing mode 2 - LOAD/STORE word or unsigned byte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -