📄 toir.c
字号:
ARM ARM A5-18*/staticBool dis_loadstore_w_ub ( UInt theInstr ){ UInt flags = (theInstr >> 20) & 0x3F; // theInstr[25:20] UChar Rn_addr = toUChar((theInstr >> 16) & 0xF); UChar Rd_addr = toUChar((theInstr >> 12) & 0xF); IRTemp address = newTemp(Ity_I32); UChar L = toUChar((flags >> 0) & 1); // Load(1) | Store(0) UChar W = toUChar((flags >> 1) & 1); // base register writeback UChar B = toUChar((flags >> 2) & 1); // access = unsigned byte(1) | word(0) IRTemp value = newTemp(Ity_I32); IRTemp data = newTemp(Ity_I32); IRTemp data_ror8 = newTemp(Ity_I32); IRTemp data_ror16 = newTemp(Ity_I32); IRTemp data_ror24 = newTemp(Ity_I32); IRExpr* expr_addr_10; HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); HChar dis_buf[50]; vassert(((theInstr >> 26) & 0x3) == 0x1); // Get the address to load/store if (!dis_loadstore_w_ub_address(theInstr, &address, dis_buf)) { return False; } DIP("%s%s%s R%d, %s\n", (L==1) ? "ldr" : "str", cond_name, (B==1) ? "b" : "", Rd_addr, dis_buf); if (Rd_addr == Rn_addr && W==1) { // Unpredictable - ARM ARM A4-39,41,89,91 vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==Rn_addr\n"); return False; } /* LOAD/STORE Rd, address */ if (L==1) { // LOAD if (B==1) { // unsigned byte (LDRB): ARM ARM A4-40 if (Rd_addr == 15) { // Unpredictable - ARM ARM A4-40 vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==15\n"); return False; } putIReg( Rd_addr, loadLE( Ity_I8, mkexpr( address ) ) ); } else { // word (LDR): ARM ARM A4-38 expr_addr_10 = binop(Iop_And32, mkexpr(address), mkU32(0x3)); /* CAB TODO if (Rd_addr == 15 && address[1:0] == 0) => Unpredictable How to bomb out using IR? */ /* LOAD memory data (4 bytes) */ assign( data, loadLE( Ity_I32, mkexpr( address ) ) ); // data ROR 8 assign( data_ror8, binop(Iop_Sub8, mkU8(32), mkU32(8)) ); assign( data_ror8, binop( Iop_Or32, binop( Iop_Shr32, mkexpr(data), mkU8(8) ), binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror8) ))); // data ROR 16 assign( data_ror16, binop(Iop_Sub8, mkU8(32), mkU32(16)) ); assign( data_ror16, binop( Iop_Or32, binop( Iop_Shr32, mkexpr(data), mkU8(16) ), binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror16) ))); // data ROR 24 assign( data_ror24, binop(Iop_Sub8, mkU8(32), mkU32(24)) ); assign( data_ror24, binop( Iop_Or32, binop( Iop_Shr32, mkexpr(data), mkU8(24) ), binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror24) ))); /* switch (address[1:0]) { 0x0: value = data; 0x1: value = data ROR 8; 0x2: value = data ROR 16; 0x3: value = data ROR 24; } */ assign( value, IRExpr_Mux0X( binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x0)), IRExpr_Mux0X( binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x1)), IRExpr_Mux0X( binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x2)), mkexpr(data_ror24), mkexpr(data_ror16) ), mkexpr(data_ror8) ), mkexpr(data) ) ); if (Rd_addr == 15) { // assuming architecture < 5: See ARM ARM A4-28 putIReg( Rd_addr, binop(Iop_And32, mkexpr(value), mkU32(0xFFFFFFFC)) ); // CAB: Need to tell vex we're doing a jump here? // irbb->jumpkind = Ijk_Boring; // irbb->next = mkexpr(value); } else { putIReg( Rd_addr, mkexpr(value) ); } } } else { // STORE: ARM ARM A4-88 if (B==1) { // unsigned byte if (Rd_addr == 15) { // Unpredictable - ARM ARM A4-90 vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==15\n"); return False; } storeLE( mkexpr(address), unop(Iop_32to8, getIReg(Rd_addr)) ); // Rd[7:0] } else { // word if (Rd_addr == 15) { // Implementation Defined - ARM ARM A4-88 vex_printf("dis_loadstore_w_ub(arm): Implementation Defined - Rd_addr==15\n"); return False; // CAB TODO: What to do here? } storeLE( mkexpr(address), getIReg(Rd_addr) ); } } return True;}/* ARMG_CC_OP_LSL, ARMG_CC_OP_LSR, ARMG_CC_OP_ASR ARM ARM A5-9... carry = carry_out[0]*/staticIRExpr* dis_shift( Bool* decode_ok, UInt theInstr, IRTemp* carry_out, HChar* buf ){ UChar Rn_addr = toUChar((theInstr >> 16) & 0xF); UChar Rd_addr = toUChar((theInstr >> 12) & 0xF); UChar Rs_addr = toUChar((theInstr >> 8) & 0xF); UChar Rm_addr = toUChar((theInstr >> 0) & 0xF); UChar by_reg = toUChar((theInstr >> 4) & 0x1); // instr[4] UChar shift_imm = toUChar((theInstr >> 7) & 0x1F); // instr[11:7] UChar shift_op = toUChar((theInstr >> 4) & 0xF); // instr[7:4] IRTemp Rm = newTemp(Ity_I32); IRTemp Rs = newTemp(Ity_I32); IRTemp shift_amt = newTemp(Ity_I8); IRTemp carry_shift = newTemp(Ity_I8); IRTemp oldFlagC = newTemp(Ity_I32); IRTemp mux_false = newTemp(Ity_I32); IRExpr* expr; IROp op; assign( oldFlagC, binop(Iop_Shr32, mk_armg_calculate_flags_c(), mkU8(ARMG_CC_SHIFT_C)) ); switch (shift_op) { case 0x0: case 0x8: case 0x1: op = Iop_Shl32; break; case 0x2: case 0xA: case 0x3: op = Iop_Shr32; break; case 0x4: case 0xC: case 0x5: op = Iop_Sar32; break; default: vex_printf("dis_shift(arm): No such case: 0x%x\n", shift_op); *decode_ok = False; return mkU32(0); } if (by_reg) { // Register Shift assign( Rm, getIReg(Rm_addr) ); if (Rd_addr == 15 || Rm_addr == 15 || Rn_addr == 15 || Rs_addr == 15) { // Unpredictable (ARM ARM A5-10) vex_printf("dis_shift(arm): Unpredictable - Rd|Rm|Rn|Rs == R15\n"); *decode_ok = False; return mkU32(0); } assign( Rs, getIReg((theInstr >> 8) & 0xF) ); // instr[11:8] // shift_amt = shift_expr & 31 => Rs[5:0] assign( shift_amt, narrowTo(Ity_I8, binop( Iop_And32, mkexpr(Rs), mkU32(0x1F)) ) ); // CAB TODO: support for >31 shift ? (Rs[7:0]) switch (shift_op) { case 0x1: // LSL(reg) assign( mux_false, mkU32(0) ); assign( carry_shift, binop(Iop_Add8, mkU8(32), mkexpr(shift_amt)) ); break; case 0x3: // LSR(reg) assign( mux_false, mkU32(0) ); assign( carry_shift, binop(Iop_Sub8, mkexpr(shift_amt), mkU8(1)) ); break; case 0x5: // ASR(reg) // Rs[31] == 0 ? 0x0 : 0xFFFFFFFF assign( mux_false, IRExpr_Mux0X( binop(Iop_CmpLT32U, mkexpr(Rs), mkU32(0x80000000)), mkU32(0xFFFFFFFF), mkU32(0) ) ); assign( carry_shift, binop(Iop_Sub8, mkexpr(shift_amt), mkU8(1)) ); break; default: vex_printf("dis_shift(arm): Reg shift: No such case: 0x%x\n", shift_op); *decode_ok = False; return mkU32(0); } expr = IRExpr_Mux0X( binop(Iop_CmpLT32U, widenUto32(mkexpr(shift_amt)), mkU32(32)), mkexpr(mux_false), binop(op, mkexpr(Rm), mkexpr(shift_amt)) ); // shift_amt == 0 ? old_flag_c : Rm >> x assign( *carry_out, IRExpr_Mux0X( binop(Iop_CmpEQ8, mkexpr(shift_amt), mkU8(0)), binop(Iop_Shr32, mkexpr(Rm), mkexpr(carry_shift)), mkexpr(oldFlagC) ) ); DIS(buf, "R%d, %s R%d", Rm_addr, name_ARMShiftOp(shift_op, 0), Rs_addr); } else { // Immediate shift // CAB: This right? // "the value used is the address of the current intruction plus 8" if (Rm_addr == 15 || Rn_addr == 15) { // ARM ARM A5-9 assign( Rm, binop(Iop_Add32, getIReg(15), mkU32(8)) ); } else { assign( Rm, getIReg(Rm_addr) ); } if (shift_imm == 0) { switch (shift_op) { case 0x0: case 0x8: // LSL(imm) expr = mkexpr(Rm); assign( *carry_out, mkexpr(oldFlagC) ); break; case 0x2: case 0xA: // LSR(imm) expr = mkexpr(0); // Rm >> 31: carry = R[0] assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), mkU8(31)) ); break; case 0x4: case 0xC: // ASR(imm) // Rs[31] == 0 ? 0x0 : 0xFFFFFFFF expr = IRExpr_Mux0X( binop(Iop_CmpLT32U, mkexpr(Rs), mkU32(0x80000000)), mkU32(0xFFFFFFFF), mkU32(0) ); // Rm >> 31: carry = R[0] assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), mkU8(31)) ); break; default: vex_printf("dis_shift(arm): Imm shift: No such case: 0x%x\n", shift_op); *decode_ok = False; return mkU32(0); } DIS(buf, "R%d", Rm_addr); } else { expr = binop(op, mkexpr(Rm), mkU8(shift_imm)); assign( *carry_out, binop(op, mkexpr(Rm), binop(Iop_Sub32, mkU32(shift_imm), mkU32(1)) ) ); DIS(buf, "R%d, %s #%d", Rm_addr, name_ARMShiftOp(shift_op, 0), shift_imm); } } return expr;}/* ARMG_CC_OP_ROR ARM ARM A5-15,16,17*/staticIRExpr* dis_rotate ( Bool* decode_ok, UInt theInstr, IRTemp* carry_out, HChar* buf ){ UChar Rn_addr = toUChar((theInstr >> 16) & 0xF); UChar Rd_addr = toUChar((theInstr >> 12) & 0xF); UChar Rs_addr = toUChar((theInstr >> 8) & 0xF); UChar Rm_addr = toUChar((theInstr >> 0) & 0xF); UChar by_reg = toUChar((theInstr >> 4) & 0x1); // instr[4] UChar rot_imm = toUChar((theInstr >> 7) & 0x1F); // instr[11:7] IRTemp Rm = newTemp(Ity_I32); IRTemp Rs = newTemp(Ity_I32); IRTemp rot_amt = newTemp(Ity_I8); // Rs[7:0] IRTemp oldFlagC = newTemp(Ity_I32); IRExpr* expr=0; assign( oldFlagC, binop(Iop_Shr32, mk_armg_calculate_flags_c(), mkU8(ARMG_CC_SHIFT_C)) ); if (by_reg) { // Register rotate assign( Rm, getIReg(Rm_addr) ); if (Rd_addr == 15 || Rm_addr == 15 || Rn_addr == 15 || Rs_addr == 15) { // Unpredictable (ARM ARM A5-10) vex_printf("dis_rotate(arm): Unpredictable - Rd|Rm|Rn|Rs == R15\n"); *decode_ok = False; return mkU32(0); } assign( Rs, getIReg((theInstr >> 8) & 0xF) ); // instr[11:8] // Rs[4:0] assign( rot_amt, narrowTo(Ity_I8, binop(Iop_And32, mkexpr(Rs), mkU32(0x1F))) ); // CAB: This right? // Rs[7:0] == 0 ? oldFlagC : (Rs[4:0] == 0 ? Rm >> 31 : Rm >> rot-1 ) assign( *carry_out, IRExpr_Mux0X( binop(Iop_CmpNE32, mkU32(0), binop(Iop_And32, mkexpr(Rs), mkU32(0xFF))), mkexpr(oldFlagC), IRExpr_Mux0X( binop(Iop_CmpEQ8, mkexpr(rot_amt), mkU8(0)), binop(Iop_Shr32, mkexpr(Rm), binop(Iop_Sub8, mkexpr(rot_amt), mkU8(1))), binop(Iop_Shr32, mkexpr(Rm), binop(Iop_Shr32, mkexpr(Rm), mkU8(31))) ) ) ); /* expr = (dst0 >> rot_amt) | (dst0 << (wordsize-rot_amt)) */ expr = binop(Iop_Or32, binop(Iop_Shr32, mkexpr(Rm), mkexpr(rot_amt)), binop(Iop_Shl32, mkexpr(Rm), binop(Iop_Sub8, mkU8(32), mkexpr(rot_amt)))); DIS(buf, "R%d, ror R%d", Rm_addr, Rs_addr); } else { // Immediate rotate // CAB: This right? // "the value used is the address of the current intruction plus 8" if (Rm_addr == 15 || Rn_addr == 15) { // ARM ARM A5-9 assign( Rm, binop(Iop_Add32, getIReg(15), mkU32(8)) ); } else { assign( Rm, getIReg(Rm_addr) ); } // Rm >> rot-1: carry = R[0] assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), binop(Iop_Sub8, mkU8(rot_imm), mkU8(1)) ) ); if (rot_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. // CAB: This right? expr = binop(Iop_Or32, binop(Iop_Shl32, mkexpr(oldFlagC), mkU8(31)), binop(Iop_Shr32, mkexpr(Rm), mkU8(1))); DIS(buf, "R%d, rrx", Rm_addr); } else { expr = binop(Iop_Or32, binop(Iop_Shr32, mkexpr(Rm), mkU8(rot_imm)), binop(Iop_Shl32, mkexpr(Rm), binop(Iop_Sub8, mkU8(32), mkU8(rot_imm)))); DIS(buf, "R%d, ror #%u", Rm_addr, (UInt)rot_imm); } } return expr;}/* CAB TODO: - Not all shifts by 0 leave c_flag unchanged, so guard_expr is more difficult... assign( flags_guard, binop( Iop_CmpEQ32, mkexpr(shift_amt), mkU32(0) ) ); setFlags_DEP1_DEP2_shift( ARMG_CC_OP_LSL, Rm, shift_op, flags_guard );*//* Addressing mode 1 - Data Processing ops General syntax: <opcode>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> Returns <shifter_operand> expression*/staticIRExpr* dis_shifter_op ( Bool *decode_ok, UInt theInstr, IRTemp* carry_out, HChar* buf ){ UChar is_immed = toUChar((theInstr >> 25) & 1); // immediate / register shift UChar shift_op = toUChar((theInstr >> 4) & 0xF); // second byte UInt immed_8, rot_imm; UInt imm; IRTemp oldFlagC = newTemp(Ity_I32); if (is_immed) { // ARM ARM A5-2 // dst = src ROR rot << 1 // = (src >> rot) | (src << (32-rot)); immed_8 = theInstr & 0xFF; rot_imm = ((theInstr >> 8) & 0xF) << 1; imm = (immed_8 >> rot_imm) | (immed_8 << (32-rot_imm)); if (rot_imm == 0) { assign( oldFlagC, binop(Iop_Shr32,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -