You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
1
(2) |
2
(9) |
3
(11) |
4
(12) |
5
(6) |
|
6
|
7
|
8
(3) |
9
(10) |
10
(18) |
11
(10) |
12
(5) |
|
13
(4) |
14
(40) |
15
(12) |
16
(8) |
17
(9) |
18
(6) |
19
|
|
20
|
21
|
22
|
23
(4) |
24
(6) |
25
(6) |
26
(1) |
|
27
(3) |
28
(10) |
|
|
|
|
|
|
From: <sv...@va...> - 2011-02-14 15:00:27
|
Author: sewardj
Date: 2011-02-14 15:00:18 +0000 (Mon, 14 Feb 2011)
New Revision: 2103
Log:
Merge from trunk, r2081 (Accept redundant REX.W for EXTRACTPS.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:58:08 UTC (rev 2102)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 15:00:18 UTC (rev 2103)
@@ -14733,7 +14733,7 @@
identical to PEXTRD, except that REX.W appears to be ignored.
*/
if ( have66noF2noF3( pfx )
- && sz == 2 /* REX.W == 0; perhaps too strict? */
+ && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
&& insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x17 ) {
Int imm8_10;
|
|
From: <sv...@va...> - 2011-02-14 14:42:33
|
Author: sewardj
Date: 2011-02-14 14:42:25 +0000 (Mon, 14 Feb 2011)
New Revision: 11559
Log:
Merge from trunk, r11510 (partial): update test's expected output.
Modified:
branches/VALGRIND_3_6_BRANCH/memcheck/tests/mempool.stderr.exp
Modified: branches/VALGRIND_3_6_BRANCH/memcheck/tests/mempool.stderr.exp
===================================================================
--- branches/VALGRIND_3_6_BRANCH/memcheck/tests/mempool.stderr.exp 2011-02-14 11:50:49 UTC (rev 11558)
+++ branches/VALGRIND_3_6_BRANCH/memcheck/tests/mempool.stderr.exp 2011-02-14 14:42:25 UTC (rev 11559)
@@ -1,19 +1,17 @@
Invalid write of size 1
at 0x........: test (mempool.c:130)
by 0x........: main (mempool.c:154)
- Address 0x........ is 7 bytes inside a block of size 100,000 alloc'd
- at 0x........: malloc (vg_replace_malloc.c:...)
- by 0x........: make_pool (mempool.c:44)
- by 0x........: test (mempool.c:117)
+ Address 0x........ is 1 bytes before a block of size 10 client-defined
+ at 0x........: allocate (mempool.c:105)
+ by 0x........: test (mempool.c:121)
by 0x........: main (mempool.c:154)
Invalid write of size 1
at 0x........: test (mempool.c:131)
by 0x........: main (mempool.c:154)
- Address 0x........ is 18 bytes inside a block of size 100,000 alloc'd
- at 0x........: malloc (vg_replace_malloc.c:...)
- by 0x........: make_pool (mempool.c:44)
- by 0x........: test (mempool.c:117)
+ Address 0x........ is 0 bytes after a block of size 10 client-defined
+ at 0x........: allocate (mempool.c:105)
+ by 0x........: test (mempool.c:121)
by 0x........: main (mempool.c:154)
Invalid write of size 1
|
|
From: <sv...@va...> - 2011-02-14 13:58:17
|
Author: sewardj
Date: 2011-02-14 13:58:08 +0000 (Mon, 14 Feb 2011)
New Revision: 2102
Log:
Merge from trunk, r2088 (Handle Ico_V128(0xFFFF))
Modified:
branches/VEX_3_6_BRANCH/priv/host_ppc_isel.c
Modified: branches/VEX_3_6_BRANCH/priv/host_ppc_isel.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/host_ppc_isel.c 2011-02-14 13:56:17 UTC (rev 2101)
+++ branches/VEX_3_6_BRANCH/priv/host_ppc_isel.c 2011-02-14 13:58:08 UTC (rev 2102)
@@ -994,7 +994,17 @@
return dst;
}
+/* Generate all-ones into a new vector register.
+*/
+static HReg generate_ones_V128 ( ISelEnv* env )
+{
+ HReg dst = newVRegV(env);
+ PPCVI5s * src = PPCVI5s_Imm(-1);
+ addInstr(env, PPCInstr_AvSplat(8, dst, src));
+ return dst;
+}
+
/*
Generates code for AvSplat
- takes in IRExpr* of type 8|16|32
@@ -3710,6 +3720,9 @@
vassert(e->Iex.Const.con->tag == Ico_V128);
if (e->Iex.Const.con->Ico.V128 == 0x0000) {
return generate_zeroes_V128(env);
+ }
+ else if (e->Iex.Const.con->Ico.V128 == 0xffff) {
+ return generate_ones_V128(env);
}
}
|
|
From: <sv...@va...> - 2011-02-14 13:56:27
|
Author: sewardj
Date: 2011-02-14 13:56:17 +0000 (Mon, 14 Feb 2011)
New Revision: 2101
Log:
Merge from trunk, r2087 (Handle moves from TPIDRURO to integer
registers in Thumb mode.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_arm_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_arm_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_arm_toIR.c 2011-02-14 13:53:18 UTC (rev 2100)
+++ branches/VEX_3_6_BRANCH/priv/guest_arm_toIR.c 2011-02-14 13:56:17 UTC (rev 2101)
@@ -17746,6 +17746,24 @@
}
}
+ /* -------------- read CP15 TPIDRURO register ------------- */
+ /* mrc p15, 0, r0, c13, c0, 3 up to
+ mrc p15, 0, r14, c13, c0, 3
+ */
+ /* I don't know whether this is really v7-only. But anyway, we
+ have to support it since arm-linux uses TPIDRURO as a thread
+ state register. */
+
+ if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
+ UInt rD = INSN1(15,12);
+ if (!isBadRegT(rD)) {
+ putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
+ DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
+ goto decode_success;
+ }
+ /* fall through */
+ }
+
/* ------------------- NOP ------------------ */
if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
DIP("nop\n");
|
|
From: <sv...@va...> - 2011-02-14 13:53:26
|
Author: sewardj
Date: 2011-02-14 13:53:18 +0000 (Mon, 14 Feb 2011)
New Revision: 2100
Log:
Merge from trunk, r2086 (Get rid of unintended complex integral constant)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_arm_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_arm_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_arm_toIR.c 2011-02-14 13:50:19 UTC (rev 2099)
+++ branches/VEX_3_6_BRANCH/priv/guest_arm_toIR.c 2011-02-14 13:53:18 UTC (rev 2100)
@@ -10985,7 +10985,7 @@
UInt rT = INSN(15,12);
UInt Q = INSN(21,21);
UInt size = (INSN(22,22) << 1) | INSN(5,5);
- if (rT == 15 || (isT && rT == 13) || size == 3i || (Q && (rD & 1))) {
+ if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) {
/* fall through */
} else {
IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
|
|
From: <sv...@va...> - 2011-02-14 13:50:27
|
Author: sewardj
Date: 2011-02-14 13:50:19 +0000 (Mon, 14 Feb 2011)
New Revision: 2099
Log:
Merge from trunk, r2085 (Implement LOOPNEL (32-bit version of LOOPNE).)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:48:03 UTC (rev 2098)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:50:19 UTC (rev 2099)
@@ -16401,18 +16401,33 @@
case 0xE1: /* LOOPE disp8: decrement count, jump if count != 0 && ZF==1 */
case 0xE2: /* LOOP disp8: decrement count, jump if count != 0 */
{ /* The docs say this uses rCX as a count depending on the
- address size override, not the operand one. Since we don't
- handle address size overrides, I guess that means RCX. */
+ address size override, not the operand one. */
IRExpr* zbit = NULL;
IRExpr* count = NULL;
IRExpr* cond = NULL;
HChar* xtra = NULL;
- if (have66orF2orF3(pfx) || haveASO(pfx)) goto decode_failure;
+ if (have66orF2orF3(pfx) || 1==getRexW(pfx)) goto decode_failure;
+ /* So at this point we've rejected any variants which appear to
+ be governed by the usual operand-size modifiers. Hence only
+ the address size prefix can have an effect. It changes the
+ size from 64 (default) to 32. */
d64 = guest_RIP_bbstart+delta+1 + getSDisp8(delta);
delta++;
- putIReg64(R_RCX, binop(Iop_Sub64, getIReg64(R_RCX), mkU64(1)));
+ if (haveASO(pfx)) {
+ /* 64to32 of 64-bit get is merely a get-put improvement
+ trick. */
+ putIReg32(R_RCX, binop(Iop_Sub32,
+ unop(Iop_64to32, getIReg64(R_RCX)),
+ mkU32(1)));
+ } else {
+ putIReg64(R_RCX, binop(Iop_Sub64, getIReg64(R_RCX), mkU64(1)));
+ }
+ /* This is correct, both for 32- and 64-bit versions. If we're
+ doing a 32-bit dec and the result is zero then the default
+ zero extension rule will cause the upper 32 bits to be zero
+ too. Hence a 64-bit check against zero is OK. */
count = getIReg64(R_RCX);
cond = binop(Iop_CmpNE64, count, mkU64(0));
switch (opc) {
@@ -16422,19 +16437,19 @@
case 0xE1:
xtra = "e";
zbit = mk_amd64g_calculate_condition( AMD64CondZ );
- cond = mkAnd1(cond, zbit);
+ cond = mkAnd1(cond, zbit);
break;
case 0xE0:
xtra = "ne";
zbit = mk_amd64g_calculate_condition( AMD64CondNZ );
- cond = mkAnd1(cond, zbit);
+ cond = mkAnd1(cond, zbit);
break;
default:
vassert(0);
}
stmt( IRStmt_Exit(cond, Ijk_Boring, IRConst_U64(d64)) );
- DIP("loop%s 0x%llx\n", xtra, d64);
+ DIP("loop%s%s 0x%llx\n", xtra, haveASO(pfx) ? "l" : "", d64);
break;
}
|
|
From: <sv...@va...> - 2011-02-14 13:48:12
|
Author: sewardj
Date: 2011-02-14 13:48:03 +0000 (Mon, 14 Feb 2011)
New Revision: 2098
Log:
Merge from trunk, r2084 (Implement rex.W/FXSAVE and also both variants
of FXRSTOR.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_defs.h
branches/VEX_3_6_BRANCH/priv/guest_amd64_helpers.c
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_defs.h
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_defs.h 2011-02-14 13:44:28 UTC (rev 2097)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_defs.h 2011-02-14 13:48:03 UTC (rev 2098)
@@ -154,7 +154,8 @@
extern void amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* );
-extern void amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State*, HWord );
+extern void amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State*, HWord );
+extern VexEmWarn amd64g_dirtyhelper_FXRSTOR ( VexGuestAMD64State*, HWord );
extern ULong amd64g_dirtyhelper_RDTSC ( void );
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_helpers.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_helpers.c 2011-02-14 13:44:28 UTC (rev 2097)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_helpers.c 2011-02-14 13:48:03 UTC (rev 2098)
@@ -1454,6 +1454,68 @@
}
+/* This is used to implement both 'frstor' and 'fldenv'. The latter
+ appears to differ from the former only in that the 8 FP registers
+ themselves are not transferred into the guest state. */
+static
+VexEmWarn do_put_x87 ( Bool moveRegs,
+ /*IN*/UChar* x87_state,
+ /*OUT*/VexGuestAMD64State* vex_state )
+{
+ Int stno, preg;
+ UInt tag;
+ ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
+ UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
+ Fpu_State* x87 = (Fpu_State*)x87_state;
+ UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7;
+ UInt tagw = x87->env[FP_ENV_TAG];
+ UInt fpucw = x87->env[FP_ENV_CTRL];
+ UInt c3210 = x87->env[FP_ENV_STAT] & 0x4700;
+ VexEmWarn ew;
+ UInt fpround;
+ ULong pair;
+
+ /* Copy registers and tags */
+ for (stno = 0; stno < 8; stno++) {
+ preg = (stno + ftop) & 7;
+ tag = (tagw >> (2*preg)) & 3;
+ if (tag == 3) {
+ /* register is empty */
+ /* hmm, if it's empty, does it still get written? Probably
+ safer to say it does. If we don't, memcheck could get out
+ of sync, in that it thinks all FP registers are defined by
+ this helper, but in reality some have not been updated. */
+ if (moveRegs)
+ vexRegs[preg] = 0; /* IEEE754 64-bit zero */
+ vexTags[preg] = 0;
+ } else {
+ /* register is non-empty */
+ if (moveRegs)
+ convert_f80le_to_f64le( &x87->reg[10*stno],
+ (UChar*)&vexRegs[preg] );
+ vexTags[preg] = 1;
+ }
+ }
+
+ /* stack pointer */
+ vex_state->guest_FTOP = ftop;
+
+ /* status word */
+ vex_state->guest_FC3210 = c3210;
+
+ /* handle the control word, setting FPROUND and detecting any
+ emulation warnings. */
+ pair = amd64g_check_fldcw ( (ULong)fpucw );
+ fpround = (UInt)pair;
+ ew = (VexEmWarn)(pair >> 32);
+
+ vex_state->guest_FPROUND = fpround & 3;
+
+ /* emulation warnings --> caller */
+ return ew;
+}
+
+
/* Create an x87 FPU state from the guest state, as close as
we can approximate it. */
static
@@ -1610,6 +1672,94 @@
}
+/* CALLED FROM GENERATED CODE */
+/* DIRTY HELPER (writes guest state, reads guest mem) */
+VexEmWarn amd64g_dirtyhelper_FXRSTOR ( VexGuestAMD64State* gst, HWord addr )
+{
+ Fpu_State tmp;
+ VexEmWarn warnX87 = EmWarn_NONE;
+ VexEmWarn warnXMM = EmWarn_NONE;
+ UShort* addrS = (UShort*)addr;
+ UChar* addrC = (UChar*)addr;
+ U128* xmm = (U128*)(addr + 160);
+ UShort fp_tags;
+ Int r, stno, i;
+
+ /* Restore %xmm0 .. %xmm15. If the host is big-endian, these need
+ to be byte-swapped. */
+ vassert(host_is_little_endian());
+
+# define COPY_U128(_dst,_src) \
+ do { _dst[0] = _src[0]; _dst[1] = _src[1]; \
+ _dst[2] = _src[2]; _dst[3] = _src[3]; } \
+ while (0)
+
+ COPY_U128( gst->guest_XMM0, xmm[0] );
+ COPY_U128( gst->guest_XMM1, xmm[1] );
+ COPY_U128( gst->guest_XMM2, xmm[2] );
+ COPY_U128( gst->guest_XMM3, xmm[3] );
+ COPY_U128( gst->guest_XMM4, xmm[4] );
+ COPY_U128( gst->guest_XMM5, xmm[5] );
+ COPY_U128( gst->guest_XMM6, xmm[6] );
+ COPY_U128( gst->guest_XMM7, xmm[7] );
+ COPY_U128( gst->guest_XMM8, xmm[8] );
+ COPY_U128( gst->guest_XMM9, xmm[9] );
+ COPY_U128( gst->guest_XMM10, xmm[10] );
+ COPY_U128( gst->guest_XMM11, xmm[11] );
+ COPY_U128( gst->guest_XMM12, xmm[12] );
+ COPY_U128( gst->guest_XMM13, xmm[13] );
+ COPY_U128( gst->guest_XMM14, xmm[14] );
+ COPY_U128( gst->guest_XMM15, xmm[15] );
+
+# undef COPY_U128
+
+ /* Copy the x87 registers out of the image, into a temporary
+ Fpu_State struct. */
+ for (i = 0; i < 14; i++) tmp.env[i] = 0;
+ for (i = 0; i < 80; i++) tmp.reg[i] = 0;
+ /* fill in tmp.reg[0..7] */
+ for (stno = 0; stno < 8; stno++) {
+ UShort* dstS = (UShort*)(&tmp.reg[10*stno]);
+ UShort* srcS = (UShort*)(&addrS[16 + 8*stno]);
+ dstS[0] = srcS[0];
+ dstS[1] = srcS[1];
+ dstS[2] = srcS[2];
+ dstS[3] = srcS[3];
+ dstS[4] = srcS[4];
+ }
+ /* fill in tmp.env[0..13] */
+ tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */
+ tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */
+
+ fp_tags = 0;
+ for (r = 0; r < 8; r++) {
+ if (addrC[4] & (1<<r))
+ fp_tags |= (0 << (2*r)); /* EMPTY */
+ else
+ fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */
+ }
+ tmp.env[FP_ENV_TAG] = fp_tags;
+
+ /* Now write 'tmp' into the guest state. */
+ warnX87 = do_put_x87( True/*moveRegs*/, (UChar*)&tmp, gst );
+
+ { UInt w32 = (((UInt)addrS[12]) & 0xFFFF)
+ | ((((UInt)addrS[13]) & 0xFFFF) << 16);
+ ULong w64 = amd64g_check_ldmxcsr( (ULong)w32 );
+
+ warnXMM = (VexEmWarn)(w64 >> 32);
+
+ gst->guest_SSEROUND = w64 & 0xFFFFFFFFULL;
+ }
+
+ /* Prefer an X87 emwarn over an XMM one, if both exist. */
+ if (warnX87 != EmWarn_NONE)
+ return warnX87;
+ else
+ return warnXMM;
+}
+
+
/* DIRTY HELPER (writes guest state) */
/* Initialise the x87 FPU state as per 'finit'. */
void amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* gst )
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:44:28 UTC (rev 2097)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:48:03 UTC (rev 2098)
@@ -9193,26 +9193,27 @@
thusly placed in guest-x86/toIR.c. */
/* 0F AE /0 = FXSAVE m512 -- write x87 and SSE state to memory.
- Note that REX.W 0F AE /0 writes a slightly different format and
- we don't handle that here. */
- if (haveNo66noF2noF3(pfx) && sz == 4
+ Note that the presence or absence of REX.W slightly affects the
+ written format: whether the saved FPU IP and DP pointers are 64
+ or 32 bits. But the helper function we call simply writes zero
+ bits in the relevant fields (which are 64 bits regardless of
+ what REX.W is) and so it's good enough (iow, equally broken) in
+ both cases. */
+ if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)
&& insn[0] == 0x0F && insn[1] == 0xAE
&& !epartIsReg(insn[2]) && gregOfRexRM(pfx,insn[2]) == 0) {
IRDirty* d;
modrm = getUChar(delta+2);
- vassert(sz == 4);
vassert(!epartIsReg(modrm));
- /* REX.W must not be set. That should be assured us by sz == 4
- above. */
- vassert(!(pfx & PFX_REXW));
addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
delta += 2+alen;
+ gen_SEGV_if_not_16_aligned(addr);
- DIP("fxsave %s\n", dis_buf);
+ DIP("%sfxsave %s\n", sz==8 ? "rex64/" : "", dis_buf);
/* Uses dirty helper:
- void amd64g_do_FXSAVE ( VexGuestAMD64State*, UInt ) */
+ void amd64g_do_FXSAVE ( VexGuestAMD64State*, ULong ) */
d = unsafeIRDirty_0_N (
0/*regparms*/,
"amd64g_dirtyhelper_FXSAVE",
@@ -9268,6 +9269,82 @@
goto decode_success;
}
+ /* 0F AE /1 = FXRSTOR m512 -- read x87 and SSE state from memory.
+ As with FXSAVE above we ignore the value of REX.W since we're
+ not bothering with the FPU DP and IP fields. */
+ if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)
+ && insn[0] == 0x0F && insn[1] == 0xAE
+ && !epartIsReg(insn[2]) && gregOfRexRM(pfx,insn[2]) == 1) {
+ IRDirty* d;
+ modrm = getUChar(delta+2);
+ vassert(!epartIsReg(modrm));
+
+ addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
+ delta += 2+alen;
+ gen_SEGV_if_not_16_aligned(addr);
+
+ DIP("%sfxrstor %s\n", sz==8 ? "rex64/" : "", dis_buf);
+
+ /* Uses dirty helper:
+ VexEmWarn amd64g_do_FXRSTOR ( VexGuestAMD64State*, ULong )
+ NOTE:
+ the VexEmWarn value is simply ignored
+ */
+ d = unsafeIRDirty_0_N (
+ 0/*regparms*/,
+ "amd64g_dirtyhelper_FXRSTOR",
+ &amd64g_dirtyhelper_FXRSTOR,
+ mkIRExprVec_1( mkexpr(addr) )
+ );
+ d->needsBBP = True;
+
+ /* declare we're reading memory */
+ d->mFx = Ifx_Read;
+ d->mAddr = mkexpr(addr);
+ d->mSize = 512;
+
+ /* declare we're writing guest state */
+ d->nFxState = 7;
+
+ d->fxState[0].fx = Ifx_Write;
+ d->fxState[0].offset = OFFB_FTOP;
+ d->fxState[0].size = sizeof(UInt);
+
+ d->fxState[1].fx = Ifx_Write;
+ d->fxState[1].offset = OFFB_FPREGS;
+ d->fxState[1].size = 8 * sizeof(ULong);
+
+ d->fxState[2].fx = Ifx_Write;
+ d->fxState[2].offset = OFFB_FPTAGS;
+ d->fxState[2].size = 8 * sizeof(UChar);
+
+ d->fxState[3].fx = Ifx_Write;
+ d->fxState[3].offset = OFFB_FPROUND;
+ d->fxState[3].size = sizeof(ULong);
+
+ d->fxState[4].fx = Ifx_Write;
+ d->fxState[4].offset = OFFB_FC3210;
+ d->fxState[4].size = sizeof(ULong);
+
+ d->fxState[5].fx = Ifx_Write;
+ d->fxState[5].offset = OFFB_XMM0;
+ d->fxState[5].size = 16 * sizeof(U128);
+
+ d->fxState[6].fx = Ifx_Write;
+ d->fxState[6].offset = OFFB_SSEROUND;
+ d->fxState[6].size = sizeof(ULong);
+
+ /* Be paranoid ... this assertion tries to ensure the 16 %xmm
+ images are packed back-to-back. If not, the value of
+ d->fxState[5].size is wrong. */
+ vassert(16 == sizeof(U128));
+ vassert(OFFB_XMM15 == (OFFB_XMM0 + 15 * 16));
+
+ stmt( IRStmt_Dirty(d) );
+
+ goto decode_success;
+ }
+
/* ------ SSE decoder main ------ */
/* 0F 58 = ADDPS -- add 32Fx4 from R/M to R */
|
|
From: <sv...@va...> - 2011-02-14 13:44:36
|
Author: sewardj
Date: 2011-02-14 13:44:28 +0000 (Mon, 14 Feb 2011)
New Revision: 2097
Log:
Merge from trunk, r2082 (Add support for SSE4.2 CRC32{B,W,L,Q}.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_defs.h
branches/VEX_3_6_BRANCH/priv/guest_amd64_helpers.c
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_defs.h
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_defs.h 2011-02-14 13:39:47 UTC (rev 2096)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_defs.h 2011-02-14 13:44:28 UTC (rev 2097)
@@ -137,6 +137,10 @@
extern ULong amd64g_calculate_mmx_pmovmskb ( ULong );
extern ULong amd64g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo );
+extern ULong amd64g_calc_crc32b ( ULong crcIn, ULong b );
+extern ULong amd64g_calc_crc32w ( ULong crcIn, ULong w );
+extern ULong amd64g_calc_crc32l ( ULong crcIn, ULong l );
+extern ULong amd64g_calc_crc32q ( ULong crcIn, ULong q );
/* --- DIRTY HELPERS --- */
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_helpers.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_helpers.c 2011-02-14 13:39:47 UTC (rev 2096)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_helpers.c 2011-02-14 13:44:28 UTC (rev 2097)
@@ -2563,7 +2563,44 @@
return ((rHi8 & 0xFF) << 8) | (rLo8 & 0xFF);
}
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+ULong amd64g_calc_crc32b ( ULong crcIn, ULong b )
+{
+ UInt i;
+ ULong crc = (b & 0xFFULL) ^ crcIn;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
+ return crc;
+}
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+ULong amd64g_calc_crc32w ( ULong crcIn, ULong w )
+{
+ UInt i;
+ ULong crc = (w & 0xFFFFULL) ^ crcIn;
+ for (i = 0; i < 16; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
+ return crc;
+}
+
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+ULong amd64g_calc_crc32l ( ULong crcIn, ULong l )
+{
+ UInt i;
+ ULong crc = (l & 0xFFFFFFFFULL) ^ crcIn;
+ for (i = 0; i < 32; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
+ return crc;
+}
+
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+ULong amd64g_calc_crc32q ( ULong crcIn, ULong q )
+{
+ ULong crc = amd64g_calc_crc32l(crcIn, q);
+ return amd64g_calc_crc32l(crc, q >> 32);
+}
+
+
/*---------------------------------------------------------------*/
/*--- Helpers for SSE4.2 PCMP{E,I}STR{I,M} ---*/
/*---------------------------------------------------------------*/
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:39:47 UTC (rev 2096)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:44:28 UTC (rev 2097)
@@ -750,6 +750,13 @@
toBool((pfx & (PFX_F2|PFX_F3)) == PFX_F3);
}
+/* Return True iff pfx has F2 set and F3 clear */
+static Bool haveF2noF3 ( Prefix pfx )
+{
+ return
+ toBool((pfx & (PFX_F2|PFX_F3)) == PFX_F2);
+}
+
/* Return True iff pfx has 66, F2 and F3 clear */
static Bool haveNo66noF2noF3 ( Prefix pfx )
{
@@ -15850,6 +15857,68 @@
goto decode_success;
}
+ /* F2 0F 38 F0 /r = CRC32 r/m8, r32 (REX.W ok, 66 not ok)
+ F2 0F 38 F1 /r = CRC32 r/m{16,32,64}, r32
+ The decoding on this is a bit unusual.
+ */
+ if (haveF2noF3(pfx)
+ && insn[0] == 0x0F && insn[1] == 0x38
+ && (insn[2] == 0xF1
+ || (insn[2] == 0xF0 && !have66(pfx)))) {
+ modrm = insn[3];
+
+ if (insn[2] == 0xF0)
+ sz = 1;
+ else
+ vassert(sz == 2 || sz == 4 || sz == 8);
+
+ IRType tyE = szToITy(sz);
+ IRTemp valE = newTemp(tyE);
+
+ if (epartIsReg(modrm)) {
+ assign(valE, getIRegE(sz, pfx, modrm));
+ delta += 3+1;
+ DIP("crc32b %s,%s\n", nameIRegE(sz, pfx, modrm),
+ nameIRegG(1==getRexW(pfx) ? 8 : 4 ,pfx, modrm));
+ } else {
+ addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
+ assign(valE, loadLE(tyE, mkexpr(addr)));
+ delta += 3+alen;
+ DIP("crc32b %s,%s\n", dis_buf,
+ nameIRegG(1==getRexW(pfx) ? 8 : 4 ,pfx, modrm));
+ }
+
+ /* Somewhat funny getting/putting of the crc32 value, in order
+ to ensure that it turns into 64-bit gets and puts. However,
+ mask off the upper 32 bits so as to not get memcheck false
+ +ves around the helper call. */
+ IRTemp valG0 = newTemp(Ity_I64);
+ assign(valG0, binop(Iop_And64, getIRegG(8, pfx, modrm),
+ mkU64(0xFFFFFFFF)));
+
+ HChar* nm = NULL;
+ void* fn = NULL;
+ switch (sz) {
+ case 1: nm = "amd64g_calc_crc32b";
+ fn = &amd64g_calc_crc32b; break;
+ case 2: nm = "amd64g_calc_crc32w";
+ fn = &amd64g_calc_crc32w; break;
+ case 4: nm = "amd64g_calc_crc32l";
+ fn = &amd64g_calc_crc32l; break;
+ case 8: nm = "amd64g_calc_crc32q";
+ fn = &amd64g_calc_crc32q; break;
+ }
+ vassert(nm && fn);
+ IRTemp valG1 = newTemp(Ity_I64);
+ assign(valG1,
+ mkIRExprCCall(Ity_I64, 0/*regparm*/, nm, fn,
+ mkIRExprVec_2(mkexpr(valG0),
+ widenUto64(mkexpr(valE)))));
+
+ putIRegG(4, pfx, modrm, unop(Iop_64to32, mkexpr(valG1)));
+ goto decode_success;
+ }
+
/* ---------------------------------------------------- */
/* --- end of the SSE4 decoder --- */
/* ---------------------------------------------------- */
|
|
From: <sv...@va...> - 2011-02-14 13:39:55
|
Author: sewardj
Date: 2011-02-14 13:39:47 +0000 (Mon, 14 Feb 2011)
New Revision: 2096
Log:
Merge from trunk, r2080 (Handle PCMPxSTRx $0x00.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
branches/VEX_3_6_BRANCH/priv/guest_generic_x87.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:37:03 UTC (rev 2095)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:39:47 UTC (rev 2096)
@@ -15583,6 +15583,7 @@
any cases for which the helper function has not been
verified. */
switch (imm) {
+ case 0x00:
case 0x02: case 0x08: case 0x0A: case 0x0C: case 0x12:
case 0x1A: case 0x3A: case 0x44: case 0x4A:
break;
Modified: branches/VEX_3_6_BRANCH/priv/guest_generic_x87.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_generic_x87.c 2011-02-14 13:37:03 UTC (rev 2095)
+++ branches/VEX_3_6_BRANCH/priv/guest_generic_x87.c 2011-02-14 13:39:47 UTC (rev 2096)
@@ -715,6 +715,7 @@
even if they would probably work. Life is too short to have
unvalidated cases in the code base. */
switch (imm8) {
+ case 0x00:
case 0x02: case 0x08: case 0x0A: case 0x0C: case 0x12:
case 0x1A: case 0x3A: case 0x44: case 0x4A:
break;
|
|
From: <sv...@va...> - 2011-02-14 13:37:11
|
Author: sewardj
Date: 2011-02-14 13:37:03 +0000 (Mon, 14 Feb 2011)
New Revision: 2095
Log:
Merge from trunk, r2079 (Tolerate redundant REX.W in POPQ m64.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:33:36 UTC (rev 2094)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:37:03 UTC (rev 2095)
@@ -16856,7 +16856,8 @@
/* There is no encoding for 32-bit pop in 64-bit mode.
So sz==4 actually means sz==8. */
if (haveF2orF3(pfx)) goto decode_failure;
- vassert(sz == 2 || sz == 4);
+ vassert(sz == 2 || sz == 4
+ || /* tolerate redundant REX.W, see #210481 */ sz == 8);
if (sz == 4) sz = 8;
if (sz != 8) goto decode_failure; // until we know a sz==2 test case exists
|
|
From: <sv...@va...> - 2011-02-14 13:33:45
|
Author: sewardj
Date: 2011-02-14 13:33:36 +0000 (Mon, 14 Feb 2011)
New Revision: 2094
Log:
Merge from trunk, r2078 (Add support for AAD and AAM (base 10 only).)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_x86_defs.h
branches/VEX_3_6_BRANCH/priv/guest_x86_helpers.c
branches/VEX_3_6_BRANCH/priv/guest_x86_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_x86_defs.h
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_x86_defs.h 2011-02-14 13:30:26 UTC (rev 2093)
+++ branches/VEX_3_6_BRANCH/priv/guest_x86_defs.h 2011-02-14 13:33:36 UTC (rev 2094)
@@ -108,6 +108,8 @@
extern UInt x86g_calculate_daa_das_aaa_aas ( UInt AX_and_flags, UInt opcode );
+extern UInt x86g_calculate_aad_aam ( UInt AX_and_flags, UInt opcode );
+
extern ULong x86g_check_fldcw ( UInt fpucw );
extern UInt x86g_create_fpucw ( UInt fpround );
Modified: branches/VEX_3_6_BRANCH/priv/guest_x86_helpers.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_x86_helpers.c 2011-02-14 13:30:26 UTC (rev 2093)
+++ branches/VEX_3_6_BRANCH/priv/guest_x86_helpers.c 2011-02-14 13:33:36 UTC (rev 2094)
@@ -2109,7 +2109,52 @@
return result;
}
+UInt x86g_calculate_aad_aam ( UInt flags_and_AX, UInt opcode )
+{
+ UInt r_AL = (flags_and_AX >> 0) & 0xFF;
+ UInt r_AH = (flags_and_AX >> 8) & 0xFF;
+ UInt r_O = (flags_and_AX >> (16 + X86G_CC_SHIFT_O)) & 1;
+ UInt r_S = (flags_and_AX >> (16 + X86G_CC_SHIFT_S)) & 1;
+ UInt r_Z = (flags_and_AX >> (16 + X86G_CC_SHIFT_Z)) & 1;
+ UInt r_A = (flags_and_AX >> (16 + X86G_CC_SHIFT_A)) & 1;
+ UInt r_C = (flags_and_AX >> (16 + X86G_CC_SHIFT_C)) & 1;
+ UInt r_P = (flags_and_AX >> (16 + X86G_CC_SHIFT_P)) & 1;
+ UInt result = 0;
+ switch (opcode) {
+ case 0xD4: { /* AAM */
+ r_AH = r_AL / 10;
+ r_AL = r_AL % 10;
+ break;
+ }
+ case 0xD5: { /* AAD */
+ r_AL = ((r_AH * 10) + r_AL) & 0xff;
+ r_AH = 0;
+ break;
+ }
+ default:
+ vassert(0);
+ }
+
+ r_O = 0; /* let's say (undefined) */
+ r_C = 0; /* let's say (undefined) */
+ r_A = 0; /* let's say (undefined) */
+ r_S = (r_AL & 0x80) ? 1 : 0;
+ r_Z = (r_AL == 0) ? 1 : 0;
+ r_P = calc_parity_8bit( r_AL );
+
+ result = ( (r_O & 1) << (16 + X86G_CC_SHIFT_O) )
+ | ( (r_S & 1) << (16 + X86G_CC_SHIFT_S) )
+ | ( (r_Z & 1) << (16 + X86G_CC_SHIFT_Z) )
+ | ( (r_A & 1) << (16 + X86G_CC_SHIFT_A) )
+ | ( (r_C & 1) << (16 + X86G_CC_SHIFT_C) )
+ | ( (r_P & 1) << (16 + X86G_CC_SHIFT_P) )
+ | ( (r_AH & 0xFF) << 8 )
+ | ( (r_AL & 0xFF) << 0 );
+ return result;
+}
+
+
/* CALLED FROM GENERATED CODE */
/* DIRTY HELPER (non-referentially-transparent) */
/* Horrible hack. On non-x86 platforms, return 1. */
Modified: branches/VEX_3_6_BRANCH/priv/guest_x86_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_x86_toIR.c 2011-02-14 13:30:26 UTC (rev 2093)
+++ branches/VEX_3_6_BRANCH/priv/guest_x86_toIR.c 2011-02-14 13:33:36 UTC (rev 2094)
@@ -12907,26 +12907,52 @@
}
break;
-//-- case 0xD4: /* AAM */
-//-- case 0xD5: /* AAD */
-//-- d32 = getIByte(delta); delta++;
-//-- if (d32 != 10) VG_(core_panic)("disInstr: AAM/AAD but base not 10 !");
-//-- t1 = newTemp(cb);
-//-- uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
-//-- /* Widen %AX to 32 bits, so it's all defined when we push it. */
-//-- uInstr1(cb, WIDEN, 4, TempReg, t1);
-//-- uWiden(cb, 2, False);
-//-- uInstr0(cb, CALLM_S, 0);
-//-- uInstr1(cb, PUSH, 4, TempReg, t1);
-//-- uInstr1(cb, CALLM, 0, Lit16,
-//-- opc == 0xD4 ? VGOFF_(helper_AAM) : VGOFF_(helper_AAD) );
-//-- uFlagsRWU(cb, FlagsEmpty, FlagsSZP, FlagsEmpty);
-//-- uInstr1(cb, POP, 4, TempReg, t1);
-//-- uInstr0(cb, CALLM_E, 0);
-//-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
-//-- DIP(opc == 0xD4 ? "aam\n" : "aad\n");
-//-- break;
+ case 0xD4: /* AAM */
+ case 0xD5: /* AAD */
+ d32 = getIByte(delta); delta++;
+ if (sz != 4 || d32 != 10) goto decode_failure;
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ /* Make up a 32-bit value (t1), with the old value of AX in the
+ bottom 16 bits, and the old OSZACP bitmask in the upper 16
+ bits. */
+ assign(t1,
+ binop(Iop_16HLto32,
+ unop(Iop_32to16,
+ mk_x86g_calculate_eflags_all()),
+ getIReg(2, R_EAX)
+ ));
+ /* Call the helper fn, to get a new AX and OSZACP value, and
+ poke both back into the guest state. Also pass the helper
+ the actual opcode so it knows which of the 2 instructions it
+ is doing the computation for. */
+ assign(t2,
+ mkIRExprCCall(
+ Ity_I32, 0/*regparm*/, "x86g_calculate_aad_aam",
+ &x86g_calculate_aad_aam,
+ mkIRExprVec_2( mkexpr(t1), mkU32( opc & 0xFF) )
+ ));
+ putIReg(2, R_EAX, unop(Iop_32to16, mkexpr(t2) ));
+ stmt( IRStmt_Put( OFFB_CC_OP, mkU32(X86G_CC_OP_COPY) ));
+ stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_DEP1,
+ binop(Iop_And32,
+ binop(Iop_Shr32, mkexpr(t2), mkU8(16)),
+ mkU32( X86G_CC_MASK_C | X86G_CC_MASK_P
+ | X86G_CC_MASK_A | X86G_CC_MASK_Z
+ | X86G_CC_MASK_S| X86G_CC_MASK_O )
+ )
+ )
+ );
+ /* Set NDEP even though it isn't used. This makes
+ redundant-PUT elimination of previous stores to this field
+ work better. */
+ stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
+
+ DIP(opc == 0xD4 ? "aam\n" : "aad\n");
+ break;
+
/* ------------------------ CWD/CDQ -------------------- */
case 0x98: /* CBW */
|
|
From: <sv...@va...> - 2011-02-14 13:30:35
|
Author: sewardj
Date: 2011-02-14 13:30:26 +0000 (Mon, 14 Feb 2011)
New Revision: 2093
Log:
Merge from trunk, r2076 (Implement SSE4.x EXTRACTPS, BLENDVPD,
BLENDVPS, PBLENDVB.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
branches/VEX_3_6_BRANCH/priv/host_amd64_isel.c
branches/VEX_3_6_BRANCH/priv/host_generic_simd128.c
branches/VEX_3_6_BRANCH/priv/host_generic_simd128.h
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:26:56 UTC (rev 2092)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:30:26 UTC (rev 2093)
@@ -14643,6 +14643,55 @@
goto decode_success;
}
+
+ /* 66 0F 3A 17 /r ib = EXTRACTPS reg/mem32, xmm2, imm8 Extract
+ float from xmm reg and store in gen.reg or mem. This is
+ identical to PEXTRD, except that REX.W appears to be ignored.
+ */
+ if ( have66noF2noF3( pfx )
+ && sz == 2 /* REX.W == 0; perhaps too strict? */
+ && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x17 ) {
+
+ Int imm8_10;
+ IRTemp xmm_vec = newTemp(Ity_V128);
+ IRTemp src_dword = newTemp(Ity_I32);
+
+ modrm = insn[3];
+ assign( xmm_vec, getXMMReg( gregOfRexRM(pfx,modrm) ) );
+ breakup128to32s( xmm_vec, &t3, &t2, &t1, &t0 );
+
+ if ( epartIsReg( modrm ) ) {
+ imm8_10 = (Int)(insn[3+1] & 3);
+ } else {
+ addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 1 );
+ imm8_10 = (Int)(insn[3+alen] & 3);
+ }
+
+ switch ( imm8_10 ) {
+ case 0: assign( src_dword, mkexpr(t0) ); break;
+ case 1: assign( src_dword, mkexpr(t1) ); break;
+ case 2: assign( src_dword, mkexpr(t2) ); break;
+ case 3: assign( src_dword, mkexpr(t3) ); break;
+ default: vassert(0);
+ }
+
+ if ( epartIsReg( modrm ) ) {
+ putIReg32( eregOfRexRM(pfx,modrm), mkexpr(src_dword) );
+ delta += 3+1+1;
+ DIP( "extractps $%d, %s,%s\n", imm8_10,
+ nameXMMReg( gregOfRexRM(pfx, modrm) ),
+ nameIReg32( eregOfRexRM(pfx, modrm) ) );
+ } else {
+ storeLE( mkexpr(addr), mkexpr(src_dword) );
+ delta += 3+alen+1;
+ DIP( "extractps $%d, %s,%s\n",
+ imm8_10, nameXMMReg( gregOfRexRM(pfx, modrm) ), dis_buf );
+ }
+
+ goto decode_success;
+ }
+
+
/* 66 0F 38 37 = PCMPGTQ
64x2 comparison (signed, presumably; the Intel docs don't say :-)
*/
@@ -15731,7 +15780,75 @@
goto decode_success;
}
+ /* 66 0F 38 15 /r = BLENDVPD xmm1, xmm2/m128 (double gran)
+ 66 0F 38 14 /r = BLENDVPS xmm1, xmm2/m128 (float gran)
+ 66 0F 38 10 /r = PBLENDVB xmm1, xmm2/m128 (byte gran)
+ Blend at various granularities, with XMM0 (implicit operand)
+ providing the controlling mask.
+ */
+ if (have66noF2noF3(pfx) && sz == 2
+ && insn[0] == 0x0F && insn[1] == 0x38
+ && (insn[2] == 0x15 || insn[2] == 0x14 || insn[2] == 0x10)) {
+ modrm = insn[3];
+ HChar* nm = NULL;
+ UInt gran = 0;
+ IROp opSAR = Iop_INVALID;
+ switch (insn[2]) {
+ case 0x15:
+ nm = "blendvpd"; gran = 8; opSAR = Iop_SarN64x2;
+ break;
+ case 0x14:
+ nm = "blendvps"; gran = 4; opSAR = Iop_SarN32x4;
+ break;
+ case 0x10:
+ nm = "pblendvb"; gran = 1; opSAR = Iop_SarN8x16;
+ break;
+ }
+ vassert(nm);
+
+ IRTemp vecE = newTemp(Ity_V128);
+ IRTemp vecG = newTemp(Ity_V128);
+ IRTemp vec0 = newTemp(Ity_V128);
+
+ if ( epartIsReg(modrm) ) {
+ assign(vecE, getXMMReg(eregOfRexRM(pfx, modrm)));
+ delta += 3+1;
+ DIP( "%s %s,%s\n", nm,
+ nameXMMReg( eregOfRexRM(pfx, modrm) ),
+ nameXMMReg( gregOfRexRM(pfx, modrm) ) );
+ } else {
+ addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
+ gen_SEGV_if_not_16_aligned( addr );
+ assign(vecE, loadLE( Ity_V128, mkexpr(addr) ));
+ delta += 3+alen;
+ DIP( "%s %s,%s\n", nm,
+ dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
+ }
+
+ assign(vecG, getXMMReg(gregOfRexRM(pfx, modrm)));
+ assign(vec0, getXMMReg(0));
+
+ /* Now the tricky bit is to convert vec0 into a suitable mask,
+ by copying the most significant bit of each lane into all
+ positions in the lane. */
+ IRTemp sh = newTemp(Ity_I8);
+ assign(sh, mkU8(8 * gran - 1));
+
+ IRTemp mask = newTemp(Ity_V128);
+ assign(mask, binop(opSAR, mkexpr(vec0), mkexpr(sh)));
+
+ IRTemp notmask = newTemp(Ity_V128);
+ assign(notmask, unop(Iop_NotV128, mkexpr(mask)));
+
+ IRExpr* res = binop(Iop_OrV128,
+ binop(Iop_AndV128, mkexpr(vecE), mkexpr(mask)),
+ binop(Iop_AndV128, mkexpr(vecG), mkexpr(notmask)));
+ putXMMReg(gregOfRexRM(pfx, modrm), res);
+
+ goto decode_success;
+ }
+
/* ---------------------------------------------------- */
/* --- end of the SSE4 decoder --- */
/* ---------------------------------------------------- */
Modified: branches/VEX_3_6_BRANCH/priv/host_amd64_isel.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/host_amd64_isel.c 2011-02-14 13:26:56 UTC (rev 2092)
+++ branches/VEX_3_6_BRANCH/priv/host_amd64_isel.c 2011-02-14 13:30:26 UTC (rev 2093)
@@ -3659,6 +3659,54 @@
return dst;
}
+ case Iop_SarN64x2: fn = (HWord)h_generic_calc_SarN64x2;
+ goto do_SseAssistedVectorAndScalar;
+ case Iop_SarN8x16: fn = (HWord)h_generic_calc_SarN8x16;
+ goto do_SseAssistedVectorAndScalar;
+ do_SseAssistedVectorAndScalar: {
+ /* RRRufff! RRRufff code is what we're generating here. Oh
+ well. */
+ vassert(fn != 0);
+ HReg dst = newVRegV(env);
+ HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+ HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2);
+ HReg argp = newVRegI(env);
+ /* subq $112, %rsp -- make a space*/
+ sub_from_rsp(env, 112);
+ /* leaq 48(%rsp), %r_argp -- point into it */
+ addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(48, hregAMD64_RSP()),
+ argp));
+ /* andq $-16, %r_argp -- 16-align the pointer */
+ addInstr(env, AMD64Instr_Alu64R(Aalu_AND,
+ AMD64RMI_Imm( ~(UInt)15 ),
+ argp));
+ /* Prepare 2 vector arg regs:
+ leaq 0(%r_argp), %rdi
+ leaq 16(%r_argp), %rsi
+ */
+ addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, argp),
+ hregAMD64_RDI()));
+ addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(16, argp),
+ hregAMD64_RSI()));
+ /* Store the vector arg, at (%rsi):
+ movupd %argL, 0(%rsi)
+ */
+ addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argL,
+ AMD64AMode_IR(0, hregAMD64_RSI())));
+ /* And get the scalar value into rdx */
+ addInstr(env, mk_iMOVsd_RR(argR, hregAMD64_RDX()));
+
+ /* call the helper */
+ addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 3 ));
+ /* fetch the result from memory, using %r_argp, which the
+ register allocator will keep alive across the call. */
+ addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dst,
+ AMD64AMode_IR(0, argp)));
+ /* and finally, clear the space */
+ add_to_rsp(env, 112);
+ return dst;
+ }
+
default:
break;
} /* switch (e->Iex.Binop.op) */
Modified: branches/VEX_3_6_BRANCH/priv/host_generic_simd128.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/host_generic_simd128.c 2011-02-14 13:26:56 UTC (rev 2092)
+++ branches/VEX_3_6_BRANCH/priv/host_generic_simd128.c 2011-02-14 13:30:26 UTC (rev 2093)
@@ -94,6 +94,16 @@
? 0xFFFFFFFFFFFFFFFFULL : 0ULL;
}
+static inline ULong sar64 ( ULong v, UInt n )
+{
+ return ((Long)v) >> n;
+}
+
+static inline UChar sar8 ( UChar v, UInt n )
+{
+ return toUChar(((Char)v) >> n);
+}
+
void h_generic_calc_Mul32x4 ( /*OUT*/V128* res,
V128* argL, V128* argR )
{
@@ -214,7 +224,45 @@
res->w64[1] = cmpGT64S(argL->w64[1], argR->w64[1]);
}
+/* ------------ Shifting ------------ */
+/* Note that because these primops are undefined if the shift amount
+ equals or exceeds the lane width, the shift amount is masked so
+ that the scalar shifts are always in range. In fact, given the
+ semantics of these primops (Sar64x2, etc) it is an error if in
+ fact we are ever given an out-of-range shift amount.
+*/
+void h_generic_calc_SarN64x2 ( /*OUT*/V128* res,
+ V128* argL, UInt nn)
+{
+ /* vassert(nn < 64); */
+ nn &= 63;
+ res->w64[0] = sar64(argL->w64[0], nn);
+ res->w64[1] = sar64(argL->w64[1], nn);
+}
+void h_generic_calc_SarN8x16 ( /*OUT*/V128* res,
+ V128* argL, UInt nn)
+{
+ /* vassert(nn < 8); */
+ nn &= 7;
+ res->w8[ 0] = sar8(argL->w8[ 0], nn);
+ res->w8[ 1] = sar8(argL->w8[ 1], nn);
+ res->w8[ 2] = sar8(argL->w8[ 2], nn);
+ res->w8[ 3] = sar8(argL->w8[ 3], nn);
+ res->w8[ 4] = sar8(argL->w8[ 4], nn);
+ res->w8[ 5] = sar8(argL->w8[ 5], nn);
+ res->w8[ 6] = sar8(argL->w8[ 6], nn);
+ res->w8[ 7] = sar8(argL->w8[ 7], nn);
+ res->w8[ 8] = sar8(argL->w8[ 8], nn);
+ res->w8[ 9] = sar8(argL->w8[ 9], nn);
+ res->w8[10] = sar8(argL->w8[10], nn);
+ res->w8[11] = sar8(argL->w8[11], nn);
+ res->w8[12] = sar8(argL->w8[12], nn);
+ res->w8[13] = sar8(argL->w8[13], nn);
+ res->w8[14] = sar8(argL->w8[14], nn);
+ res->w8[15] = sar8(argL->w8[15], nn);
+}
+
/*---------------------------------------------------------------*/
/*--- end host_generic_simd128.c ---*/
/*---------------------------------------------------------------*/
Modified: branches/VEX_3_6_BRANCH/priv/host_generic_simd128.h
===================================================================
--- branches/VEX_3_6_BRANCH/priv/host_generic_simd128.h 2011-02-14 13:26:56 UTC (rev 2092)
+++ branches/VEX_3_6_BRANCH/priv/host_generic_simd128.h 2011-02-14 13:30:26 UTC (rev 2093)
@@ -58,6 +58,8 @@
extern void h_generic_calc_Max8Sx16 ( /*OUT*/V128*, V128*, V128* );
extern void h_generic_calc_Min8Sx16 ( /*OUT*/V128*, V128*, V128* );
extern void h_generic_calc_CmpGT64Sx2 ( /*OUT*/V128*, V128*, V128* );
+extern void h_generic_calc_SarN64x2 ( /*OUT*/V128*, V128*, UInt );
+extern void h_generic_calc_SarN8x16 ( /*OUT*/V128*, V128*, UInt );
#endif /* ndef __VEX_HOST_GENERIC_SIMD128_H */
|
|
From: <sv...@va...> - 2011-02-14 13:27:04
|
Author: sewardj
Date: 2011-02-14 13:26:56 +0000 (Mon, 14 Feb 2011)
New Revision: 2092
Log:
Merge from trunk, r2075 (Implement SSE4.1 PBLENDW.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:23:21 UTC (rev 2091)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:26:56 UTC (rev 2092)
@@ -13967,6 +13967,59 @@
}
+ /* 66 0F 3A 0E /r ib = PBLENDW xmm1, xmm2/m128, imm8
+ Blend Packed Words (XMM) */
+ if ( have66noF2noF3( pfx )
+ && sz == 2
+ && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0E ) {
+
+ Int imm8;
+ IRTemp dst_vec = newTemp(Ity_V128);
+ IRTemp src_vec = newTemp(Ity_V128);
+
+ modrm = insn[3];
+
+ assign( dst_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
+
+ if ( epartIsReg( modrm ) ) {
+ imm8 = (Int)insn[3+1];
+ assign( src_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
+ delta += 3+1+1;
+ DIP( "pblendw $%d, %s,%s\n", imm8,
+ nameXMMReg( eregOfRexRM(pfx, modrm) ),
+ nameXMMReg( gregOfRexRM(pfx, modrm) ) );
+ } else {
+ addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf,
+ 1/* imm8 is 1 byte after the amode */ );
+ gen_SEGV_if_not_16_aligned( addr );
+ assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
+ imm8 = (Int)insn[3+alen];
+ delta += 3+alen+1;
+ DIP( "pblendw $%d, %s,%s\n",
+ imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
+ }
+
+ /* Make w be a 16-bit version of imm8, formed by duplicating each
+ bit in imm8. */
+ Int i;
+ UShort imm16 = 0;
+ for (i = 0; i < 8; i++) {
+ if (imm8 & (1 << i))
+ imm16 |= (3 << (2*i));
+ }
+ IRTemp imm16_mask = newTemp(Ity_V128);
+ assign( imm16_mask, mkV128( imm16 ));
+
+ putXMMReg( gregOfRexRM(pfx, modrm),
+ binop( Iop_OrV128,
+ binop( Iop_AndV128, mkexpr(src_vec), mkexpr(imm16_mask) ),
+ binop( Iop_AndV128, mkexpr(dst_vec),
+ unop( Iop_NotV128, mkexpr(imm16_mask) ) ) ) );
+
+ goto decode_success;
+ }
+
+
/* 66 0F 3A 44 /r ib = PCLMULQDQ xmm1, xmm2/m128, imm8
* Carry-less multiplication of selected XMM quadwords into XMM
* registers (a.k.a multiplication of polynomials over GF(2))
|
|
From: <sv...@va...> - 2011-02-14 13:23:30
|
Author: sewardj
Date: 2011-02-14 13:23:21 +0000 (Mon, 14 Feb 2011)
New Revision: 2091
Log:
Merge from trunk, r2074 (Handle non-immediate-rounding-mode versions
of ROUND{P,S}{S,D}.)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:19:51 UTC (rev 2090)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:23:21 UTC (rev 2091)
@@ -15196,10 +15196,7 @@
/* 66 0F 3A 0B /r ib = ROUNDSD imm8, xmm2/m64, xmm1
- (Partial implementation only -- only deal with cases where
- the rounding mode is specified directly by the immediate byte.)
66 0F 3A 0A /r ib = ROUNDSS imm8, xmm2/m32, xmm1
- (Limitations ditto)
*/
if (have66noF2noF3(pfx)
&& sz == 2
@@ -15218,7 +15215,7 @@
isD ? getXMMRegLane64F( eregOfRexRM(pfx, modrm), 0 )
: getXMMRegLane32F( eregOfRexRM(pfx, modrm), 0 ) );
imm = insn[3+1];
- if (imm & ~3) goto decode_failure;
+ if (imm & ~7) goto decode_failure;
delta += 3+1+1;
DIP( "rounds%c $%d,%s,%s\n",
isD ? 'd' : 's',
@@ -15228,7 +15225,7 @@
addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
assign( src, loadLE( isD ? Ity_F64 : Ity_F32, mkexpr(addr) ));
imm = insn[3+alen];
- if (imm & ~3) goto decode_failure;
+ if (imm & ~7) goto decode_failure;
delta += 3+alen+1;
DIP( "rounds%c $%d,%s,%s\n",
isD ? 'd' : 's',
@@ -15240,7 +15237,9 @@
we can use that value directly in the IR as a rounding
mode. */
assign(res, binop(isD ? Iop_RoundF64toInt : Iop_RoundF32toInt,
- mkU32(imm & 3), mkexpr(src)) );
+ (imm & 4) ? get_sse_roundingmode()
+ : mkU32(imm & 3),
+ mkexpr(src)) );
if (isD)
putXMMRegLane64F( gregOfRexRM(pfx, modrm), 0, mkexpr(res) );
@@ -15251,10 +15250,7 @@
}
- /* 66 0F 3A 09 /r ib = ROUNDPD imm8, xmm2/m128, xmm1
- (Partial implementation only -- only deal with cases where
- the rounding mode is specified directly by the immediate byte.)
- */
+ /* 66 0F 3A 09 /r ib = ROUNDPD imm8, xmm2/m128, xmm1 */
if (have66noF2noF3(pfx)
&& sz == 2
&& insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x09) {
@@ -15263,6 +15259,7 @@
IRTemp src1 = newTemp(Ity_F64);
IRTemp res0 = newTemp(Ity_F64);
IRTemp res1 = newTemp(Ity_F64);
+ IRTemp rm = newTemp(Ity_I32);
Int imm = 0;
modrm = insn[3];
@@ -15273,7 +15270,7 @@
assign( src1,
getXMMRegLane64F( eregOfRexRM(pfx, modrm), 1 ) );
imm = insn[3+1];
- if (imm & ~3) goto decode_failure;
+ if (imm & ~7) goto decode_failure;
delta += 3+1+1;
DIP( "roundpd $%d,%s,%s\n",
imm, nameXMMReg( eregOfRexRM(pfx, modrm) ),
@@ -15286,7 +15283,7 @@
assign( src1, loadLE(Ity_F64,
binop(Iop_Add64, mkexpr(addr), mkU64(8) )));
imm = insn[3+alen];
- if (imm & ~3) goto decode_failure;
+ if (imm & ~7) goto decode_failure;
delta += 3+alen+1;
DIP( "roundpd $%d,%s,%s\n",
imm, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
@@ -15296,9 +15293,11 @@
that encoding is the same as the encoding for IRRoundingMode,
we can use that value directly in the IR as a rounding
mode. */
- assign(res0, binop(Iop_RoundF64toInt, mkU32(imm & 3), mkexpr(src0)) );
- assign(res1, binop(Iop_RoundF64toInt, mkU32(imm & 3), mkexpr(src1)) );
+ assign(rm, (imm & 4) ? get_sse_roundingmode() : mkU32(imm & 3));
+ assign(res0, binop(Iop_RoundF64toInt, mkexpr(rm), mkexpr(src0)) );
+ assign(res1, binop(Iop_RoundF64toInt, mkexpr(rm), mkexpr(src1)) );
+
putXMMRegLane64F( gregOfRexRM(pfx, modrm), 0, mkexpr(res0) );
putXMMRegLane64F( gregOfRexRM(pfx, modrm), 1, mkexpr(res1) );
@@ -15306,10 +15305,7 @@
}
- /* 66 0F 3A 08 /r ib = ROUNDPS imm8, xmm2/m128, xmm1
- (Partial implementation only -- only deal with cases where
- the rounding mode is specified directly by the immediate byte.)
- */
+ /* 66 0F 3A 08 /r ib = ROUNDPS imm8, xmm2/m128, xmm1 */
if (have66noF2noF3(pfx)
&& sz == 2
&& insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x08) {
@@ -15322,6 +15318,7 @@
IRTemp res1 = newTemp(Ity_F32);
IRTemp res2 = newTemp(Ity_F32);
IRTemp res3 = newTemp(Ity_F32);
+ IRTemp rm = newTemp(Ity_I32);
Int imm = 0;
modrm = insn[3];
@@ -15336,7 +15333,7 @@
assign( src3,
getXMMRegLane32F( eregOfRexRM(pfx, modrm), 3 ) );
imm = insn[3+1];
- if (imm & ~3) goto decode_failure;
+ if (imm & ~7) goto decode_failure;
delta += 3+1+1;
DIP( "roundps $%d,%s,%s\n",
imm, nameXMMReg( eregOfRexRM(pfx, modrm) ),
@@ -15353,7 +15350,7 @@
assign( src3, loadLE(Ity_F32,
binop(Iop_Add64, mkexpr(addr), mkU64(12) )));
imm = insn[3+alen];
- if (imm & ~3) goto decode_failure;
+ if (imm & ~7) goto decode_failure;
delta += 3+alen+1;
DIP( "roundps $%d,%s,%s\n",
imm, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
@@ -15363,11 +15360,13 @@
that encoding is the same as the encoding for IRRoundingMode,
we can use that value directly in the IR as a rounding
mode. */
- assign(res0, binop(Iop_RoundF32toInt, mkU32(imm & 3), mkexpr(src0)) );
- assign(res1, binop(Iop_RoundF32toInt, mkU32(imm & 3), mkexpr(src1)) );
- assign(res2, binop(Iop_RoundF32toInt, mkU32(imm & 3), mkexpr(src2)) );
- assign(res3, binop(Iop_RoundF32toInt, mkU32(imm & 3), mkexpr(src3)) );
+ assign(rm, (imm & 4) ? get_sse_roundingmode() : mkU32(imm & 3));
+ assign(res0, binop(Iop_RoundF32toInt, mkexpr(rm), mkexpr(src0)) );
+ assign(res1, binop(Iop_RoundF32toInt, mkexpr(rm), mkexpr(src1)) );
+ assign(res2, binop(Iop_RoundF32toInt, mkexpr(rm), mkexpr(src2)) );
+ assign(res3, binop(Iop_RoundF32toInt, mkexpr(rm), mkexpr(src3)) );
+
putXMMRegLane32F( gregOfRexRM(pfx, modrm), 0, mkexpr(res0) );
putXMMRegLane32F( gregOfRexRM(pfx, modrm), 1, mkexpr(res1) );
putXMMRegLane32F( gregOfRexRM(pfx, modrm), 2, mkexpr(res2) );
|
|
From: <sv...@va...> - 2011-02-14 13:20:03
|
Author: sewardj
Date: 2011-02-14 13:19:51 +0000 (Mon, 14 Feb 2011)
New Revision: 2090
Log:
Merge from trunk, r2072 (Implement ROUNDPD and ROUNDPS (imm rounding
mode only).)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:10:35 UTC (rev 2089)
+++ branches/VEX_3_6_BRANCH/priv/guest_amd64_toIR.c 2011-02-14 13:19:51 UTC (rev 2090)
@@ -15230,7 +15230,8 @@
imm = insn[3+alen];
if (imm & ~3) goto decode_failure;
delta += 3+alen+1;
- DIP( "roundsd $%d,%s,%s\n",
+ DIP( "rounds%c $%d,%s,%s\n",
+ isD ? 'd' : 's',
imm, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
}
@@ -15249,6 +15250,133 @@
goto decode_success;
}
+
+ /* 66 0F 3A 09 /r ib = ROUNDPD imm8, xmm2/m128, xmm1
+ (Partial implementation only -- only deal with cases where
+ the rounding mode is specified directly by the immediate byte.)
+ */
+ if (have66noF2noF3(pfx)
+ && sz == 2
+ && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x09) {
+
+ IRTemp src0 = newTemp(Ity_F64);
+ IRTemp src1 = newTemp(Ity_F64);
+ IRTemp res0 = newTemp(Ity_F64);
+ IRTemp res1 = newTemp(Ity_F64);
+ Int imm = 0;
+
+ modrm = insn[3];
+
+ if (epartIsReg(modrm)) {
+ assign( src0,
+ getXMMRegLane64F( eregOfRexRM(pfx, modrm), 0 ) );
+ assign( src1,
+ getXMMRegLane64F( eregOfRexRM(pfx, modrm), 1 ) );
+ imm = insn[3+1];
+ if (imm & ~3) goto decode_failure;
+ delta += 3+1+1;
+ DIP( "roundpd $%d,%s,%s\n",
+ imm, nameXMMReg( eregOfRexRM(pfx, modrm) ),
+ nameXMMReg( gregOfRexRM(pfx, modrm) ) );
+ } else {
+ addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
+ gen_SEGV_if_not_16_aligned(addr);
+ assign( src0, loadLE(Ity_F64,
+ binop(Iop_Add64, mkexpr(addr), mkU64(0) )));
+ assign( src1, loadLE(Ity_F64,
+ binop(Iop_Add64, mkexpr(addr), mkU64(8) )));
+ imm = insn[3+alen];
+ if (imm & ~3) goto decode_failure;
+ delta += 3+alen+1;
+ DIP( "roundpd $%d,%s,%s\n",
+ imm, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
+ }
+
+ /* (imm & 3) contains an Intel-encoded rounding mode. Because
+ that encoding is the same as the encoding for IRRoundingMode,
+ we can use that value directly in the IR as a rounding
+ mode. */
+ assign(res0, binop(Iop_RoundF64toInt, mkU32(imm & 3), mkexpr(src0)) );
+ assign(res1, binop(Iop_RoundF64toInt, mkU32(imm & 3), mkexpr(src1)) );
+
+ putXMMRegLane64F( gregOfRexRM(pfx, modrm), 0, mkexpr(res0) );
+ putXMMRegLane64F( gregOfRexRM(pfx, modrm), 1, mkexpr(res1) );
+
+ goto decode_success;
+ }
+
+
+ /* 66 0F 3A 08 /r ib = ROUNDPS imm8, xmm2/m128, xmm1
+ (Partial implementation only -- only deal with cases where
+ the rounding mode is specified directly by the immediate byte.)
+ */
+ if (have66noF2noF3(pfx)
+ && sz == 2
+ && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x08) {
+
+ IRTemp src0 = newTemp(Ity_F32);
+ IRTemp src1 = newTemp(Ity_F32);
+ IRTemp src2 = newTemp(Ity_F32);
+ IRTemp src3 = newTemp(Ity_F32);
+ IRTemp res0 = newTemp(Ity_F32);
+ IRTemp res1 = newTemp(Ity_F32);
+ IRTemp res2 = newTemp(Ity_F32);
+ IRTemp res3 = newTemp(Ity_F32);
+ Int imm = 0;
+
+ modrm = insn[3];
+
+ if (epartIsReg(modrm)) {
+ assign( src0,
+ getXMMRegLane32F( eregOfRexRM(pfx, modrm), 0 ) );
+ assign( src1,
+ getXMMRegLane32F( eregOfRexRM(pfx, modrm), 1 ) );
+ assign( src2,
+ getXMMRegLane32F( eregOfRexRM(pfx, modrm), 2 ) );
+ assign( src3,
+ getXMMRegLane32F( eregOfRexRM(pfx, modrm), 3 ) );
+ imm = insn[3+1];
+ if (imm & ~3) goto decode_failure;
+ delta += 3+1+1;
+ DIP( "roundps $%d,%s,%s\n",
+ imm, nameXMMReg( eregOfRexRM(pfx, modrm) ),
+ nameXMMReg( gregOfRexRM(pfx, modrm) ) );
+ } else {
+ addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
+ gen_SEGV_if_not_16_aligned(addr);
+ assign( src0, loadLE(Ity_F32,
+ binop(Iop_Add64, mkexpr(addr), mkU64(0) )));
+ assign( src1, loadLE(Ity_F32,
+ binop(Iop_Add64, mkexpr(addr), mkU64(4) )));
+ assign( src2, loadLE(Ity_F32,
+ binop(Iop_Add64, mkexpr(addr), mkU64(8) )));
+ assign( src3, loadLE(Ity_F32,
+ binop(Iop_Add64, mkexpr(addr), mkU64(12) )));
+ imm = insn[3+alen];
+ if (imm & ~3) goto decode_failure;
+ delta += 3+alen+1;
+ DIP( "roundps $%d,%s,%s\n",
+ imm, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
+ }
+
+ /* (imm & 3) contains an Intel-encoded rounding mode. Because
+ that encoding is the same as the encoding for IRRoundingMode,
+ we can use that value directly in the IR as a rounding
+ mode. */
+ assign(res0, binop(Iop_RoundF32toInt, mkU32(imm & 3), mkexpr(src0)) );
+ assign(res1, binop(Iop_RoundF32toInt, mkU32(imm & 3), mkexpr(src1)) );
+ assign(res2, binop(Iop_RoundF32toInt, mkU32(imm & 3), mkexpr(src2)) );
+ assign(res3, binop(Iop_RoundF32toInt, mkU32(imm & 3), mkexpr(src3)) );
+
+ putXMMRegLane32F( gregOfRexRM(pfx, modrm), 0, mkexpr(res0) );
+ putXMMRegLane32F( gregOfRexRM(pfx, modrm), 1, mkexpr(res1) );
+ putXMMRegLane32F( gregOfRexRM(pfx, modrm), 2, mkexpr(res2) );
+ putXMMRegLane32F( gregOfRexRM(pfx, modrm), 3, mkexpr(res3) );
+
+ goto decode_success;
+ }
+
+
/* F3 0F BD -- LZCNT (count leading zeroes. An AMD extension,
which we can only decode if we're sure this is an AMD cpu that
supports LZCNT, since otherwise it's BSR, which behaves
|
|
From: <sv...@va...> - 2011-02-14 13:10:43
|
Author: sewardj
Date: 2011-02-14 13:10:35 +0000 (Mon, 14 Feb 2011)
New Revision: 2089
Log:
Merge from trunk, r2073 (Fix bug in ppc64g_dirtyhelper_LVS)
Modified:
branches/VEX_3_6_BRANCH/priv/guest_ppc_helpers.c
Modified: branches/VEX_3_6_BRANCH/priv/guest_ppc_helpers.c
===================================================================
--- branches/VEX_3_6_BRANCH/priv/guest_ppc_helpers.c 2011-02-10 12:20:02 UTC (rev 2088)
+++ branches/VEX_3_6_BRANCH/priv/guest_ppc_helpers.c 2011-02-14 13:10:35 UTC (rev 2089)
@@ -154,11 +154,17 @@
void ppc64g_dirtyhelper_LVS ( VexGuestPPC64State* gst,
UInt vD_off, UInt sh, UInt shift_right )
{
- static
- UChar ref[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+ UChar ref[32];
+ ULong i;
+ /* ref[] used to be a static const array, but this doesn't work on
+ ppc64 because VEX doesn't load the TOC pointer for the call here,
+ and so we wind up picking up some totally random other data.
+ (It's a wonder we don't segfault.) So, just to be clear, this
+ "fix" (vex r2073) is really a kludgearound for the fact that
+ VEX's 64-bit ppc code generation doesn't provide a valid TOC
+ pointer for helper function calls. Ick. (Bug 250038) */
+ for (i = 0; i < 32; i++) ref[i] = i;
+
U128* pU128_src;
U128* pU128_dst;
|
|
From: <sv...@va...> - 2011-02-14 11:50:59
|
Author: sewardj
Date: 2011-02-14 11:50:49 +0000 (Mon, 14 Feb 2011)
New Revision: 11558
Log:
Merge from trunk, r11538 (x86-linux: make ld.so:index redir mandatory
for glibc-2.12 and later)
Modified:
branches/VALGRIND_3_6_BRANCH/coregrind/m_redir.c
Modified: branches/VALGRIND_3_6_BRANCH/coregrind/m_redir.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/coregrind/m_redir.c 2011-02-14 11:48:39 UTC (rev 11557)
+++ branches/VALGRIND_3_6_BRANCH/coregrind/m_redir.c 2011-02-14 11:50:49 UTC (rev 11558)
@@ -891,7 +891,11 @@
"for your Linux distribution to please in future ship a non-",
"stripped ld.so (or whatever the dynamic linker .so is called)",
"that exports the above-named function using the standard",
- "calling conventions for this platform.",
+ "calling conventions for this platform. The package you need",
+ "to install for fix (1) is called",
+ "",
+ " On Debian, Ubuntu: libc6-dbg",
+ " On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo",
NULL
};
@@ -923,7 +927,16 @@
add_hardwired_spec(
"ld-linux.so.2", "index",
(Addr)&VG_(x86_linux_REDIR_FOR_index),
+# if defined(GLIBC_2_2) || defined(GLIBC_2_3) || defined(GLIBC_2_4) \
+ || defined(GLIBC_2_5) || defined(GLIBC_2_6) || defined(GLIBC_2_7) \
+ || defined(GLIBC_2_8) || defined(GLIBC_2_9) \
+ || defined(GLIBC_2_10) || defined(GLIBC_2_11)
NULL
+# else
+ /* for glibc-2.12 and later, this is mandatory - can't sanely
+ continue without it */
+ complain_about_stripped_glibc_ldso
+# endif
);
}
|
|
From: <sv...@va...> - 2011-02-14 11:48:47
|
Author: sewardj
Date: 2011-02-14 11:48:39 +0000 (Mon, 14 Feb 2011)
New Revision: 11557
Log:
Merge from trunk, r11534 (Add glibc 2.13 support.)
Modified:
branches/VALGRIND_3_6_BRANCH/configure.in
Modified: branches/VALGRIND_3_6_BRANCH/configure.in
===================================================================
--- branches/VALGRIND_3_6_BRANCH/configure.in 2011-02-14 11:45:37 UTC (rev 11556)
+++ branches/VALGRIND_3_6_BRANCH/configure.in 2011-02-14 11:48:39 UTC (rev 11557)
@@ -749,6 +749,13 @@
DEFAULT_SUPP="glibc-2.34567-NPTL-helgrind.supp ${DEFAULT_SUPP}"
DEFAULT_SUPP="glibc-2.X-drd.supp ${DEFAULT_SUPP}"
;;
+ 2.13)
+ AC_MSG_RESULT(2.13 family)
+ AC_DEFINE([GLIBC_2_13], 1, [Define to 1 if you're using glibc 2.13.x])
+ DEFAULT_SUPP="glibc-2.X.supp ${DEFAULT_SUPP}"
+ DEFAULT_SUPP="glibc-2.34567-NPTL-helgrind.supp ${DEFAULT_SUPP}"
+ DEFAULT_SUPP="glibc-2.X-drd.supp ${DEFAULT_SUPP}"
+ ;;
aix5)
AC_MSG_RESULT(AIX 5.1 or 5.2 or 5.3)
AC_DEFINE([AIX5_LIBC], 1, [Define to 1 if you're using AIX 5.1 or 5.2 or 5.3])
@@ -762,7 +769,7 @@
*)
AC_MSG_RESULT([unsupported version ${GLIBC_VERSION}])
- AC_MSG_ERROR([Valgrind requires glibc version 2.2 - 2.12])
+ AC_MSG_ERROR([Valgrind requires glibc version 2.2 - 2.13])
AC_MSG_ERROR([or AIX 5.1 or 5.2 or 5.3 GLIBC_VERSION])
AC_MSG_ERROR([or Darwin libc])
;;
|
|
From: <sv...@va...> - 2011-02-14 11:45:46
|
Author: sewardj
Date: 2011-02-14 11:45:37 +0000 (Mon, 14 Feb 2011)
New Revision: 11556
Log:
Merge from trunk, r11478 and r11479. (Add replacements for strcasecmp
and related functions)
Modified:
branches/VALGRIND_3_6_BRANCH/memcheck/mc_replace_strmem.c
Modified: branches/VALGRIND_3_6_BRANCH/memcheck/mc_replace_strmem.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/memcheck/mc_replace_strmem.c 2011-02-14 11:13:22 UTC (rev 11555)
+++ branches/VALGRIND_3_6_BRANCH/memcheck/mc_replace_strmem.c 2011-02-14 11:45:37 UTC (rev 11556)
@@ -403,6 +403,118 @@
#endif
+#define STRCASECMP(soname, fnname) \
+ int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+ ( const char* s1, const char* s2 ); \
+ int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+ ( const char* s1, const char* s2 ) \
+ { \
+ extern int tolower(int); \
+ register unsigned char c1; \
+ register unsigned char c2; \
+ while (True) { \
+ c1 = tolower(*(unsigned char *)s1); \
+ c2 = tolower(*(unsigned char *)s2); \
+ if (c1 != c2) break; \
+ if (c1 == 0) break; \
+ s1++; s2++; \
+ } \
+ if ((unsigned char)c1 < (unsigned char)c2) return -1; \
+ if ((unsigned char)c1 > (unsigned char)c2) return 1; \
+ return 0; \
+ }
+
+STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp)
+#if defined(VGO_linux)
+STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp)
+#endif
+
+
+#define STRNCASECMP(soname, fnname) \
+ int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+ ( const char* s1, const char* s2, SizeT nmax ); \
+ int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+ ( const char* s1, const char* s2, SizeT nmax ) \
+ { \
+ extern int tolower(int); \
+ SizeT n = 0; \
+ while (True) { \
+ if (n >= nmax) return 0; \
+ if (*s1 == 0 && *s2 == 0) return 0; \
+ if (*s1 == 0) return -1; \
+ if (*s2 == 0) return 1; \
+ \
+ if (tolower(*(unsigned char*)s1) < tolower(*(unsigned char*)s2)) return -1; \
+ if (tolower(*(unsigned char*)s1) > tolower(*(unsigned char*)s2)) return 1; \
+ \
+ s1++; s2++; n++; \
+ } \
+ }
+
+STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp)
+#if defined(VGO_linux)
+STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp)
+#elif defined(VGO_darwin)
+STRNCASECMP(VG_Z_DYLD, strncasecmp)
+#endif
+
+
+#define STRCASECMP_L(soname, fnname) \
+ int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+ ( const char* s1, const char* s2, void* locale ); \
+ int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+ ( const char* s1, const char* s2, void* locale ) \
+ { \
+ extern int tolower_l(int, void*) __attribute__((weak)); \
+ register unsigned char c1; \
+ register unsigned char c2; \
+ while (True) { \
+ c1 = tolower_l(*(unsigned char *)s1, locale); \
+ c2 = tolower_l(*(unsigned char *)s2, locale); \
+ if (c1 != c2) break; \
+ if (c1 == 0) break; \
+ s1++; s2++; \
+ } \
+ if ((unsigned char)c1 < (unsigned char)c2) return -1; \
+ if ((unsigned char)c1 > (unsigned char)c2) return 1; \
+ return 0; \
+ }
+
+STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l)
+#if defined(VGO_linux)
+STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l)
+#endif
+
+
+#define STRNCASECMP_L(soname, fnname) \
+ int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+ ( const char* s1, const char* s2, SizeT nmax, void* locale ); \
+ int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+ ( const char* s1, const char* s2, SizeT nmax, void* locale ) \
+ { \
+ extern int tolower_l(int, void*) __attribute__((weak)); \
+ SizeT n = 0; \
+ while (True) { \
+ if (n >= nmax) return 0; \
+ if (*s1 == 0 && *s2 == 0) return 0; \
+ if (*s1 == 0) return -1; \
+ if (*s2 == 0) return 1; \
+ \
+ if (tolower_l(*(unsigned char*)s1, locale) < tolower_l(*(unsigned char*)s2, locale)) return -1; \
+ if (tolower_l(*(unsigned char*)s1, locale) > tolower_l(*(unsigned char*)s2, locale)) return 1; \
+ \
+ s1++; s2++; n++; \
+ } \
+ }
+
+STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l)
+#if defined(VGO_linux)
+STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l)
+#elif defined(VGO_darwin)
+STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l)
+#endif
+
+
#define STRCMP(soname, fnname) \
int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
( const char* s1, const char* s2 ); \
|
|
From: <sv...@va...> - 2011-02-14 11:13:30
|
Author: sewardj
Date: 2011-02-14 11:13:22 +0000 (Mon, 14 Feb 2011)
New Revision: 11555
Log:
Merge from trunk, r11533 (helgrind, drd: _pre_mem_asciiz handlers:
don't segfault if passed an obviously invalid address.)
Modified:
branches/VALGRIND_3_6_BRANCH/drd/drd_main.c
branches/VALGRIND_3_6_BRANCH/helgrind/hg_main.c
Modified: branches/VALGRIND_3_6_BRANCH/drd/drd_main.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/drd/drd_main.c 2011-02-14 11:10:53 UTC (rev 11554)
+++ branches/VALGRIND_3_6_BRANCH/drd/drd_main.c 2011-02-14 11:13:22 UTC (rev 11555)
@@ -51,6 +51,7 @@
#include "pub_tool_replacemalloc.h"
#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
#include "pub_tool_tooliface.h"
+#include "pub_tool_aspacemgr.h" // VG_(am_is_valid_for_client)
/* Local variables. */
@@ -259,6 +260,13 @@
const char* p = (void*)a;
SizeT size = 0;
+ // Don't segfault if the string starts in an obviously stupid
+ // place. Actually we should check the whole string, not just
+ // the start address, but that's too much trouble. At least
+ // checking the first byte is better than nothing. See #255009.
+ if (!VG_(am_is_valid_for_client) (a, 1, VKI_PROT_READ))
+ return;
+
/* Note: the expression '*p' reads client memory and may crash if the */
/* client provided an invalid pointer ! */
while (*p)
Modified: branches/VALGRIND_3_6_BRANCH/helgrind/hg_main.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/helgrind/hg_main.c 2011-02-14 11:10:53 UTC (rev 11554)
+++ branches/VALGRIND_3_6_BRANCH/helgrind/hg_main.c 2011-02-14 11:13:22 UTC (rev 11555)
@@ -53,6 +53,7 @@
#include "pub_tool_redir.h" // sonames for the dynamic linkers
#include "pub_tool_vki.h" // VKI_PAGE_SIZE
#include "pub_tool_libcproc.h" // VG_(atfork)
+#include "pub_tool_aspacemgr.h" // VG_(am_is_valid_for_client)
#include "hg_basics.h"
#include "hg_wordset.h"
@@ -1797,7 +1798,12 @@
if (SHOW_EVENTS >= 1)
VG_(printf)("evh__pre_mem_asciiz(ctid=%d, \"%s\", %p)\n",
(Int)tid, s, (void*)a );
- // FIXME: think of a less ugly hack
+ // Don't segfault if the string starts in an obviously stupid
+ // place. Actually we should check the whole string, not just
+ // the start address, but that's too much trouble. At least
+ // checking the first byte is better than nothing. See #255009.
+ if (!VG_(am_is_valid_for_client) (a, 1, VKI_PROT_READ))
+ return;
len = VG_(strlen)( (Char*) a );
shadow_mem_cread_range( map_threads_lookup(tid), a, len+1 );
if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE))
|
|
From: <sv...@va...> - 2011-02-14 11:11:02
|
Author: sewardj
Date: 2011-02-14 11:10:53 +0000 (Mon, 14 Feb 2011)
New Revision: 11554
Log:
Merge from trunk, r11523 and r11524 (fixes for #246152, segfault on
pthread_cancel)
Modified:
branches/VALGRIND_3_6_BRANCH/callgrind/bbcc.c
branches/VALGRIND_3_6_BRANCH/callgrind/callstack.c
branches/VALGRIND_3_6_BRANCH/callgrind/global.h
branches/VALGRIND_3_6_BRANCH/callgrind/jumps.c
Modified: branches/VALGRIND_3_6_BRANCH/callgrind/bbcc.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/callgrind/bbcc.c 2011-02-14 11:05:57 UTC (rev 11553)
+++ branches/VALGRIND_3_6_BRANCH/callgrind/bbcc.c 2011-02-14 11:10:53 UTC (rev 11554)
@@ -741,7 +741,11 @@
}
}
else {
- CLG_(unwind_call_stack)(sp, 0);
+ Int unwind_count = CLG_(unwind_call_stack)(sp, 0);
+ if (unwind_count > 0) {
+ /* if unwinding was done, this actually is a return */
+ jmpkind = Ijk_Ret;
+ }
if (jmpkind == Ijk_Call) {
delayed_push = True;
Modified: branches/VALGRIND_3_6_BRANCH/callgrind/callstack.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/callgrind/callstack.c 2011-02-14 11:05:57 UTC (rev 11553)
+++ branches/VALGRIND_3_6_BRANCH/callgrind/callstack.c 2011-02-14 11:10:53 UTC (rev 11554)
@@ -394,11 +394,13 @@
}
-/* remove CallStack items to sync with current SP
+/* Unwind enough CallStack items to sync with current stack pointer.
+ * Returns the number of stack frames unwinded.
*/
-void CLG_(unwind_call_stack)(Addr sp, Int minpops)
+Int CLG_(unwind_call_stack)(Addr sp, Int minpops)
{
Int csp;
+ Int unwind_count = 0;
CLG_DEBUG(4,"+ unwind_call_stack(sp %#lx, minpops %d): frame %d\n",
sp, minpops, CLG_(current_call_stack).sp);
@@ -415,6 +417,7 @@
((top_ce->sp == sp) && minpops>0)) {
minpops--;
+ unwind_count++;
CLG_(pop_call_stack)();
csp=CLG_(current_call_stack).sp;
continue;
@@ -423,4 +426,5 @@
}
CLG_DEBUG(4,"- unwind_call_stack\n");
+ return unwind_count;
}
Modified: branches/VALGRIND_3_6_BRANCH/callgrind/global.h
===================================================================
--- branches/VALGRIND_3_6_BRANCH/callgrind/global.h 2011-02-14 11:05:57 UTC (rev 11553)
+++ branches/VALGRIND_3_6_BRANCH/callgrind/global.h 2011-02-14 11:10:53 UTC (rev 11554)
@@ -779,7 +779,7 @@
void CLG_(push_call_stack)(BBCC* from, UInt jmp, BBCC* to, Addr sp, Bool skip);
void CLG_(pop_call_stack)(void);
-void CLG_(unwind_call_stack)(Addr sp, Int);
+Int CLG_(unwind_call_stack)(Addr sp, Int);
/* from context.c */
void CLG_(init_fn_stack)(fn_stack*);
Modified: branches/VALGRIND_3_6_BRANCH/callgrind/jumps.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/callgrind/jumps.c 2011-02-14 11:05:57 UTC (rev 11553)
+++ branches/VALGRIND_3_6_BRANCH/callgrind/jumps.c 2011-02-14 11:10:53 UTC (rev 11554)
@@ -160,6 +160,8 @@
* This list is only used at dumping time */
if (from) {
+ /* Prohibit corruption by array overrun */
+ CLG_ASSERT((0 <= jmp) && (jmp <= from->bb->cjmp_count));
jcc->next_from = from->jmp[jmp].jcc_list;
from->jmp[jmp].jcc_list = jcc;
}
|
|
From: <sv...@va...> - 2011-02-14 11:06:06
|
Author: sewardj
Date: 2011-02-14 11:05:57 +0000 (Mon, 14 Feb 2011)
New Revision: 11553
Log:
Merge from trunk, r11520 and r11532 (drd: don't assert in the child
after threaded fork())
Modified:
branches/VALGRIND_3_6_BRANCH/drd/drd_main.c
branches/VALGRIND_3_6_BRANCH/drd/drd_thread.c
branches/VALGRIND_3_6_BRANCH/drd/drd_thread.h
Modified: branches/VALGRIND_3_6_BRANCH/drd/drd_main.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/drd/drd_main.c 2011-02-14 10:57:15 UTC (rev 11552)
+++ branches/VALGRIND_3_6_BRANCH/drd/drd_main.c 2011-02-14 11:05:57 UTC (rev 11553)
@@ -625,6 +625,18 @@
DRD_(thread_finished)(drd_tid);
}
+/*
+ * Called immediately after fork for the child process only. 'tid' is the
+ * only surviving thread in the child process. Cleans up thread state.
+ * See also http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html for a detailed discussion of using fork() in combination with mutexes.
+ */
+static
+void drd__atfork_child(ThreadId tid)
+{
+ DRD_(drd_thread_atfork_child)(tid);
+}
+
+
//
// Implementation of the tool interface.
//
@@ -754,6 +766,8 @@
VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
VG_(track_pre_thread_first_insn)(drd_post_thread_create);
VG_(track_pre_thread_ll_exit) (drd_thread_finished);
+ VG_(atfork) (NULL/*pre*/, NULL/*parent*/,
+ drd__atfork_child/*child*/);
// Other stuff.
DRD_(register_malloc_wrappers)(drd_start_using_mem_w_ecu,
Modified: branches/VALGRIND_3_6_BRANCH/drd/drd_thread.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/drd/drd_thread.c 2011-02-14 10:57:15 UTC (rev 11552)
+++ branches/VALGRIND_3_6_BRANCH/drd/drd_thread.c 2011-02-14 11:05:57 UTC (rev 11553)
@@ -367,7 +367,7 @@
DRD_(thread_get_stack_max)(drd_joinee));
}
DRD_(clientobj_delete_thread)(drd_joinee);
- DRD_(thread_delete)(drd_joinee);
+ DRD_(thread_delete)(drd_joinee, False);
}
/**
@@ -450,7 +450,7 @@
* Clean up thread-specific data structures. Call this just after
* pthread_join().
*/
-void DRD_(thread_delete)(const DrdThreadId tid)
+void DRD_(thread_delete)(const DrdThreadId tid, const Bool detached)
{
Segment* sg;
Segment* sg_prev;
@@ -467,7 +467,10 @@
}
DRD_(g_threadinfo)[tid].vg_thread_exists = False;
DRD_(g_threadinfo)[tid].posix_thread_exists = False;
- tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
+ if (detached)
+ DRD_(g_threadinfo)[tid].detached_posix_thread = False;
+ else
+ tl_assert(!DRD_(g_threadinfo)[tid].detached_posix_thread);
DRD_(g_threadinfo)[tid].first = 0;
DRD_(g_threadinfo)[tid].last = 0;
@@ -504,6 +507,21 @@
}
}
+/** Called just after fork() in the child process. */
+void DRD_(drd_thread_atfork_child)(const DrdThreadId tid)
+{
+ unsigned i;
+
+ for (i = 1; i < DRD_N_THREADS; i++)
+ {
+ if (i == tid)
+ continue;
+ if (DRD_(IsValidDrdThreadId(i)))
+ DRD_(thread_delete)(i, True);
+ tl_assert(!DRD_(IsValidDrdThreadId(i)));
+ }
+}
+
/** Called just before pthread_cancel(). */
void DRD_(thread_pre_cancel)(const DrdThreadId tid)
{
Modified: branches/VALGRIND_3_6_BRANCH/drd/drd_thread.h
===================================================================
--- branches/VALGRIND_3_6_BRANCH/drd/drd_thread.h 2011-02-14 10:57:15 UTC (rev 11552)
+++ branches/VALGRIND_3_6_BRANCH/drd/drd_thread.h 2011-02-14 11:05:57 UTC (rev 11553)
@@ -134,8 +134,9 @@
const ThreadId vg_created);
DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created);
void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee);
-void DRD_(thread_delete)(const DrdThreadId tid);
+void DRD_(thread_delete)(const DrdThreadId tid, Bool detached);
void DRD_(thread_finished)(const DrdThreadId tid);
+void DRD_(drd_thread_atfork_child)(const DrdThreadId tid);
void DRD_(thread_pre_cancel)(const DrdThreadId tid);
void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
const Addr stack_startup);
|
|
From: <sv...@va...> - 2011-02-14 10:57:23
|
Author: sewardj
Date: 2011-02-14 10:57:15 +0000 (Mon, 14 Feb 2011)
New Revision: 11552
Log:
Merge from trunk, r11525 (hg: Don't assert in the child after a
threaded program does fork())
Modified:
branches/VALGRIND_3_6_BRANCH/helgrind/hg_main.c
Modified: branches/VALGRIND_3_6_BRANCH/helgrind/hg_main.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/helgrind/hg_main.c 2011-02-14 10:51:56 UTC (rev 11551)
+++ branches/VALGRIND_3_6_BRANCH/helgrind/hg_main.c 2011-02-14 10:57:15 UTC (rev 11552)
@@ -52,6 +52,7 @@
#include "pub_tool_debuginfo.h" // VG_(find_seginfo), VG_(seginfo_soname)
#include "pub_tool_redir.h" // sonames for the dynamic linkers
#include "pub_tool_vki.h" // VKI_PAGE_SIZE
+#include "pub_tool_libcproc.h" // VG_(atfork)
#include "hg_basics.h"
#include "hg_wordset.h"
@@ -1679,6 +1680,8 @@
- tell libhb the thread is gone
- clear the map_threads entry, in order that the Valgrind core
can re-use it. */
+ /* Cleanup actions (next 5 lines) copied in evh__atfork_child; keep
+ in sync. */
tl_assert(thr_q->hbthr);
libhb_async_exit(thr_q->hbthr);
tl_assert(thr_q->coretid == quit_tid);
@@ -1689,7 +1692,36 @@
all__sanity_check("evh__pre_thread_ll_exit-post");
}
+/* This is called immediately after fork, for the child only. 'tid'
+ is the only surviving thread (as per POSIX rules on fork() in
+ threaded programs), so we have to clean up map_threads to remove
+ entries for any other threads. */
+static
+void evh__atfork_child ( ThreadId tid )
+{
+ UInt i;
+ Thread* thr;
+ /* Slot 0 should never be used. */
+ thr = map_threads_maybe_lookup( 0/*INVALID*/ );
+ tl_assert(!thr);
+ /* Clean up all other slots except 'tid'. */
+ for (i = 1; i < VG_N_THREADS; i++) {
+ if (i == tid)
+ continue;
+ thr = map_threads_maybe_lookup(i);
+ if (!thr)
+ continue;
+ /* Cleanup actions (next 5 lines) copied from end of
+ evh__pre_thread_ll_exit; keep in sync. */
+ tl_assert(thr->hbthr);
+ libhb_async_exit(thr->hbthr);
+ tl_assert(thr->coretid == i);
+ thr->coretid = VG_INVALID_THREADID;
+ map_threads_delete(i);
+ }
+}
+
static
void evh__HG_PTHREAD_JOIN_POST ( ThreadId stay_tid, Thread* quit_thr )
{
@@ -4916,6 +4948,8 @@
hg_mallocmeta_table
= VG_(HT_construct)( "hg_malloc_metadata_table" );
+ // add a callback to clean up on (threaded) fork.
+ VG_(atfork)(NULL/*pre*/, NULL/*parent*/, evh__atfork_child/*child*/);
}
VG_DETERMINE_INTERFACE_VERSION(hg_pre_clo_init)
|
|
From: <sv...@va...> - 2011-02-14 10:52:04
|
Author: sewardj
Date: 2011-02-14 10:51:56 +0000 (Mon, 14 Feb 2011)
New Revision: 11551
Log:
Merge from trunk, r11519 (Add suppressions for __setenv leak.)
Modified:
branches/VALGRIND_3_6_BRANCH/darwin10.supp
Modified: branches/VALGRIND_3_6_BRANCH/darwin10.supp
===================================================================
--- branches/VALGRIND_3_6_BRANCH/darwin10.supp 2011-02-14 10:49:30 UTC (rev 11550)
+++ branches/VALGRIND_3_6_BRANCH/darwin10.supp 2011-02-14 10:51:56 UTC (rev 11551)
@@ -35,3 +35,12 @@
fun:_ZN13TFontFeaturesC2EP6CGFont
fun:_ZNK9TBaseFont12CopyFeaturesEv
}
+
+# See https://bugs.kde.org/show_bug.cgi?id=188572 about this; it's
+# unavoidable due to BSD setenv() semantics.
+{
+ macos-__setenv-leak-see-our-bug-188572
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:__setenv
+}
|
|
From: <sv...@va...> - 2011-02-14 10:49:42
|
Author: sewardj
Date: 2011-02-14 10:49:30 +0000 (Mon, 14 Feb 2011)
New Revision: 11550
Log:
Merge from trunk, r11517 (Handle Dwarf3 types created by GNAT.)
Modified:
branches/VALGRIND_3_6_BRANCH/coregrind/m_debuginfo/readdwarf3.c
Modified: branches/VALGRIND_3_6_BRANCH/coregrind/m_debuginfo/readdwarf3.c
===================================================================
--- branches/VALGRIND_3_6_BRANCH/coregrind/m_debuginfo/readdwarf3.c 2011-02-14 10:41:06 UTC (rev 11549)
+++ branches/VALGRIND_3_6_BRANCH/coregrind/m_debuginfo/readdwarf3.c 2011-02-14 10:49:30 UTC (rev 11550)
@@ -1943,7 +1943,10 @@
typedef
struct {
- /* What source language? 'C'=C/C++, 'F'=Fortran, '?'=other
+ /* What source language? 'A'=Ada83/95,
+ 'C'=C/C++,
+ 'F'=Fortran,
+ '?'=other
Established once per compilation unit. */
UChar language;
/* A stack of types which are currently under construction */
@@ -2031,6 +2034,22 @@
typestack_show( parser, "after push" );
}
+/* True if the subrange type being parsed gives the bounds of an array. */
+static Bool subrange_type_denotes_array_bounds ( D3TypeParser* parser,
+ DW_TAG dtag ) {
+ vg_assert(dtag == DW_TAG_subrange_type);
+ /* For most languages, a subrange_type dtag always gives the
+ bounds of an array.
+ For Ada, there are additional conditions as a subrange_type
+ is also used for other purposes. */
+ if (parser->language != 'A')
+ /* not Ada, so it definitely denotes an array bound. */
+ return True;
+ else
+ /* Extra constraints for Ada: it only denotes an array bound if .. */
+ return (! typestack_is_empty(parser)
+ && parser->qparentE[parser->sp].tag == Te_TyArray);
+}
/* Parse a type-related DIE. 'parser' holds the current parser state.
'admin' is where the completed types are dumped. 'dtag' is the tag
@@ -2114,10 +2133,12 @@
case DW_LANG_Fortran77: case DW_LANG_Fortran90:
case DW_LANG_Fortran95:
parser->language = 'F'; break;
- case DW_LANG_Ada83: case DW_LANG_Cobol74:
+ case DW_LANG_Ada83: case DW_LANG_Ada95:
+ parser->language = 'A'; break;
+ case DW_LANG_Cobol74:
case DW_LANG_Cobol85: case DW_LANG_Pascal83:
case DW_LANG_Modula2: case DW_LANG_Java:
- case DW_LANG_Ada95: case DW_LANG_PLI:
+ case DW_LANG_PLI:
case DW_LANG_D: case DW_LANG_Python:
case DW_LANG_Mips_Assembler:
parser->language = '?'; break;
@@ -2269,7 +2290,11 @@
"<anon_enum_type>" );
/* Do we have something that looks sane? */
- if (typeE.Te.TyEnum.szB == 0 /* we must know the size */)
+ if (typeE.Te.TyEnum.szB == 0
+ /* we must know the size */
+ /* but not for Ada, which uses such dummy
+ enumerations as helper for gdb ada mode. */
+ && parser->language != 'A')
goto bad_DIE;
/* On't stack! */
typestack_push( cc, parser, td3, &typeE, level );
@@ -2528,7 +2553,9 @@
goto acquire_Type;
}
- if (dtag == DW_TAG_subrange_type) {
+ /* this is a subrange type defining the bounds of an array. */
+ if (dtag == DW_TAG_subrange_type
+ && subrange_type_denotes_array_bounds(parser, dtag)) {
Bool have_lower = False;
Bool have_upper = False;
Bool have_count = False;
@@ -2539,6 +2566,7 @@
case 'C': have_lower = True; lower = 0; break;
case 'F': have_lower = True; lower = 1; break;
case '?': have_lower = False; break;
+ case 'A': have_lower = False; break;
default: vg_assert(0); /* assured us by handling of
DW_TAG_compile_unit in this fn */
}
@@ -2614,8 +2642,13 @@
goto acquire_Bound;
}
- if (dtag == DW_TAG_typedef) {
- /* We can pick up a new typedef any time. */
+ /* typedef or subrange_type other than array bounds. */
+ if (dtag == DW_TAG_typedef
+ || (dtag == DW_TAG_subrange_type
+ && !subrange_type_denotes_array_bounds(parser, dtag))) {
+ /* subrange_type other than array bound is only for Ada. */
+ vg_assert (dtag == DW_TAG_typedef || parser->language == 'A');
+ /* We can pick up a new typedef/subrange_type any time. */
VG_(memset)(&typeE, 0, sizeof(typeE));
typeE.cuOff = D3_INVALID_CUOFF;
typeE.tag = Te_TyTyDef;
@@ -2639,6 +2672,12 @@
/* Do we have something that looks sane? */
if (/* must have a name */
typeE.Te.TyTyDef.name == NULL
+ /* However gcc gnat Ada generates minimal typedef
+ such as the below => accept no name for Ada.
+ <6><91cc>: DW_TAG_typedef
+ DW_AT_abstract_ori: <9066>
+ */
+ && parser->language != 'A'
/* but the referred-to type can be absent */)
goto bad_DIE;
else
|