From: Julian Seward Date: Fri, 12 Jan 2007 21:26:51 +0000 (+0000) Subject: Merge r1725 (Implement rcl{b,w,l,q} on amd64.) X-Git-Tag: svn/VALGRIND_3_2_3^2~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cea23180a6bc0094305dd9f56061fe1c932a00c;p=thirdparty%2Fvalgrind.git Merge r1725 (Implement rcl{b,w,l,q} on amd64.) git-svn-id: svn://svn.valgrind.org/vex/branches/VEX_3_2_BRANCH@1727 --- diff --git a/VEX/priv/guest-amd64/gdefs.h b/VEX/priv/guest-amd64/gdefs.h index dd7c957b4b..1bbfc4c98a 100644 --- a/VEX/priv/guest-amd64/gdefs.h +++ b/VEX/priv/guest-amd64/gdefs.h @@ -111,6 +111,10 @@ extern ULong amd64g_calculate_RCR ( ULong arg, ULong rot_amt, ULong rflags_in, Long sz ); +extern ULong amd64g_calculate_RCL ( + ULong arg, ULong rot_amt, ULong rflags_in, Long sz + ); + extern ULong amd64g_check_fldcw ( ULong fpucw ); extern ULong amd64g_create_fpucw ( ULong fpround ); diff --git a/VEX/priv/guest-amd64/ghelpers.c b/VEX/priv/guest-amd64/ghelpers.c index bdb5d6c4d3..f4a49a0683 100644 --- a/VEX/priv/guest-amd64/ghelpers.c +++ b/VEX/priv/guest-amd64/ghelpers.c @@ -1899,6 +1899,72 @@ ULong amd64g_calculate_RCR ( ULong arg, return wantRflags ? rflags_in : arg; } +ULong amd64g_calculate_RCL ( ULong arg, + ULong rot_amt, + ULong rflags_in, + Long szIN ) +{ + Bool wantRflags = toBool(szIN < 0); + ULong sz = wantRflags ? (-szIN) : szIN; + ULong tempCOUNT = rot_amt & (sz == 8 ? 0x3F : 0x1F); + ULong cf=0, of=0, tempcf; + + switch (sz) { + case 8: + cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; + while (tempCOUNT > 0) { + tempcf = (arg >> 63) & 1; + arg = (arg << 1) | (cf & 1); + cf = tempcf; + tempCOUNT--; + } + of = ((arg >> 63) ^ cf) & 1; + break; + case 4: + while (tempCOUNT >= 33) tempCOUNT -= 33; + cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; + while (tempCOUNT > 0) { + tempcf = (arg >> 31) & 1; + arg = 0xFFFFFFFFULL & ((arg << 1) | (cf & 1)); + cf = tempcf; + tempCOUNT--; + } + of = ((arg >> 31) ^ cf) & 1; + break; + case 2: + while (tempCOUNT >= 17) tempCOUNT -= 17; + cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; + while (tempCOUNT > 0) { + tempcf = (arg >> 15) & 1; + arg = 0xFFFFULL & ((arg << 1) | (cf & 1)); + cf = tempcf; + tempCOUNT--; + } + of = ((arg >> 15) ^ cf) & 1; + break; + case 1: + while (tempCOUNT >= 9) tempCOUNT -= 9; + cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; + while (tempCOUNT > 0) { + tempcf = (arg >> 7) & 1; + arg = 0xFFULL & ((arg << 1) | (cf & 1)); + cf = tempcf; + tempCOUNT--; + } + of = ((arg >> 7) ^ cf) & 1; + break; + default: + vpanic("calculate_RCL(amd64g): invalid size"); + } + + cf &= 1; + of &= 1; + rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O); + rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O); + + return wantRflags ? rflags_in : arg; +} + /* CALLED FROM GENERATED CODE */ /* DIRTY HELPER (non-referentially-transparent) */ diff --git a/VEX/priv/guest-amd64/toIR.c b/VEX/priv/guest-amd64/toIR.c index f5440552e5..ff0c74f010 100644 --- a/VEX/priv/guest-amd64/toIR.c +++ b/VEX/priv/guest-amd64/toIR.c @@ -2996,7 +2996,7 @@ ULong dis_Grp2 ( Prefix pfx, /* delta on entry points at the modrm byte. */ HChar dis_buf[50]; Int len; - Bool isShift, isRotate, isRotateRC; + Bool isShift, isRotate, isRotateC; IRType ty = szToITy(sz); IRTemp dst0 = newTemp(ty); IRTemp dst1 = newTemp(ty); @@ -3020,14 +3020,15 @@ ULong dis_Grp2 ( Prefix pfx, isRotate = False; switch (gregLO3ofRM(modrm)) { case 0: case 1: isRotate = True; } - isRotateRC = toBool(gregLO3ofRM(modrm) == 3); + isRotateC = False; + switch (gregLO3ofRM(modrm)) { case 2: case 3: isRotateC = True; } - if (!isShift && !isRotate && !isRotateRC) { + if (!isShift && !isRotate && !isRotateC) { vex_printf("\ncase %d\n", gregLO3ofRM(modrm)); vpanic("dis_Grp2(Reg): unhandled case(amd64)"); } - if (isRotateRC) { + if (isRotateC) { /* Call a helper; this insn is so ridiculous it does not deserve better. One problem is, the helper has to calculate both the new value and the new flags. This is more than 64 bits, and @@ -3036,6 +3037,7 @@ ULong dis_Grp2 ( Prefix pfx, using the sign of the sz field to indicate whether it is the value or rflags result we want. */ + Bool left = toBool(gregLO3ofRM(modrm) == 2); IRExpr** argsVALUE; IRExpr** argsRFLAGS; @@ -3054,7 +3056,8 @@ ULong dis_Grp2 ( Prefix pfx, mkIRExprCCall( Ity_I64, 0/*regparm*/, - "amd64g_calculate_RCR", &amd64g_calculate_RCR, + left ? "amd64g_calculate_RCL" : "amd64g_calculate_RCR", + left ? &amd64g_calculate_RCL : &amd64g_calculate_RCR, argsVALUE ) ); @@ -3068,7 +3071,8 @@ ULong dis_Grp2 ( Prefix pfx, mkIRExprCCall( Ity_I64, 0/*regparm*/, - "amd64g_calculate_RCR", &amd64g_calculate_RCR, + left ? "amd64g_calculate_RCL" : "amd64g_calculate_RCR", + left ? &amd64g_calculate_RCL : &amd64g_calculate_RCR, argsRFLAGS ) );