From: Julian Seward Date: Thu, 12 Jun 2003 00:56:06 +0000 (+0000) Subject: Fill in a few more SSE/SSE2 insns, with current aim of being able to X-Git-Tag: svn/VALGRIND_2_0_0~108 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ac90e2a5a61e1a74104ee3cdbeb7e3f9539bffcf;p=thirdparty%2Fvalgrind.git Fill in a few more SSE/SSE2 insns, with current aim of being able to run Qt-3.1 as built with "icc -xW" (P4 code generation). Hopefully by now I've worked through most SSE/SSE2 conceptual nasties, and it's mostly a question of filling in the gaps. I think I might have created a bug of some kind with SSE3g_RegWr. My current test app segfaults if I run without --optimise=no, which makes me think I've written something erroneous in the UInstr predicates controlling optimisation. I don't know what though. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1676 --- diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c index c609a89f7c..0b90f11146 100644 --- a/coregrind/vg_from_ucode.c +++ b/coregrind/vg_from_ucode.c @@ -1464,7 +1464,8 @@ static void emit_SSE3g ( FlagSet uses_sflags, UChar second_byte, UChar third_byte, UChar fourth_byte, - Int ireg ) + Int ireg, + Bool reads_ireg ) { VG_(new_emit)(True, uses_sflags, sets_sflags); VG_(emitB) ( first_byte ); @@ -1475,10 +1476,14 @@ static void emit_SSE3g ( FlagSet uses_sflags, fourth_byte |= (ireg & 7); /* patch in our ireg */ VG_(emitB) ( fourth_byte ); if (dis) - VG_(printf)("\n\t\tsse-reg-to-xmmreg--0x%x:0x%x:0x%x:0x%x-(%s)\n", - (UInt)first_byte, (UInt)second_byte, - (UInt)third_byte, (UInt)fourth_byte, - nameIReg(4,ireg) ); + VG_(printf)( + reads_ireg + ? "\n\t\tireg-to-ssereg--0x%x:0x%x:0x%x:0x%x-(%s)\n" + : "\n\t\tssereg-to-ireg--0x%x:0x%x:0x%x:0x%x-(%s)\n", + (UInt)first_byte, (UInt)second_byte, + (UInt)third_byte, (UInt)fourth_byte, + nameIReg(4,ireg) + ); } static void emit_SSE4 ( FlagSet uses_sflags, @@ -3713,7 +3718,6 @@ static void emitUInstr ( UCodeBlock* cb, Int i, vg_assert(u->tag1 == Lit16); vg_assert(u->tag2 == Lit16); vg_assert(u->tag3 == RealReg); - vg_assert(!anyFlagUse(u)); if (!(*sselive)) { emit_get_sse_state(); *sselive = True; @@ -3727,6 +3731,7 @@ static void emitUInstr ( UCodeBlock* cb, Int i, break; case SSE3g_RegRd: + case SSE3g_RegWr: vg_assert(u->size == 4); vg_assert(u->tag1 == Lit16); vg_assert(u->tag2 == Lit16); @@ -3741,7 +3746,8 @@ static void emitUInstr ( UCodeBlock* cb, Int i, u->val1 & 0xFF, (u->val2 >> 8) & 0xFF, u->val2 & 0xFF, - u->val3 ); + u->val3, + u->opcode==SSE3g_RegRd ? True : False ); break; case SSE4: diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c index 98374ecc23..31dc89be8b 100644 --- a/coregrind/vg_to_ucode.c +++ b/coregrind/vg_to_ucode.c @@ -3293,6 +3293,7 @@ Addr dis_SSE3_reg_or_mem ( UCodeBlock* cb, UChar opc2, UChar opc3 ) { + UChar dis_buf[50]; UChar modrm = getUChar(eip); if (epartIsReg(modrm)) { /* Completely internal SSE insn. */ @@ -3305,7 +3306,18 @@ Addr dis_SSE3_reg_or_mem ( UCodeBlock* cb, nameXMMReg(gregOfRM(modrm)) ); eip++; } else { - VG_(core_panic)("dis_SSE3_reg_or_mem: mem"); + UInt pair = disAMode ( cb, sorb, eip, dis?dis_buf:NULL ); + Int tmpa = LOW24(pair); + eip += HI8(pair); + uInstr3(cb, SSE3a_MemRd, sz, + Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2), + Lit16, (((UShort)(opc3)) << 8) | ((UShort)modrm), + TempReg, tmpa); + if (dis) + VG_(printf)("%s %s, %s\n", + name, + dis_buf, + nameXMMReg(gregOfRM(modrm))); } return eip; } @@ -3608,8 +3620,53 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) goto decode_success; } - /* CVTSI2SS -- convert int reg to low 4 bytes of XMM reg. */ - if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) { + /* CVTTSD2SI -- convert a double-precision float value in memory or + xmm reg to int and put it in an ireg. */ + if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x2C) { + vg_assert(sz == 4); + modrm = insn[3]; + if (epartIsReg(modrm)) { + /* We're moving a value in an xmm reg to an ireg. */ + eip += 4; + t1 = newTemp(cb); + uInstr3(cb, SSE3g_RegWr, 4, + Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1], + Lit16, (((UShort)insn[2]) << 8) | (UShort)modrm, + TempReg, t1 ); + uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm)); + if (dis) + VG_(printf)("cvttsd2si %s, %s\n", + nameXMMReg(eregOfRM(modrm)), + nameIReg(4,gregOfRM(modrm)) ); + } else { +#if 0 + /* So, we're reading memory and writing an ireg. This calls + for the ultra-horrible SSE3ag_MemRd_RegWr uinstr. */ + t1 = newTemp(cb); /* t1 holds value on its way to ireg */ + pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL ); + t2 = LOW24(pair); /* t2 holds addr */ + eip += 3+HI8(pair); + uInstr2(cb, SSE3ag_MemRd_RegWr, 8, + TempReg, t2, /* address */ + TempReg, t1 /* dest */); + uLiteral(cb, (((UInt)insn[0]) << 16) + | (((UInt)insn[1]) << 8) + | ((UInt)insn[2]) ); + uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm)); + /* PRINTING CODE */ +#endif + VG_(core_panic)("CVTTSD2SI mem"); + } + goto decode_success; + } + + /* CVTSI2SS -- convert int reg, or int value in memory, to low 4 + bytes of XMM reg. */ + /* CVTSI2SD -- convert int reg, or int value in memory, to low 8 + bytes of XMM reg. */ + if ((insn[0] == 0xF3 /*CVTSI2SS*/ || insn[0] == 0xF2 /* CVTSI2SD*/) + && insn[1] == 0x0F && insn[2] == 0x2A) { + Char* s_or_d = insn[0]==0xF3 ? "s" : "d"; vg_assert(sz == 4); modrm = insn[3]; t1 = newTemp(cb); @@ -3621,8 +3678,9 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) TempReg, t1 ); eip += 4; if (dis) - VG_(printf)("cvtsi2ss %s, %s\n", nameIReg(4,eregOfRM(modrm)), - nameXMMReg(gregOfRM(modrm))); + VG_(printf)("cvtsi2s%s %s, %s\n", s_or_d, + nameIReg(4,eregOfRM(modrm)), + nameXMMReg(gregOfRM(modrm))); } else { pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL ); t2 = LOW24(pair); @@ -3633,8 +3691,9 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3], TempReg, t1 ); if (dis) - VG_(printf)("cvtsi2ss %s, %s\n", dis_buf, - nameXMMReg(gregOfRM(modrm))); + VG_(printf)("cvtsi2s%s %s, %s\n", s_or_d, + dis_buf, + nameXMMReg(gregOfRM(modrm))); } goto decode_success; } @@ -3655,6 +3714,14 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) goto decode_success; } + /* CVTSD2SS -- convert one single double. to float. */ + if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) { + vg_assert(sz == 4); + eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "cvtsd2ss", + insn[0], insn[1], insn[2] ); + goto decode_success; + } + /* SHUFPS */ if (insn[0] == 0x0F && insn[1] == 0xC6) { vg_assert(sz == 4); @@ -3679,6 +3746,22 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) goto decode_success; } + /* DIVSD */ + if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5E) { + vg_assert(sz == 4); + eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "divsd", + insn[0], insn[1], insn[2] ); + goto decode_success; + } + + /* ADDSD */ + if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x58) { + vg_assert(sz == 4); + eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "addsd", + insn[0], insn[1], insn[2] ); + goto decode_success; + } + /* ADDPS */ if (insn[0] == 0x0F && insn[1] == 0x58) { vg_assert(sz == 4); @@ -3713,6 +3796,17 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) goto decode_success; } + /* COMISD (src)xmmreg-or-mem, (dst)xmmreg */ + if (sz == 2 + && insn[0] == 0x0F && insn[1] == 0x2F) { + eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 8, "comisd", + 0x66, insn[0], insn[1] ); + vg_assert(LAST_UINSTR(cb).opcode == SSE3a_MemRd + || LAST_UINSTR(cb).opcode == SSE4); + uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty); + goto decode_success; + } + /* MOVSD -- move 8 bytes of XMM reg to/from XMM reg or mem. */ if (insn[0] == 0xF2 && insn[1] == 0x0F diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c index e2d998ebd9..b2e30ced24 100644 --- a/coregrind/vg_translate.c +++ b/coregrind/vg_translate.c @@ -561,8 +561,9 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) case SSE2a_MemWr: return LIT0 && SZ416 && CC0 && Ls1 && Ls2 && TR3 && XOTHER; case SSE2a_MemRd: return LIT0 && SZ416 && CC0 && Ls1 && Ls2 && TR3 && XOTHER; case SSE3a_MemWr: return LIT0 && SZsse && CC0 && Ls1 && Ls2 && TR3 && XOTHER; - case SSE3a_MemRd: return LIT0 && SZsse && CC0 && Ls1 && Ls2 && TR3 && XOTHER; + case SSE3a_MemRd: return LIT0 && SZsse && CCf && Ls1 && Ls2 && TR3 && XOTHER; case SSE3g_RegRd: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER; + case SSE3g_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER; case SSE3: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && N3 && XOTHER; case SSE4: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && N3 && XOTHER; default: @@ -879,6 +880,7 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc ) case SSE2a_MemWr: return "SSE2a_MWr"; case SSE2a_MemRd: return "SSE2a_MRd"; case SSE3g_RegRd: return "SSE3g_RRd"; + case SSE3g_RegWr: return "SSE3g_RWr"; case SSE3: return "SSE3"; case SSE4: return "SSE4"; case SSE3a_MemWr: return "SSE3a_MWr"; @@ -1049,6 +1051,7 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) break; case SSE3g_RegRd: + case SSE3g_RegWr: VG_(printf)("0x%x:0x%x:0x%x:0x%x", (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, (u->val2 >> 8) & 0xFF, u->val2 & 0xFF ); @@ -1216,7 +1219,9 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites ) case SSE3a_MemWr: case SSE3a_MemRd: case SSE2a_MemWr: - case SSE2a_MemRd: RD(3); + case SSE2a_MemRd: RD(3); break; + + case SSE3g_RegWr: WR(3); break; case MMX2_RegRd: RD(2); break; case MMX2_RegWr: WR(2); break; @@ -1375,7 +1380,7 @@ Int maybe_uinstrReadsArchReg ( UInstr* u ) case MMX2_RegRd: case MMX2_RegWr: case SSE2a_MemWr: case SSE2a_MemRd: case SSE3a_MemWr: case SSE3a_MemRd: - case SSE3g_RegRd: + case SSE3g_RegRd: case SSE3g_RegWr: case SSE4: case SSE3: case WIDEN: /* GETSEG and USESEG are to do with ArchRegS, not ArchReg */ @@ -2244,7 +2249,7 @@ void VG_(translate) ( /*IN*/ ThreadState* tst, UChar* final_code; UCodeBlock* cb; Bool notrace_until_done; - Int notrace_until_limit = 0; + Int notrace_until_limit = 15000; VGP_PUSHCC(VgpTranslate); debugging_translation diff --git a/include/vg_skin.h b/include/vg_skin.h index 5ef6581c6f..fc4c1909fa 100644 --- a/include/vg_skin.h +++ b/include/vg_skin.h @@ -643,6 +643,22 @@ typedef */ SSE3g_RegRd, + /* 4 bytes, reads memory, writes an integer register, but is + nevertheless an SSE insn. The insn is of the form + bbbbbbbb:bbbbbbbb:bbbbbbbb:mod ireg rm where mod indicates + memory (ie is not 11b) and ireg is the int reg written. The + first 3 bytes are held in lit32[23:0] since there is + insufficient space elsewhere. mod and rm are to be replaced + at codegen time by a reference to the Temp/RealReg holding + the address. Arg1 holds this Temp/RealReg. ireg is to be + replaced at codegen time by a reference to the relevant + RealReg in which the answer is to be written. Arg2 holds + this Temp/RealReg. Transfer to the destination reg is always + at size 4. However the memory read can be at sizes 4 or 8 + and so this is what the sz field holds. + */ + SSE3ag_MemRd_RegWr, + /* 5 bytes, no memrefs, no iregdefs, copy exactly to the output. Held in val1[15:0], val2[15:0] and val3[7:0]. */ SSE5,