home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
kaffe-0.5p4-src.tgz
/
tar.out
/
contrib
/
kaffe
/
config
/
i386
/
jit-i386.def
next >
Wrap
Text File
|
1996-09-28
|
24KB
|
1,418 lines
/* jit-i386.def
* i386 instruction definition.
*
* Copyright (c) 1996 Systems Architecture Research Centre,
* City University, London, UK.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* Written by Tim Wilkinson <tim@sarc.city.ac.uk>, June 1996.
*/
#undef DEBUG
#ifdef DEBUG
#define debug(x) printf##x
#else
#define debug(x)
#endif
#define do_move_int(t, f) { \
OUT = 0x89; \
OUT = 0xC0|(f<<3)|t; \
debug(("movl %s,%s\n", regname(f), regname(t)));\
}
#define check_reg_01() { \
int _r_ = rreg_int(1); \
int _w_ = wreg_int(0); \
assert(_r_ == _w_); \
}
#define do_force_move_int(t, f, n) \
if ((t) != (f)) { \
forceRegister(seq_slot(s, (n)), (t), Rint); \
do_move_int((t), (f)); \
f = (t); \
}
#define return_dst() slot_return(seq_dst(s))
char* rnames[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
#define regname(n) rnames[n]
#define REG_eax 0
#define REG_ecx 1
#define REG_edx 2
#define REG_ebx 3
#define REG_esp 4
#define REG_ebp 5
#define REG_esi 6
#define REG_edi 7
#define REG_flt0 8
#define REG_dbl0 REG_flt0
/* --------------------------------------------------------------------- */
define_insn(unimplemented, unimplemented)
{
abort();
}
define_insn(nop, nop)
{
OUT = 0x90;
}
/* --------------------------------------------------------------------- */
define_insn(prologue, prologue_xxx)
{
int framesize = SLOTSIZE * (maxLocal + maxStack + maxTemp - maxArgs);
OUT = 0x50|REG_ebp;
OUT = 0x89;
OUT = 0xC0|(REG_esp<<3)|REG_ebp;
if (framesize > 0) {
OUT = 0x81;
OUT = 0xE8|REG_esp;
OUT = framesize & 0xff;
OUT = (framesize >> 8) & 0xff;
OUT = (framesize >> 16) & 0xff;
OUT = (framesize >> 24) & 0xff;
}
OUT = 0x50|REG_edi;
OUT = 0x50|REG_esi;
OUT = 0x50|REG_ebx;
debug(("pushl ebp\n"));
debug(("movl esp,ebp\n"));
if (framesize > 0) {
debug(("subl #%d,esp\n", framesize));
}
debug(("pushl edi\n"));
debug(("pushl esi\n"));
debug(("pushl ebx\n"));
}
define_insn(epilogue, epilogue_xxx)
{
OUT = 0x58|REG_ebx;
OUT = 0x58|REG_esi;
OUT = 0x58|REG_edi;
OUT = 0x89;
OUT = 0xC0|(REG_ebp<<3)|REG_esp;
OUT = 0x58|REG_ebp;
debug(("popl ebx\n"));
debug(("popl esi\n"));
debug(("popl edi\n"));
debug(("movl ebp,esp\n"));
debug(("popl ebp\n"));
}
/* --------------------------------------------------------------------- */
define_insn(spill_int, spill_Rxx)
{
int r = rreg_int(0);
/* int o = -4 * (1 + const_int(1)); */
int o = SLOT2FRAMEOFFSET(seq_dst(s));
OUT = 0x89;
OUT = 0x80|(r<<3)|REG_ebp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("movl %s,%d(ebp)\n", regname(r), o));
}
define_insn(spill_float, fspill_Rxx)
{
int r = rreg_float(0);
int o = SLOT2FRAMEOFFSET(seq_dst(s));
OUT = 0xD9;
OUT = 0x98|REG_ebp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("fstp %d(ebp)\n", o));
}
define_insn(spill_double, fspilll_Rxx)
{
int r = rreg_double(0);
int o = SLOT2FRAMEOFFSET(seq_dst(s));
OUT = 0xDD;
OUT = 0x98|REG_ebp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("fstpl %d(ebp)\n", o));
}
define_insn(reload_int, reload_Rxx)
{
int r = rreg_int(0);
/* int o = -4 * (1 + const_int(1)); */
int o = SLOT2FRAMEOFFSET(seq_dst(s));
OUT = 0x8B;
OUT = 0x80|(r<<3)|REG_ebp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("movl %d(ebp),%s\n", o, regname(r)));
}
define_insn(reload_float, freload_Rxx)
{
int w = wreg_float(0);
int o = SLOT2FRAMEOFFSET(seq_dst(s));
OUT = 0xD9;
OUT = 0x80|REG_ebp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("fld %d(ebp)\n", o));
}
define_insn(reload_double, freloadl_Rxx)
{
int w = wreg_double(0);
int o = SLOT2FRAMEOFFSET(seq_dst(s));
OUT = 0xDD;
OUT = 0x80|REG_ebp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("fldl %d(ebp)\n", o));
}
/* --------------------------------------------------------------------- */
define_insn(move_int_const, move_RxC)
{
int val = const_int(2);
int w = wreg_int(0);
OUT = 0xB8|w;
OUT = val & 0xff;
OUT = (val >> 8) & 0xff;
OUT = (val >> 16) & 0xff;
OUT = (val >> 24) & 0xff;
debug(("movl #%d,%s\n", val, regname(w)));
}
define_insn(move_label_const, move_RxL)
{
label* l = (label*)const_int(2);
int w = wreg_int(0);
OUT = 0xB8|w;
l->type |= Llong|Labsolute;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
debug(("movl #?,%s\n", regname(w)));
}
define_insn(move_int, move_RxR)
{
int r = rreg_int(2);
int w = wreg_int(0);
if (r != w) {
/* If destination is a return slot, clobber the register
* associated with it. If we dont do this we might
* overwrite something which is still important.
*/
if (return_dst()) {
clobberRegister(w);
}
OUT = 0x89;
OUT = 0xC0|(r<<3)|w;
debug(("movl %s,%s\n", regname(r), regname(w)));
}
}
define_insn(move_float_const, fmove_RxC)
{
double val = const_float(2);
int w = wreg_float(0);
if (val == 0.0) {
OUT = 0xD9;
OUT = 0xEE;
debug(("fldz\n"));
}
else if (val == 1.0) {
OUT = 0xD9;
OUT = 0xE8;
debug(("fld1\n"));
}
else {
abort();
}
}
define_insn(move_float, fmove_RxR)
{
int or = rslot_float(2);
int ow = rslot_float(0);
if (or != ow) {
int w = wreg_float(0);
OUT = 0xD9;
OUT = 0x80|REG_ebp;
OUT = or & 0xff;
OUT = (or >> 8) & 0xff;
OUT = (or >> 16) & 0xff;
OUT = (or >> 24) & 0xff;
debug(("fld %d(ebp)\n", or));
}
}
define_insn(move_double_const, fmovel_RxC)
{
double val = const_double(2);
int w = wreg_double(0);
if (val == 0.0) {
OUT = 0xD9;
OUT = 0xEE;
debug(("fldz\n"));
}
else if (val == 1.0) {
OUT = 0xD9;
OUT = 0xE8;
debug(("fld1\n"));
}
else {
abort();
}
}
define_insn(move_double, fmovel_RxR)
{
int or = rslot_double(2);
int ow = rslot_double(0);
if (or != ow) {
int w = wreg_double(0);
OUT = 0xDD;
OUT = 0x80|REG_ebp;
OUT = or & 0xff;
OUT = (or >> 8) & 0xff;
OUT = (or >> 16) & 0xff;
OUT = (or >> 24) & 0xff;
debug(("fldl %d(ebp)\n", or));
}
}
/* --------------------------------------------------------------------- */
define_insn(add_int, add_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
w = rwreg_int(0);
OUT = 0x01;
OUT = 0xC0|(r<<3)|w;
debug(("addl %s,%s\n", regname(r), regname(w)));
}
define_insn(adc_int, adc_RRR)
{
int r;
int w;
r = rreg_int(2);
w = rwreg_int(0);
OUT = 0x11;
OUT = 0xC0|(r<<3)|w;
debug(("adcl %s,%s\n", regname(r), regname(w)));
}
define_insn(add_float, fadd_RRR)
{
int r2 = rslot_float(2); /* Get r2 into memory */
int r1 = rreg_float(1); /* Load r1 into the register stack */
int w = wreg_float(0); /* Result will be in register stack */
OUT = 0xD8;
OUT = 0x80|REG_ebp;
OUT = r2 & 0xff;
OUT = (r2 >> 8) & 0xff;
OUT = (r2 >> 16) & 0xff;
OUT = (r2 >> 24) & 0xff;
debug(("fadd %d(ebp)\n", r2));
}
define_insn(add_double, faddl_RRR)
{
int r2 = rslot_double(2); /* Get r2 into memory */
int r1 = rreg_double(1); /* Load r1 into the register stack */
int w = wreg_double(0); /* Result will be in register stack */
OUT = 0xDC;
OUT = 0x80|REG_ebp;
OUT = r2 & 0xff;
OUT = (r2 >> 8) & 0xff;
OUT = (r2 >> 16) & 0xff;
OUT = (r2 >> 24) & 0xff;
debug(("faddl %d(ebp)\n", r2));
}
define_insn(sub_int, sub_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
w = rwreg_int(0);
OUT = 0x29;
OUT = 0xC0|(r<<3)|w;
debug(("subl %s,%s\n", regname(r), regname(w)));
}
define_insn(sbc_int, sbc_RRR)
{
int r;
int w;
r = rreg_int(2);
w = rwreg_int(0);
OUT = 0x19;
OUT = 0xC0|(r<<3)|w;
debug(("sbbl %s,%s\n", regname(r), regname(w)));
}
define_insn(sub_float, fsub_RRR)
{
int r2 = rslot_float(2); /* Get r2 into memory */
int r1 = rreg_float(1); /* Load r1 into the register stack */
int w = wreg_float(0); /* Result will be in register stack */
OUT = 0xD8;
OUT = 0xA0|REG_ebp;
OUT = r2 & 0xff;
OUT = (r2 >> 8) & 0xff;
OUT = (r2 >> 16) & 0xff;
OUT = (r2 >> 24) & 0xff;
debug(("fsub %d(ebp)\n", r2));
}
define_insn(sub_double, fsubl_RRR)
{
int r2 = rslot_double(2); /* Get r2 into memory */
int r1 = rreg_double(1); /* Load r1 into the register stack */
int w = wreg_double(0); /* Result will be in register stack */
OUT = 0xDC;
OUT = 0xA0|REG_ebp;
OUT = r2 & 0xff;
OUT = (r2 >> 8) & 0xff;
OUT = (r2 >> 16) & 0xff;
OUT = (r2 >> 24) & 0xff;
debug(("fsubl %d(ebp)\n", r2));
}
define_insn(mul_int, mul_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
w = rwreg_int(0);
OUT = 0x0F;
OUT = 0xAF;
OUT = 0xC0|(w<<3)|r;
debug(("imull %s,%s\n", regname(r), regname(w)));
}
define_insn(mul_float, fmul_RRR)
{
int r2 = rslot_float(2); /* Get r2 into memory */
int r1 = rreg_float(1); /* Load r1 into the register stack */
int w = wreg_float(0); /* Result will be in register stack */
OUT = 0xD8;
OUT = 0x88|REG_ebp;
OUT = r2 & 0xff;
OUT = (r2 >> 8) & 0xff;
OUT = (r2 >> 16) & 0xff;
OUT = (r2 >> 24) & 0xff;
debug(("fmul %d(ebp)\n", r2));
}
define_insn(mul_double, fmull_RRR)
{
int r2 = rslot_double(2); /* Get r2 into memory */
int r1 = rreg_double(1); /* Load r1 into the register stack */
int w = wreg_double(0); /* Result will be in register stack */
OUT = 0xDC;
OUT = 0x88|REG_ebp;
OUT = r2 & 0xff;
OUT = (r2 >> 8) & 0xff;
OUT = (r2 >> 16) & 0xff;
OUT = (r2 >> 24) & 0xff;
debug(("fmull %d(ebp)\n", r2));
}
define_insn(div_int, div_RRR)
{
int r;
int w;
check_reg_01();
w = rwreg_int(0);
/* Can only divide accumulator. */
do_force_move_int(REG_eax, w, 0);
/* EDX is also used so get hold of it */
clobberRegister(REG_edx);
/* Setup EDX - should contains the sign of EAX */
do_move_int(REG_edx, REG_eax);
OUT = 0xC1;
OUT = 0xF8|REG_edx;
OUT = 31;
debug(("sarl #31,edx\n"));
r = rreg_int(2);
OUT = 0xF7;
OUT = 0xF8|r;
assert(r != REG_eax);
assert(r != REG_edx);
debug(("idivl %s,%s\n", regname(r), regname(w)));
}
define_insn(div_float, fdiv_RRR)
{
int r2 = rslot_float(2); /* Get r2 into memory */
int r1 = rreg_float(1); /* Load r1 into the register stack */
int w = wreg_float(0); /* Result will be in register stack */
OUT = 0xD8;
OUT = 0xB0|REG_ebp;
OUT = r2 & 0xff;
OUT = (r2 >> 8) & 0xff;
OUT = (r2 >> 16) & 0xff;
OUT = (r2 >> 24) & 0xff;
debug(("fdiv %d(ebp)\n", r2));
}
define_insn(div_double, fdivl_RRR)
{
int r2 = rslot_double(2); /* Get r2 into memory */
int r1 = rreg_double(1); /* Load r1 into the register stack */
int w = wreg_double(0); /* Result will be in register stack */
OUT = 0xDC;
OUT = 0xB0|REG_ebp;
OUT = r2 & 0xff;
OUT = (r2 >> 8) & 0xff;
OUT = (r2 >> 16) & 0xff;
OUT = (r2 >> 24) & 0xff;
debug(("fdivl %d(ebp)\n", r2));
}
define_insn(rem_int, rem_RRR)
{
int r;
int w;
check_reg_01();
w = rwreg_int(0);
/* Can only divide accumulator. */
do_force_move_int(REG_eax, w, 0);
/* EDX is also used so get hold of it */
clobberRegister(REG_edx);
/* Setup EDX - should contains the sign of EAX */
do_move_int(REG_edx, REG_eax);
OUT = 0xC1;
OUT = 0xF8|REG_edx;
OUT = 31;
debug(("sarl #31,edx\n"));
r = rreg_int(2);
OUT = 0xF7;
OUT = 0xF8|r;
assert(r != REG_eax);
assert(r != REG_edx);
debug(("idivl %s,%s\n", regname(r), regname(w)));
/* Result is in EDX not EAX - we must force the slot register */
forceRegister(seq_dst(s), REG_edx, Rint);
}
/* --------------------------------------------------------------------- */
define_insn(and_int, and_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
w = rwreg_int(0);
OUT = 0x21;
OUT = 0xC0|(r<<3)|w;
debug(("andl %s,%s\n", regname(r), regname(w)));
}
define_insn(or_int, or_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
w = rwreg_int(0);
OUT = 0x09;
OUT = 0xC0|(r<<3)|w;
debug(("orl %s,%s\n", regname(r), regname(w)));
}
define_insn(xor_int, xor_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
w = rwreg_int(0);
OUT = 0x31;
OUT = 0xC0|(r<<3)|w;
debug(("xorl %s,%s\n", regname(r), regname(w)));
}
define_insn(ashr_int, ashr_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
/* Can only shift by ECX. */
do_force_move_int(REG_ecx, r, 2);
w = rwreg_int(0);
OUT = 0xD3;
OUT = 0xF8|w;
debug(("sarl %s,%s\n", regname(r), regname(w)));
}
define_insn(lshr_int, lshr_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
/* Can only shift by ECX. */
do_force_move_int(REG_ecx, r, 2);
w = rwreg_int(0);
OUT = 0xD3;
OUT = 0xE8|w;
debug(("shrl %s,%s\n", regname(r), regname(w)));
}
define_insn(lshl_int, lshl_RRR)
{
int r;
int w;
check_reg_01();
r = rreg_int(2);
/* Can only shift by ECX. */
do_force_move_int(REG_ecx, r, 2);
w = rwreg_int(0);
OUT = 0xD3;
OUT = 0xE0|w;
debug(("shll %s,%s\n", regname(r), regname(w)));
}
/* --------------------------------------------------------------------- */
define_insn(load_int, load_RxR)
{
int r = rreg_int(2);
int w = wreg_int(0);
OUT = 0x8B;
OUT = 0x00|(w<<3)|r;
if (r == REG_esp) {
OUT = 0x20|REG_esp;
}
debug(("movl (%s),%s\n", regname(r), regname(w)));
}
define_insn(load_float, fload_RxR)
{
int r = rreg_int(2);
int w = wreg_float(0);
OUT = 0xD9;
OUT = 0x00|r;
debug(("fld (%s)\n", regname(r)));
}
define_insn(load_double, floadl_RxR)
{
int r = rreg_int(2);
int w = wreg_double(0);
OUT = 0xDD;
OUT = 0x00|r;
debug(("fldl (%s)\n", regname(r)));
}
define_insn(store_int, store_xRR)
{
int r = rreg_int(2);
int w = rreg_int(1);
OUT = 0x89;
OUT = 0x00|(r<<3)|w;
if (w == REG_esp) {
OUT = 0x20|REG_esp;
}
debug(("movl %s,(%s)\n", regname(r), regname(w)));
}
define_insn(store_float, fstore_RxR)
{
int r = rreg_float(2);
int w = rreg_int(1);
OUT = 0xD9;
OUT = 0x18|w;
debug(("fstp (%s)\n", regname(w)));
}
define_insn(store_double, fstorel_RxR)
{
int r = rreg_double(2);
int w = rreg_int(1);
OUT = 0xDD;
OUT = 0x18|w;
debug(("fstlp (%s)\n", regname(w)));
}
/* --------------------------------------------------------------------- */
define_insn(cmp_int, cmp_xRR)
{
int r1 = rreg_int(1);
int r2 = rreg_int(2);
OUT = 0x39;
OUT = 0xC0|(r2<<3)|r1;
debug(("cmpl %s,%s\n", regname(r2), regname(r1)));
}
/* --------------------------------------------------------------------- */
define_insn(cvt_int_float, cvtif_RxR)
{
int r = rslot_int(2);
int w = wreg_float(0);
OUT = 0xDB;
OUT = 0x80|REG_ebp;
OUT = r & 0xff;
OUT = (r >> 8) & 0xff;
OUT = (r >> 16) & 0xff;
OUT = (r >> 24) & 0xff;
debug(("fild %d(ebp)\n", r));
}
define_insn(cvt_int_double, cvtid_RxR)
{
int r = rslot_int(2);
int w = wreg_double(0);
OUT = 0xDB;
OUT = 0x80|REG_ebp;
OUT = r & 0xff;
OUT = (r >> 8) & 0xff;
OUT = (r >> 16) & 0xff;
OUT = (r >> 24) & 0xff;
debug(("fild %d(ebp)\n", r));
}
define_insn(cvt_long_float, cvtlf_RxR)
{
int r = rslot_long(2);
int w = wreg_float(0);
OUT = 0xDF;
OUT = 0xA8|REG_ebp;
OUT = r & 0xff;
OUT = (r >> 8) & 0xff;
OUT = (r >> 16) & 0xff;
OUT = (r >> 24) & 0xff;
debug(("fildll %d(ebp)\n", r));
}
define_insn(cvt_long_double, cvtld_RxR)
{
int r = rslot_long(2);
int w = wreg_double(0);
OUT = 0xDF;
OUT = 0xA8|REG_ebp;
OUT = r & 0xff;
OUT = (r >> 8) & 0xff;
OUT = (r >> 16) & 0xff;
OUT = (r >> 24) & 0xff;
debug(("fildll %d(ebp)\n", r));
}
define_insn(cvt_float_int, cvtfi_RxR)
{
int r = rreg_float(2);
int w = wslot_int(0);
OUT = 0xDB;
OUT = 0x98|REG_ebp;
OUT = w & 0xff;
OUT = (w >> 8) & 0xff;
OUT = (w >> 16) & 0xff;
OUT = (w >> 24) & 0xff;
debug(("fistp %d(ebp)\n", w));
}
define_insn(cvt_double_int, cvtdi_RxR)
{
int r = rreg_double(2);
int w = wslot_int(0);
OUT = 0xDB;
OUT = 0x98|REG_ebp;
OUT = w & 0xff;
OUT = (w >> 8) & 0xff;
OUT = (w >> 16) & 0xff;
OUT = (w >> 24) & 0xff;
debug(("fistp %d(ebp)\n", w));
}
define_insn(cvt_float_long, cvtfl_RxR)
{
int r = rreg_float(2);
int w = wslot_long(0);
OUT = 0xDF;
OUT = 0xB8|REG_ebp;
OUT = w & 0xff;
OUT = (w >> 8) & 0xff;
OUT = (w >> 16) & 0xff;
OUT = (w >> 24) & 0xff;
debug(("fistpl %d(ebp)\n", w));
}
define_insn(cvt_double_long, cvtdl_RxR)
{
int r = rreg_double(2);
int w = wslot_long(0);
OUT = 0xDF;
OUT = 0xB8|REG_ebp;
OUT = w & 0xff;
OUT = (w >> 8) & 0xff;
OUT = (w >> 16) & 0xff;
OUT = (w >> 24) & 0xff;
debug(("fistpl %d(ebp)\n", w));
}
define_insn(cvt_float_double, cvtfd_RxR)
{
int o = rslot_float(2);
int w = wreg_double(0);
OUT = 0xD9;
OUT = 0x80|REG_ebp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("fld %d(ebp)\n", o));
}
define_insn(cvt_double_float, cvtdf_RxR)
{
int o = rslot_double(2);
int w = wreg_float(0);
OUT = 0xDD;
OUT = 0x80|REG_ebp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("fldl %d(ebp)\n", o));
}
/* --------------------------------------------------------------------- */
define_insn(build_key, set_word_xxC)
{
jint val = const_int(2);
OUT = val & 0xff;
OUT = (val >> 8) & 0xff;
OUT = (val >> 16) & 0xff;
OUT = (val >> 24) & 0xff;
debug((".word %08x\n", val));
}
define_insn(build_code_ref, set_wordpc_xxC)
{
label* l = (label*)const_int(2);
l->type |= Llong|Labsolute;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug((".word ?\n"));
}
/* --------------------------------------------------------------------- */
define_insn(set_label, set_label_xxC)
{
label* l = (label*)const_int(2);
l->to = (uint32)CODEPC;
}
define_insn(branch, branch_xCC)
{
label* l = (label*)const_int(1);
int bt = const_int(2);
l->type |= Llong|Lrelative;
switch (bt) {
case ba:
OUT = 0xE9;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug(("jmpl ?\n"));
break;
case beq:
OUT = 0x0F;
OUT = 0x84;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug(("je ?\n"));
break;
case bne:
OUT = 0x0F;
OUT = 0x85;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug(("jne ?\n"));
break;
case blt:
OUT = 0x0F;
OUT = 0x8C;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug(("jlt ?\n"));
break;
case ble:
OUT = 0x0F;
OUT = 0x8E;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug(("jle ?\n"));
break;
case bgt:
OUT = 0x0F;
OUT = 0x8F;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug(("jgt ?\n"));
break;
case bge:
OUT = 0x0F;
OUT = 0x8D;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug(("jge ?\n"));
break;
default:
abort();
}
}
define_insn(branch_indirect, branch_indirect_xRC)
{
int r = rreg_int(1);
assert(const_int(2) == ba);
OUT = 0xFF;
OUT = 0xE0|r;
debug(("jmp (%s)\n", regname(r)));
}
define_insn(call_ref, call_xCC)
{
label* l = (label*)const_int(1);
assert(const_int(2) == ba);
OUT = 0xE8;
l->type |= Llong|Lrelative;
l->at = (uintp)CODEPC;
OUT = 0;
OUT = 0;
OUT = 0;
OUT = 0;
l->from = (uintp)CODEPC;
debug(("call ?\n"));
}
define_insn(call, call_xRC)
{
int r = rreg_int(1);
assert(const_int(2) == ba);
OUT = 0xFF;
OUT = 0xD0|r;
debug(("call %s\n", regname(r)));
}
define_insn(ret, ret_xxx)
{
OUT = 0xC3;
debug(("ret\n"));
}
define_insn(push_int, push_xxR)
{
int r = rreg_int(2);
OUT = 0xFF;
OUT = 0xF0|r;
debug(("pushl %s\n", regname(r)));
}
define_insn(push_float, fpush_xxR)
{
int r = rreg_int(2); /* Move the float into a register */
OUT = 0xFF;
OUT = 0xF0|r;
debug(("pushl %s\n", regname(r)));
}
define_insn(push_double, fpushl_xxR)
{
int r = rslot_int(2); /* Move the float into a slot */
OUT = 0xFF;
OUT = 0xB0|REG_ebp;
OUT = (r+4) & 0xff;
OUT = ((r+4) >> 8) & 0xff;
OUT = ((r+4) >> 16) & 0xff;
OUT = ((r+4) >> 24) & 0xff;
debug(("pushl %d(ebp)\n", (r+4)));
OUT = 0xFF;
OUT = 0xB0|REG_ebp;
OUT = r & 0xff;
OUT = (r >> 8) & 0xff;
OUT = (r >> 16) & 0xff;
OUT = (r >> 24) & 0xff;
debug(("pushl %d(ebp)\n", r));
}
define_insn(popargs, popargs_xxC)
{
int o = const_int(2);
o *= 4;
OUT = 0x81;
OUT = 0xC0|REG_esp;
OUT = o & 0xff;
OUT = (o >> 8) & 0xff;
OUT = (o >> 16) & 0xff;
OUT = (o >> 24) & 0xff;
debug(("addl %d,esp\n", o));
}
define_insn(return_int, return_Rxx)
{
forceRegister(seq_dst(s), REG_eax, Rint);
}
define_insn(return_long, returnl_Rxx)
{
forceRegister(seq_dst(s), REG_eax, Rint);
forceRegister(seq_dst(s)+1, REG_edx, Rint);
}
define_insn(return_float, freturn_Rxx)
{
forceRegister(seq_dst(s), REG_flt0, Rfloat);
}
define_insn(return_double, freturnl_Rxx)
{
forceRegister(seq_dst(s), REG_dbl0, Rdouble);
}
/* --------------------------------------------------------------------- */
define_insn(add_int_const, add_RRC)
{
int rw;
int v;
check_reg_01();
v = const_int(2);
rw = rwreg_int(0);
OUT = 0x81;
OUT = 0xC0|rw;
OUT = v & 0xff;
OUT = (v >> 8) & 0xff;
OUT = (v >> 16) & 0xff;
OUT = (v >> 24) & 0xff;
debug(("addl #%d,%s\n", v, regname(rw)));
}
define_insn(sub_int_const, sub_RRC)
{
int rw;
int v;
check_reg_01();
v = const_int(2);
rw = rwreg_int(0);
OUT = 0x81;
OUT = 0xE8|rw;
OUT = v & 0xff;
OUT = (v >> 8) & 0xff;
OUT = (v >> 16) & 0xff;
OUT = (v >> 24) & 0xff;
debug(("subl #%d,%s\n", v, regname(rw)));
}
define_insn(load_int_addregconst, load_RRC)
{
int v = const_int(2);
int r = rreg_int(1);
int w = wreg_int(0);
assert(r != REG_esp);
OUT = 0x8B;
OUT = 0x80|(w<<3)|r;
OUT = v & 0xff;
OUT = (v >> 8) & 0xff;
OUT = (v >> 16) & 0xff;
OUT = (v >> 24) & 0xff;
debug(("movl %d(%s),%s\n", o, regname(r), regname(w)));
}
define_insn(load_byte, loadb_RxR)
{
int r = rreg_int(2);
int w = wreg_int(0);
OUT = 0x0F;
OUT = 0xBE;
OUT = 0x00|(w<<3)|r;
if (r == REG_esp) {
OUT = 0x20|REG_esp;
}
debug(("movsb (%s),%s\n", regname(r), regname(w)));
}
define_insn(load_char, loadc_RxR)
{
int r = rreg_int(2);
int w = wreg_int(0);
OUT = 0x0F;
OUT = 0xB6;
OUT = 0x00|(w<<3)|r;
if (r == REG_esp) {
OUT = 0x20|REG_esp;
}
debug(("movzb (%s),%s\n", regname(r), regname(w)));
}
define_insn(load_short, loads_RxR)
{
int r = rreg_int(2);
int w = wreg_int(0);
OUT = 0x0F;
OUT = 0xBF;
OUT = 0x00|(w<<3)|r;
if (r == REG_esp) {
OUT = 0x20|REG_esp;
}
debug(("movsw (%s),%s\n", regname(r), regname(w)));
}
define_insn(store_int_addregconst, store_xRRC)
{
int v;
int r1;
int r0;
r0 = rreg_int(2);
s = seq_seq(s, 1);
assert(s->ref == 0);
v = const_int(2);
r1 = rreg_int(1);
assert(r0 != REG_esp);
OUT = 0x89;
OUT = 0x80|(r0<<3)|r1;
OUT = v & 0xff;
OUT = (v >> 8) & 0xff;
OUT = (v >> 16) & 0xff;
OUT = (v >> 24) & 0xff;
debug(("movl %s,%d(%s)\n", regname(r0), v, regname(r1)));
}
define_insn(store_byte, storeb_xRR)
{
int r = rreg_int(2);
int w = rreg_int(1);
OUT = 0x88;
OUT = 0x00|(r<<3)|w;
if (w == REG_esp) {
OUT = 0x20|REG_esp;
}
debug(("movb %s,(%s)\n", regname(r), regname(w)));
}
define_insn(store_short, stores_xRR)
{
int r = rreg_int(2);
int w = rreg_int(1);
OUT = 0x66;
OUT = 0x89;
OUT = 0x00|(r<<3)|w;
if (w == REG_esp) {
OUT = 0x20|REG_esp;
}
debug(("movw %s,(%s)\n", regname(r), regname(w)));
}
define_insn(cmp_int_const, cmp_xRC)
{
int r1 = rreg_int(1);
int v = const_int(2);
OUT = 0x81;
OUT = 0xF8|r1;
OUT = v & 0xff;
OUT = (v >> 8) & 0xff;
OUT = (v >> 16) & 0xff;
OUT = (v >> 24) & 0xff;
debug(("cmpl #%d,%s\n", v, regname(r1)));
}
define_insn(push_int_const, push_xxC)
{
int v = const_int(2);
OUT = 0x68;
OUT = v & 0xff;
OUT = (v >> 8) & 0xff;
OUT = (v >> 16) & 0xff;
OUT = (v >> 24) & 0xff;
debug(("pushl #%d\n", v));
}
define_insn(lshl_int_const, lshl_RRC)
{
int rw;
int v;
check_reg_01();
rw = rreg_int(0);
v = const_int(2);
assert(v < 256);
OUT = 0xC1;
OUT = 0xE0|rw;
OUT = v
debug(("shll #%d,%s\n", v, regname(rw)));
}