case Pun_NEG: return "neg";
case Pun_CLZ32: return "cntlzw";
case Pun_CLZ64: return "cntlzd";
+ case Pun_EXTSW: return "extsw";
default: vpanic("showPPCUnaryOp");
}
}
vassert(cond.test != Pct_ALWAYS);
return i;
}
-PPCInstr* PPCInstr_Load ( UChar sz, Bool syned,
+PPCInstr* PPCInstr_Load ( UChar sz,
HReg dst, PPCAMode* src, Bool mode64 ) {
PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
i->tag = Pin_Load;
i->Pin.Load.sz = sz;
- i->Pin.Load.syned = syned;
i->Pin.Load.src = src;
i->Pin.Load.dst = dst;
vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
UChar sz = i->Pin.Load.sz;
UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
- HChar* s_syned = i->Pin.Load.syned ? "a" : sz==8 ? "" : "z";
- vex_printf("l%c%s%s ", c_sz, s_syned, idxd ? "x" : "" );
+ vex_printf("l%cz%s ", c_sz, idxd ? "x" : "" );
ppHRegPPC(i->Pin.Load.dst);
vex_printf(",");
ppPPCAMode(i->Pin.Load.src);
switch (hregClass(rreg)) {
case HRcInt64:
vassert(mode64);
- return PPCInstr_Load( 8, False, rreg, am, mode64 );
+ return PPCInstr_Load( 8, rreg, am, mode64 );
case HRcInt32:
vassert(!mode64);
- return PPCInstr_Load( 4, False, rreg, am, mode64 );
+ return PPCInstr_Load( 4, rreg, am, mode64 );
case HRcFlt64:
return PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
case HRcVec128:
UChar* ptmp = p;
vassert(nbuf >= 32);
-// vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
+ if (0) {
+ vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
+ }
switch (i->tag) {
p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
break;
case Pun_CLZ64: // cntlzd r_dst, r_src
+ vassert(mode64);
p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0);
break;
+ case Pun_EXTSW: // extsw r_dst, r_src
+ vassert(mode64);
+ p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0);
+ break;
default: goto bad;
}
goto done;
case Pin_Load: {
PPCAMode* am_addr = i->Pin.Load.src;
UInt r_dst = iregNo(i->Pin.Load.dst, mode64);
- Bool syned = i->Pin.Load.syned;
UInt opc1, opc2, sz = i->Pin.Load.sz;
switch (am_addr->tag) {
case Pam_IR:
switch(sz) {
- case 1: opc1 = 34; break;
- case 2: opc1 = (syned) ? 42: 40; break;
- case 4: opc1 = 32; break;
- case 8: opc1 = 58; break;
- default:
- goto bad;
+ case 1: opc1 = 34; break;
+ case 2: opc1 = 40; break;
+ case 4: opc1 = 32; break;
+ case 8: opc1 = 58; vassert(mode64); break;
+ default: goto bad;
}
p = doAMode_IR(p, opc1, r_dst, am_addr, mode64);
goto done;
case Pam_RR:
switch(sz) {
- case 1: opc2 = 87; break;
- case 2: opc2 = (syned) ? 343: 279; break;
- case 4: opc2 = 23; break;
- case 8: opc2 = 21; break;
- default:
- goto bad;
+ case 1: opc2 = 87; break;
+ case 2: opc2 = 279; break;
+ case 4: opc2 = 23; break;
+ case 8: opc2 = 21; vassert(mode64); break;
+ default: goto bad;
}
p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64);
goto done;
p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0);
goto done;
}
+ if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) {
+ // fctid (conv f64 to i64), PPC64 p437
+ p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0);
+ goto done;
+ }
+ if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
+ // fcfid (conv i64 to f64), PPC64 p434
+ p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
+ goto done;
+ }
goto bad;
}
-// case Pin_FpF64toI32: {
-// UInt r_dst = iregNo(i->Pin.FpF64toI32.dst, mode64);
-// UInt fr_src = fregNo(i->Pin.FpF64toI32.src);
-// UChar fr_tmp = 7; // Temp freg
-// PPCAMode* am_addr;
-//
-// // fctiw (conv f64 to i32), PPC32 p404
-// p = mkFormX(p, 63, fr_tmp, 0, fr_src, 14, 0);
-//
-// // No RI form of stfiwx, so need PPCAMode_RR:
-// am_addr = PPCAMode_RR( StackFramePtr(mode64),
-// hregPPC_GPR0(mode64) );
-//
-// // stfiwx (store fp64[lo32] as int32), PPC32 p517
-// p = doAMode_RR(p, 31, 983, fr_tmp, am_addr, mode64);
-//
-// // lwzx (load int32), PPC32 p463
-// p = doAMode_RR(p, 31, 23, r_dst, am_addr, mode64);
-// goto done;
-// }
-//
-// case Pin_FpF64toI64: {
-// UInt r_dst = iregNo(i->Pin.FpF64toI64.dst, mode64);
-// UInt fr_src = fregNo(i->Pin.FpF64toI64.src);
-// UChar fr_tmp = 7; // Temp freg
-// PPCAMode* am_addr;
-//
-// // fctid (conv f64 to i64), PPC64 p437
-// p = mkFormX(p, 63, fr_tmp, 0, fr_src, 814, 0);
-//
-// am_addr = PPCAMode_RR( StackFramePtr(mode64),
-// hregPPC_GPR0(mode64) );
-//
-// // stfdx (store fp64), PPC64 p589
-// p = doAMode_RR(p, 31, 727, fr_tmp, am_addr, mode64);
-//
-// // ldx (load int64), PPC64 p476
-// p = doAMode_RR(p, 31, 21, r_dst, am_addr, mode64);
-// goto done;
-// }
-//
-// case Pin_FpI64toF64: {
-// UInt r_src = iregNo(i->Pin.FpI64toF64.src, mode64);
-// UInt fr_dst = fregNo(i->Pin.FpI64toF64.dst);
-// UChar fr_tmp = 7; // Temp freg
-// PPCAMode* am_addr = PPCAMode_RR( StackFramePtr(mode64),
-// hregPPC_GPR0(mode64) );
-//
-// // stdx r_src,r0,r1
-// p = doAMode_RR(p, 31, 149, r_src, am_addr, mode64);
-//
-// // lfdx fr7,r0,r1
-// p = doAMode_RR(p, 31, 599, fr_tmp, am_addr, mode64);
-//
-// // fcfid (conv i64 to f64), PPC64 p434
-// p = mkFormX(p, 63, fr_dst, 0, fr_tmp, 846, 0);
-// goto done;
-// }
-
case Pin_FpCMov: {
UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
UInt fr_src = fregNo(i->Pin.FpCMov.src);
Pun_NEG,
Pun_NOT,
Pun_CLZ32,
- Pun_CLZ64
+ Pun_CLZ64,
+ Pun_EXTSW
}
PPCUnaryOp;
Pin_Call, /* call to address in register */
Pin_Goto, /* conditional/unconditional jmp to dst */
Pin_CMov, /* conditional move */
- Pin_Load, /* load a 8|16|32|64 bit value from mem */
+ Pin_Load, /* zero-extending load a 8|16|32|64 bit value from mem */
Pin_Store, /* store a 8|16|32|64 bit value to mem */
Pin_Set, /* convert condition code to value 0 or 1 */
Pin_MfCR, /* move from condition register to GPR */
HReg srcL;
PPCRH* srcR;
} Cmp;
- /* Not and Neg */
+ /* Not, Neg, Clz32/64, Extsw */
struct {
PPCUnaryOp op;
HReg dst;
HReg dst;
PPCRI* src;
} CMov;
- /* Sign/Zero extending loads. Dst size is host word size */
+ /* Zero extending loads. Dst size is host word size */
struct {
UChar sz; /* 1|2|4|8 */
- Bool syned;
HReg dst;
PPCAMode* src;
} Load;
extern PPCInstr* PPCInstr_Call ( PPCCondCode, Addr64, UInt );
extern PPCInstr* PPCInstr_Goto ( IRJumpKind, PPCCondCode cond, PPCRI* dst );
extern PPCInstr* PPCInstr_CMov ( PPCCondCode, HReg dst, PPCRI* src );
-extern PPCInstr* PPCInstr_Load ( UChar sz, Bool syned,
+extern PPCInstr* PPCInstr_Load ( UChar sz,
HReg dst, PPCAMode* src, Bool mode64 );
extern PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst,
HReg src, Bool mode64 );
if (e->Iex.Load.end != Iend_BE)
goto irreducible;
addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
- False, r_dst, am_addr, mode64 ));
+ r_dst, am_addr, mode64 ));
return r_dst;
break;
}
HReg fsrc = iselDblExpr(env, e->Iex.Binop.arg2);
HReg ftmp = newVRegF(env);
HReg idst = newVRegI(env);
- vassert(!env->mode64); // wait for 64-bit test case
+
/* Set host rounding mode */
set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/,
ftmp, fsrc));
addInstr(env, PPCInstr_FpSTFIW(r1, ftmp));
- addInstr(env, PPCInstr_Load(4, True/*signed*/,
- idst, zero_r1, mode64));
+ addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64));
+
+ /* in 64-bit mode we need to sign-widen idst. */
+ if (mode64)
+ addInstr(env, PPCInstr_Unary(Pun_EXTSW, idst, idst));
+
add_to_sp( env, 16 );
/* Restore default FPU rounding. */
}
if (e->Iex.Binop.op == Iop_F64toI64) {
- HReg fr_src = iselDblExpr(env, e->Iex.Binop.arg2);
- HReg r_dst = newVRegI(env);
- /* Set host rounding mode */
- set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
-
- sub_from_sp( env, 16 );
-vassert(0);
-// addInstr(env, PPCInstr_FpF64toI64(r_dst, fr_src));
- add_to_sp( env, 16 );
-
- /* Restore default FPU rounding. */
- set_FPU_rounding_default( env );
- return r_dst;
+ if (mode64) {
+ HReg r1 = StackFramePtr(env->mode64);
+ PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
+ HReg fsrc = iselDblExpr(env, e->Iex.Binop.arg2);
+ HReg idst = newVRegI(env);
+ HReg ftmp = newVRegF(env);
+
+ /* Set host rounding mode */
+ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+
+ sub_from_sp( env, 16 );
+ addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
+ ftmp, fsrc));
+ addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
+ addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
+ add_to_sp( env, 16 );
+
+ /* Restore default FPU rounding. */
+ set_FPU_rounding_default( env );
+ return idst;
+ }
}
break;
if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) {
HReg r_dst = newVRegI(env);
PPCAMode* amode = iselWordExpr_AMode( env, mi.bindee[0] );
- addInstr(env, PPCInstr_Load(2,False,r_dst,amode, mode64));
+ addInstr(env, PPCInstr_Load(2,r_dst,amode, mode64));
return r_dst;
}
}
addInstr(env,
PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
addInstr(env,
- PPCInstr_Load( 4, False, dst, am_off12, mode64 ));
+ PPCInstr_Load( 4, dst, am_off12, mode64 ));
add_to_sp( env, 32 ); // Reset SP
return dst;
PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
addInstr(env,
PPCInstr_Load(
- 8, False, dst,
+ 8, dst,
op_unop == Iop_V128HIto64 ? am_off0 : am_off8,
mode64 ));
addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
fr_src, am_addr ));
// load as Ity_I64
- addInstr(env, PPCInstr_Load( 8, False,
- r_dst, am_addr, mode64 ));
+ addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
add_to_sp( env, 16 ); // Reset SP
return r_dst;
PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
GuestStatePtr(mode64) );
addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
- False, r_dst, am_addr, mode64 ));
+ r_dst, am_addr, mode64 ));
return r_dst;
}
break;
e->Iex.GetI.ix, e->Iex.GetI.bias );
HReg r_dst = newVRegI(env);
addInstr(env, PPCInstr_Load( toUChar(8),
- False, r_dst, src_am, mode64 ));
+ r_dst, src_am, mode64 ));
return r_dst;
}
break;
PPCAMode* am_addr4 = advance4(env, am_addr);
HReg tLo = newVRegI(env);
HReg tHi = newVRegI(env);
- addInstr(env, PPCInstr_Load( 4, False, tHi, am_addr, False/*mode32*/ ));
- addInstr(env, PPCInstr_Load( 4, False, tLo, am_addr4, False/*mode32*/ ));
+ addInstr(env, PPCInstr_Load( 4, tHi, am_addr, False/*mode32*/ ));
+ addInstr(env, PPCInstr_Load( 4, tLo, am_addr4, False/*mode32*/ ));
*rHi = tHi;
*rLo = tLo;
return;
// load hi,lo words (of hi/lo half of vec) as Ity_I32's
addInstr(env,
- PPCInstr_Load( 4, False, tHi, am_offHI, False/*mode32*/ ));
+ PPCInstr_Load( 4, tHi, am_offHI, False/*mode32*/ ));
addInstr(env,
- PPCInstr_Load( 4, False, tLo, am_offLO, False/*mode32*/ ));
+ PPCInstr_Load( 4, tLo, am_offLO, False/*mode32*/ ));
add_to_sp( env, 32 ); // Reset SP
*rHi = tHi;
fr_src, am_addr0 ));
// load hi,lo as Ity_I32's
- addInstr(env, PPCInstr_Load( 4, False, r_dstHi,
+ addInstr(env, PPCInstr_Load( 4, r_dstHi,
am_addr0, False/*mode32*/ ));
- addInstr(env, PPCInstr_Load( 4, False, r_dstLo,
+ addInstr(env, PPCInstr_Load( 4, r_dstLo,
am_addr1, False/*mode32*/ ));
*rHi = r_dstHi;
*rLo = r_dstLo;
}
if (e->Iex.Binop.op == Iop_I64toF64) {
- HReg fr_dst = newVRegF(env);
- HReg r_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
- vassert(mode64);
+ if (mode64) {
+ HReg fdst = newVRegF(env);
+ HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
+ HReg r1 = StackFramePtr(env->mode64);
+ PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
- /* Set host rounding mode */
- set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+ /* Set host rounding mode */
+ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
- sub_from_sp( env, 16 );
-vassert(0);
-// addInstr(env, PPCInstr_FpI64toF64(fr_dst, r_src));
- add_to_sp( env, 16 );
+ sub_from_sp( env, 16 );
- /* Restore default FPU rounding. */
- set_FPU_rounding_default( env );
- return fr_dst;
+ addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
+ addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
+ addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
+ fdst, fdst));
+
+ add_to_sp( env, 16 );
+
+ /* Restore default FPU rounding. */
+ set_FPU_rounding_default( env );
+ return fdst;
+ }
}
}