From 42b522cf9be21db8a32937d0642a093ed2b01723 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Fri, 30 Jul 2004 01:52:45 +0000 Subject: [PATCH] Rehash handling of multiply insns in the x86 front end, so as to make the flags work right. git-svn-id: svn://svn.valgrind.org/vex/trunk@160 --- VEX/priv/guest-x86/gdefs.h | 16 ++++++-------- VEX/priv/guest-x86/ghelpers.c | 39 ++++++++++++++++++++++++++++------- VEX/priv/guest-x86/toIR.c | 33 ++++++++++++++++++++++------- 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index b86a392f9..808e9a314 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -92,17 +92,13 @@ enum { CC_OP_RORW, CC_OP_RORL, /* 33 */ - CC_OP_MULB, /* modify all flags, CC_DST = one arg */ - CC_OP_MULW, /* CC_SRC = the other arg */ - CC_OP_MULL, /* 36 */ + CC_OP_UMULB, /* modify all flags, CC_DST = one arg */ + CC_OP_UMULW, /* CC_SRC = the other arg */ + CC_OP_UMULL, /* 36 */ - CC_OP_MULLSB, /* modify all flags, CC_DST = one arg */ - CC_OP_MULLSW, /* CC_SRC = the other arg */ - CC_OP_MULLSL, /* 39 */ - - CC_OP_MULLUB, /* modify all flags, CC_DST = one arg */ - CC_OP_MULLUW, /* CC_SRC = the other arg */ - CC_OP_MULLUL, /* 42 */ + CC_OP_SMULB, /* modify all flags, CC_DST = one arg */ + CC_OP_SMULW, /* CC_SRC = the other arg */ + CC_OP_SMULL, /* 39 */ CC_OP_NUMBER }; diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index 6df69f6bd..9ab4beb5b 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -256,17 +256,38 @@ static inline int lshift(int x, int n) return fl; \ } -#define ACTIONS_MUL(DATA_BITS,DATA_UTYPE,DATA_S2TYPE) \ +#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE,DATA_S2TYPE) \ { \ PREAMBLE(DATA_BITS); \ int cf, pf, af, zf, sf, of; \ - DATA_UTYPE r = ((DATA_UTYPE)CC_SRC) * ((DATA_UTYPE)CC_DST); \ - DATA_S2TYPE rr = ((DATA_S2TYPE)CC_SRC) * ((DATA_S2TYPE)CC_DST); \ - cf = (r == (DATA_UTYPE)(rr >>/*signed*/ DATA_BITS)); \ - pf = parity_table[(uint8_t)r]; \ + DATA_STYPE hi; \ + DATA_STYPE lo = ((DATA_STYPE)CC_SRC) * ((DATA_STYPE)CC_DST); \ + DATA_S2TYPE rr = ((DATA_S2TYPE)((DATA_STYPE)CC_SRC)) \ + * ((DATA_S2TYPE)((DATA_STYPE)CC_DST)); \ + hi = (DATA_STYPE)(rr >>/*s*/ DATA_BITS); \ + cf = (hi != (lo >>/*s*/ (DATA_BITS-1))); \ + pf = parity_table[(uint8_t)lo]; \ af = 0; /* undefined */ \ - zf = (r == 0) << 6; \ - sf = lshift(r, 8 - DATA_BITS) & 0x80; \ + zf = (lo == 0) << 6; \ + sf = lshift(lo, 8 - DATA_BITS) & 0x80; \ + of = cf << 11; \ + return cf | pf | af | zf | sf | of; \ +} + +#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE,DATA_U2TYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + int cf, pf, af, zf, sf, of; \ + DATA_UTYPE hi; \ + DATA_UTYPE lo = ((DATA_UTYPE)CC_SRC) * ((DATA_UTYPE)CC_DST); \ + DATA_U2TYPE rr = ((DATA_U2TYPE)((DATA_UTYPE)CC_SRC)) \ + * ((DATA_U2TYPE)((DATA_UTYPE)CC_DST)); \ + hi = (DATA_UTYPE)(rr >>/*u*/ DATA_BITS); \ + cf = (hi != 0); \ + pf = parity_table[(uint8_t)lo]; \ + af = 0; /* undefined */ \ + zf = (lo == 0) << 6; \ + sf = lshift(lo, 8 - DATA_BITS) & 0x80; \ of = cf << 11; \ return cf | pf | af | zf | sf | of; \ } @@ -324,7 +345,9 @@ static inline int lshift(int x, int n) case CC_OP_RORW: ACTIONS_ROR( 16, UShort ); case CC_OP_RORL: ACTIONS_ROR( 32, UInt ); - case CC_OP_MULL: ACTIONS_MUL( 32, UInt, Long ); + case CC_OP_UMULL: ACTIONS_UMUL( 32, UInt, ULong ); + + case CC_OP_SMULL: ACTIONS_SMUL( 32, Int, Long ); default: /* shouldn't really make these calls from generated code */ diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 770590b1f..0830474b5 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -653,6 +653,10 @@ static IRExpr* calculate_condition ( Condcode cond ) : mk_calculate_eflags_all() ); switch (cond) { + case CondNO: + case CondO: /* OF == 1 */ + e = flag_to_bit0( CC_MASK_O, eflags ); + break; case CondNZ: case CondZ: /* ZF == 1 */ e = flag_to_bit0( CC_MASK_Z, eflags ); @@ -671,6 +675,7 @@ static IRExpr* calculate_condition ( Condcode cond ) case CondS: /* SF == 1 */ e = flag_to_bit0( CC_MASK_S, eflags ); break; + case CondNP: case CondP: /* PF == 1 */ e = flag_to_bit0( CC_MASK_P, eflags ); break; @@ -2457,13 +2462,25 @@ static void codegen_mulL_A_D ( Int sz, Bool syned, case Ity_I32: { IRTemp res64 = newTemp(Ity_I64); IROp mulOp = syned ? Iop_MullS32 : Iop_MullU32; - UInt thunkOp = syned ? CC_OP_MULLSB : CC_OP_MULLUB; + UInt thunkOp = syned ? CC_OP_SMULB : CC_OP_UMULB; 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_64to32,mkexpr(res64))); break; } +#if 0 + case Ity_I16: { + IRTemp res32 = newTemp(Ity_I32); + IROp mulOp = syned ? Iop_MullS16 : Iop_MullU16; + UInt thunkOp = syned ? CC_OP_MULLSB : CC_OP_MULLUB; + setFlags_MUL ( Ity_I16, t1, tmp, thunkOp ); + assign( res32, binop(mulOp, mkexpr(t1), mkexpr(tmp)) ); + putIReg(2, R_EDX, unop(Iop_32HIto16,mkexpr(res32))); + putIReg(2, R_EAX, unop(Iop_32to16,mkexpr(res32))); + break; + } +#endif default: vpanic("codegen_mulL_A_D(x86)"); } @@ -2964,7 +2981,7 @@ static UInt dis_mul_E_G ( UChar sorb, Int size, UInt delta0, - Bool signed_multiply ) + Bool syned ) { Int alen; UChar dis_buf[50]; @@ -2973,17 +2990,17 @@ UInt dis_mul_E_G ( UChar sorb, IRTemp te = newTemp(ty); IRTemp tg = newTemp(ty); - vassert(signed_multiply); + vassert(syned); if (epartIsReg(rm)) { assign( tg, getIReg(size, gregOfRM(rm)) ); assign( te, getIReg(size, eregOfRM(rm)) ); - setFlags_MUL ( ty, te, tg, CC_OP_MULB ); + setFlags_MUL ( ty, te, tg, syned ? CC_OP_SMULB : CC_OP_UMULB ); putIReg(size, gregOfRM(rm), binop(mkSizedOp(ty,Iop_Mul8), mkexpr(te), mkexpr(tg))); - DIP("%smul%c %s, %s\n", signed_multiply ? "i" : "", + DIP("%smul%c %s, %s\n", syned ? "i" : "", nameISize(size), nameIReg(size,eregOfRM(rm)), nameIReg(size,gregOfRM(rm))); @@ -2992,12 +3009,12 @@ UInt dis_mul_E_G ( UChar sorb, IRTemp addr = disAMode( &alen, sorb, delta0, dis_buf ); assign( tg, getIReg(size, gregOfRM(rm)) ); assign( te, loadLE(ty,mkexpr(addr)) ); - setFlags_MUL ( ty, te, tg, CC_OP_MULB ); + setFlags_MUL ( ty, te, tg, syned ? CC_OP_SMULB : CC_OP_UMULB ); putIReg(size, gregOfRM(rm), binop(mkSizedOp(ty,Iop_Mul8), mkexpr(te), mkexpr(tg))); - DIP("%smul%c %s, %s\n", signed_multiply ? "i" : "", + DIP("%smul%c %s, %s\n", syned ? "i" : "", nameISize(size), dis_buf, nameIReg(size,gregOfRM(rm))); return alen+delta0; @@ -3036,7 +3053,7 @@ UInt dis_imul_I_E_G ( UChar sorb, delta += litsize; assign(tl, mkU(ty,d32)); - setFlags_MUL ( ty, te, tl, CC_OP_MULB ); + setFlags_MUL ( ty, te, tl, CC_OP_SMULB ); putIReg(size, gregOfRM(rm), binop(mkSizedOp(ty,Iop_Mul8), mkexpr(te), mkexpr(tl)));