CC = gcc341
-CCFLAGS = -g -Wall -Wshadow
+CCFLAGS = -g -Wall -Wshadow -O
#CC = icc
#CCFLAGS = -g -Wbrief -Wall -wd981 -wd279 -wd1287 -wd869 \
/* TODO:
XOR reg with itself
+ SBB reg with itself
is Iop_Neg* used?
-
+ xadd %reg,%reg fix
+ MOVAPS fix (vg_to_ucode rev 1.143)
*/
/* Translates x86 code to IR. */
while (True) {
if (!first_stmt)
break;
- vex_printf(" ");
- ppIRStmt(first_stmt);
- DIP("\n");
+ if (print_codegen) {
+ vex_printf(" ");
+ ppIRStmt(first_stmt);
+ vex_printf("\n");
+ }
if (first_stmt == last_stmt)
break;
first_stmt = first_stmt->link;
return regno | (((UInt)rc) << 28) | (virtual ? (1<<24) : 0);
}
-HRegClass hregClass ( HReg r )
-{
- UInt rc = r;
- rc = (rc >> 28) & 0x0F;
- vassert(rc == HRcInt || rc == HRcFloat || rc == HRcVector
- || rc == HRcInt64 || rc == HRcVector128);
- return (HRegClass)rc;
-}
-
-Bool hregIsVirtual ( HReg r )
-{
- return (((UInt)r) & (1<<24)) ? True : False;
-}
-
-UInt hregNumber ( HReg r )
-{
- return ((UInt)r) & 0x00FFFFFF;
-}
-
void ppHRegClass ( HRegClass hrc )
{
switch (hrc) {
/* Construct/destruct. */
extern HReg mkHReg ( UInt regno, HRegClass rc, Bool virtual );
-extern HRegClass hregClass ( HReg );
-extern Bool hregIsVirtual ( HReg );
-extern UInt hregNumber ( HReg );
+static inline HRegClass hregClass ( HReg r ) {
+ UInt rc = r;
+ rc = (rc >> 28) & 0x0F;
+ vassert(rc >= HRcInt || rc <= HRcVector128);
+ return (HRegClass)rc;
+}
+
+static inline UInt hregNumber ( HReg r ) {
+ return ((UInt)r) & 0x00FFFFFF;
+}
+
+static inline Bool hregIsVirtual ( HReg r ) {
+ return (((UInt)r) & (1<<24)) ? True : False;
+}
+
+
#define INVALID_HREG ((HReg)0xFFFFFFFF)
}
+
+/* Double the size of the real-reg-info array, if needed. */
+static void ensureRRIspace ( RRegInfo** info, Int* size, Int used )
+{
+ Int k;
+ if (used < *size) return;
+ if (0)
+ vex_printf("ensureRRISpace: %d -> %d\n", *size, 2 * *size);
+ vassert(used == *size);
+ RRegInfo* arr2
+ = LibVEX_Alloc(2 * *size * sizeof(RRegInfo));
+ for (k = 0; k < *size; k++)
+ arr2[k] = (*info)[k];
+ *size *= 2;
+ *info = arr2;
+}
+
+
/* A target-independent register allocator for Valgrind. Requires
various functions which it uses to deal abstractly with
instructions and registers, since it cannot have any
if (flush) {
vassert(flush_la != INVALID_INSTRNO);
vassert(flush_db != INVALID_INSTRNO);
- vex_printf("FLUSH 1 (%d,%d)\n", flush_la, flush_db);
- if (rreg_info_used == rreg_info_size) {
- vpanic("make rreg info array bigger(1)");
- }
+ ensureRRIspace(&rreg_info, &rreg_info_size, rreg_info_used);
+ if (0)
+ vex_printf("FLUSH 1 (%d,%d)\n", flush_la, flush_db);
rreg_info[rreg_info_used].rreg = rreg;
rreg_info[rreg_info_used].live_after = flush_la;
rreg_info[rreg_info_used].dead_before = flush_db;
if (rreg_live_after[j] == INVALID_INSTRNO)
continue;
- if (rreg_info_used == rreg_info_size) {
- vpanic("make rreg info array bigger(2)");
- }
+
+ ensureRRIspace(&rreg_info, &rreg_info_size, rreg_info_used);
+ if (0)
+ vex_printf("FLUSH 2 (%d,%d)\n",
+ rreg_live_after[j], rreg_dead_before[j]);
rreg_info[rreg_info_used].rreg = available_real_regs[j];
rreg_info[rreg_info_used].live_after = rreg_live_after[j];
rreg_info[rreg_info_used].dead_before = rreg_dead_before[j];
&& ii < rreg_info[j].dead_before) {
/* ii is the middle of a hard live range for some real reg.
Check it's marked as such in the running state. */
- vassert(state[rreg_info[j].rreg].disp == Unavail);
+
+# if 0
+ vex_printf("considering la %d .. db %d reg = ",
+ rreg_info[j].live_after,
+ rreg_info[j].dead_before);
+ (*ppReg)(rreg_info[j].rreg);
+ vex_printf("\n");
+# endif
+
+ /* find the state entry for this rreg */
+ for (k = 0; k < n_state; k++)
+ if (state[k].rreg == rreg_info[j].rreg)
+ break;
+
+ /* and assert that this rreg is marked as unavailable */
+ vassert(state[k].disp == Unavail);
}
}
#include "libvex.h"
#include "vex_util.h"
+#include "vex_globals.h"
#include "host_regs.h"
#include "x86h_defs.h"
static void addInstr ( ISelEnv* env, X86Instr* instr )
{
addHInstr(env->code, instr);
- ppX86Instr(instr);
- vex_printf("\n");
+ if (vex_verbosity > 0) {
+ ppX86Instr(instr);
+ vex_printf("\n");
+ }
}
static HReg newVRegI ( ISelEnv* env )
static void iselStmt ( ISelEnv* env, IRStmt* stmt )
{
- vex_printf("-- ");
- ppIRStmt(stmt);
- vex_printf("\n");
+ if (vex_verbosity > 0) {
+ vex_printf("-- ");
+ ppIRStmt(stmt);
+ vex_printf("\n");
+ }
switch (stmt->tag) {
case Ist_Exit: {
if (stmt->Ist.Exit.dst->tag != Ico_U32)
vpanic("isel_x86: Ist_Exit: dst is not a 32-bit value");
-
X86RI* dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
X86CondCode cc = iselCondCode(env,stmt->Ist.Exit.cond);
addInstr(env, X86Instr_Goto(cc, dst));
static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk )
{
X86RI* ri;
- vex_printf("-- goto ");
- ppIRExpr(next);
- vex_printf("\n");
+ if (vex_verbosity > 0) {
+ vex_printf("-- goto ");
+ ppIRExpr(next);
+ vex_printf("\n");
+ }
ri = iselIntExpr_RI(env, next);
addInstr(env, X86Instr_Goto(Xcc_ALWAYS,ri));
addRegUsage_X86RI(u, i->Xin.Alu32M.src);
addRegUsage_X86AMode(u, i->Xin.Alu32M.dst);
return;
+ case Xin_Unary32:
+ addRegUsage_X86RM(u, i->Xin.Unary32.dst, HRmModify);
+ return;
+ case Xin_MulL:
+ addRegUsage_X86RM(u, i->Xin.MulL.src, HRmRead);
+ addHRegUse(u, HRmModify, hregX86_EAX());
+ addHRegUse(u, HRmWrite, hregX86_EDX());
+ return;
+ case Xin_Div:
+ addRegUsage_X86RM(u, i->Xin.Div.src, HRmRead);
+ addHRegUse(u, HRmModify, hregX86_EAX());
+ addHRegUse(u, HRmModify, hregX86_EDX());
+ return;
case Xin_Sh32:
addRegUsage_X86RM(u, i->Xin.Sh32.dst, HRmModify);
if (i->Xin.Sh32.src == 0)
addHRegUse(u, HRmRead, hregX86_ECX());
return;
+ case Xin_Sh3232:
+ addHRegUse(u, HRmRead, i->Xin.Sh3232.rLo);
+ addHRegUse(u, HRmModify, i->Xin.Sh3232.rHi);
+ if (i->Xin.Sh3232.amt == 0)
+ addHRegUse(u, HRmRead, hregX86_ECX());
+ return;
case Xin_Push:
addRegUsage_X86RMI(u, i->Xin.Push.src);
addHRegUse(u, HRmModify, hregX86_ESP());
addRegUsage_X86RI(u, i->Xin.Goto.dst);
addHRegUse(u, HRmWrite, hregX86_EAX());
return;
+ case Xin_CMov32:
+ addRegUsage_X86RM(u, i->Xin.CMov32.src, HRmRead);
+ addHRegUse(u, HRmModify, i->Xin.CMov32.dst);
+ return;
+ case Xin_LoadEX:
+ addRegUsage_X86AMode(u, i->Xin.LoadEX.src);
+ addHRegUse(u, HRmWrite, i->Xin.LoadEX.dst);
+ return;
+ case Xin_Store:
+ addHRegUse(u, HRmRead, i->Xin.Store.src);
+ addRegUsage_X86AMode(u, i->Xin.Store.dst);
+ return;
default:
ppX86Instr(i);
vpanic("getRegUsage_X86Instr");
}
}
+/* local helper */
+static void mapReg(HRegRemap* m, HReg* r)
+{
+ *r = lookupHRegRemap(m, *r);
+}
+
void mapRegs_X86Instr (HRegRemap* m, X86Instr* i)
{
switch (i->tag) {
case Xin_Alu32R:
mapRegs_X86RMI(m, i->Xin.Alu32R.src);
- i->Xin.Alu32R.dst = lookupHRegRemap(m, i->Xin.Alu32R.dst);
+ mapReg(m, &i->Xin.Alu32R.dst);
return;
case Xin_Alu32M:
mapRegs_X86RI(m, i->Xin.Alu32M.src);
mapRegs_X86AMode(m, i->Xin.Alu32M.dst);
return;
+ case Xin_Unary32:
+ mapRegs_X86RM(m, i->Xin.Unary32.dst);
+ return;
+ case Xin_MulL:
+ mapRegs_X86RM(m, i->Xin.MulL.src);
+ return;
+ case Xin_Div:
+ mapRegs_X86RM(m, i->Xin.Div.src);
+ return;
case Xin_Sh32:
mapRegs_X86RM(m, i->Xin.Sh32.dst);
return;
+ case Xin_Sh3232:
+ mapReg(m, &i->Xin.Sh3232.rLo);
+ mapReg(m, &i->Xin.Sh3232.rHi);
+ return;
+ case Xin_Push:
+ mapRegs_X86RMI(m, i->Xin.Push.src);
+ return;
+ case Xin_Call:
+ mapReg(m, &i->Xin.Call.target);
+ return;
case Xin_Goto:
mapRegs_X86RI(m, i->Xin.Goto.dst);
return;
+ case Xin_CMov32:
+ mapRegs_X86RM(m, i->Xin.CMov32.src);
+ mapReg(m, &i->Xin.CMov32.dst);
+ return;
+ case Xin_LoadEX:
+ mapRegs_X86AMode(m, i->Xin.LoadEX.src);
+ mapReg(m, &i->Xin.LoadEX.dst);
+ return;
+ case Xin_Store:
+ mapReg(m, &i->Xin.Store.src);
+ mapRegs_X86AMode(m, i->Xin.Store.dst);
+ return;
default:
ppX86Instr(i);
vpanic("mapRegs_X86Instr");
/* Not and Neg */
struct {
X86UnaryOp op;
- X86RM* dst;
+ X86RM* dst;
} Unary32;
/* DX:AX = AX *s/u r/m16, or EDX:EAX = EAX *s/u r/m32 */
struct {
X86ScalarSz ssz;
X86RM* src;
} MulL;
- /* x86 div/idiv instruction */
+ /* x86 div/idiv instruction. Modifies EDX and EAX and reads src. */
struct {
Bool syned;
X86ScalarSz ssz;
/* Turn it into virtual-registerised code. */
vcode = iselBB ( irbb );
-LibVEX_ClearTemporary(True); return TransOK;
- vex_printf("\n-------- Virtual registerised code --------\n");
- for (i = 0; i < vcode->arr_used; i++) {
- ppInstr(vcode->arr[i]);
+ if (vex_verbosity > 0) {
+ vex_printf("\n-------- Virtual registerised code --------\n");
+ for (i = 0; i < vcode->arr_used; i++) {
+ vex_printf("%3d ", i);
+ ppInstr(vcode->arr[i]);
+ vex_printf("\n");
+ }
vex_printf("\n");
}
- vex_printf("\n");
/* Register allocate. */
rcode = doRegisterAllocation ( vcode, available_real_regs,
genSpill, genReload,
ppInstr, ppReg );
- vex_printf("\n-------- Post-regalloc code --------\n");
- for (i = 0; i < rcode->arr_used; i++) {
- ppInstr(rcode->arr[i]);
+ if (vex_verbosity > 0) {
+ vex_printf("\n-------- Post-regalloc code --------\n");
+ for (i = 0; i < rcode->arr_used; i++) {
+ vex_printf("%3d ", i);
+ ppInstr(rcode->arr[i]);
+ vex_printf("\n");
+ }
vex_printf("\n");
}
- vex_printf("\n");
/* Assemble, etc. */
- LibVEX_ClearTemporary(True);
+ // LibVEX_ClearTemporary(True);
+ LibVEX_ClearTemporary(False);
return TransOK;
}
static Char origbuf[N_ORIGBUF];
static Char transbuf[N_TRANSBUF];
+static Bool verbose = True;
int main ( int argc, char** argv )
{
}
LibVEX_Init ( &failure_exit, &log_bytes,
- 1, 1, //False,
- True,
+ 1, /* debug_paranoia */
+ 1, /* verbosity */
+ False,
+ //True,
100 );
while (!feof(f)) {
assert(linebuf[0] == '.');
/* second line is: . byte byte byte etc */
//printf("%s", linebuf);
- printf("\n\n============ Basic Block %d, "
- "Start %x, nbytes %d ============\n\n",
- bb_number, orig_addr, orig_nbytes);
+ if (verbose)
+ printf("\n\n============ Basic Block %d, "
+ "Start %x, nbytes %d ============\n\n",
+ bb_number, orig_addr, orig_nbytes);
assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
for (i = 0; i < orig_nbytes; i++) {
assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
origbuf[i] = (UChar)u;
}
+ // if (bb_number == 50) exit(1);
+ { int i;
+ for (i = 0; i < 1; i++)
tres =
LibVEX_Translate ( InsnSetX86, InsnSetX86,
origbuf, (Addr64)orig_addr, &orig_used,
NULL, NULL );
assert(tres == TransOK);
assert(orig_used == orig_nbytes);
+ }
}
fclose(f);
+ LibVEX_ClearTemporary(True);
#if 0
Int* p;