From: Julian Seward Date: Sun, 25 May 2003 01:07:34 +0000 (+0000) Subject: Implement a few SSE instructions, enough to run bzip2 when compiled X-Git-Tag: svn/VALGRIND_2_0_0~133 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5777e313ad8c8d1b8a469185edf6d6ff53ab82b2;p=thirdparty%2Fvalgrind.git Implement a few SSE instructions, enough to run bzip2 when compiled with the Intel C compiler (7.1.009) with vectorisation for SSE engaged (-xK). git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1651 --- diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c index 2236a47d27..9b8fb84d02 100644 --- a/coregrind/vg_from_ucode.c +++ b/coregrind/vg_from_ucode.c @@ -1419,6 +1419,86 @@ static void emit_MMX2_regmem ( FlagSet uses_sflags, nameIReg(4,ireg) ); } +static void emit_SSE2a ( FlagSet uses_sflags, + FlagSet sets_sflags, + UChar first_byte, + UChar second_byte, + UChar third_byte, + Int ireg ) +{ + VG_(new_emit)(True, uses_sflags, sets_sflags); + VG_(emitB) ( first_byte ); + VG_(emitB) ( second_byte ); + third_byte &= 0x38; /* mask out mod and rm fields */ + emit_amode_regmem_reg ( ireg, third_byte >> 3 ); + if (dis) + VG_(printf)("\n\t\tsse-0x%x:0x%x:0x%x-(%s)\n", + (UInt)first_byte, (UInt)second_byte, (UInt)third_byte, + nameIReg(4,ireg) ); +} + +static void emit_SSE3a ( FlagSet uses_sflags, + FlagSet sets_sflags, + UChar first_byte, + UChar second_byte, + UChar third_byte, + UChar fourth_byte, + Int ireg ) +{ + VG_(new_emit)(True, uses_sflags, sets_sflags); + VG_(emitB) ( first_byte ); + VG_(emitB) ( second_byte ); + VG_(emitB) ( third_byte ); + fourth_byte &= 0x38; /* mask out mod and rm fields */ + emit_amode_regmem_reg ( ireg, fourth_byte >> 3 ); + if (dis) + VG_(printf)("\n\t\tsse-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_SSE3g ( FlagSet uses_sflags, + FlagSet sets_sflags, + UChar first_byte, + UChar second_byte, + UChar third_byte, + UChar fourth_byte, + Int ireg ) +{ + VG_(new_emit)(True, uses_sflags, sets_sflags); + VG_(emitB) ( first_byte ); + VG_(emitB) ( second_byte ); + VG_(emitB) ( third_byte ); + fourth_byte &= 0x38; /* mask out mod and rm fields */ + fourth_byte |= 0xC0; /* set top two bits: mod = 11b */ + 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) ); +} + +static void emit_SSE4 ( FlagSet uses_sflags, + FlagSet sets_sflags, + UChar first_byte, + UChar second_byte, + UChar third_byte, + UChar fourth_byte ) +{ + VG_(new_emit)(True, uses_sflags, sets_sflags); + VG_(emitB) ( first_byte ); + VG_(emitB) ( second_byte ); + VG_(emitB) ( third_byte ); + VG_(emitB) ( fourth_byte ); + if (dis) + VG_(printf)("\n\t\tsse-0x%x:0x%x:0x%x:0x%x\n", + (UInt)first_byte, (UInt)second_byte, + (UInt)third_byte, (UInt)fourth_byte ); +} + static void emit_MMX2_reg_to_mmxreg ( FlagSet uses_sflags, FlagSet sets_sflags, UChar first_byte, @@ -3593,6 +3673,78 @@ static void emitUInstr ( UCodeBlock* cb, Int i, u->val2 & 0xFF ); break; + case SSE2a_MemWr: + case SSE2a_MemRd: + vg_assert(u->size == 4 || u->size == 16); + 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; + } + emit_SSE2a ( u->flags_r, u->flags_w, + (u->val1 >> 8) & 0xFF, + u->val1 & 0xFF, + u->val2 & 0xFF, + u->val3 ); + break; + + case SSE3a_MemWr: + case SSE3a_MemRd: + vg_assert(u->size == 4 || u->size == 16); + 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; + } + emit_SSE3a ( u->flags_r, u->flags_w, + (u->val1 >> 8) & 0xFF, + u->val1 & 0xFF, + (u->val2 >> 8) & 0xFF, + u->val2 & 0xFF, + u->val3 ); + break; + + case SSE3g_RegRd: + vg_assert(u->size == 4); + 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; + } + emit_SSE3g ( u->flags_r, u->flags_w, + (u->val1 >> 8) & 0xFF, + u->val1 & 0xFF, + (u->val2 >> 8) & 0xFF, + u->val2 & 0xFF, + u->val3 ); + break; + + case SSE4: + vg_assert(u->size == 0); + vg_assert(u->tag1 == Lit16); + vg_assert(u->tag2 == Lit16); + vg_assert(u->tag3 == NoValue); + vg_assert(!anyFlagUse(u)); + if (!(*sselive)) { + emit_get_sse_state(); + *sselive = True; + } + emit_SSE4 ( u->flags_r, u->flags_w, + (u->val1 >> 8) & 0xFF, + u->val1 & 0xFF, + (u->val2 >> 8) & 0xFF, + u->val2 & 0xFF ); + break; + default: if (VG_(needs).extended_UCode) { if (*sselive) { diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c index f138dc591d..d4548a942b 100644 --- a/coregrind/vg_to_ucode.c +++ b/coregrind/vg_to_ucode.c @@ -146,6 +146,14 @@ Char* VG_(name_of_mmx_reg) ( Int mmxreg ) return mmx_names[mmxreg]; } +Char* VG_(name_of_xmm_reg) ( Int xmmreg ) +{ + static Char* xmm_names[8] + = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" }; + if (xmmreg < 0 || xmmreg > 7) VG_(core_panic)("name_of_xmm_reg"); + return xmm_names[xmmreg]; +} + Char* VG_(name_of_mmx_gran) ( UChar gran ) { switch (gran) { @@ -3247,11 +3255,48 @@ Addr dis_MMXop_regmem_to_reg ( UCodeBlock* cb, } + +/* Simple SSE operations, either + op (src)xmmreg, (dst)xmmreg + or + op (src)address, (dst)xmmreg + It is assumed that there are 3 opcode bytes preceding the start + of the address mode. eip points to the first opcode byte. +*/ +static +Addr dis_SSE3_reg_or_mem ( UCodeBlock* cb, + UChar sorb, + Char* name, + Int sz, + Addr eip ) +{ + UChar opc1 = getUChar(eip); + UChar opc2 = getUChar(eip+1); + UChar opc3 = getUChar(eip+2); + UChar modrm = getUChar(eip+3); + eip += 3; + if (epartIsReg(modrm)) { + /* Completely internal SSE insn. */ + uInstr2(cb, SSE4, 0, /* ignore sz for internal ops */ + Lit16, (((UShort)opc1) << 8) | (UShort)opc2, + Lit16, (((UShort)opc3) << 8) | (UShort)modrm ); + if (dis) + VG_(printf)("%s %s, %s\n", name, + nameXMMReg(eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)) ); + eip++; + } else { + VG_(core_panic)("dis_SSE3_reg_or_mem: mem"); + } + return eip; +} + + + /*------------------------------------------------------------*/ /*--- Disassembling entire basic blocks ---*/ /*------------------------------------------------------------*/ -/* Disassemble a single instruction into ucode, returning the update +/* Disassemble a single instruction into ucode, returning the updated eip, and setting *isEnd to True if this is the last insn in a basic block. Also do debug printing if (dis). */ @@ -3339,9 +3384,107 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) break; } + /* ---------------------------------------------------- */ + /* --- The SSE/SSE2 decoder. --- */ + /* ---------------------------------------------------- */ + + /* If it looks like this CPU might support SSE, try decoding SSE + insns. */ + if (VG_(have_ssestate)) { + UChar* insn = (UChar*)eip; + + /* STMXCSR/LDMXCSR m32 */ + if (insn[0] == 0x0F && insn[1] == 0xAE + && (gregOfRM(insn[2]) == 3 || gregOfRM(insn[2]) == 2) ) { + Bool store = gregOfRM(insn[2]) == 3; + pair = disAMode ( cb, sorb, eip+2, dis?dis_buf:NULL ); + t1 = LOW24(pair); + eip += 2+HI8(pair); + uInstr3(cb, store ? SSE2a_MemWr : SSE2a_MemRd, 4, + Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1], + Lit16, (UShort)insn[2], + TempReg, t1 ); + if (dis) + VG_(printf)("%smxcsr %s\n", store ? "st" : "ld", dis_buf ); + goto sse_done; + } + + /* CVTSI2SS */ + if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) { + modrm = insn[3]; + t1 = newTemp(cb); + if (epartIsReg(modrm)) { + uInstr2(cb, GET, 4, ArchReg, eregOfRM(modrm), TempReg, t1); + uInstr3(cb, SSE3g_RegRd, 4, + Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1], + Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3], + TempReg, t1 ); + eip += 4; + if (dis) + VG_(printf)("cvtsi2ss %s, %s\n", nameIReg(4,eregOfRM(modrm)), + nameXMMReg(gregOfRM(modrm))); + } else { + pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL ); + t2 = LOW24(pair); + eip += 3+HI8(pair); + uInstr2(cb, LOAD, 4, TempReg, t2, TempReg, t1); + uInstr3(cb, SSE3g_RegRd, 4, + Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1], + Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3], + TempReg, t1 ); + if (dis) + VG_(printf)("cvtsi2ss %s, %s\n", dis_buf, + nameXMMReg(gregOfRM(modrm))); + } + goto sse_done; + } + + /* DIVSS */ + if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5E) { + eip = dis_SSE3_reg_or_mem ( cb, sorb, "divss", 4, eip ); + goto sse_done; + } + + /* MOVSS */ + if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x11) { + if (epartIsReg(insn[3])) { + /* MOVSS xmm, xmm */ + VG_(core_panic)("MOVSS reg"); + eip = dis_SSE3_reg_or_mem ( cb, sorb, "movss", 4, eip ); + } else { + Bool store = insn[2] == 0x11; + pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL ); + t1 = LOW24(pair); + eip += 3+HI8(pair); + uInstr3(cb, store ? SSE3a_MemWr : SSE3a_MemRd, 4, + Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1], + Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3], + TempReg, t1 ); + if (dis && store) + VG_(printf)("movss %s, %s\n", + nameXMMReg(gregOfRM(insn[3])), dis_buf ); + if (dis && !store) + VG_(printf)("movss %s, %s\n", + dis_buf, nameXMMReg(gregOfRM(insn[3])) ); + } + goto sse_done; + } + + /* Fall through into the non-SSE decoder. */ + } /* if (VG_(have_ssestate)) */ + + + /* ---------------------------------------------------- */ + /* --- end of the SSE/SSE2 decoder. --- */ + /* ---------------------------------------------------- */ + + /* Get the primary opcode. */ opc = getUChar(eip); eip++; + /* We get here if the current insn isn't SSE, or this CPU doesn't + support SSE. */ + switch (opc) { /* ------------------------ Control flow --------------- */ @@ -3705,7 +3848,7 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) handleSegOverride(cb, sorb, t2); uInstr2(cb, LOAD, sz, TempReg, t2, TempReg, t1); uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, R_EAX); - if (dis) VG_(printf)("mov%c %s0x%x,%s\n", nameISize(sz), + if (dis) VG_(printf)("mov%c %s0x%x, %s\n", nameISize(sz), sorbTxt(sorb), d32, nameIReg(sz,R_EAX)); break; @@ -3721,9 +3864,9 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) uLiteral(cb, d32); handleSegOverride(cb, sorb, t2); uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2); - if (dis) VG_(printf)("mov%c %s,%s0x%x\n", nameISize(sz), - sorbTxt(sorb), - nameIReg(sz,R_EAX), d32); + if (dis) VG_(printf)("mov%c %s, %s0x%x\n", nameISize(sz), + nameIReg(sz,R_EAX), + sorbTxt(sorb), d32); break; case 0xB0: /* MOV imm,AL */ @@ -4316,7 +4459,8 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) if (dis) VG_(printf)("repe nop (P4 pause)\n"); /* do nothing; apparently a hint to the P4 re spin-wait loop */ } else { - VG_(printf)("REPE then 0x%x\n", (UInt)abyte); + VG_(printf)("Insn bytes: 0xF3 0x%x 0x%x\n", + (UInt)abyte, (UInt)getUChar(eip)); VG_(core_panic)("Unhandled REPE case"); } break; @@ -5105,6 +5249,7 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) VG_(core_panic)("unhandled x86 opcode"); } + sse_done: if (dis) VG_(printf)("\n"); for (; first_uinstr < cb->used; first_uinstr++) { diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c index 0010807602..9c2445f1e3 100644 --- a/coregrind/vg_translate.c +++ b/coregrind/vg_translate.c @@ -411,6 +411,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) # define SZ0 (u->size == 0) # define SZ42 (u->size == 4 || u->size == 2) # define SZ48 (u->size == 4 || u->size == 8) +# define SZ416 (u->size == 4 || u->size == 16) # define SZi (u->size == 4 || u->size == 2 || u->size == 1) # define SZf ( u->size == 4 || u->size == 8 || u->size == 2 \ || u->size == 10 || u->size == 28 || u->size == 108) @@ -454,6 +455,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) # define L1 (u->tag1 == Literal && u->val1 == 0) # define L2 (u->tag2 == Literal && u->val2 == 0) # define Ls1 (u->tag1 == Lit16) +# define Ls2 (u->tag2 == Lit16) # define Ls3 (u->tag3 == Lit16) # define TRL1 (TR1 || L1) # define TRAL1 (TR1 || A1 || L1) @@ -548,11 +550,19 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */ case MMX1: case MMX2: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER; - case MMX3: return LIT0 && SZ0 && CC0 && Ls1 && Ls1 && N3 && XOTHER; + case MMX3: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && N3 && XOTHER; case MMX2_MemRd: return LIT0 && SZ48 && CC0 && Ls1 && TR2 && N3 && XOTHER; case MMX2_MemWr: return LIT0 && SZ48 && CC0 && Ls1 && TR2 && N3 && XOTHER; case MMX2_RegRd: return LIT0 && SZ4 && CC0 && Ls1 && TR2 && N3 && XOTHER; case MMX2_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && TR2 && N3 && XOTHER; + + /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */ + 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 && SZ416 && CC0 && Ls1 && Ls2 && TR3 && XOTHER; + case SSE3a_MemRd: return LIT0 && SZ416 && CC0 && Ls1 && Ls2 && TR3 && XOTHER; + case SSE3g_RegRd: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER; + case SSE4: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && N3 && XOTHER; default: if (VG_(needs).extended_UCode) return SK_(sane_XUInstr)(beforeRA, beforeLiveness, u); @@ -573,6 +583,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) # undef SZ0 # undef SZ42 # undef SZ48 +# undef SZ416 # undef SZi # undef SZf # undef SZ4m @@ -600,6 +611,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) # undef L1 # undef L2 # undef Ls1 +# undef Ls2 # undef Ls3 # undef TRL1 # undef TRAL1 @@ -861,6 +873,12 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc ) case MMX2_MemWr: return "MMX2_MWr" ; case MMX2_RegRd: return "MMX2_RRd" ; case MMX2_RegWr: return "MMX2_RWr" ; + case SSE2a_MemWr: return "SSE2a_MWr"; + case SSE2a_MemRd: return "SSE2a_MRd"; + case SSE3g_RegRd: return "SSE3g_RRd"; + case SSE4: return "SSE4"; + case SSE3a_MemWr: return "SSE3a_MWr"; + case SSE3a_MemRd: return "SSE3a_MRd"; default: if (VG_(needs).extended_UCode) return SK_(name_XUOpcode)(opc); @@ -930,20 +948,23 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) case 2: VG_(printf)("W"); break; case 4: VG_(printf)("L"); break; case 8: VG_(printf)("Q"); break; + case 16: VG_(printf)("QQ"); break; default: VG_(printf)("%d", (Int)u->size); break; } + VG_(printf)(" \t"); + switch (u->opcode) { case CALLM_S: case CALLM_E: break; case INCEIP: - VG_(printf)("\t$%d", u->val1); + VG_(printf)("$%d", u->val1); break; case LEA2: - VG_(printf)("\t%d(" , u->lit32); + VG_(printf)("%d(" , u->lit32); VG_(pp_UOperand)(u, 1, 4, False); VG_(printf)(","); VG_(pp_UOperand)(u, 2, 4, False); @@ -952,7 +973,7 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) break; case LEA1: - VG_(printf)("\t%d" , u->lit32); + VG_(printf)("%d" , u->lit32); VG_(pp_UOperand)(u, 1, 4, True); VG_(printf)(", "); VG_(pp_UOperand)(u, 2, 4, False); @@ -962,55 +983,82 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) break; case FPU_W: - VG_(printf)("\t0x%x:0x%x, ", + VG_(printf)("0x%x:0x%x, ", (u->val1 >> 8) & 0xFF, u->val1 & 0xFF ); VG_(pp_UOperand)(u, 2, 4, True); break; case FPU_R: - VG_(printf)("\t"); + VG_(printf)(""); VG_(pp_UOperand)(u, 2, 4, True); VG_(printf)(", 0x%x:0x%x", (u->val1 >> 8) & 0xFF, u->val1 & 0xFF ); break; case FPU: - VG_(printf)("\t0x%x:0x%x", + VG_(printf)("0x%x:0x%x", (u->val1 >> 8) & 0xFF, u->val1 & 0xFF ); break; case MMX1: - VG_(printf)("\t0x%x", + VG_(printf)("0x%x", u->val1 & 0xFF ); break; case MMX2: - VG_(printf)("\t0x%x:0x%x", + VG_(printf)("0x%x:0x%x", (u->val1 >> 8) & 0xFF, u->val1 & 0xFF ); break; case MMX3: - VG_(printf)("\t0x%x:0x%x:0x%x", + VG_(printf)("0x%x:0x%x:0x%x", (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF ); break; case MMX2_RegWr: case MMX2_RegRd: - VG_(printf)("\t0x%x:0x%x, ", + VG_(printf)("0x%x:0x%x, ", (u->val1 >> 8) & 0xFF, u->val1 & 0xFF ); VG_(pp_UOperand)(u, 2, 4, False); break; case MMX2_MemWr: case MMX2_MemRd: - VG_(printf)("\t0x%x:0x%x", + VG_(printf)("0x%x:0x%x", (u->val1 >> 8) & 0xFF, u->val1 & 0xFF ); VG_(pp_UOperand)(u, 2, 4, True); break; + case SSE2a_MemWr: + case SSE2a_MemRd: + VG_(printf)("0x%x:0x%x:0x%x", + (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF ); + VG_(pp_UOperand)(u, 3, 4, True); + break; + + case SSE3a_MemWr: + case SSE3a_MemRd: + VG_(printf)("0x%x:0x%x:0x%x:0x%x", + (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, + (u->val1 >> 8) & 0xFF, u->val2 & 0xFF ); + VG_(pp_UOperand)(u, 3, 4, True); + break; + + case SSE3g_RegRd: + VG_(printf)("0x%x:0x%x:0x%x:0x%x", + (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, + (u->val2 >> 8) & 0xFF, u->val2 & 0xFF ); + VG_(pp_UOperand)(u, 3, 4, True); + break; + + case SSE4: + VG_(printf)("0x%x:0x%x:0x%x:0x%x", + (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, + (u->val2 >> 8) & 0xFF, u->val2 & 0xFF ); + break; + case GET: case PUT: case MOV: case LOAD: case STORE: case CMOV: case GETSEG: case PUTSEG: - VG_(printf)("\t"); VG_(pp_UOperand)(u, 1, u->size, u->opcode==LOAD); VG_(printf)(", "); VG_(pp_UOperand)(u, 2, u->size, u->opcode==STORE); @@ -1024,7 +1072,6 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) case JmpClientReq: VG_(printf)("-cli"); break; default: break; } - VG_(printf)("\t"); VG_(pp_UOperand)(u, 1, u->size, False); if (CondAlways == u->cond) { /* Print x86 instruction size if filled in */ @@ -1036,13 +1083,11 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) case GETF: case PUTF: case CC2VAL: case PUSH: case POP: case CLEAR: case CALLM: case NOT: case NEG: case INC: case DEC: case BSWAP: - VG_(printf)("\t"); VG_(pp_UOperand)(u, 1, u->size, False); break; /* Print a "(s)" after args passed on stack */ case CCALL: - VG_(printf)("\t"); if (u->has_ret_val) { VG_(pp_UOperand)(u, 3, 0, False); VG_(printf)(" = "); @@ -1074,7 +1119,6 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) case XOR: case SUB: case SBB: case SHL: case SHR: case SAR: case ROL: case ROR: case RCL: case RCR: - VG_(printf)("\t"); VG_(pp_UOperand)(u, 1, u->size, False); VG_(printf)(", "); VG_(pp_UOperand)(u, 2, u->size, False); @@ -1083,7 +1127,6 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) case WIDEN: VG_(printf)("_%c%c", VG_(toupper)(nameISize(u->extra4b)), u->signed_widen?'s':'z'); - VG_(printf)("\t"); VG_(pp_UOperand)(u, 1, u->size, False); break; @@ -1159,9 +1202,16 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites ) case LEA1: RD(1); WR(2); break; case LEA2: RD(1); RD(2); WR(3); break; + case SSE3g_RegRd: + case SSE3a_MemWr: + case SSE3a_MemRd: + case SSE2a_MemWr: + case SSE2a_MemRd: RD(3); + case MMX2_RegRd: RD(2); break; case MMX2_RegWr: WR(2); break; + case SSE4: case MMX1: case MMX2: case MMX3: case NOP: case FPU: case INCEIP: case CALLM_S: case CALLM_E: case CLEAR: case CALLM: case LOCK: break; @@ -1313,6 +1363,10 @@ Int maybe_uinstrReadsArchReg ( UInstr* u ) case MMX1: case MMX2: case MMX3: case MMX2_MemRd: case MMX2_MemWr: case MMX2_RegRd: case MMX2_RegWr: + case SSE2a_MemWr: case SSE2a_MemRd: + case SSE3a_MemWr: case SSE3a_MemRd: + case SSE3g_RegRd: + case SSE4: case WIDEN: /* GETSEG and USESEG are to do with ArchRegS, not ArchReg */ case GETSEG: case PUTSEG: @@ -1441,6 +1495,9 @@ static void vg_improve ( UCodeBlock* cb ) if (cb->instrs[m].tag2 == TempReg && cb->instrs[m].val2 == tr) cb->instrs[m].val2 = told; + if (cb->instrs[m].tag3 == TempReg + && cb->instrs[m].val3 == tr) + cb->instrs[m].val3 = told; } BIND_ARCH_TO_TEMP(ar,told); } @@ -1577,6 +1634,9 @@ static void vg_improve ( UCodeBlock* cb ) if (cb->instrs[j].tag2 == TempReg && cb->instrs[j].val2 == u->val2) cb->instrs[j].val2 = u->val1; + if (cb->instrs[j].tag3 == TempReg + && cb->instrs[j].val3 == u->val2) + cb->instrs[j].val3 = u->val1; } last_live_before[u->val1] = last_live_before[u->val2]; last_live_before[u->val2] = i-1; diff --git a/include/vg_skin.h b/include/vg_skin.h index 6dd05ccb8c..e71d342e7d 100644 --- a/include/vg_skin.h +++ b/include/vg_skin.h @@ -572,8 +572,8 @@ typedef /* ------------ SSE/SSE2 ops ------------ */ /* In the following: - a digit N indicates the next N bytes are to be copied exactly to the - output. + a digit N indicates the next N bytes are to be copied exactly + to the output. 'a' indicates a mod-xmmreg-rm byte, where the mod-rm part is to be replaced at codegen time to a Temp/RealReg holding the @@ -596,7 +596,7 @@ typedef Held in val1[15:0] and val2[7:0], and mod and rm are to be replaced at codegen time by a reference to the Temp/RealReg holding the address. Arg3 holds this Temp/Real Reg. - Transfer is always at size 16. */ + Transfer is usually, but not always, at size 16. */ SSE2a_MemRd, SSE2a_MemWr, @@ -631,12 +631,12 @@ typedef SSE3g_RegWr, /* 4 bytes, reads an integer register. Insns of the form - bbbbbbbb:bbbbbbbb:bbbbbbbb:11 ireg xmmreg. + bbbbbbbb:bbbbbbbb:bbbbbbbb:11 xmmreg ireg. Held in val1[15:0] and val2[15:0], and ireg is to be replaced at codegen time by a reference to the relevant RealReg. Transfer is always at size 4. Arg3 holds this Temp/Real Reg. */ - SSE3h_RegRd, + SSE3g_RegRd, /* 5 bytes, no memrefs, no iregdefs, copy exactly to the output. Held in val1[15:0], val2[15:0] and val3[7:0]. */ @@ -1082,6 +1082,7 @@ extern Char VG_(name_of_int_size) ( Int size ); #define nameSReg VG_(name_of_seg_reg) #define nameMMXReg VG_(name_of_mmx_reg) #define nameMMXGran VG_(name_of_mmx_gran) +#define nameXMMReg VG_(name_of_xmm_reg) /* Randomly useful things */ extern UInt VG_(extend_s_8to32) ( UInt x );