mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-16 15:44:56 +00:00
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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user