📄 jit-i386.def
字号:
/* jit-i386.def * i386 instruction definition. * * Copyright (c) 1996, 1997 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "debug.h"#include "classMethod.h"#include "gtypes.h"#ifdef KAFFE_VMDEBUGint jit_debug;#define debug(x) (jit_debug ? dprintf("%x:\t", CODEPC), dprintf x : 0)#else#define debug(x)#endif#define do_move_int(t, f) { \ if ((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); \ }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/* IEEE mode setup */#define IEEE_INVAL 0x0001#define IEEE_DENORM 0x0002#define IEEE_DIVZ 0x0004#define IEEE_OVERF 0x0008#define IEEE_UNDERF 0x0010#define IEEE_LOS 0x0020#define IEEE_NEAREST 0x0000#define IEEE_DOWN 0x0400#define IEEE_UP 0x0800#define IEEE_CHOP 0x0C00#define IEEE_EXTRA 0x1200#define IEEE_MODE (IEEE_DENORM|IEEE_UNDERF|IEEE_LOS|IEEE_DIVZ|IEEE_NEAREST|IEEE_EXTRA)extern bool used_ieee_division;#if defined(KAFFE_PROFILER)/* This code reads the timestamp register, and substracts it * from COUNTER. As this will scratch EDX and EAX, the second * parameter said if they must be saved. */#define profiler_start(COUNTER, SAVE_EDX_EAX) do { \ int *__counter = (int *)&(COUNTER); \ if (SAVE_EDX_EAX) { \ /* Save EAX and EDX */ \ OUT = 0x50|REG_edx; \ OUT = 0x50|REG_eax; \ debug(("pushl edx\n")); \ debug(("pushl eax\n")); \ } \ \ OUT = 0x0F; \ OUT = 0x31; \ debug(("rdtsc\n")); \ \ OUT = 0x29; \ OUT = 0x05; \ LOUT = (int)(__counter); \ debug(("sub eax, 0x%x\n", (int)(__counter))); \ \ OUT = 0x19; \ OUT = 0x15; \ LOUT = (int)(__counter + 1); \ debug(("sbb edx, 0x%x\n", (int)(__counter + 1))); \ \ if (SAVE_EDX_EAX) { \ /* Restore EAX and EDX */ \ OUT = 0x58|REG_eax; \ OUT = 0x58|REG_edx; \ debug(("popl eax\n")); \ debug(("popl edx\n")); \ } \} while(0)/* This code reads the timestamp register, and add it to COUNTER. * As this will scratch EDX and EAX, the second parameter said if * they must be saved. */#define profiler_end(COUNTER, SAVE_EDX_EAX) do { \ int *__counter = (int *)&(COUNTER); \ if (SAVE_EDX_EAX) { \ /* Save EAX and EDX */ \ OUT = 0x50|REG_edx; \ OUT = 0x50|REG_eax; \ debug(("pushl edx\n")); \ debug(("pushl eax\n")); \ } \ \ OUT = 0x0F; \ OUT = 0x31; \ debug(("rdtsc\n")); \ \ OUT = 0x01; \ OUT = 0x05; \ LOUT = (int)(__counter); \ debug(("add eax, 0x%x\n", (int)(__counter))); \ \ OUT = 0x11; \ OUT = 0x15; \ LOUT = (int)(__counter + 1); \ debug(("adc edx, 0x%x\n", (int)(__counter + 1))); \ \ if (SAVE_EDX_EAX) { \ /* Restore EAX and EDX */ \ OUT = 0x58|REG_eax; \ OUT = 0x58|REG_edx; \ debug(("popl eax\n")); \ debug(("popl edx\n")); \ } \} while(0)#endif/* --------------------------------------------------------------------- */define_insn(unimplemented, unimplemented){ ABORT();}define_insn(nop, nop){ OUT = 0x90; debug(("nop\n"));}/* --------------------------------------------------------------------- */define_insn(prologue, prologue_xxx){ label* l; OUT = 0x50|REG_ebp; OUT = 0x89; OUT = 0xC0|(REG_esp<<3)|REG_ebp; OUT = 0x81; OUT = 0xE8|REG_esp; l = (label*)const_int(1); l->type = Lframe|Labsolute|Lgeneral; l->at = (uintp)CODEPC; LOUT = 0; OUT = 0x50|REG_edi; OUT = 0x50|REG_esi; OUT = 0x50|REG_ebx; debug(("pushl ebp\n")); debug(("movl esp,ebp\n")); debug(("subl #?,esp\n")); debug(("pushl edi\n")); debug(("pushl esi\n")); debug(("pushl ebx\n"));#if defined(KAFFE_PROFILER) if (profFlag) { profiler_start(globalMethod->totalClicks, 0); OUT = 0xFF; OUT = 0x05; LOUT = (int)&(globalMethod->callsCount); debug(("incl 0x%x\n",(int)&(globalMethod->callsCount))); }#endif /* If this method uses IEEE, set up the mode here */ if (used_ieee_division == true && 0) { OUT = 0x68; LOUT = 0; OUT = 0x68; LOUT = 0; debug(("pushl #0\n")); debug(("pushl #0\n")); OUT = 0xD9; OUT = 0x3C; OUT = 0x24; debug(("fnstcw (esp)\n")); OUT = 0x8B; OUT = (REG_ebx<<3)|0x04; OUT = 0x24; debug(("movl (esp),ebx\n")); OUT = 0xB8|REG_ebx; LOUT = IEEE_MODE; debug(("movl %d,ebx\n", IEEE_MODE)); OUT = 0x89; OUT = (REG_ebx<<3)|0x44; OUT = 0x24; OUT = 0x04; debug(("movl ebx,4(esp)\n")); OUT = 0xD9; OUT = 0x6C; OUT = 0x24; OUT = 0x04; debug(("fldcw 4(esp)\n")); }}define_insn(exception_prologue, eprologue_xLx){ label* l; OUT = 0x89; OUT = 0xC0|(REG_ebp<<3)|REG_ebx; OUT = 0x81; OUT = 0xE8|REG_ebx; /* Remember where the framesize is to go */ l = (label*)const_int(1); l->type = Lframe|Labsolute|Lgeneral; l->at = (uintp)CODEPC; LOUT = 0; OUT = 0x81; OUT = 0xE8|REG_ebx; LOUT = 3*SLOTSIZE; OUT = 0x89; OUT = 0xC0|(REG_ebx<<3)|REG_esp; debug(("movl ebp,ebx\n")); debug(("subl #?,ebx\n")); debug(("subl #3*SLOTSIZE,ebx\n")); debug(("movl ebx,esp\n")); if (used_ieee_division == true && 0) { OUT = 0x81; OUT = 0xE8|REG_esp; LOUT = SLOTSIZE; debug(("subl #%d,esp\n", SLOTSIZE)); OUT = 0x8B; OUT = (REG_ebx<<3)|0x04; OUT = 0x24; debug(("movl (esp),ebx\n")); OUT = 0xB8|REG_ebx; LOUT = IEEE_MODE; debug(("movl %d,ebx\n", IEEE_MODE)); OUT = 0x89; OUT = (REG_ebx<<3)|0x44; OUT = 0x24; OUT = 0x04; debug(("movl ebx,4(esp)\n")); OUT = 0xD9; OUT = 0x6C; OUT = 0x24; OUT = 0x04; debug(("fldcw 4(esp)\n")); }}define_insn(epilogue, epilogue_xxx){ setEpilogueLabel((uintp)CODEPC); /* If this method uses IEEE, restore it */ if (used_ieee_division == true && 0) {#if 0 OUT = 0xD9; OUT = 0x2C; OUT = 0x24; debug(("fldcw (esp)\n"));#endif OUT = 0xD9; OUT = 0x6C; OUT = 0x24; OUT = 0; debug(("fldcw 0(esp)\n")); OUT = 0x81; OUT = 0xC0|REG_esp; LOUT = 8; debug(("addl 8,esp\n")); }#if defined(KAFFE_PROFILER) if (profFlag) { profiler_end(globalMethod->totalClicks, 1); }#endif 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")); OUT = 0xC3; debug(("ret\n"));}/* --------------------------------------------------------------------- */define_insn(spill_int, spill_Rxx){ int r = sreg_int(0); int o = const_int(1); OUT = 0x89; OUT = 0x80|(r<<3)|REG_ebp; LOUT = o; debug(("movl %s,%d(ebp)\n", regname(r), o));}define_insn(spill_float, fspill_Rxx){ int o = const_int(1); sreg_float(0); OUT = 0xD9; OUT = 0x98|REG_ebp; LOUT = o; debug(("fstp %d(ebp)\n", o));}define_insn(spill_double, fspilll_Rxx){ int o = const_int(1); sreg_double(0); OUT = 0xDD; OUT = 0x98|REG_ebp; LOUT = o; debug(("fstpl %d(ebp)\n", o));}define_insn(reload_int, reload_Rxx){ int r = lreg_int(0); int o = const_int(1); OUT = 0x8B; OUT = 0x80|(r<<3)|REG_ebp; LOUT = o; debug(("movl %d(ebp),%s\n", o, regname(r)));}define_insn(reload_float, freload_Rxx){ int o = const_int(1); lreg_float(0); OUT = 0xD9; OUT = 0x80|REG_ebp; LOUT = o; debug(("fld %d(ebp)\n", o));}define_insn(reload_double, freloadl_Rxx){ int o = const_int(1); lreg_double(0); OUT = 0xDD; OUT = 0x80|REG_ebp; LOUT = o; 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; LOUT = val; debug(("movl #%d,%s\n", val, regname(w)));}define_insn(move_label_const, move_RxL){ label* l = const_label(2); int w = wreg_int(0); OUT = 0xB8|w; l->type |= Llong|Labsolute; l->at = CODEPC; LOUT = 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) { 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); wreg_float(0); if (val == 0.0) { OUT = 0xD9; OUT = 0xEE; debug(("fldz\n")); { jvalue d; d.d = val; if ((d.j >> 63) & 1) { OUT = 0xD9; OUT = 0xe0; debug(("fchs\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 = wslot_float(0); if (or != ow) { wreg_float(0); OUT = 0xD9; OUT = 0x80|REG_ebp; LOUT = or; debug(("fld %d(ebp)\n", or)); }}define_insn(move_double_const, fmovel_RxC){ double val = const_double(2); wreg_double(0); if (val == 0.0) { OUT = 0xD9; OUT = 0xEE; debug(("fldz\n")); { jvalue d; d.d = val; if ((d.j >> 63) & 1) { OUT = 0xD9; OUT = 0xe0; debug(("fchsl\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 = wslot_double(0); if (or != ow) { wreg_double(0); OUT = 0xDD; OUT = 0x80|REG_ebp; LOUT = or; 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 */ rreg_float(1); /* Load r1 into the register stack */ wreg_float(0); /* Result will be in register stack */ OUT = 0xD8; OUT = 0x80|REG_ebp; LOUT = r2; debug(("fadd %d(ebp)\n", r2));}define_insn(add_double, faddl_RRR){ int r2 = rslot_double(2); /* Get r2 into memory */ rreg_double(1); /* Load r1 into the register stack */ wreg_double(0); /* Result will be in register stack */ OUT = 0xDC; OUT = 0x80|REG_ebp; LOUT = r2; 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 */ rreg_float(1); /* Load r1 into the register stack */ wreg_float(0); /* Result will be in register stack */ OUT = 0xD8; OUT = 0xA0|REG_ebp; LOUT = r2; debug(("fsub %d(ebp)\n", r2));}define_insn(sub_double, fsubl_RRR){ int r2 = rslot_double(2); /* Get r2 into memory */ rreg_double(1); /* Load r1 into the register stack */ wreg_double(0); /* Result will be in register stack */ OUT = 0xDC; OUT = 0xA0|REG_ebp; LOUT = r2; debug(("fsubl %d(ebp)\n", r2));}define_insn(neg_float, negf_RxR){ rreg_float(2); wreg_float(0); OUT = 0xD9; OUT = 0xe0; debug(("fchs\n"));}define_insn(neg_double, negd_RxR){ rreg_double(2); wreg_double(0); OUT = 0xD9; OUT = 0xe0; debug(("fchsl\n"));}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 */ rreg_float(1); /* Load r1 into the register stack */ wreg_float(0); /* Result will be in register stack */ OUT = 0xD8; OUT = 0x88|REG_ebp; LOUT = r2; debug(("fmul %d(ebp)\n", r2));}define_insn(mul_double, fmull_RRR){ int r2 = rslot_double(2); /* Get r2 into memory */ rreg_double(1); /* Load r1 into the register stack */ wreg_double(0); /* Result will be in register stack */ OUT = 0xDC; OUT = 0x88|REG_ebp; LOUT = r2; debug(("fmull %d(ebp)\n", r2));}define_insn(div_int, div_RRR){ int r; int w; label *l1; 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); r = rreg_int(2); assert(r != REG_eax); assert(r != REG_edx); /* special case for LONG_MIN / -1l: r == -1 ? -eax : eax / r */ OUT = 0x83; OUT = 0xF8|r; OUT = 0xFF; debug(("cmp #0xFF,%s\n", regname(r))); l1 = newLabel(); l1->type = Linternal| Llong8|Lrelative; OUT = 0x74; l1->at = CODEPC; OUT = 0; l1->from = CODEPC; debug(("je neg\n")); /* Setup EDX - should contains the sign of EAX */ do_move_int(REG_edx, REG_eax);#if 0 OUT = 0xC1; OUT = 0xF8|REG_edx; OUT = 31; debug(("sarl #31,edx\n"));#else OUT = 0x99; debug(("cltd\n"));#endif OUT = 0xF7; OUT = 0xF8|r; debug(("idivl %s,%s\n", regname(r), regname(w))); OUT = 0xEB; OUT = 2; debug(("jmp +2\n")); debug(("neg:\n")); l1->to = CODEPC; OUT = 0xF7; OUT = 0xD8|REG_eax; debug(("neg eax\n"));}define_insn(div_float, fdiv_RRR){ int r2 = rslot_float(2); /* Get r2 into memory */ rreg_float(1); /* Load r1 into the register stack */ wreg_float(0); /* Result will be in register stack */ OUT = 0xD8; OUT = 0xB0|REG_ebp; LOUT = r2; debug(("fdiv %d(ebp)\n", r2));}define_insn(div_double, fdivl_RRR){ int r2 = rslot_double(2); /* Get r2 into memory */ rreg_double(1); /* Load r1 into the register stack */ wreg_double(0); /* Result will be in register stack */ OUT = 0xDC; OUT = 0xB0|REG_ebp; LOUT = r2; debug(("fdivl %d(ebp)\n", r2));}define_insn(rem_int, rem_RRR){ int r; int w; label *l1; 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); r = rreg_int(2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -