From: Cerion Armour-Brown Date: Wed, 23 Feb 2005 23:13:29 +0000 (+0000) Subject: Added front-end code for conditional register logic instrs X-Git-Tag: svn/VALGRIND_3_0_1^2~379 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a68a60fb09d9bd99461ed6c32b4918d760421f1a;p=thirdparty%2Fvalgrind.git Added front-end code for conditional register logic instrs Cleaned up the register access interface a little. git-svn-id: svn://svn.valgrind.org/vex/trunk@955 --- diff --git a/VEX/priv/guest-ppc32/toIR.c b/VEX/priv/guest-ppc32/toIR.c index 5b90b27461..e75f66ba33 100644 --- a/VEX/priv/guest-ppc32/toIR.c +++ b/VEX/priv/guest-ppc32/toIR.c @@ -835,51 +835,11 @@ static void setFlags_XER_CA( UInt op, IRExpr* res, Others are represented by the thunk */ -/* Get single bits from given [register,idx] */ -static IRExpr* getReg_bit ( PPC32Reg reg, UInt bit_idx ) -{ - vassert( bit_idx <= 32 ); - vassert( reg < REG_NUMBER ); - - IRExpr* val; - - switch (reg) { - case REG_XER: - switch (bit_idx) { - case OFFBIT_XER_SO: - val = IRExpr_Get(OFFB_XER_SO, Ity_I8); - break; - case OFFBIT_XER_OV: - val = IRExpr_Get(OFFB_XER_OV, Ity_I8); - break; - case OFFBIT_XER_CA: - val = IRExpr_Get(OFFB_XER_CA, Ity_I8); - break; - case OFFBIT_XER_BC: - val = IRExpr_Get(OFFB_XER_BC, Ity_I8); - break; - default: - vpanic("getReg_bit(ppc32, bit_idx)"); - } - break; +/* Forward decls... */ +static IRExpr* getReg_bit ( PPC32Reg reg, UInt bit_idx, Bool do_shift ); - default: - vpanic("getReg_bit(ppc32, reg)"); - } - return unop(Iop_8Uto32, binop(Iop_And8, val, mkU8(1)) ); -} - -/* Get single bits from given [register,idx], - shifted to position bit_idx */ -static IRExpr* getReg_bit_shifted ( PPC32Reg reg, UInt bit_idx ) -{ - vassert( bit_idx <= 32 ); - vassert( reg < REG_NUMBER ); - return binop(Iop_Shl32, getReg_bit( reg, bit_idx ), mkU8(bit_idx)); -} - -/* Get a word, controlled by a mask, from the given register */ +/* Get a masked word from the given reg */ static IRExpr* getReg_masked ( PPC32Reg reg, UInt mask ) { IRTemp val = newTemp(Ity_I32); @@ -892,10 +852,12 @@ static IRExpr* getReg_masked ( PPC32Reg reg, UInt mask ) switch (reg) { case REG_LR: + vassert(mask == 0xFFFFFFFF); assign( val, IRExpr_Get(OFFB_LR, Ity_I32) ); break; case REG_CTR: + vassert(mask == 0xFFFFFFFF); assign( val, IRExpr_Get(OFFB_CTR, Ity_I32) ); break; @@ -911,35 +873,56 @@ static IRExpr* getReg_masked ( PPC32Reg reg, UInt mask ) break; case REG_XER: - if (mask & 0x80000000) { - irx_tmp1 = getReg_bit_shifted( REG_XER, OFFBIT_XER_SO ); +#if 1 + if (mask & (1< X" ? + // Is this a reasonable thing to do? + // Same goes for putReg_masked() + + if (mask & (1<tyenv,src ) == Ity_I1 ); vassert( bit_idx <= 32 ); vassert( reg < REG_NUMBER ); + IRExpr* val; + +#if 1 switch (reg) { + case REG_CR: + val = getReg_masked( REG_CR, 1<= 0 && bit_idx <= 6) { // XER_BC + val = getReg_masked( REG_XER, 1<tyenv,src ) == Ity_I32 ); @@ -1054,30 +1077,10 @@ static void putReg_field ( PPC32Reg reg, UInt field_idx, IRExpr* src ) vassert( field_idx <= 8 ); vassert( reg < REG_NUMBER ); - UInt bit_idx = field_idx * 4; - UInt field_mask = 0x0000000F << field_idx; - - IRTemp val = newTemp(Ity_I32); - - // About to be masked, so don't bother here. - if (bit_idx != 0) { - assign( val, binop(Iop_Shl32, src, mkU8(bit_idx)) ); - } else { - assign( val, src ); - } - - switch (reg) { - case REG_CR: - putReg_masked( REG_CR, mkexpr(val), field_mask ); - break; - - case REG_XER: - putReg_masked( REG_XER, mkexpr(val), field_mask ); - break; - - default: - vpanic("putReg_field(ppc32)"); - } + if (field_idx != 0) { + src = binop(Iop_Shl32, src, mkU8(field_idx * 4)); + } + putReg_masked( reg, src, (0xF << field_idx) ); } @@ -1095,8 +1098,6 @@ static void putReg_field ( PPC32Reg reg, UInt field_idx, IRExpr* src ) - - /* Integer Arithmetic Instructions */ @@ -1137,21 +1138,21 @@ static Bool dis_int_arith ( UInt theInstr ) arg1 = mkexpr(Ra); arg2 = mkU32(EXTS_SIMM); - assign( xer_ca, getReg_bit(REG_XER, OFFBIT_XER_CA) ); + assign( xer_ca, getReg_bit(REG_XER, OFFBIT_XER_CA, True) ); switch (opc1) { /* D-Form */ case 0x0C: // addic (Add Immediate Carrying, p381) - DIP("addic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + 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) ) ); op = PPC32G_FLAG_OP_ADD; do_ca = True; break; case 0x0D: // addic. (Add Immediate Carrying and Record, p382) - DIP("addic. r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + 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) ) ); op = PPC32G_FLAG_OP_ADD; do_ca = True; @@ -1521,7 +1522,7 @@ static Bool dis_int_cmp ( UInt theInstr ) mkU32(2) )); assign( cr_f7, binop(Iop_Or32, mkexpr(tmp), - getReg_bit(REG_XER, OFFBIT_XER_SO)) ); + getReg_bit(REG_XER, OFFBIT_XER_SO, True)) ); putReg_field( REG_CR, 7-crfD, mkexpr(cr_f7) ); return True; } @@ -2558,6 +2559,89 @@ static Bool dis_branch ( UInt theInstr, DisResult *whatNext ) +static Bool dis_cond_logic ( UInt theInstr ) +{ + /* XL-Form */ + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar crbD_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar crfD_addr = toUChar((theInstr >> 23) & 0x7); /* theInstr[23:25] */ + UChar crbA_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UChar crfS_addr = toUChar((theInstr >> 18) & 0x7); /* theInstr[18:20] */ + UChar crbB_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + IRTemp crbD = newTemp(Ity_I32); + IRTemp crbA = newTemp(Ity_I32); + IRTemp crbB = newTemp(Ity_I32); + + if (opc1 != 19 || b0 != 0) { + vex_printf("dis_cond_logic(PPC32)(opc1)\n"); + return False; + } + + if (opc2 == 0) { // mcrf (Move Cond Reg Field, p464-ppc32) + if (((crbD_addr & 0x3) != 0) || + ((crbA_addr & 0x3) != 0) || (crbB != 0)) + return False; + DIP("mcrf crf%d,crf%d\n", crfD_addr, crfS_addr); + putReg_field( REG_CR, (7-crfD_addr), + getReg_field( REG_CR, (7-crfS_addr) ) ); + } else { + assign( crbA, getReg_bit( REG_CR, (31-crbA_addr), True) ); + assign( crbB, getReg_bit( REG_CR, (31-crbB_addr), True) ); + + switch (opc2) { + case 0x101: // crand (Cond Reg AND, p372-ppc32) + DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); + assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); + break; + case 0x081: // crandc (Cond Reg AND w. Complement, p373-ppc32) + DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); + assign( crbD, binop(Iop_And32, mkexpr(crbA), + unop(Iop_Not32, mkexpr(crbB))) ); + break; + case 0x121: // creqv (Cond Reg Equivalent, p374-ppc32) + DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); + assign( crbD, unop(Iop_Not32, + binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); + break; + case 0x0E1: // crnand (Cond Reg NAND, p375-ppc32) + DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); + assign( crbD, unop(Iop_Not32, + binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); + break; + case 0x021: // crnor (Cond Reg NOR, p376-ppc32) + DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); + assign( crbD, unop(Iop_Not32, + binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); + break; + case 0x1C1: // cror (Cond Reg OR, p377-ppc32) + DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); + assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); + break; + case 0x1A1: // crorc (Cond Reg OR w. Complement, p378-ppc32) + DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); + assign( crbD, binop(Iop_Or32, mkexpr(crbA), + unop(Iop_Not32, mkexpr(crbB))) ); + break; + case 0x0C1: // crxor (Cond Reg XOR, p379-ppc32) + DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); + assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); + break; + + default: + vex_printf("dis_cond_logic(PPC32)(opc2)\n"); + return False; + } + + putReg_masked( REG_CR, mkexpr(crbD), 1<<(31-crbD_addr) ); + } + return True; +} + + + static Bool dis_syslink ( UInt theInstr, DisResult *whatNext ) { if (theInstr != 0x44000002) { @@ -2664,7 +2748,7 @@ static Bool dis_memsync ( UInt theInstr ) // Set CR7[LT GT EQ S0] = 0b001 || XER[SO] assign( cr_f7, binop(Iop_Or32, mkU32(2), - getReg_bit(REG_XER, OFFBIT_XER_SO)) ); + getReg_bit(REG_XER, OFFBIT_XER_SO, True)) ); putReg_field( REG_CR, 7, mkexpr(cr_f7) ); break; @@ -3393,7 +3477,8 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, case 0x1A1: // crorc case 0x0C1: // crxor case 0x000: // mcrf - DIP("condition register logical op => not implemented\n"); + if (dis_cond_logic(theInstr)) + break; goto decode_failure; /* diff --git a/VEX/priv/host-ppc32/isel.c b/VEX/priv/host-ppc32/isel.c index 0599578f0c..c30a42de33 100644 --- a/VEX/priv/host-ppc32/isel.c +++ b/VEX/priv/host-ppc32/isel.c @@ -918,6 +918,25 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) shOp = Psh_INVALID; break; } if (shOp != Psh_INVALID) { +#if 0 + /* Shr32(Shl32(expr32,imm8),imm8) */ + { + DECLARE_PATTERN(p_Shl32_then_Shr32); + DEFINE_PATTERN(p_Shl32_then_Shr32, + binop(Iop_Shr32, + binop(Iop_Shl32,bind(0),bind(1)), + bind(2))); + if (matchIRExpr(&mi,p_Shl32_then_Shr32,e)) { + HReg src = iselIntExpr_R( env, mi.bindee[0] ); + PPC32RI* sh1 = mk_FitRI16(env, iselIntExpr_RI( env, mi.bindee[1] )); + PPC32RI* sh2 = mk_FitRI16(env, iselIntExpr_RI( env, mi.bindee[2] )); + if (sh1->tag == Pri_Imm && sh2->tag == Pri_Imm && + sh1->Pri.Imm.imm32 ==sh1->Pri.Imm.imm32) { + return src; + } + } + } +#endif HReg dst = newVRegI(env); /* regL = the value to be shifted */