Make a start on x86 instruction emission.

git-svn-id: svn://svn.valgrind.org/vex/trunk@101
This commit is contained in:
Julian Seward
2004-07-22 01:14:11 +00:00
parent 9d3db569b5
commit e2d3aacfb4
3 changed files with 175 additions and 5 deletions

View File

@@ -785,17 +785,178 @@ X86Instr* genReload_X86 ( HReg rreg, Int offset )
/* --------- The x86 assembler (bleh.) --------- */
static UInt iregNo ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcInt);
vassert(!hregIsVirtual(r));
n = hregNumber(r);
vassert(n <= 7);
return n;
}
static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
{
return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7);
}
static UChar mkSIB ( Int shift, Int regindex, Int regbase )
{
return ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7);
}
static UChar* emit32 ( UChar* p, UInt w32 )
{
*p++ = (w32) & 0x000000FF;
*p++ = (w32 >> 8) & 0x000000FF;
*p++ = (w32 >> 16) & 0x000000FF;
*p++ = (w32 >> 24) & 0x000000FF;
return p;
}
static Bool fits8bits ( UInt w32 )
{
w32 &= 0xFFFFFF00;
return (w32 == 0 || w32 == 0xFFFFFF00);
}
/* Forming mod-reg-rm bytes and scale-index-base bytes.
greg, 0(ereg) | ereg != ESP && ereg != EBP
= 00 greg ereg
greg, d8(ereg) | ereg != ESP
= 01 greg ereg, d8
greg, d32(ereg) | ereg != ESP
= 10 greg ereg, d32
-----------------------------------------------
greg, d8(base,index,scale)
| index != ESP
= 01 greg 100, scale index base, d8
greg, d32(base,index,scale)
| index != ESP
= 10 greg 100, scale index base, d32
*/
static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
{
if (am->tag == Xam_IR) {
if (am->Xam.IR.imm == 0
&& am->Xam.IR.reg != hregX86_ESP()
&& am->Xam.IR.reg != hregX86_EBP() ) {
*p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg));
return p;
}
if (fits8bits(am->Xam.IR.imm)
&& am->Xam.IR.reg != hregX86_ESP()) {
*p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg));
*p++ = am->Xam.IR.imm & 0xFF;
return p;
}
if (am->Xam.IR.reg != hregX86_ESP()) {
*p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg));
p = emit32(p, am->Xam.IR.imm);
return p;
}
ppX86AMode(am);
vpanic("doAMode_M: can't emit amode IR");
/*NOTREACHED*/
}
if (am->tag == Xam_IRRS) {
if (fits8bits(am->Xam.IRRS.imm)
&& am->Xam.IRRS.index != hregX86_ESP()) {
*p++ = mkModRegRM(1, iregNo(greg), 4);
*p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
am->Xam.IRRS.base);
*p++ = am->Xam.IRRS.imm & 0xFF;
return p;
}
if (am->Xam.IRRS.index != hregX86_ESP()) {
*p++ = mkModRegRM(2, iregNo(greg), 4);
*p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
am->Xam.IRRS.base);
p = emit32(p, am->Xam.IRRS.imm);
return p;
}
ppX86AMode(am);
vpanic("doAMode_M: can't emit amode IRRS");
/*NOTREACHED*/
}
vpanic("doAMode_M: unknown amode");
/*NOTREACHED*/
}
/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
{
*p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
return p;
}
/* Emit an instruction into buf and return the number of bytes used.
Note that buf is not the insn's final place, and therefore it is
imperative to emit position-independent code. */
Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
{
UChar* p = &buf[0];
vassert(nbuf >= 32);
switch (i->tag) {
default:
ppX86Instr(i);
vpanic("emit_X86Instr");
case Xin_Alu32R:
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_Mem:
*p++ = 0x8B;
p = doAMode_M(p, i->Xin.Alu32R.dst,
i->Xin.Alu32R.src->Xrmi.Mem.am);
goto done;
default:
goto bad;
}
} else {
goto bad;
}
break;
case Xin_Alu32M:
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;
}
break;
bad:
default:
ppX86Instr(i);
vpanic("emit_X86Instr");
/*NOTREACHED*/
}
done:
vassert(p - &buf[0] <= 32);
return p - &buf[0];
}

View File

@@ -185,7 +185,16 @@ TranslateResult LibVEX_Translate (
UChar insn_bytes[32];
out_used = 0; /* tracks along the host_bytes array */
for (i = 0; i < rcode->arr_used; i++) {
if (vex_verbosity > 0) {
ppInstr(rcode->arr[i]);
vex_printf("\n");
}
j = (*emit)( insn_bytes, 32, rcode->arr[i] );
if (vex_verbosity > 0) {
for (k = 0; k < j; k++)
vex_printf("0x%-2x ", (UInt)insn_bytes[k]);
vex_printf("\n\n");
}
if (out_used + j > host_bytes_size) {
LibVEX_ClearTemporary(False);
return TransOutputFull;

View File

@@ -66,8 +66,8 @@ int main ( int argc, char** argv )
LibVEX_Init ( &failure_exit, &log_bytes,
1, /* debug_paranoia */
1, /* verbosity */
False,
//True,
//False,
True,
100 );
while (!feof(f)) {