More x86 insn emitter hacking.
git-svn-id: svn://svn.valgrind.org/vex/trunk@102 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/Makefile b/Makefile
index 0b43083..8608a16 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@
CC = gcc341
-CCFLAGS = -g -Wall -Wshadow -O
+CCFLAGS = -g -Wall -Wshadow
#CC = icc
#CCFLAGS = -g -Wbrief -Wall -wd981 -wd279 -wd1287 -wd869 \
diff --git a/priv/host-x86/x86host_defs.c b/priv/host-x86/x86host_defs.c
index b14e817..e5bac3e 100644
--- a/priv/host-x86/x86host_defs.c
+++ b/priv/host-x86/x86host_defs.c
@@ -117,7 +117,10 @@
void ppX86AMode ( X86AMode* am ) {
switch (am->tag) {
case Xam_IR:
- vex_printf("0x%x(", am->Xam.IR.imm);
+ if (am->Xam.IR.imm == 0)
+ vex_printf("(");
+ else
+ vex_printf("0x%x(", am->Xam.IR.imm);
ppHRegX86(am->Xam.IR.reg);
vex_printf(")");
return;
@@ -126,7 +129,7 @@
ppHRegX86(am->Xam.IRRS.base);
vex_printf(",");
ppHRegX86(am->Xam.IRRS.index);
- vex_printf(",%d)", am->Xam.IRRS.shift);
+ vex_printf(",%d)", 1 << am->Xam.IRRS.shift);
return;
default:
vpanic("ppX86AMode");
@@ -537,7 +540,7 @@
case Xin_Sh32:
vex_printf("%sl ", showX86ShiftOp(i->Xin.Sh32.op));
if (i->Xin.Sh32.src == 0)
- vex_printf(" %%cl,");
+ vex_printf(" %%cl,");
else
vex_printf(" $%d,", i->Xin.Sh32.src);
ppX86RM(i->Xin.Sh32.dst);
@@ -545,7 +548,7 @@
case Xin_Sh3232:
vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
if (i->Xin.Sh3232.amt == 0)
- vex_printf(" %%cl,");
+ vex_printf(" %%cl,");
else
vex_printf(" $%d,", i->Xin.Sh3232.amt);
ppHRegX86(i->Xin.Sh3232.rLo);
@@ -629,7 +632,7 @@
addHRegUse(u, HRmWrite, hregX86_EDX());
return;
case Xin_Div:
- addRegUsage_X86RM(u, i->Xin.Div.src, HRmRead);
+ addRegUsage_X86RM(u, i->Xin.Div.src, HRmRead);
addHRegUse(u, HRmModify, hregX86_EAX());
addHRegUse(u, HRmModify, hregX86_EDX());
return;
@@ -702,7 +705,7 @@
mapRegs_X86RM(m, i->Xin.MulL.src);
return;
case Xin_Div:
- mapRegs_X86RM(m, i->Xin.Div.src);
+ mapRegs_X86RM(m, i->Xin.Div.src);
return;
case Xin_Sh32:
mapRegs_X86RM(m, i->Xin.Sh32.dst);
@@ -757,8 +760,8 @@
switch (hregClass(rreg)) {
case HRcInt:
return
- X86Instr_Alu32M ( Xalu_MOV, X86RI_Reg(rreg),
- X86AMode_IR(offset + 0x1000,
+ X86Instr_Alu32M ( Xalu_MOV, X86RI_Reg(rreg),
+ X86AMode_IR(offset + 0x1000,
hregX86_EBP()));
default:
ppHRegClass(hregClass(rreg));
@@ -772,8 +775,8 @@
switch (hregClass(rreg)) {
case HRcInt:
return
- X86Instr_Alu32R ( Xalu_MOV,
- X86RMI_Mem(X86AMode_IR(offset + 0x1000,
+ X86Instr_Alu32R ( Xalu_MOV,
+ X86RMI_Mem(X86AMode_IR(offset + 0x1000,
hregX86_EBP())),
rreg );
default:
@@ -814,10 +817,12 @@
return p;
}
+/* Does a sign-extend of the lowest 8 bits give
+ the original number? */
static Bool fits8bits ( UInt w32 )
{
- w32 &= 0xFFFFFF00;
- return (w32 == 0 || w32 == 0xFFFFFF00);
+ Int i32 = (Int)w32;
+ return i32 == ((i32 << 24) >> 24);
}
@@ -906,60 +911,226 @@
Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
{
+ UInt opc, opc_rr, subopc_imm, opc_imma;
+
UChar* p = &buf[0];
vassert(nbuf >= 32);
+ /* Wrap an integer as a int register, for use assembling
+ GrpN insns, in which the greg field is used as a sub-opcode
+ and does not really contain a register. */
+# define fake(_n) mkHReg((_n), HRcInt, False)
+
switch (i->tag) {
case Xin_Alu32R:
+ /* Deal specially with MOV */
if (i->Xin.Alu32R.op == Xalu_MOV) {
switch (i->Xin.Alu32R.src->tag) {
- // case Xrmi_Imm:
- //*p++ = 0xB8 + iregNo(i->Xin.Alu32.dst);
- //p = emit32(i->Xin.Alu32.src->Xrmi.Imm.imm32);
- //return p;
- //case Xrmi_Reg:
+ case Xrmi_Imm:
+ *p++ = 0xB8 + iregNo(i->Xin.Alu32R.dst);
+ p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
+ goto done;
+ case Xrmi_Reg:
+ *p++ = 0x89;
+ p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg,
+ i->Xin.Alu32R.dst);
+ goto done;
+ case Xrmi_Mem:
+ *p++ = 0x8B;
+ p = doAMode_M(p, i->Xin.Alu32R.dst,
+ i->Xin.Alu32R.src->Xrmi.Mem.am);
+ goto done;
+ default:
+ goto bad;
+ }
+ }
+ /* ADD/SUB/ADC/SBB/AND/OR/XOR/TEST/CMP */
+ opc = opc_rr = subopc_imm = opc_imma = 0;
+ switch (i->Xin.Alu32R.op) {
+ case Xalu_ADD: opc = 0x03; opc_rr = 0x01;
+ subopc_imm = 0; opc_imma = 0x05; break;
+ case Xalu_SUB: opc = 0x2B; opc_rr = 0x29;
+ subopc_imm = 5; opc_imma = 0x2D; break;
+ default: goto bad;
+ }
+ switch (i->Xin.Alu32R.src->tag) {
+ case Xrmi_Imm:
+ if (i->Xin.Alu32R.dst == hregX86_EAX()
+ && !fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
+ *p++ = opc_imma;
+ p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
+ } else
+ if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
+ *p++ = 0x83;
+ p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
+ *p++ = 0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32;
+ } else {
+ *p++ = 0x81;
+ p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
+ p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
+ }
+ goto done;
+ case Xrmi_Reg:
+ *p++ = opc_rr;
+ p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg,
+ i->Xin.Alu32R.dst);
+ goto done;
case Xrmi_Mem:
- *p++ = 0x8B;
- p = doAMode_M(p, i->Xin.Alu32R.dst,
+ *p++ = opc;
+ p = doAMode_M(p, i->Xin.Alu32R.dst,
i->Xin.Alu32R.src->Xrmi.Mem.am);
goto done;
- default:
+ default:
goto bad;
- }
- } else {
- goto bad;
}
break;
case Xin_Alu32M:
+ /* Deal specially with MOV */
if (i->Xin.Alu32M.op == Xalu_MOV) {
- if (i->Xin.Alu32M.src->tag == Xri_Reg) {
- *p++ = 0x89;
- p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
- i->Xin.Alu32M.dst);
- goto done;
- } else {
- goto bad;
- }
- } else {
- goto bad;
+ switch (i->Xin.Alu32M.src->tag) {
+ case Xri_Reg:
+ *p++ = 0x89;
+ p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
+ i->Xin.Alu32M.dst);
+ goto done;
+ case Xri_Imm:
+ *p++ = 0xC7;
+ p = doAMode_M(p, fake(0), i->Xin.Alu32M.dst);
+ p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
+ goto done;
+ default:
+ goto bad;
+ }
+ }
+ /* ADD/SUB/ADC/SBB/AND/OR/XOR/TEST/CMP */
+ opc = subopc_imm = opc_imma = 0;
+ switch (i->Xin.Alu32M.op) {
+ case Xalu_ADD: opc = 0x01; subopc_imm = 0; break;
+ default: goto bad;
+ }
+ switch (i->Xin.Alu32M.src->tag) {
+ case Xri_Reg:
+ *p++ = opc;
+ p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
+ i->Xin.Alu32M.dst);
+ goto done;
+ case Xri_Imm:
+ if (fits8bits(i->Xin.Alu32M.src->Xri.Imm.imm32)) {
+ *p++ = 0x83;
+ p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
+ *p++ = 0xFF & i->Xin.Alu32M.src->Xri.Imm.imm32;
+ goto done;
+ } else {
+ *p++ = 0x81;
+ p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
+ p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
+ goto done;
+ }
+ default:
+ goto bad;
}
break;
-
- bad:
- default:
- ppX86Instr(i);
- vpanic("emit_X86Instr");
- /*NOTREACHED*/
+ default:
+ goto bad;
}
+
+ bad:
+ ppX86Instr(i);
+ vpanic("emit_X86Instr");
+ /*NOTREACHED*/
+
done:
vassert(p - &buf[0] <= 32);
return p - &buf[0];
+
+# undef fake
}
+/* Self-contained test; can be called directly from
+ main. */
+void test_asm86 ( void )
+{
+ UChar buf[32];
+ Int i, n;
+ HReg edi = hregX86_EDI();
+ HReg esi = hregX86_ESI();
+ HReg ecx = hregX86_ECX();
+ HReg ebp = hregX86_EBP();
+ HReg eax = hregX86_EAX();
+ HReg esp = hregX86_ESP();
+
+#define T(_iii) \
+ do { X86Instr* iii = _iii; \
+ vex_printf("\n "); \
+ ppX86Instr(iii); \
+ vex_printf("\n "); \
+ n = emit_X86Instr( buf, 32, iii ); \
+ for (i = 0; i < n; i++) { \
+ if (buf[i] < 0x10) \
+ vex_printf("0%x ", (Int)buf[i]); \
+ else \
+ vex_printf("%x ", (Int)buf[i]); \
+ } \
+ vex_printf("\n"); \
+ } while (0)
+
+#if 0
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Reg(esi), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0x12345678), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IR(0,esi)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IR(0,ebp)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IR(1,esi)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IR(1,ebp)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IR(127,esi)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IR(256,esi)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IRRS(1,esi,ecx,0)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IRRS(1,esi,ecx,3)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IRRS(127,esi,ecx,3)), edi) );
+T( X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(X86AMode_IRRS(256,esi,ecx,3)), edi) );
+#endif
+
+#if 0
+T( X86Instr_Alu32M(Xalu_MOV, X86RI_Imm(9), X86AMode_IR(0,esi)) );
+T( X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(edi), X86AMode_IR(0,esi)) );
+T( X86Instr_Alu32M(Xalu_MOV, X86RI_Imm(999), X86AMode_IRRS(256,esi,ecx,3)) );
+T( X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(ebp), X86AMode_IRRS(256,esi,ecx,3)) );
+#endif
+
+#if 0
+T( X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(0x42), eax) );
+T( X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(0x41424344), eax) );
+T( X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(0x42), esp) );
+T( X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(0x41424344), esp) );
+T( X86Instr_Alu32R(Xalu_ADD, X86RMI_Reg(esi), edi) );
+T( X86Instr_Alu32R(Xalu_ADD, X86RMI_Mem(X86AMode_IR(1,esi)), edi) );
+#endif
+
+#if 0
+T( X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(0x42), eax) );
+T( X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(0x41424344), eax) );
+T( X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(0x42), esp) );
+T( X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(0x41424344), esp) );
+T( X86Instr_Alu32R(Xalu_SUB, X86RMI_Reg(esi), edi) );
+T( X86Instr_Alu32R(Xalu_SUB, X86RMI_Mem(X86AMode_IR(1,esi)), edi) );
+#endif
+
+#if 0
+T( X86Instr_Alu32M(Xalu_ADD, X86RI_Imm(0x42), X86AMode_IR(0x99,esi)) );
+T( X86Instr_Alu32M(Xalu_ADD, X86RI_Imm(0x4243), X86AMode_IR(0x99,esi)) );
+T( X86Instr_Alu32M(Xalu_ADD, X86RI_Reg(ecx), X86AMode_IR(0x99,ebp)) );
+T( X86Instr_Alu32M(Xalu_ADD, X86RI_Reg(ecx), X86AMode_IR(0x80,ebp)) );
+T( X86Instr_Alu32M(Xalu_ADD, X86RI_Reg(ecx), X86AMode_IR(0x7F,ebp)) );
+#endif
+
+#undef T
+}
+
+
+
/*---------------------------------------------------------------*/
/*--- end x86h_defs.c ---*/
/*---------------------------------------------------------------*/
diff --git a/test_main.c b/test_main.c
index b08d8cd..ad1c717 100644
--- a/test_main.c
+++ b/test_main.c
@@ -70,6 +70,11 @@
True,
100 );
+ {extern void test_asm86(void);
+ test_asm86();
+ return 0;
+ }
+
while (!feof(f)) {
fgets(linebuf, N_LINEBUF,f);
//printf("%s", linebuf);