📄 toir.c
字号:
bit of argL. */ /* This term valid for shift amount < 32 only */ xer_ca = binop( Iop_And32, binop(Iop_Sar32, argL, mkU8(31)), binop( Iop_And32, argL, binop( Iop_Sub32, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,argR)), mkU32(1) ) ) ); xer_ca = IRExpr_Mux0X( /* shift amt > 31 ? */ unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)), /* no -- be like srawi */ unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))), /* yes -- get sign bit of argL */ binop(Iop_Shr32, argL, mkU8(31)) ); break; case /* 11 */ PPC32G_FLAG_OP_SRAWI: /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. Since the shift amount is known to be in the range 0 .. 31 inclusive the following seems viable: xer.ca == 1 iff the following is nonzero: (argL >>s 31) -- either all 0s or all 1s & (argL & (1<<argR)-1) -- the stuff shifted out */ xer_ca = binop( Iop_And32, binop(Iop_Sar32, argL, mkU8(31)), binop( Iop_And32, argL, binop( Iop_Sub32, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,argR)), mkU32(1) ) ) ); xer_ca = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); break; default: vex_printf("set_XER_CA: op = %d\n", op); vpanic("set_XER_CA(ppc32)"); } /* xer_ca MUST denote either 0 or 1, no other value allowed */ stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_32to8, xer_ca) ) );}static IRExpr* /* :: Ity_I32 */ get_XER_CA ( void ){ return binop( Iop_And32, unop( Iop_8Uto32, IRExpr_Get(OFFB_XER_CA, Ity_I8) ), mkU32(1) );}/*------------------------------------------------------------*//*--- Abstract register interface --- *//*------------------------------------------------------------*//* Get a masked word from the given reg */static IRExpr* getReg_masked ( PPC32SPR reg, UInt mask ){ IRTemp val = newTemp(Ity_I32); vassert( reg < PPC32_SPR_MAX ); switch (reg) { case PPC32_SPR_FPSCR: { vassert((mask & 0x3) == 0x3 || (mask & 0x3) == 0x0); vassert((mask & 0xF000) == 0xF000 || (mask & 0xF000) == 0x0); /* all masks now refer to valid fields */ /* Vex-generated code expects to run with the FPSCR set as follows: all exceptions masked, round-to-nearest. This corresponds to a FPSCR value of 0x0. */ /* We're only keeping track of the rounding mode, so if the mask isn't asking for this, just return 0x0 */ if (mask & 0x3) { assign( val, IRExpr_Get(OFFB_FPROUND, Ity_I32) ); } else { assign( val, mkU32(0x0) ); } break; }//zz case PPC32_SPR_VRSAVE://zz assign( val, IRExpr_Get(OFFB_VRSAVE, Ity_I32) );//zz break;//zz //zz case PPC32_SPR_VSCR://zz // All other bits are 'Reserved'. Returning zero for these bits.//zz mask = mask & 0x00010001;//zz assign( val, IRExpr_Get(OFFB_VSCR, Ity_I32) );//zz break; default: vpanic("getReg(ppc32)"); } if (mask != 0xFFFFFFFF) { return binop(Iop_And32, mkexpr(val), mkU32(mask)); } else { return mkexpr(val); }}//zz /* Get word from the given reg *///zz static IRExpr* getReg ( PPC32SPR reg )//zz {//zz vassert( reg < PPC32_SPR_MAX );//zz return getReg_masked( reg, 0xFFFFFFFF );//zz }//zz //zz /* Get a right-shifted nibble from given reg[field_idx]//zz returns zero padded word *///zz static IRExpr* getReg_field ( PPC32SPR reg, UInt field_idx )//zz {//zz IRExpr* fld;//zz vassert( field_idx < 8 );//zz vassert( reg < PPC32_SPR_MAX );//zz //zz fld = getReg_masked( reg, (0xF << (field_idx*4)) );//zz //zz if (field_idx != 0) {//zz fld = binop(Iop_Shr32, fld, mkU8(toUChar(field_idx * 4)));//zz }//zz return fld;//zz }//zz //zz /* Get a right-shifted bit from given reg[bit_idx]//zz returns zero padded word *///zz static IRExpr* getReg_bit ( PPC32SPR reg, UInt bit_idx )//zz {//zz IRExpr* val;//zz vassert( bit_idx < 32 );//zz vassert( reg < PPC32_SPR_MAX );//zz //zz val = getReg_masked( reg, 1<<bit_idx );//zz //zz if (bit_idx != 0) {//zz val = binop(Iop_Shr32, val, mkU8(toUChar(bit_idx)));//zz }//zz return val;//zz }/* Write masked src to the given reg */static void putReg_masked ( PPC32SPR reg, IRExpr* src, UInt mask ){ vassert( reg < PPC32_SPR_MAX ); vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); switch (reg) {//zz case PPC32_SPR_CIA://zz vassert(mask == 0xFFFFFFFF); // Only ever need whole reg//zz stmt( IRStmt_Put( OFFB_CIA, src ) );//zz break; case PPC32_SPR_FPSCR: vassert((mask & 0x3) == 0x3 || (mask & 0x3) == 0x0); vassert((mask & 0xF000) == 0xF000 || (mask & 0xF000) == 0x0); /* all masks now refer to valid fields */ /* Allow writes to Rounding Mode */ if (mask & 0x3) { stmt( IRStmt_Put( OFFB_FPROUND, binop(Iop_And32, src, mkU32(0x3)) )); } /* Give EmWarn for attempted writes to: - Exception Controls - Non-IEEE Mode */ if (mask & 0xFC) { // Exception Control, Non-IEE mode VexEmWarn ew = EmWarn_PPC32exns; /* If any of the src::exception_control bits are actually set, side-exit to the next insn, reporting the warning, so that Valgrind's dispatcher sees the warning. */ put_emwarn( mkU32(ew) ); stmt( IRStmt_Exit( binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)), Ijk_EmWarn, IRConst_U32(guest_CIA_curr_instr + 4) ) ); } /* Ignore all other writes */ break;//zz case PPC32_SPR_VRSAVE://zz vassert(mask == 0xFFFFFFFF); // Only ever need whole reg//zz stmt( IRStmt_Put( OFFB_VRSAVE, src ) );//zz break;//zz //zz case PPC32_SPR_VSCR://zz //CAB: There are only 2 valid bits in VSCR - maybe split into two vars...//zz //zz // All other bits are 'Reserved'. Ignoring writes to these bits.//zz stmt( IRStmt_Put( OFFB_VSCR,//zz binop(Iop_Or32,//zz binop(Iop_And32, src, mkU32(mask & 0x00010001)),//zz getReg_masked( PPC32_SPR_VSCR, (~mask & 0x00010001) ))));//zz break;//zz } default: vpanic("putReg(ppc32)"); }}//zz /* Write src to the given reg *///zz static void putReg ( PPC32SPR reg, IRExpr* src )//zz {//zz vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 );//zz vassert( reg < PPC32_SPR_MAX );//zz putReg_masked( reg, src, 0xFFFFFFFF );//zz }static void putSPR ( PPC32SPR reg, IRExpr* src ){ vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); switch (reg) { case PPC32_SPR_CIA: stmt( IRStmt_Put( OFFB_CIA, src ) ); break; case PPC32_SPR_LR: stmt( IRStmt_Put( OFFB_LR, src ) ); break; case PPC32_SPR_CTR: stmt( IRStmt_Put( OFFB_CTR, src ) ); break; case PPC32_SPR_VRSAVE: stmt( IRStmt_Put( OFFB_VRSAVE, src ) ); break; default: vpanic("putSPR(ppc32)"); }}static IRExpr* /* :: Ity_I32 */ getSPR ( PPC32SPR reg ){ switch (reg) { case PPC32_SPR_LR: return IRExpr_Get( OFFB_LR, Ity_I32 ); case PPC32_SPR_CTR: return IRExpr_Get( OFFB_CTR, Ity_I32 ); case PPC32_SPR_VRSAVE: return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); default: vpanic("getSPR(ppc32)"); }}/* Write least-significant nibble of src to reg[field_idx] */static void putReg_field ( PPC32SPR reg, IRExpr* src, UInt field_idx ){ vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); vassert( field_idx < 8 ); vassert( reg < PPC32_SPR_MAX ); if (field_idx != 0) { src = binop(Iop_Shl32, src, mkU8(toUChar(field_idx * 4))); } putReg_masked( reg, src, (0xF << (field_idx*4)) );}/* Write least-significant bit of src to reg[bit_idx] */static void putReg_bit ( PPC32SPR reg, IRExpr* src, UInt bit_idx ){ vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); vassert( bit_idx < 32 ); vassert( reg < PPC32_SPR_MAX ); if (bit_idx != 0) { src = binop(Iop_Shl32, src, mkU8(toUChar(bit_idx))); } putReg_masked( reg, src, (1<<bit_idx) );}/*------------------------------------------------------------*//*--- Integer Instruction Translation --- *//*------------------------------------------------------------*//* Integer Arithmetic Instructions*/static Bool dis_int_arith ( UInt theInstr ){ UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ /* D-Form */ UInt SIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ /* XO-Form */ UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ UChar flag_OE = toUChar((theInstr >> 10) & 1); /* theInstr[10] */ UInt opc2 = (theInstr >> 1) & 0x1FF; /* theInstr[1:9] */ UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ UInt EXTS_SIMM = 0; IRTemp Ra = newTemp(Ity_I32); IRTemp Rb = newTemp(Ity_I32); IRTemp Rd = newTemp(Ity_I32); IRTemp res64 = newTemp(Ity_I64); // multiplies need this.//zz UInt flag_op = PPC32G_FLAG_OP_NUMBER; Bool do_rc = False; assign( Ra, getIReg(Ra_addr) ); assign( Rb, getIReg(Rb_addr) ); // XO-Form: Rd, Ra, Rb EXTS_SIMM = extend_s_16to32(SIMM_16); // D-Form: Rd, Ra, EXTS(SIMM)//zz assign( xer_ca, getReg_bit( PPC32_SPR_XER, SHIFT_XER_CA ) ); switch (opc1) { /* D-Form */ case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 DIP("addic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, EXTS_SIMM); assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); set_XER_CA( PPC32G_FLAG_OP_ADD, mkexpr(Rd), mkexpr(Ra), mkU32(EXTS_SIMM), mkU32(0)/*old xer.ca, which is ignored*/ ); break; case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) DIP("addic. r%d,r%d,0x%x\n", Rd_addr, Ra_addr, EXTS_SIMM); assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); set_XER_CA( PPC32G_FLAG_OP_ADD, mkexpr(Rd), mkexpr(Ra), mkU32(EXTS_SIMM), mkU32(0)/*old xer.ca, which is ignored*/ ); do_rc = True; // Always record to CR flag_Rc = 1; break; case 0x0E: // addi (Add Immediate, PPC32 p350) // li rD,val == addi rD,0,val // la disp(rA) == addi rD,rA,disp if ( Ra_addr == 0 ) { DIP("li r%d,%d\n", Rd_addr, EXTS_SIMM); assign( Rd, mkU32(EXTS_SIMM) ); } else { DIP("addi r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); } break; case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) // lis rD,val == addis rD,0,val if ( Ra_addr == 0 ) { DIP("lis r%d,%d\n", Rd_addr, SIMM_16); assign( Rd, mkU32(SIMM_16 << 16) ); } else { DIP("addis r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkU32(SIMM_16 << 16)) ); } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -