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,
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) {
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) {
}
+
+/* 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). */
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 --------------- */
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;
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 */
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;
VG_(core_panic)("unhandled x86 opcode");
}
+ sse_done:
if (dis)
VG_(printf)("\n");
for (; first_uinstr < cb->used; first_uinstr++) {
# 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)
# 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)
/* 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);
# undef SZ0
# undef SZ42
# undef SZ48
+# undef SZ416
# undef SZi
# undef SZf
# undef SZ4m
# undef L1
# undef L2
# undef Ls1
+# undef Ls2
# undef Ls3
# undef TRL1
# undef TRAL1
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);
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);
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);
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);
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 */
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)(" = ");
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);
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;
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;
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:
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);
}
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;
/* ------------ 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
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,
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]. */
#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 );