From a028fc9dcf5ac8083edfc9ee36ede176a7cc079a Mon Sep 17 00:00:00 2001 From: Cerion Armour-Brown Date: Wed, 16 Feb 2005 10:25:26 +0000 Subject: [PATCH] More instr emitting: - most 'forms' done - had a go at Pin_Call, Pin_Goto Changed CondTest & added invertCondTest() Fixed Div - only takes reg operands Fixed iselIntExpr_R_wrk: alu32, div, shft - dtrt with large immediates git-svn-id: svn://svn.valgrind.org/vex/trunk@912 --- VEX/priv/host-ppc32/hdefs.c | 320 +++++++++++++++++++++++------------- VEX/priv/host-ppc32/hdefs.h | 19 ++- VEX/priv/host-ppc32/isel.c | 48 ++++-- 3 files changed, 249 insertions(+), 138 deletions(-) diff --git a/VEX/priv/host-ppc32/hdefs.c b/VEX/priv/host-ppc32/hdefs.c index bb28e5b42..ae44e9be6 100644 --- a/VEX/priv/host-ppc32/hdefs.c +++ b/VEX/priv/host-ppc32/hdefs.c @@ -227,6 +227,13 @@ HChar* showPPC32CondCode ( PPC32CondCode cond ) } } +PPC32CondTest invertCondTest ( PPC32CondTest ct ) +{ + vassert(ct != Pct_ALWAYS); + return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE; +} + + /* --------- PPCAMode: memory address expressions. --------- */ PPC32AMode* PPC32AMode_IR ( UInt idx, HReg base ) { @@ -436,6 +443,8 @@ HChar* showPPC32CmpOp ( PPC32CmpOp op ) { //.. } PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst, HReg src1, PPC32RI* src2 ) { + if (src2->tag == Pri_Imm) + vassert(src2->Pri.Imm.imm32 < 0x10000); PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr)); i->tag = Pin_Alu32; i->Pin.Alu32.op = op; @@ -492,8 +501,7 @@ PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst, i->Pin.MulL.src2 = src2; return i; } -PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, - HReg src1, PPC32RI* src2 ) { +PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg src1, HReg src2 ) { PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr)); i->tag = Pin_Div; i->Pin.Div.syned = syned; @@ -740,11 +748,11 @@ void ppPPC32Instr ( PPC32Instr* i ) case Pin_Div: vex_printf("divw%s ", i->Pin.Div.syned ? "" : "u"); - ppHRegPPC32(i->Pin.MulL.dst); + ppHRegPPC32(i->Pin.Div.dst); vex_printf(","); - ppHRegPPC32(i->Pin.MulL.src1); + ppHRegPPC32(i->Pin.Div.src1); vex_printf(","); - ppPPC32RI(i->Pin.MulL.src2); + ppHRegPPC32(i->Pin.Div.src2); return; //.. case Xin_Sh3232: //.. vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op)); @@ -761,19 +769,13 @@ void ppPPC32Instr ( PPC32Instr* i ) //.. ppX86RMI(i->Xin.Push.src); //.. return; case Pin_Call: -// CAB: Add representation of BO to Pin_Call... -// 001xx => branch if false -// 011xx => branch if true -// 1x100 => branch always - -// bcl false|true,cond,target - vex_printf("bcl (%s)[%d] ", - showPPC32CondCode(i->Pin.Call.cond), - i->Pin.Call.regparms); - vex_printf("0x%x", i->Pin.Call.target); + vex_printf("call: la r12, 0x%x ; mtctr r12 ; bcctrl[%d] %s,reg", + i->Pin.Call.target, + i->Pin.Call.regparms, + showPPC32CondCode(i->Pin.Call.cond)); break; case Pin_Goto: -// bc false|true,cond,target + vex_printf("goto: "); if (i->Pin.Goto.cond.test != Pct_ALWAYS) { vex_printf("if (%%CR.%s) { ", showPPC32CondCode(i->Pin.Goto.cond)); @@ -783,8 +785,7 @@ void ppPPC32Instr ( PPC32Instr* i ) ppIRJumpKind(i->Pin.Goto.jk); vex_printf(" ; "); } - vex_printf("bc "); - vex_printf("%%r4, "); + vex_printf("bca %s,%%r4, ", showPPC32CondCode(i->Pin.Goto.cond)); ppPPC32RI(i->Pin.Goto.dst); vex_printf(" ; ret"); if (i->Pin.Goto.cond.test != Pct_ALWAYS) { @@ -1030,7 +1031,7 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i ) case Pin_Div: addHRegUse(u, HRmWrite, i->Pin.Div.dst); addHRegUse(u, HRmRead, i->Pin.Div.src1); - addRegUsage_PPC32RI(u, i->Pin.Div.src2); + addHRegUse(u, HRmRead, i->Pin.Div.src2); return; //.. case Xin_Sh3232: //.. addHRegUse(u, HRmRead, i->Xin.Sh3232.src); @@ -1261,7 +1262,7 @@ void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i) case Pin_Div: mapReg(m, &i->Pin.Div.dst); mapReg(m, &i->Pin.Div.src1); - mapRegs_PPC32RI(m, i->Pin.Div.src2); + mapReg(m, &i->Pin.Div.src2); return; //.. case Xin_Sh3232: //.. mapReg(m, &i->Xin.Sh3232.src); @@ -1734,13 +1735,94 @@ static UChar* mkFormXO ( UChar* p, UInt op1, UInt r1, UInt r2, vassert(r2 < 0x20); vassert(r3 < 0x20); vassert(b10 < 0x2); - vassert(op2 < 0x400); + vassert(op2 < 0x200); vassert(b0 < 0x2); UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (b10 << 10) | (op2<<1) | (b0)); return emit32(p, theInstr); } +static UChar* mkFormXL ( UChar* p, UInt op1, UInt f1, UInt f2, + UInt f3, UInt op2, UInt b0 ) +{ + vassert(op1 < 0x40); + vassert(f1 < 0x20); + vassert(f2 < 0x20); + vassert(f3 < 0x20); + vassert(op2 < 0x400); + vassert(b0 < 0x2); + UInt theInstr = ((op1<<26) | (f1<<21) | (f2<<16) | + (f3<<11) | (op2<<1) | (b0)); + return emit32(p, theInstr); +} + +// Note: for split field ops, give mnemonic arg +static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt op2 ) +{ + vassert(r1 < 0x20); + vassert(f2 < 0x20); + vassert(op2 < 0x400); + switch (op2) { + case 144: // mtcrf + vassert(f2 < 0x100); + f2 = f2 << 1; + break; + case 339: // mfspr + case 371: // mftb + case 467: // mtspr + vassert(f2 < 0x400); + f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); // re-arrange split field + break; + default: vpanic("mkFormXFX(PPC32)"); + } + UInt theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (op2<<1)); + return emit32(p, theInstr); +} + +#if 0 +// 'b' +static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK ) +{ + vassert(LI < 0x1000000); + vassert(AA < 0x2); + vassert(LK < 0x2); + UInt theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK)); + return emit32(p, theInstr); +} +#endif + +// 'bc' +static UChar* mkFormB ( UChar* p, UInt BO, UInt BI, + UInt BD, UInt AA, UInt LK ) +{ + vassert(BO < 0x20); + vassert(BI < 0x20); + vassert(BD < 0x4000); + vassert(AA < 0x2); + vassert(LK < 0x2); + UInt theInstr = ((16<<26) | (BO<<21) | (BI<<16) | + (BD<<2) | (AA<<1) | (LK)); + return emit32(p, theInstr); +} + +#if 0 +// rotates +static UChar* mkFormM ( UChar* p, UInt op1, UInt r1, UInt r2, + UInt f3, UInt MB, UInt ME, UInt Rc ) +{ + vassert(op1 < 0x40); + vassert(r1 < 0x20); + vassert(r2 < 0x20); + vassert(f3 < 0x20); + vassert(MB < 0x20); + vassert(ME < 0x20); + vassert(Rc < 0x2); + UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) | + (f3<<11) | (MB<<6) | (ME<<1) | (Rc)); + return emit32(p, theInstr); +} +#endif + static UChar* doAMode_IR ( UChar* p, UInt op1, HReg hrSD, PPC32AMode* am ) { vassert(am->tag == Pam_IR); @@ -1881,30 +1963,30 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) } case Pin_Sh32: { - UInt op1 = 31, op2, rB, imm; + UInt opc1 = 31, opc2, rB, sh; UInt op = i->Pin.Sh32.op; - UInt rD = iregNo(i->Pin.Alu32.dst); - UInt rA = iregNo(i->Pin.Alu32.src1); - PPC32RITag ri_tag = i->Pin.Alu32.src2->tag; + UInt rS = iregNo(i->Pin.Sh32.dst); + UInt rA = iregNo(i->Pin.Sh32.src); + PPC32RITag ri_tag = i->Pin.Sh32.shft->tag; if ((op == Psh_SHL || op == Psh_SHR) && ri_tag == Pri_Imm) goto bad; // No imm versions of these switch (op) { - case Psh_SHL: op2 = 24; break; - case Psh_SHR: op2 = 536; break; - case Psh_SAR: op2 = (ri_tag == Pri_Reg) ? 792 : 824; break; + case Psh_SHL: opc2 = 24; break; + case Psh_SHR: opc2 = 536; break; + case Psh_SAR: opc2 = (ri_tag == Pri_Reg) ? 792 : 824; break; default: goto bad; } switch (i->Pin.Sh32.shft->tag) { case Pri_Reg: - rB = iregNo(i->Pin.Alu32.src2->Pri.Reg.reg); - p = mkFormX(p, op1, rD, rA, rB, op2, 0); + rB = iregNo(i->Pin.Sh32.shft->Pri.Reg.reg); + p = mkFormX(p, opc1, rS, rA, rB, opc2, 0); break; case Pri_Imm: - imm = i->Pin.Alu32.src2->Pri.Imm.imm32; - p = mkFormX(p, op1, rD, rA, imm, op2, 0); + sh = i->Pin.Sh32.shft->Pri.Imm.imm32; + p = mkFormX(p, opc1, rS, rA, sh, opc2, 0); break; default: goto bad; @@ -1923,9 +2005,8 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) //.. } //.. break; -//.. case Pin_Cmp32: -//.. //... -//.. break; +//.. case Pin_Cmp32: +//.. goto done; //.. case Xin_Unary32: //.. if (i->Xin.Unary32.op == Xun_NOT) { @@ -2018,99 +2099,104 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) //.. goto bad; //.. } - case Pin_Call: + case Pin_Call: { + Addr32 target; + /* As per detailed comment for Ain_Call in getRegUsage_PPC32Instr above, %r12 is used as an address temporary. */ /* jump over the following two insns if the condition does not hold */ if (i->Pin.Call.cond.test != Pct_ALWAYS) { - -//.. *p++ = 0x70 + (0xF & (i->Pin.Call.cond ^ 1)); -//.. *p++ = 16; /* 16 bytes in the next two insns */ + target = 16; /* num bytes in next insts */ + /* bca ct,cf,target */ + p = mkFormB(p, invertCondTest(i->Pin.Call.cond.test), + (31 - i->Pin.Call.cond.flag), + target, 1, 0); } - /* la $target, %r12 */ -//.. *p++ = 0x49; -//.. *p++ = 0xBB; -//.. p = emit32(p, i->Ain.Call.target); + /* addi r12,0,(target & 0xFFFF) + addis r12,r12,((target >> 16) & 0xFFFF) => load target to r12 */ + target = i->Pin.Call.target; + p = mkFormD(p, 14, 12, 0, (target & 0xFFFF)); + p = mkFormD(p, 15, 12, 12, ((target>>16) & 0xFFFF) ); - /* call *%r12 */ -//.. *p++ = 0x41; -//.. *p++ = 0xFF; -//.. *p++ = 0xD3; + /* mtspr 9,r12 => move r12 to count register */ + p = mkFormXFX(p, 12, 9, 467); + + /* bcctrl 20,0 => branch w. link to count register */ + p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); -// goto done; - goto bad; +/* CAB: Hmm... + "When possible, independent instructions should separate the load + of the Count Register from the branch to prevent pipeline stalls." */ -//.. case Xin_Goto: -//.. /* Use ptmp for backpatching conditional jumps. */ -//.. ptmp = NULL; -//.. -//.. /* First off, if this is conditional, create a conditional -//.. jump over the rest of it. */ -//.. if (i->Xin.Goto.cond != Xcc_ALWAYS) { -//.. /* jmp fwds if !condition */ -//.. *p++ = 0x70 + (i->Xin.Goto.cond ^ 1); -//.. ptmp = p; /* fill in this bit later */ -//.. *p++ = 0; /* # of bytes to jump over; don't know how many yet. */ -//.. } -//.. -//.. /* If a non-boring, set %ebp (the guest state pointer) -//.. appropriately. */ -//.. /* movl $magic_number, %ebp */ -//.. switch (i->Xin.Goto.jk) { -//.. case Ijk_ClientReq: -//.. *p++ = 0xBD; -//.. p = emit32(p, VEX_TRC_JMP_CLIENTREQ); break; -//.. case Ijk_Syscall: -//.. *p++ = 0xBD; -//.. p = emit32(p, VEX_TRC_JMP_SYSCALL); break; -//.. case Ijk_Yield: -//.. *p++ = 0xBD; -//.. p = emit32(p, VEX_TRC_JMP_YIELD); break; -//.. case Ijk_EmWarn: -//.. *p++ = 0xBD; -//.. p = emit32(p, VEX_TRC_JMP_EMWARN); break; -//.. case Ijk_MapFail: -//.. *p++ = 0xBD; -//.. p = emit32(p, VEX_TRC_JMP_MAPFAIL); break; -//.. case Ijk_NoDecode: -//.. *p++ = 0xBD; -//.. p = emit32(p, VEX_TRC_JMP_NODECODE); break; -//.. case Ijk_Ret: -//.. case Ijk_Call: -//.. case Ijk_Boring: -//.. break; -//.. default: -//.. ppIRJumpKind(i->Xin.Goto.jk); -//.. vpanic("emit_X86Instr.Xin_Goto: unknown jump kind"); -//.. } -//.. -//.. /* Get the destination address into %eax */ -//.. if (i->Xin.Goto.dst->tag == Xri_Imm) { -//.. /* movl $immediate, %eax ; ret */ -//.. *p++ = 0xB8; -//.. p = emit32(p, i->Xin.Goto.dst->Xri.Imm.imm32); -//.. } else { -//.. vassert(i->Xin.Goto.dst->tag == Xri_Reg); -//.. /* movl %reg, %eax ; ret */ -//.. if (i->Xin.Goto.dst->Xri.Reg.reg != hregX86_EAX()) { -//.. *p++ = 0x89; -//.. p = doAMode_R(p, i->Xin.Goto.dst->Xri.Reg.reg, hregX86_EAX()); -//.. } -//.. } -//.. -//.. /* ret */ -//.. *p++ = 0xC3; -//.. -//.. /* Fix up the conditional jump, if there was one. */ -//.. if (i->Xin.Goto.cond != Xcc_ALWAYS) { -//.. Int delta = p - ptmp; -//.. vassert(delta > 0 && delta < 20); -//.. *ptmp = (UChar)(delta-1); -//.. } -//.. goto done; + goto done; + } + + case Pin_Goto: { + UInt magic_num = 0; + UChar r_dst, r_src; + PPC32CondCode cond = i->Pin.Goto.cond; + UInt imm; + + /* First off, if this is conditional, create a conditional + jump over the rest of it. */ + if (cond.test != Pct_ALWAYS) { + /* jmp fwds if !condition */ + imm = 8; /* num bytes in next insts */ + /* bca ct,cf,imm */ + p = mkFormB(p, invertCondTest(cond.test), + (31 - cond.flag), imm, 1, 0); + } + + /* If a non-boring, set GuestStatePtr appropriately. */ + /* addi r31,0,magic_num */ + switch (i->Pin.Goto.jk) { + case Ijk_ClientReq: magic_num = VEX_TRC_JMP_CLIENTREQ; break; + case Ijk_Syscall: magic_num = VEX_TRC_JMP_SYSCALL; break; + case Ijk_Yield: magic_num = VEX_TRC_JMP_YIELD; break; + case Ijk_EmWarn: magic_num = VEX_TRC_JMP_EMWARN; break; + case Ijk_MapFail: magic_num = VEX_TRC_JMP_MAPFAIL; break; + case Ijk_NoDecode: magic_num = VEX_TRC_JMP_NODECODE; break; + case Ijk_Ret: + case Ijk_Call: + case Ijk_Boring: + break; + default: + ppIRJumpKind(i->Pin.Goto.jk); + vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind"); + } + if (magic_num !=0) { + vassert(magic_num < 0x10000); + p = mkFormD(p, 14, 31, 0, magic_num); + } + + + /* Get the destination address into %r4 */ +// CAB: Which reg? On amd64,x86, does 'ret' use rax,eax somehow? + r_dst = 4; + if (i->Pin.Goto.dst->tag == Pri_Imm) { + /* addi r_dst,0,(imm & 0xFFFF) + addis r_dst,r_dst,((imm >> 16) & 0xFFFF) */ + imm = i->Pin.Goto.dst->Pri.Imm.imm32; + p = mkFormD(p, 14, r_dst, 0, (imm & 0xFFFF)); + p = mkFormD(p, 15, r_dst, r_dst, ((imm>>16) & 0xFFFF)); + } else { + vassert(i->Pin.Goto.dst->tag == Pri_Reg); + if (i->Pin.Goto.dst->Pri.Reg.reg != hregPPC32_GPR4()) { + /* add r_dst, 0, r_src */ + r_src = iregNo(i->Pin.Goto.dst->Pri.Reg.reg); + p = mkFormXO(p, 31, r_dst, 0, r_src, 0, 266, 0); + /* noop */ + p = mkFormD(p, 24, 0, 0, 0); + } + } + + /* ret => bclr (always),0 */ + p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); + goto done; + } //.. case Xin_CMov32: //.. vassert(i->Xin.CMov32.cond != Xcc_ALWAYS); diff --git a/VEX/priv/host-ppc32/hdefs.h b/VEX/priv/host-ppc32/hdefs.h index 750706017..8708d3243 100644 --- a/VEX/priv/host-ppc32/hdefs.h +++ b/VEX/priv/host-ppc32/hdefs.h @@ -179,12 +179,14 @@ typedef typedef enum { /* Reflects bc bitfield BO */ - Pct_TRUE = 0, - Pct_FALSE = 1, - Pct_ALWAYS = 2 + Pct_FALSE = 0x4, + Pct_TRUE = 0xC, + Pct_ALWAYS = 0x14 } PPC32CondTest; +extern PPC32CondTest invertCondTest ( PPC32CondTest ); + typedef struct { PPC32CondFlag flag; @@ -197,6 +199,7 @@ extern HChar* showPPC32CondCode ( PPC32CondCode ); + /* --------- Memory address expressions (amodes). --------- */ typedef @@ -415,10 +418,10 @@ typedef } MulL; /* ppc32 div/idiv instruction. Modifies EDX and EAX and reads src. */ struct { - Bool syned; - HReg dst; - HReg src1; - PPC32RI* src2; + Bool syned; + HReg dst; + HReg src1; + HReg src2; } Div; //.. /* shld/shrd. op may only be Xsh_SHL or Xsh_SHR */ //.. struct { @@ -559,7 +562,7 @@ extern PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp, HReg, HReg, PPC32RI* ); extern PPC32Instr* PPC32Instr_Cmp32 ( PPC32CmpOp, UInt, HReg, PPC32RI* ); extern PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ); extern PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg, HReg, PPC32RI* ); -extern PPC32Instr* PPC32Instr_Div ( Bool syned, HReg, HReg, PPC32RI* ); +extern PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg src1, HReg src2 ); //.. extern X86Instr* X86Instr_Sh3232 ( X86ShiftOp, UInt amt, HReg src, HReg dst ); //.. extern X86Instr* X86Instr_Push ( X86RMI* ); extern PPC32Instr* PPC32Instr_Call ( PPC32CondCode, Addr32, Int ); diff --git a/VEX/priv/host-ppc32/isel.c b/VEX/priv/host-ppc32/isel.c index 78c9113a7..9a9b908a3 100644 --- a/VEX/priv/host-ppc32/isel.c +++ b/VEX/priv/host-ppc32/isel.c @@ -825,9 +825,16 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) values are on the second operand. */ if (aluOp != Palu_INVALID) { HReg dst = newVRegI(env); + HReg tmp = newVRegI(env); HReg src = iselIntExpr_R(env, e->Iex.Binop.arg1); PPC32RI* ri = iselIntExpr_RI(env, e->Iex.Binop.arg2); - addInstr(env, PPC32Instr_Alu32(aluOp, dst, src, ri)); + + if (ri->tag == Pri_Imm && ri->Pri.Imm.imm32 < 0x10000) { + addInstr(env, PPC32Instr_Alu32(aluOp, dst, src, ri)); + } else { + addInstr(env, mk_iMOVds_RRI(env, tmp, ri)); + addInstr(env, PPC32Instr_Alu32(aluOp, dst, src, PPC32RI_Reg(tmp))); + } return dst; } //.. /* Could do better here; forcing the first arg into a reg @@ -850,17 +857,31 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) /* How about a div? */ if (e->Iex.Binop.op == Iop_DivU32) { - HReg dst = newVRegI(env); - HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1); - PPC32RI* ri_src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2); - addInstr(env, PPC32Instr_Div(False, dst, src1, ri_src2)); + HReg dst = newVRegI(env); + HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1); + PPC32RI* ri = iselIntExpr_RI(env, e->Iex.Binop.arg2); + HReg src2; + if (ri->tag == Pri_Imm) { + src2 = newVRegI(env); + addInstr(env, mk_iMOVds_RRI(env, src2, ri)); + } else { + src2 = ri->Pri.Reg.reg; + } + addInstr(env, PPC32Instr_Div(False, dst, src1, src2)); return dst; } if (e->Iex.Binop.op == Iop_DivS32) { - HReg dst = newVRegI(env); - HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1); - PPC32RI* ri_src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2); - addInstr(env, PPC32Instr_Div(True, dst, src1, ri_src2)); + HReg dst = newVRegI(env); + HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1); + PPC32RI* ri = iselIntExpr_RI(env, e->Iex.Binop.arg2); + HReg src2; + if (ri->tag == Pri_Imm) { + src2 = newVRegI(env); + addInstr(env, mk_iMOVds_RRI(env, src2, ri)); + } else { + src2 = ri->Pri.Reg.reg; + } + addInstr(env, PPC32Instr_Div(True, dst, src1, src2)); return dst; } @@ -900,9 +921,10 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) default: break; } - /* Now consider the shift amount. If it's a literal, we + /* Now consider the shift amount. If it's a small literal, we can do a much better job than the general case. */ - if (e->Iex.Binop.arg2->tag == Iex_Const) { + if (e->Iex.Binop.arg2->tag == Iex_Const && + e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 < 32) { /* assert that the IR is well-typed */ Int nshift; vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); @@ -1339,7 +1361,7 @@ static PPC32AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e ) return PPC32AMode_IR(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32, iselIntExpr_R(env, e->Iex.Binop.arg1)); } - + /* Add32(expr,expr) */ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32) { @@ -1446,7 +1468,7 @@ static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) /* Generate code for the arg, and negate the test condition */ PPC32CondCode cond = iselCondCode(env, e->Iex.Unop.arg); vassert(cond.test != Pct_ALWAYS); - cond.test = cond.test ^ 1; + cond.test = invertCondTest(cond.test); return cond; }