From: Julian Seward Date: Sat, 14 Aug 2004 11:50:01 +0000 (+0000) Subject: More x86 FP stuff, including conversion stuff to/from Ints. X-Git-Tag: svn/VALGRIND_3_0_1^2~1167 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0755c154c1eee5531b8e0d78294af235104f62e2;p=thirdparty%2Fvalgrind.git More x86 FP stuff, including conversion stuff to/from Ints. git-svn-id: svn://svn.valgrind.org/vex/trunk@167 --- diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 43f9044792..1b15922143 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -3142,8 +3142,9 @@ static UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) { Int len; + UInt src; Char dis_buf[32]; - UInt opc_aux; + IRTemp t1; /* On entry, delta points at the second byte of the insn (the modrm byte).*/ @@ -3159,13 +3160,56 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */ else if (first_opcode == 0xD9) { - goto decode_fail; + if (modrm < 0xC0) { + goto decode_fail; + } else { + delta++; + switch (modrm) { + case 0xC0 ... 0xC7: /* FLD %st(?) */ + src = (UInt)modrm - 0xC0; + DIP("fld %%st(%d)\n", src); + t1 = newTemp(Ity_F64); + assign(t1, get_ST(src)); + stmt( do_push() ); + stmt( put_ST(0, mkexpr(t1)) ); + break; + + default: + goto decode_fail; + } + } } /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */ else if (first_opcode == 0xDA) { - goto decode_fail; + + if (modrm < 0xC0) { + + /* bits 5,4,3 are an opcode extension, and the modRM also + specifies an address. */ + IRTemp addr = disAMode( &len, sorb, delta, dis_buf ); + delta += len; + + switch (gregOfRM(modrm)) { + case 1: /* FIMUL m32int */ + DIP("fimull %s", dis_buf); + stmt( put_ST(0, + binop(Iop_MulF64, + get_ST(0), + unop(Iop_I64toF64, + unop(Iop_32Sto64, + loadLE(Ity_I32, mkexpr(addr))))))); + break; + + default: + vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm)); + vex_printf("first_opcode == 0xDA\n"); + goto decode_fail; + } + } else { + goto decode_fail; + } } /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */ @@ -3186,18 +3230,18 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) if (modrm < 0xC0) { - /* bits 5,4,3 are an opcode extension, and the modRM also + /* bits 5,4,3 are an opcode extension, and the modRM also specifies an address. */ - IRTemp addr = disAMode( &len, sorb, delta, dis_buf ); - delta += len; + IRTemp addr = disAMode( &len, sorb, delta, dis_buf ); + delta += len; switch (gregOfRM(modrm)) { case 0: /* FLD double-real */ DIP("fldD %s\n", dis_buf); - stmt( do_push() ); - stmt( put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr))) ); - break; + stmt( do_push() ); + stmt( put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr))) ); + break; #if 0 case 2: /* FST double-real */ @@ -3225,10 +3269,10 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) #endif default: - vex_printf("unhandled opc_aux = 0x%2x\n", opc_aux); - vex_printf("first_opcode == 0xDD"); + vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm)); + vex_printf("first_opcode == 0xDD\n"); goto decode_fail; - } + } } else { goto decode_fail; } @@ -3653,7 +3697,7 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb, mask))) ); setFlags_DSTus_DST1 ( left_shift ? Iop_Shl32 : Iop_Sar32, - tmpSubSh, tmpRes, ty, tmpSH ); + tmpSubSh, tmpRes, ty, tmpSH ); /* Put result back. */ @@ -4359,7 +4403,7 @@ void codegen_xchg_eAX_Reg ( Int sz, Int reg ) //-- static //-- Addr dis_SSE3_reg_or_mem ( UCodeBlock* cb, //-- UChar sorb, -//-- Addr eip, +//-- Addr eip, //-- Int sz, //-- Char* name, //-- UChar opc1, diff --git a/VEX/priv/host-x86/hdefs.c b/VEX/priv/host-x86/hdefs.c index dff3c8a037..9ae499ffbc 100644 --- a/VEX/priv/host-x86/hdefs.c +++ b/VEX/priv/host-x86/hdefs.c @@ -410,12 +410,13 @@ Char* showX86ShiftOp ( X86ShiftOp op ) { Char* showX86FpOp ( X86FpOp op ) { switch (op) { - case Xfp_Add: return "add"; - case Xfp_Sub: return "sub"; - case Xfp_Mul: return "mul"; - case Xfp_Div: return "div"; - case Xfp_Sqrt: return "sqrt"; - case Xfp_Negate: return "chs"; + case Xfp_ADD: return "add"; + case Xfp_SUB: return "sub"; + case Xfp_MUL: return "mul"; + case Xfp_DIV: return "div"; + case Xfp_SQRT: return "sqrt"; + case Xfp_NEGATE: return "chs"; + case Xfp_MOV: return "mov"; default: vpanic("ppX86FpOp"); } } @@ -591,9 +592,9 @@ void ppX86Instr ( X86Instr* i ) { case Xin_Sh32: vex_printf("%sl ", showX86ShiftOp(i->Xin.Sh32.op)); if (i->Xin.Sh32.src == 0) - vex_printf(" %%cl,"); + vex_printf("%%cl,"); else - vex_printf(" $%d,", i->Xin.Sh32.src); + vex_printf("$%d,", i->Xin.Sh32.src); ppX86RM(i->Xin.Sh32.dst); return; case Xin_Test32: @@ -674,6 +675,20 @@ void ppX86Instr ( X86Instr* i ) { vex_printf(","); ppX86AMode(i->Xin.Store.dst); return; + case Xin_FpUnary: + vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op)); + ppHRegX86(i->Xin.FpUnary.src); + vex_printf(","); + ppHRegX86(i->Xin.FpUnary.dst); + break; + case Xin_FpBinary: + vex_printf("g%sD ", showX86FpOp(i->Xin.FpBinary.op)); + ppHRegX86(i->Xin.FpBinary.srcL); + vex_printf(","); + ppHRegX86(i->Xin.FpBinary.srcR); + vex_printf(","); + ppHRegX86(i->Xin.FpBinary.dst); + break; case Xin_FpLdSt: if (i->Xin.FpLdSt.isLoad) { vex_printf("gld%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F'); @@ -687,6 +702,18 @@ void ppX86Instr ( X86Instr* i ) { ppX86AMode(i->Xin.FpLdSt.addr); } return; + case Xin_FpI64: + if (i->Xin.FpI64.toInt) { + vassert(0); + } else { + vex_printf("gi64tof64 "); + ppHRegX86(i->Xin.FpI64.iregHi); + vex_printf(":"); + ppHRegX86(i->Xin.FpI64.iregLo); + vex_printf(", "); + ppHRegX86(i->Xin.FpI64.freg); + } + return; default: vpanic("ppX86Instr"); } @@ -773,11 +800,29 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i) addHRegUse(u, HRmRead, i->Xin.Store.src); addRegUsage_X86AMode(u, i->Xin.Store.dst); return; + case Xin_FpUnary: + addHRegUse(u, HRmRead, i->Xin.FpUnary.src); + addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst); + return; + case Xin_FpBinary: + addHRegUse(u, HRmRead, i->Xin.FpBinary.srcL); + addHRegUse(u, HRmRead, i->Xin.FpBinary.srcR); + addHRegUse(u, HRmWrite, i->Xin.FpBinary.dst); + return; case Xin_FpLdSt: addRegUsage_X86AMode(u, i->Xin.FpLdSt.addr); addHRegUse(u, i->Xin.FpLdSt.isLoad ? HRmWrite : HRmRead, i->Xin.FpLdSt.reg); return; + case Xin_FpI64: + if (i->Xin.FpI64.toInt) { + vassert(0); + } else { + addHRegUse(u, HRmWrite, i->Xin.FpI64.freg); + addHRegUse(u, HRmRead, i->Xin.FpI64.iregHi); + addHRegUse(u, HRmRead, i->Xin.FpI64.iregLo); + } + return; default: ppX86Instr(i); vpanic("getRegUsage_X86Instr"); @@ -842,29 +887,54 @@ void mapRegs_X86Instr (HRegRemap* m, X86Instr* i) mapReg(m, &i->Xin.Store.src); mapRegs_X86AMode(m, i->Xin.Store.dst); return; + case Xin_FpBinary: + mapReg(m, &i->Xin.FpBinary.srcL); + mapReg(m, &i->Xin.FpBinary.srcR); + mapReg(m, &i->Xin.FpBinary.dst); + return; case Xin_FpLdSt: mapRegs_X86AMode(m, i->Xin.FpLdSt.addr); mapReg(m, &i->Xin.FpLdSt.reg); return; + case Xin_FpI64: + mapReg(m, &i->Xin.FpI64.freg); + mapReg(m, &i->Xin.FpI64.iregHi); + mapReg(m, &i->Xin.FpI64.iregLo); + return; default: ppX86Instr(i); vpanic("mapRegs_X86Instr"); } } +/* Figure out if i represents a reg-reg move, and if so assign the + source and destination to *src and *dst. If in doubt say No. Used + by the register allocator to do move coalescing. +*/ Bool isMove_X86Instr ( X86Instr* i, HReg* src, HReg* dst ) { - if (i->tag != Xin_Alu32R) - return False; - if (i->Xin.Alu32R.op != Xalu_MOV) - return False; - if (i->Xin.Alu32R.src->tag != Xrmi_Reg) - return False; - *src = i->Xin.Alu32R.src->Xrmi.Reg.reg; - *dst = i->Xin.Alu32R.dst; - return True; + /* Moves between integer regs */ + if (i->tag == Xin_Alu32R) { + if (i->Xin.Alu32R.op != Xalu_MOV) + return False; + if (i->Xin.Alu32R.src->tag != Xrmi_Reg) + return False; + *src = i->Xin.Alu32R.src->Xrmi.Reg.reg; + *dst = i->Xin.Alu32R.dst; + return True; + } + /* Moves between FP regs */ + if (i->tag == Xin_FpUnary) { + if (i->Xin.FpUnary.op != Xfp_MOV) + return False; + *src = i->Xin.FpUnary.src; + *dst = i->Xin.FpUnary.dst; + return True; + } + return False; } + /* x86 spill/reload using the hacked104 testbed. Spill slots start at word 51, and there are 24 in total. */ @@ -1051,6 +1121,20 @@ static UChar* do_fld_st ( UChar* p, Int i ) return p; } +/* Emit f %st(i), 1 <= i <= 5 */ +static UChar* do_fop_st ( UChar* p, X86FpOp op, Int i ) +{ +# define fake(_n) mkHReg((_n), HRcInt, False) + Int subopc; + switch (op) { + case Xfp_MUL: subopc = 1; break; + default: vpanic("do_fop_st: unknown op"); + } + *p++ = 0xD8; + p = doAMode_R(p, fake(subopc), fake(i)); + return p; +# undef fake +} /* Emit an instruction into buf and return the number of bytes used. Note that buf is not the insn's final place, and therefore it is @@ -1511,10 +1595,20 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) } /* if (i->Xin.Store.sz == 1) */ break; + case Xin_FpBinary: + /* gop %srcL, %srcR, %dst + --> ffree %st7 ; fld %st(srcL) ; fop %st(1+srcR) ; fstp %st(1+dst) + */ + p = do_ffree_st7(p); + p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL)); + p = do_fop_st(p, i->Xin.FpBinary.op, 1+hregNumber(i->Xin.FpBinary.srcR)); + p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst)); + goto done; + case Xin_FpLdSt: if (i->Xin.FpLdSt.isLoad) { /* Load from memory into %fakeN. - --> ffree %st(7) ; fld{s/l} amode ; fstp st(I+1) + --> ffree %st(7) ; fld{s/l} amode ; fstp st(N+1) */ p = do_ffree_st7(p); *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD; @@ -1523,7 +1617,7 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) goto done; } else { /* Store from %fakeN into memory. - --> ffree %st(7) ; fld st(I) ; fstp{l|s} amode + --> ffree %st(7) ; fld st(N) ; fstp{l|s} amode */ p = do_ffree_st7(p); p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg)); @@ -1533,6 +1627,27 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) } break; + case Xin_FpI64: + if (i->Xin.FpI64.toInt) { + vassert(0); + } else { + /* gi64tof64 %hi:%lo %fakeN + --> ffree %st7; pushl hi ; pushl lo ; fildll 0(%esp) ; + addl $8,%esp ; fstpl %st(N+1) + */ + /* ffree %st(7) */ + p = do_ffree_st7(p); + /* pushl %hi ; pushl %lo */ + *p++ = 0x50 + hregNumber(i->Xin.FpI64.iregHi); + *p++ = 0x50 + hregNumber(i->Xin.FpI64.iregLo); + /* fildll 0(%esp) */ + *p++ = 0xDF; *p++ = 0x6C; *p++ = 0x24; *p++ = 0x00; + /* addl $8, %esp */ + *p++ = 0x83; *p++ = 0xC4; *p++ = 0x08; + p = do_fstp_st(p, 1+hregNumber(i->Xin.FpI64.freg)); + goto done; + } + default: goto bad; } diff --git a/VEX/priv/host-x86/hdefs.h b/VEX/priv/host-x86/hdefs.h index 32afc1acd0..5e698f703f 100644 --- a/VEX/priv/host-x86/hdefs.h +++ b/VEX/priv/host-x86/hdefs.h @@ -245,8 +245,11 @@ extern Char* showX86ShiftOp ( X86ShiftOp ); /* --------- */ typedef enum { - Xfp_Add, Xfp_Sub, Xfp_Mul, Xfp_Div, - Xfp_Sqrt, Xfp_Negate + Xfp_INVALID, + /* Binary */ + Xfp_ADD, Xfp_SUB, Xfp_MUL, Xfp_DIV, + /* Unary */ + Xfp_SQRT, Xfp_NEGATE, Xfp_MOV } X86FpOp; diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index d5b892a792..622241e970 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -841,6 +841,20 @@ static void iselIntExpr64 ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) return; } + /* 32Sto64(e) */ + if (e->tag == Iex_Unop + && e->Iex.Unop.op == Iop_32Sto64) { + HReg tLo = newVRegI(env); + HReg tHi = newVRegI(env); + HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); + addInstr(env, mk_MOVsd_RR(src,tHi)); + addInstr(env, mk_MOVsd_RR(src,tLo)); + addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(tHi))); + *rHi = tHi; + *rLo = tLo; + return; + } + /* 64-bit shifts */ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Shl64) { @@ -949,6 +963,10 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) vassert(e); vassert(typeOfIRExpr(env->type_env,e) == Ity_F64); + if (e->tag == Iex_Tmp) { + return lookupIRTemp(env, e->Iex.Tmp.tmp); + } + if (e->tag == Iex_LDle) { X86AMode* am; HReg res = newVRegF(env); @@ -958,8 +976,45 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) return res; } + if (e->tag == Iex_GetI) { + /* First off, compute the index expression into an integer reg. + The written address will then be 0 + ebp + reg*1, that is, an + X86AMode_IRRS. */ + HReg idx = iselIntExpr_R(env, e->Iex.GetI.offset); + HReg res = newVRegF(env); + addInstr(env, + X86Instr_FpLdSt( True/*load*/, 8, res, + X86AMode_IRRS(0, hregX86_EBP(), idx, 0)) ); + return res; + } + + if (e->tag == Iex_Binop) { + X86FpOp fpop = Xfp_INVALID; + switch (e->Iex.Binop.op) { + case Iop_MulF64: fpop = Xfp_MUL; break; + default: break; + } + if (fpop != Xfp_INVALID) { + HReg res = newVRegF(env); + HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1); + HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2); + addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res)); + return res; + } + } + + if (e->tag == Iex_Unop) { + if (e->Iex.Unop.op == Iop_I64toF64) { + HReg iHi, iLo; + HReg dst = newVRegF(env); + iselIntExpr64(&iHi, &iLo, env, e->Iex.Unop.arg); + addInstr(env, X86Instr_FpI64(False/*i->f*/,dst,iHi,iLo)); + return dst; + } + } + ppIRExpr(e); - vpanic("iselIntExpr64"); + vpanic("iselDblExpr"); } @@ -1015,9 +1070,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) return; } if (ty == Ity_I8 || ty == Ity_I16) { - /* We're going to write to memory, so compute the RHS into an - X86RI. */ - HReg r = iselIntExpr_R(env, stmt->Ist.Put.expr); + HReg r = iselIntExpr_R(env, stmt->Ist.Put.expr); addInstr(env, X86Instr_Store( ty==Ity_I8 ? 1 : 2, r, @@ -1064,6 +1117,12 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) addInstr(env, mk_MOVsd_RR(rLo,dstLo) ); return; } + if (ty == Ity_F64) { + HReg dst = lookupIRTemp(env, tmp); + HReg src = iselDblExpr(env, stmt->Ist.Tmp.expr); + addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst)); + return; + } break; } @@ -1148,6 +1207,7 @@ HInstrArray* iselBB_X86 ( IRBB* bb, Addr64(*find_helper)(Char*) ) case Ity_I32: hreg = mkHReg(j++, HRcInt, True); break; case Ity_I64: hreg = mkHReg(j++, HRcInt, True); hregHI = mkHReg(j++, HRcInt, True); break; + case Ity_F64: hreg = mkHReg(j++, HRcFloat, True); break; default: ppIRType(bb->tyenv->types[i]); vpanic("iselBB: IRTemp type"); } diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index c28d12ae14..2ce5bd97e7 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -90,6 +90,7 @@ void ppIROp ( IROp op ) case Iop_8Sto16: vex_printf("8Sto16"); return; case Iop_8Sto32: vex_printf("8Sto32"); return; case Iop_16Sto32: vex_printf("16Sto32"); return; + case Iop_32Sto64: vex_printf("32Sto64"); return; case Iop_32to8: vex_printf("32to8"); return; case Iop_32to1: vex_printf("32to1"); return; case Iop_1Uto8: vex_printf("1Uto8"); return; @@ -116,6 +117,9 @@ void ppIROp ( IROp op ) case Iop_64to32: vex_printf("64to32"); return; case Iop_32HLto64: vex_printf("32HLto64"); return; + case Iop_MulF64: vex_printf("MulF64"); return; + case Iop_I64toF64: vex_printf("I64toF64"); return; + default: vpanic("ppIROp(1)"); } @@ -140,6 +144,12 @@ void ppIRExpr ( IRExpr* e ) ppIRType(e->Iex.Get.ty); vex_printf(")"); break; + case Iex_GetI: + vex_printf( "GETI[%d,%d](", e->Iex.GetI.minoff, e->Iex.GetI.maxoff); + ppIRExpr(e->Iex.GetI.offset); + vex_printf("):"); + ppIRType(e->Iex.GetI.ty); + break; case Iex_Tmp: ppIRTemp(e->Iex.Tmp.tmp); break; @@ -542,8 +552,12 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 ) case Iop_8Sto32: UNARY(Ity_I32,Ity_I8); case Iop_16Uto32: UNARY(Ity_I32,Ity_I16); case Iop_16Sto32: UNARY(Ity_I32,Ity_I16); + case Iop_32Sto64: UNARY(Ity_I64,Ity_I32); case Iop_32to8: UNARY(Ity_I8,Ity_I32); + case Iop_MulF64: BINARY(Ity_F64,Ity_F64,Ity_F64); + case Iop_I64toF64: UNARY(Ity_F64,Ity_I64); + default: ppIROp(op); vpanic("typeOfPrimop"); @@ -618,6 +632,8 @@ IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e ) return e->Iex.LDle.ty; case Iex_Get: return e->Iex.Get.ty; + case Iex_GetI: + return e->Iex.GetI.ty; case Iex_Tmp: return lookupIRTypeEnv(tyenv, e->Iex.Tmp.tmp); case Iex_Const: @@ -646,6 +662,7 @@ Bool isPlausibleType ( IRType ty ) switch (ty) { case Ity_INVALID: case Ity_Bit: case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64: + case Ity_F32: case Ity_F64: return True; default: return False; @@ -692,6 +709,9 @@ void useBeforeDef_Expr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, Int* def_counts ) switch (expr->tag) { case Iex_Get: break; + case Iex_GetI: + useBeforeDef_Expr(bb,stmt,expr->Iex.GetI.offset,def_counts); + break; case Iex_Tmp: if (expr->Iex.Tmp.tmp < 0 || expr->Iex.Tmp.tmp >= bb->tyenv->types_used) sanityCheckFail(bb,stmt, "out of range Temp in IRExpr"); @@ -760,6 +780,11 @@ void tcExpr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, IRType gWordTy ) case Iex_Get: case Iex_Tmp: break; + case Iex_GetI: + tcExpr(bb,stmt, expr->Iex.GetI.offset, gWordTy ); + if (typeOfIRExpr(tyenv,expr->Iex.GetI.offset) != Ity_I32) + sanityCheckFail(bb,stmt,"IRExpr.GetI.offset: not :: Ity_I32"); + break; case Iex_Binop: { IRType ttarg1, ttarg2; tcExpr(bb,stmt, expr->Iex.Binop.arg1, gWordTy ); diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 9dd701edef..880cfb8e9c 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -98,7 +98,7 @@ typedef Iop_DivModS64to32, // ditto, signed /* Widening conversions */ Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, - Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, + Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64, /* Narrowing conversions */ Iop_32to8, /* 8 <-> 16 bit conversions */