From: Julian Seward Date: Thu, 29 Jul 2004 20:31:09 +0000 (+0000) Subject: Fill in many more cases thrown up the QEMU test program. X-Git-Tag: svn/VALGRIND_3_0_1^2~1179 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9511754a3b0b575692cd7a5ac37d439aea668e29;p=thirdparty%2Fvalgrind.git Fill in many more cases thrown up the QEMU test program. git-svn-id: svn://svn.valgrind.org/vex/trunk@155 --- diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index 6ac2557f37..7bf38d6c5d 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -230,6 +230,19 @@ static inline int lshift(int x, int n) return cf | pf | af | zf | sf | of; \ } +/* ROL: cf' = msb(result). of' = msb(result) ^ lsb(result). */ +/* DST = result, SRC = old flags */ +#define ACTIONS_ROL(DATA_BITS,DATA_TYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + int fl \ + = (CC_SRC & ~(CC_O | CC_C)) \ + | (CC_C & (CC_DST >> (DATA_BITS-1))) \ + | (CC_O & (lshift(CC_DST, 11-(DATA_BITS-1)) \ + ^ lshift(CC_DST, 11))); \ + return fl; \ +} + /* ROR: cf' = msb(result). of' = msb(result) ^ msb-1(result). */ /* DST = result, SRC = old flags */ #define ACTIONS_ROR(DATA_BITS,DATA_TYPE) \ @@ -267,39 +280,49 @@ static inline int lshift(int x, int n) return cc_src & (CC_MASK_O | CC_MASK_S | CC_MASK_Z | CC_MASK_A | CC_MASK_C | CC_MASK_O); - case CC_OP_ADDB: ACTIONS_ADD( 8, UChar ); + case CC_OP_ADDB: ACTIONS_ADD( 8, UChar ); case CC_OP_ADDW: ACTIONS_ADD( 16, UShort ); - case CC_OP_ADDL: ACTIONS_ADD( 32, UInt ); + case CC_OP_ADDL: ACTIONS_ADD( 32, UInt ); - case CC_OP_ADCB: ACTIONS_ADC( 8, UChar ); + case CC_OP_ADCB: ACTIONS_ADC( 8, UChar ); case CC_OP_ADCW: ACTIONS_ADC( 16, UShort ); - case CC_OP_ADCL: ACTIONS_ADC( 32, UInt ); + case CC_OP_ADCL: ACTIONS_ADC( 32, UInt ); - case CC_OP_SUBB: ACTIONS_SUB( 8, UChar ); + case CC_OP_SUBB: ACTIONS_SUB( 8, UChar ); case CC_OP_SUBW: ACTIONS_SUB( 16, UShort ); - case CC_OP_SUBL: ACTIONS_SUB( 32, UInt ); + case CC_OP_SUBL: ACTIONS_SUB( 32, UInt ); - case CC_OP_SBBB: ACTIONS_SBB( 8, UChar ); + case CC_OP_SBBB: ACTIONS_SBB( 8, UChar ); case CC_OP_SBBW: ACTIONS_SBB( 16, UShort ); - case CC_OP_SBBL: ACTIONS_SBB( 32, UInt ); + case CC_OP_SBBL: ACTIONS_SBB( 32, UInt ); - case CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar ); + case CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar ); case CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort ); - case CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt ); + case CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt ); - case CC_OP_INCB: ACTIONS_INC( 8, UChar ); + case CC_OP_INCB: ACTIONS_INC( 8, UChar ); case CC_OP_INCW: ACTIONS_INC( 16, UShort ); - case CC_OP_INCL: ACTIONS_INC( 32, UInt ); + case CC_OP_INCL: ACTIONS_INC( 32, UInt ); - case CC_OP_DECB: ACTIONS_DEC( 8, UChar ); + case CC_OP_DECB: ACTIONS_DEC( 8, UChar ); case CC_OP_DECW: ACTIONS_DEC( 16, UShort ); - case CC_OP_DECL: ACTIONS_DEC( 32, UInt ); + case CC_OP_DECL: ACTIONS_DEC( 32, UInt ); + + case CC_OP_SHLB: ACTIONS_SHL( 8, UChar ); + case CC_OP_SHLW: ACTIONS_SHL( 16, UShort ); + case CC_OP_SHLL: ACTIONS_SHL( 32, UInt ); + + case CC_OP_SARB: ACTIONS_SAR( 8, UChar ); + case CC_OP_SARW: ACTIONS_SAR( 16, UShort ); + case CC_OP_SARL: ACTIONS_SAR( 32, UInt ); - case CC_OP_SHLL: ACTIONS_SHL( 32, UInt ); - case CC_OP_SARL: ACTIONS_SAR( 32, UInt ); + case CC_OP_ROLB: ACTIONS_ROL( 8, UChar ); + case CC_OP_ROLW: ACTIONS_ROL( 16, UShort ); + case CC_OP_ROLL: ACTIONS_ROL( 32, UInt ); + case CC_OP_RORB: ACTIONS_ROR( 8, UChar ); case CC_OP_RORW: ACTIONS_ROR( 16, UShort ); - case CC_OP_RORL: ACTIONS_ROR( 32, UInt ); + case CC_OP_RORL: ACTIONS_ROR( 32, UInt ); case CC_OP_MULL: ACTIONS_MUL( 32, UInt, Long ); diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index ee6b569784..97b29ee6bd 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -1974,7 +1974,7 @@ void codegen_div ( Int sz, IRTemp t, Bool signed_divide ) assign( src64, binop(Iop_32HLto64, getIReg(4,R_EDX), getIReg(4,R_EAX)) ); assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) ); - putIReg( 4, R_EAX, unop(Iop_64LOto32,mkexpr(dst64)) ); + putIReg( 4, R_EAX, unop(Iop_64to32,mkexpr(dst64)) ); putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) ); break; } @@ -2147,16 +2147,6 @@ UInt dis_Grp2 ( UChar sorb, vassert(sz == 1 || sz == 2 || sz == 4); -#if 0 - switch (gregOfRM(modrm)) { - case 0: op8 = Iop_RolROL; break; case 1: op8 = ROR; break; - case 2: op8 = RCL; break; case 3: op8 = RCR; break; - case 4: op8 = Iop_Shl8; break; case 5: op8 = Iop_Shr8; break; - case 7: op8 = Iop_Sar8; break; - default: vpanic("dis_Grp2(Reg): unhandled case(x86)"); - } -#endif - /* Put value to shift/rotate in dst0. */ if (epartIsReg(modrm)) { assign(dst0, getIReg(sz, eregOfRM(modrm))); @@ -2173,6 +2163,11 @@ UInt dis_Grp2 ( UChar sorb, isRotate = False; switch (gregOfRM(modrm)) { case 0: case 1: isRotate = True; } + if (!isShift && !isRotate) { + vex_printf("\ncase %d\n", gregOfRM(modrm)); + vpanic("dis_Grp2(Reg): unhandled case(x86)"); + } + if (isShift) { IRTemp subshift = newTemp(ty); @@ -2434,7 +2429,7 @@ static void codegen_mulL_A_D ( Int sz, Bool syned, setFlags_MUL ( Ity_I32, t1, tmp, thunkOp ); assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) ); putIReg(4, R_EDX, unop(Iop_64HIto32,mkexpr(res64))); - putIReg(4, R_EAX, unop(Iop_64LOto32,mkexpr(res64))); + putIReg(4, R_EAX, unop(Iop_64to32,mkexpr(res64))); break; } default: @@ -3383,18 +3378,25 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb, tmpRes = newTemp(Ity_I32); tmpSubSh = newTemp(Ity_I32); mkpair = Iop_32HLto64; - getres = left_shift ? Iop_64HIto32 : Iop_64LOto32; + getres = left_shift ? Iop_64HIto32 : Iop_64to32; shift = left_shift ? Iop_Shl64 : Iop_Shr64; mask = mkU8(31); - assign( tmpSH, binop(Iop_And8, shift_amt, mask) ); } else { /* sz == 2 */ - vassert(0); + tmpL = newTemp(Ity_I32); + tmpRes = newTemp(Ity_I16); + tmpSubSh = newTemp(Ity_I16); + mkpair = Iop_16HLto32; + getres = left_shift ? Iop_32HIto16 : Iop_32to16; + shift = left_shift ? Iop_Shl32 : Iop_Shr32; + mask = mkU8(15); } /* Do the shift, calculate the subshift value, and set the flag thunk. */ + assign( tmpSH, binop(Iop_And8, shift_amt, mask) ); + if (left_shift) assign( tmpL, binop(mkpair, mkexpr(esrc), mkexpr(gsrc)) ); else @@ -3408,11 +3410,9 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb, binop(Iop_And8, binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ), mask))) ); - //assign( guard, binop(Iop_CmpNE8, mkexpr(tmpSH), mkU8(0)) ); - setFlags_DSTus_DST1 ( - left_shift ? Iop_Shl8 : Iop_Sar8, - tmpSubSh, tmpRes, ty, tmpSH ); + setFlags_DSTus_DST1 ( left_shift ? Iop_Shl8 : Iop_Sar8, + tmpSubSh, tmpRes, ty, tmpSH ); /* Put result back. */ @@ -7261,13 +7261,14 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) mkU8(d32), NULL ); break; -//-- case 0xD2: /* Grp2 CL,Eb */ -//-- modrm = getUChar(eip); -//-- am_sz = lengthAMode(eip); -//-- d_sz = 0; -//-- sz = 1; -//-- eip = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, ArchReg, R_ECX ); -//-- break; + case 0xD2: /* Grp2 CL,Eb */ + modrm = getUChar(delta); + am_sz = lengthAMode(delta); + d_sz = 0; + sz = 1; + delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, + getIReg(1,R_ECX), "%cl" ); + break; case 0xD3: /* Grp2 CL,Ev */ modrm = getIByte(delta); diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index 9a313f975e..aed8aece4c 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -281,19 +281,17 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) case Iex_Binop: { X86AluOp aluOp; X86ShiftOp shOp; + /* Is it an addition or logical style op? */ switch (e->Iex.Binop.op) { case Iop_Add8: case Iop_Add16: case Iop_Add32: aluOp = Xalu_ADD; break; - case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: aluOp = Xalu_SUB; break; - case Iop_And8: case Iop_And16: case Iop_And32: aluOp = Xalu_AND; break; case Iop_Or8: case Iop_Or16: case Iop_Or32: aluOp = Xalu_OR; break; - case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: aluOp = Xalu_XOR; break; case Iop_Mul32: aluOp = Xalu_MUL; break; @@ -309,19 +307,20 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) addInstr(env, X86Instr_Alu32R(aluOp, rmi, dst)); return dst; } + /* Perhaps a shift op? */ switch (e->Iex.Binop.op) { case Iop_Shl32: case Iop_Shl16: case Iop_Shl8: shOp = Xsh_SHL; break; case Iop_Shr32: case Iop_Shr16: case Iop_Shr8: shOp = Xsh_SHR; break; - case Iop_Sar32: + case Iop_Sar32: case Iop_Sar16: case Iop_Sar8: shOp = Xsh_SAR; break; default: shOp = Xsh_INVALID; break; } if (shOp != Xsh_INVALID) { - HReg dst = newVRegI(env); + HReg dst = newVRegI(env); /* regL = the value to be shifted */ HReg regL = iselIntExpr_R(env, e->Iex.Binop.arg1); @@ -337,7 +336,14 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) addInstr(env, X86Instr_Alu32R( Xalu_AND, X86RMI_Imm(0xFFFF), dst)); break; - case Iop_Sar8: case Iop_Sar16: vassert(0); // fill this in! + case Iop_Sar8: + addInstr(env, X86Instr_Sh32(Xsh_SHL, 24, X86RM_Reg(dst))); + addInstr(env, X86Instr_Sh32(Xsh_SAR, 24, X86RM_Reg(dst))); + break; + case Iop_Sar16: + addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(dst))); + addInstr(env, X86Instr_Sh32(Xsh_SAR, 16, X86RM_Reg(dst))); + break; default: break; } @@ -362,6 +368,21 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) } return dst; } + + /* Handle misc other ops. */ + if (e->Iex.Binop.op == Iop_16HLto32) { + HReg hi16 = newVRegI(env); + HReg lo16 = newVRegI(env); + HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1); + HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2); + addInstr(env, mk_MOVsd_RR(hi16s, hi16)); + addInstr(env, mk_MOVsd_RR(lo16s, lo16)); + addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(hi16))); + addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFFFF), lo16)); + addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo16), hi16)); + return hi16; + } + break; } @@ -405,12 +426,18 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) iselIntExpr64(&rHi,&rLo, env, e->Iex.Unop.arg); return rHi; /* and abandon rLo .. poor wee thing :-) */ } - case Iop_64LOto32: { + case Iop_64to32: { HReg rHi, rLo; iselIntExpr64(&rHi,&rLo, env, e->Iex.Unop.arg); return rLo; /* similar stupid comment to the above ... */ } - + case Iop_32HIto16: { + HReg dst = newVRegI(env); + HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); + addInstr(env, mk_MOVsd_RR(src,dst) ); + addInstr(env, X86Instr_Sh32(Xsh_SHR, 16, X86RM_Reg(dst))); + return dst; + } case Iop_32to8: case Iop_32to16: /* These are both no-ops. */ diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index 600af3e3c7..11d2515fc5 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -89,7 +89,6 @@ void ppIROp ( IROp op ) case Iop_8Sto32: vex_printf("8Sto32"); return; case Iop_16Sto32: vex_printf("16Sto32"); return; case Iop_32to8: vex_printf("32to8"); return; - case Iop_32to16: vex_printf("32to16"); return; case Iop_32to1: vex_printf("32to1"); return; case Iop_1Uto8: vex_printf("1Uto8"); return; @@ -103,8 +102,12 @@ void ppIROp ( IROp op ) case Iop_DivModU64to32: vex_printf("DivModU64to32"); return; case Iop_DivModS64to32: vex_printf("DivModS64to32"); return; + case Iop_32HIto16: vex_printf("32HIto16"); return; + case Iop_32to16: vex_printf("32to16"); return; + case Iop_16HLto32: vex_printf("16HLto32"); return; + case Iop_64HIto32: vex_printf("64HIto32"); return; - case Iop_64LOto32: vex_printf("64LOto32"); return; + case Iop_64to32: vex_printf("64to32"); return; case Iop_32HLto64: vex_printf("32HLto64"); return; default: vpanic("ppIROp(1)"); @@ -481,7 +484,12 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 ) case Iop_DivModS64to32: BINARY(Ity_I64,Ity_I64,Ity_I32); - case Iop_64HIto32: case Iop_64LOto32: + case Iop_32HIto16: case Iop_32to16: + UNARY(Ity_I16,Ity_I32); + case Iop_16HLto32: + BINARY(Ity_I32,Ity_I16,Ity_I16); + + case Iop_64HIto32: case Iop_64to32: UNARY(Ity_I32, Ity_I64); case Iop_32HLto64: BINARY(Ity_I64,Ity_I32,Ity_I32); @@ -491,7 +499,6 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 ) case Iop_8Uto32: UNARY(Ity_I32,Ity_I8); case Iop_16Uto32: UNARY(Ity_I32,Ity_I16); case Iop_32to8: UNARY(Ity_I8,Ity_I32); - case Iop_32to16: UNARY(Ity_I16,Ity_I32); default: ppIROp(op); diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 9c262cdcfb..959a24f228 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -98,9 +98,13 @@ typedef Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, /* Narrowing conversions */ - Iop_32to16, Iop_32to8, + Iop_32to8, + /* 16 <-> 32 bit conversions */ + Iop_32to16, // :: I32 -> I16, low half + Iop_32HIto16, // :: I32 -> I16, high half + Iop_16HLto32, // :: (I16,I16) -> I32 /* 32 <-> 64 bit conversions */ - Iop_64LOto32, // :: I64 -> I32, low half + Iop_64to32, // :: I64 -> I32, low half Iop_64HIto32, // :: I64 -> I32, high half Iop_32HLto64, // :: (I32,I32) -> I64 /* 1-bit stuff */