📄 jit3-i386.def
字号:
/* jit3-i386.def * i386 instruction definition. * * Copyright (c) 1996, 1997 * Transvirtual Technologies, Inc. All rights reserved. * * Cross-language profiling changes contributed by * the Flux Research Group, Department of Computer Science, * University of Utah, http://www.cs.utah.edu/flux/ * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "debug.h"#include "classMethod.h"#include "md.h"#include "xprofiler.h"#if defined(TRACE_METHOD_END) && defined(__GNUC__)asm(".globl tStore\ntStore: .long 0,0");#endif#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); \ do_move_int(_w_, _r_); \ }#define set_slot_register(S,R,T) \ forceRegister(S, R, T)#define force_move_int(S, T, F) \ if ((T) != (F)) { \ set_slot_register(S, (T), Rint); \ do_move_int((T), (F)); \ F = (T); \ }#define safe_move_int(T, F) \ if ((T) != (F)) { \ clobberRegister(T); \ do_move_int((T), (F)); \ F = (T); \ }const char* rnames[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "flt0/dbl0" };#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 { \ profiler_click_t *__counter = &(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 { \ profiler_click_t *__counter = &(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; debug(("instr\t%s\n",__PRETTY_FUNCTION__)); if (profFlag) { debug(("Method: %s\n", globalMethod->name->data)); }#if defined(KAFFE_XPROFILER) if (xProfFlag) { /* Store the pointer to this function in eax */ OUT(0xB8|REG_eax); l = (label*)KaffeJIT3_newLabel(); l->type = Llong|Linternal|Labsolute; l->to = 0; l->at = (uintp)CODEPC; LOUT(0); debug(("movl #?,eax\n")); /* Push second arg to profileArcHit */ OUT(0x50|REG_eax); debug(("pushl eax\n")); /* Get return address from the stack */ OUT(0x8B); OUT((REG_eax<<3)|0x44); OUT(0x24); OUT(0x04); debug(("movl eax,4(esp)\n")); /* Push first arg to profileArcHit */ OUT(0x50|REG_eax); debug(("pushl eax\n")); /* Load the address to profileArcHit */ OUT(0xB8|REG_eax); LOUT((int)profileArcHit); debug(("movl profileArcHit,eax\n")); /* Make the call */ OUT(0xFF); OUT(0xD0|REG_eax); debug(("call profileArcHit\n")); /* Pop the args off */ OUT(0x58|REG_eax); debug(("popl eax\n")); OUT(0x58|REG_eax); debug(("popl eax\n")); }#endif 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 defined (HAVE_GCJ_SUPPORT)#include "gcj/gcj.h"/* * Establish JIT3 callee-saved register information for i386 * We must tell gcj where esi, edi, and ebx have been stored * on this frame, as an offset from the CFA. * In addition, we must tell it where the caller's esp was stored * * This depends on prologue_xxx so I put it here (XXX?). */voidarch_get_frame_description(int framesize, struct kaffe_frame_descriptor frame_desc[], int *n){ int i = 0; int rsave_area_offset = CFA_OFFSET + framesize; frame_desc[i].idx = DWARF_FRAME_RETURN_COLUMN; frame_desc[i].offset = RETADDR_SAVED_OFFSET; i++; frame_desc[i].idx = CFA_REGISTER; /* gcc_esp */ frame_desc[i].offset = CFA_SAVED_OFFSET; i++; if (framesize == -1) { /* -1 indicates trampoline frame */ *n = i; return; } /* NB: since CFA is pointing at caller's ret pc + 4, * subtracting CFA_OFFSET + framesize points at the last * slot. The callee-saved registers are stored one word * below, hence the 1 * 4 */ frame_desc[i].idx = DBX_REGISTER_NUMBER(/* gcc_edi */ 5); frame_desc[i].offset = - (rsave_area_offset + 1 * 4); i++; frame_desc[i].idx = DBX_REGISTER_NUMBER(/* gcc_esi */ 4); frame_desc[i].offset = - (rsave_area_offset + 2 * 4); i++; frame_desc[i].idx = DBX_REGISTER_NUMBER(/* gcc_ebx */ 3); frame_desc[i].offset = - (rsave_area_offset + 3 * 4); i++; *n = i;}#endif /* HAVE_GCJ_SUPPORT */define_insn(check_stack_limit, check_stack_limit_xRC){ int r = rreg_int(1); label* l = const_label(2); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); OUT(0x39); OUT(0xC0|(r<<3)|REG_esp); debug(("cmpl esp,%s\n", regname(r))); OUT(0x0F); OUT(0x87); LOUT(5); debug(("jugt +5\n")); OUT(0xE8); l->type |= Llong|Lrelative; l->at = CODEPC; LOUT(0); l->from = CODEPC; debug(("call soft_stackoverflow\n"));}define_insn(exception_prologue, eprologue_xLx){ label* l; debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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){ label *el; debug(("instr\t%s\n",__PRETTY_FUNCTION__)); if( (el = KaffeJIT3_getLastEpilogueLabel()) && (el->at == (CODEPC - 4)) ) { /* * Nothing to jump over to get to the epilogue... Replace * the jump code with regular epilogue. */ el->type = Lnull; CODEPC -= 5; } else if( el && (el->at != (CODEPC - 4)) ) { /* The function ends with a throw, not a return. */ } KaffeJIT3_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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); (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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); (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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); OUT(0xDD); OUT(0x80|REG_ebp); LOUT(o); debug(("fldl %d(ebp) %d\n", o, r));}voidmovereg_RR(int toreg, int fromreg){ do_move_int(toreg, fromreg);}/* --------------------------------------------------------------------- */define_insn(move_int_const, move_RxC){ int val = const_int(2); int w = wreg_int(0); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); OUT(0xB8|w); l->type |= Llong|Labsolute; l->at = CODEPC; LOUT(0); debug(("movl #%s,%s\n", KaffeJIT3_getLabelName(l), regname(w)));}define_insn(move_int, move_RxR){ int r = rreg_int(2); int w = wreg_int(0); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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; debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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; debug(("instr\t%s\n",__PRETTY_FUNCTION__)); 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); debug(("instr\t%s\n",__PRETTY_FUNCTION__)); if (or != ow) { wreg_double(0); OUT(0xDD); OUT(0x80|REG_ebp); LOUT(or);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -