📄 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(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}define_insn(exception_prologue, eprologue_xLx){ label* l; OUT(0x89); OUT(0xC0|(REG_ebp<<3)|REG_ecx); OUT(0x81); OUT(0xE8|REG_ecx); /* 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_ecx); LOUT(3*SLOTSIZE); OUT(0x89); OUT(0xC0|(REG_ecx<<3)|REG_esp); debug(("movl ebp,ecx\n")); debug(("subl #?,ecx\n")); debug(("subl #3*SLOTSIZE,ecx\n")); debug(("movl ecx,esp\n"));}define_insn(epilogue, epilogue_xxx){ KaffeJIT_setEpilogueLabel((uintp)CODEPC);#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); (void)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); (void)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 r = lreg_double(0); int o = const_int(1); OUT(0xDD); OUT(0x80|REG_ebp); LOUT(o); debug(("fldl %d(ebp) %d\n", o, r));}/* --------------------------------------------------------------------- */define_insn(move_int_const, move_RxC){ int val = const_int(2); int w = wreg_int(0); if (val == 0) { OUT(0x31); OUT(0xC0|(w<<3)|w); debug(("xorl %s,%s\n", regname(w), regname(w))); } else { 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){ jvalue d; d.d = const_float(2); wreg_float(0); if (d.d == 0.0) { OUT(0xD9); OUT(0xEE); debug(("fldz\n")); if ((d.j >> 63) & 1) { OUT(0xD9); OUT(0xe0); debug(("fchs\n")); } } else if (d.d == 1.0) { OUT(0xD9); OUT(0xE8); debug(("fld1\n")); } else { KAFFEVM_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){ jvalue d; d.d = const_double(2); wreg_double(0); if (d.d == 0.0) { OUT(0xD9); OUT(0xEE); debug(("fldz\n")); if ((d.j >> 63) & 1) { OUT(0xD9); OUT(0xe0); debug(("fchs\n")); } } else if (d.d == 1.0) { OUT(0xD9); OUT(0xE8); debug(("fld1\n")); } else { KAFFEVM_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(("fchs\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 = KaffeJIT_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); OUT(0x99); debug(("cltd\n")); 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); assert(r != REG_eax); assert(r != REG_edx); /* special case for LONG_MIN % -1l: r == -1 ? 0 : eax / r */ OUT(0x83); OUT(0xF8|r); OUT(0xFF); debug(("cmp #0xFF,%s\n", regname(r))); l1 = KaffeJIT_newLabel(); l1->type = Linternal| Llong8|Lrelative; OUT(0x74); l1->at = CODEPC; OUT(0); l1->from = CODEPC; debug(("je const0\n")); /* Setup EDX - should contains the sign of EAX */ do_move_int(REG_edx, REG_eax); OUT(0x99); debug(("cltd\n")); OUT(0xF7); OUT(0xF8|r); debug(("idivl %s,%s\n", regname(r), regname(w))); OUT(0xEB); OUT(2); debug(("jmp +2\n")); debug(("const0:\n")); l1->to = CODEPC; OUT(0x31); OUT(0xC0|(REG_edx<<3)|REG_edx); debug(("xorl edx,edx\n")); /* 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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -