jitemitter_cpu.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,543 行 · 第 1/5 页
C
2,543 行
/* * * @(#)jitemitter_cpu.c 1.6 06/10/04 * * Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights * Reserved. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include "javavm/include/defs.h"#include "javavm/include/objects.h"#include "javavm/include/utils.h"#include "javavm/include/globals.h"#include "javavm/include/interpreter.h"#include "javavm/include/ccm_runtime.h"#include "javavm/include/ccee.h"#include "javavm/include/jit/jit.h"#include "javavm/include/jit/jitcontext.h"#include "javavm/include/jit/jitutils.h"#include "javavm/include/jit/jitmemory.h"#include "javavm/include/jit/jitstats.h"#include "javavm/include/jit/jitcomments.h"#include "javavm/include/jit/jitirnode.h"#include "javavm/include/jit/jitarchemitter.h"#include "javavm/include/jit/ccmcisc.h"#include "javavm/include/jit/jitregman.h"#include "javavm/include/jit/jitconstantpool.h"#include "javavm/include/jit/jitcodebuffer.h"#include "javavm/include/jit/jitpcmap.h"#include "javavm/include/jit/jitfixup.h"#include "javavm/include/jit/jitstackmap.h"#include "javavm/include/porting/doubleword.h"#include "javavm/include/porting/jit/jit.h"#include "javavm/include/clib.h"#include "javavm/include/float_arch.h"#include "javavm/include/bag.h"struct CVMCPUALURhsTokenStruct CVMCPUALURhsTokenStructConstZero = {CVMCPU_ALURHS_CONSTANT, 0, CVMCPU_INVALID_REG};/* ------------------- x86 assembler implementation ---------------------- */#ifdef CVM_TRACE_JIT/* some headers of functions the assembler uses for tracing */static void printPC(CVMJITCompilationContext* con);static void getRegName(char *buf, int regID);static void getcc(char *buf, CVMX86Condition cc);static void printAddress(CVMX86Address addr);#endif /* CVM_TRACE_JIT */static int CVMX86RegEnc[16] = {0,2,3,1,4,5,6,7,8,9,10,11,12,13,14,15};#define CVMX86is8bit(x) (-0x80 <= (x) && (x) < 0x80)#define CVMX86isByte(x) (0 <= (x) && (x) < 0x100)#define CVMX86isWord(x) (-0x8000 <= (x) && (x) < 0x8000)#define CVMX86is_valid(reg) (0 <= (int)reg && (int)reg <= CVMCPU_MAX_INTERESTING_REG)#define CVMX86RegisterEncoding(reg) CVMX86RegEnc[reg]#define CVMX86encoding(reg) (CVMassert(CVMX86is_valid(reg) /* invalid register */), CVMX86RegisterEncoding(reg) )/* only eax, ebx, ecx, and edx can be used as byte registers */#define CVMX86has_byte_register(reg) (0 <= (int)reg && (int)reg <= CVMX86_ECX)#define CVMX86isShiftCount(x) (0 <= (x) && (x) < 32)CVMBoolCVMCPUAddress_uses(CVMCPUAddress addr, CVMCPURegister reg){ return addr._base == reg || addr._index == reg;}CVMCPUAddress*CVMCPUinit_Address(CVMCPUAddress *addr, CVMCPUMemSpecType type){ addr->_base = CVMX86no_reg; addr->_index = CVMX86no_reg; addr->_scale = CVMX86no_scale; addr->_disp = 0; addr->_type = type; return addr;}CVMCPUAddress*CVMCPUinit_Address_disp(CVMCPUAddress *addr, int disp, CVMCPUMemSpecType type){ addr->_base = CVMX86no_reg; addr->_index = CVMX86no_reg; addr->_scale = CVMX86no_scale; addr->_disp = disp; addr->_type = type; return addr;}CVMCPUAddress*CVMCPUinit_Address_base_disp(CVMCPUAddress *addr, CVMCPURegister base, int disp, CVMCPUMemSpecType type){ addr->_base = base; addr->_index = CVMX86no_reg; addr->_scale = CVMX86no_scale; addr->_disp = disp; addr->_type = type; return addr;}CVMCPUAddress*CVMCPUinit_Address_base_memspec(CVMX86Address *addr, CVMX86Register base, CVMCPUMemSpec *ms){ addr->_base = base; if (NULL != ms->offsetReg) addr->_index = CVMRMgetRegisterNumber(ms->offsetReg); else addr->_index = CVMX86no_reg; addr->_disp = ms->offsetValue; addr->_scale = ms->scale; addr->_type = ms->type; return addr;}CVMCPUAddress*CVMCPUinit_Address_base_memspectoken(CVMCPUAddress *addr, CVMCPURegister base, CVMCPUMemSpecToken mst){ addr->_base = base; addr->_index = mst->regid; addr->_disp = mst->offset; addr->_scale = mst->scale; addr->_type = mst->type; return addr;}CVMCPUAddress*CVMCPUinit_Address_base_idx_scale_disp(CVMCPUAddress* addr, CVMCPURegister base, CVMCPURegister index, CVMCPUScaleFactor scale, int disp /* = 0 */, CVMCPUMemSpecType type){ addr->_base = base; addr->_index = index; addr->_scale = scale; addr->_disp = disp; addr->_type = type; CVMassert(!CVMX86is_valid(index) == (scale == CVMX86no_scale) /* inconsistent address */ ); return addr;}void CVMX86emit_byte(CVMJITCompilationContext* con, int x){ CVMassert(CVMX86isByte(x) /* not a byte */); CVMJITcbufEmit1(con, x);}/* `word' is 16 bit in x86 language */void CVMX86emit_word(CVMJITCompilationContext* con, int x){ CVMassert(CVMX86isWord(x) /* not a word */); CVMJITcbufEmit2(con, x);}void CVMX86emit_long(CVMJITCompilationContext* con, CVMInt32 x){ CVMJITcbufEmit4(con, x);}void CVMX86emit_data(CVMJITCompilationContext* con, CVMInt32 data) { /* CVMassert(imm32_operand == 0, "default format must be imm32 in this file"); CVMassert(_inst_mark != NULL, "must be inside InstructionMark"); */ CVMX86emit_long(con, data);}void CVMX86emit_arith_reg_imm8(CVMJITCompilationContext* con, int op1, int op2, CVMX86Register dst, int imm8) { /* CVMassert(dst->has_byte_register(), "must have byte register"); */ CVMassert(CVMX86isByte(op1) && CVMX86isByte(op2) /* wrong opcode */); CVMassert(CVMX86isByte(imm8) /* not a byte */); CVMassert((op1 & 0x01) == 0 /* should be 8bit operation */); CVMX86emit_byte(con, op1); CVMX86emit_byte(con, op2 | CVMX86encoding(dst)); CVMX86emit_byte(con, imm8);}static void CVMX86emit_arith_reg_imm32(CVMJITCompilationContext* con, int op1, int op2, CVMX86Register dst, int imm32 ) { CVMassert(CVMX86isByte(op1) && CVMX86isByte(op2) /* wrong opcode */); CVMassert((op1 & 0x01) == 1 /* should be 32bit operation */); CVMassert((op1 & 0x02) == 0 /* sign-extension bit should not be set */); if (CVMX86is8bit(imm32)) { CVMX86emit_byte(con, op1 | 0x02); // set sign bit CVMX86emit_byte(con, op2 | CVMX86encoding(dst)); CVMX86emit_byte(con, imm32 & 0xFF); } else { CVMX86emit_byte(con, op1); CVMX86emit_byte(con, op2 | CVMX86encoding(dst)); CVMX86emit_long(con, imm32); }}void CVMX86emit_arith_reg_reg(CVMJITCompilationContext* con, int op1, int op2, CVMX86Register dst, CVMX86Register src) { CVMassert(CVMX86isByte(op1) && CVMX86isByte(op2) /* wrong opcode */); CVMX86emit_byte(con, op1); CVMX86emit_byte(con, op2 | CVMX86encoding(dst) << 3 | CVMX86encoding(src));}static void CVMX86emit_operand(CVMJITCompilationContext* con, CVMX86Register reg, CVMX86Register base, CVMX86Register index, CVMX86ScaleFactor scale, int disp, CVMBool fixed_length ) { if (CVMX86is_valid(base)) { if (CVMX86is_valid(index)) { CVMassert(scale != CVMX86no_scale /* inconsistent address */); /* [base + index*scale + disp] */ if (disp == 0 && fixed_length != CVM_TRUE) { /* [base + index*scale] [00 reg 100][ss index base] */ CVMassert(index != CVMX86esp && base != CVMX86ebp /* illegal addressing mode */); CVMX86emit_byte(con, 0x04 | CVMX86encoding(reg) << 3); CVMX86emit_byte(con, scale << 6 | CVMX86encoding(index) << 3 | CVMX86encoding(base)); } else if (CVMX86is8bit(disp) && fixed_length != CVM_TRUE) { /* [base + index*scale + imm8] [01 reg 100][ss index base] imm8 */ CVMassert(index != CVMX86esp /* illegal addressing mode */); CVMX86emit_byte(con, 0x44 | CVMX86encoding(reg) << 3); CVMX86emit_byte(con, scale << 6 | CVMX86encoding(index) << 3 | CVMX86encoding(base)); CVMX86emit_byte(con, disp & 0xFF); } else { /* [base + index*scale + imm32] [10 reg 100][ss index base] imm32 */ CVMassert(index != CVMX86esp /* illegal addressing mode */); CVMX86emit_byte(con, 0x84 | CVMX86encoding(reg) << 3); CVMX86emit_byte(con, scale << 6 | CVMX86encoding(index) << 3 | CVMX86encoding(base)); CVMX86emit_data(con, disp); } } else if (base == CVMX86esp) { /* [esp + disp] */ if (disp == 0 && fixed_length != CVM_TRUE) { /* [esp] [00 reg 100][00 100 100] */ CVMX86emit_byte(con, 0x04 | CVMX86encoding(reg) << 3); CVMX86emit_byte(con, 0x24); } else if (CVMX86is8bit(disp) && fixed_length != CVM_TRUE) { /* [esp + imm8] [01 reg 100][00 100 100] imm8 */ CVMX86emit_byte(con, 0x44 | CVMX86encoding(reg) << 3); CVMX86emit_byte(con, 0x24); CVMX86emit_byte(con, disp & 0xFF); } else { /* [esp + imm32] [10 reg 100][00 100 100] imm32 */ CVMX86emit_byte(con, 0x84 | CVMX86encoding(reg) << 3); CVMX86emit_byte(con, 0x24); CVMX86emit_data(con, disp); } } else { // [base + disp] CVMassert(base != CVMX86esp /* "illegal addressing mode" */); if (disp == 0 && base != CVMX86ebp && fixed_length != CVM_TRUE) { /* [base] [00 reg base] */ CVMassert(base != CVMX86ebp /* illegal addressing mode */); CVMX86emit_byte(con, 0x00 | CVMX86encoding(reg) << 3 | CVMX86encoding(base)); } else if (CVMX86is8bit(disp) && fixed_length != CVM_TRUE) { /* [base + imm8] [01 reg base] imm8 */ CVMX86emit_byte(con, 0x40 | CVMX86encoding(reg) << 3 | CVMX86encoding(base)); CVMX86emit_byte(con, disp & 0xFF); } else { /* [base + imm32] [10 reg base] imm32 */ CVMX86emit_byte(con, 0x80 | CVMX86encoding(reg) << 3 | CVMX86encoding(base)); CVMX86emit_data(con, disp); } } } else { if (CVMX86is_valid(index)) { CVMassert(scale != CVMX86no_scale /* inconsistent address */); /* [index*scale + disp] [00 reg 100][ss index 101] imm32 */ CVMassert(index != CVMX86esp /* illegal addressing mode */); CVMX86emit_byte(con, 0x04 | CVMX86encoding(reg) << 3); CVMX86emit_byte(con, scale << 6 | CVMX86encoding(index) << 3 | 0x05); CVMX86emit_data(con, disp); } else { /* [disp] [00 reg 101] imm32 */ CVMX86emit_byte(con, 0x05 | CVMX86encoding(reg) << 3); CVMX86emit_data(con, disp); } }}static void CVMX86emit_operand_wrapper(CVMJITCompilationContext* con, CVMX86Register reg, CVMX86Address adr, CVMBool fixed_length ) { CVMX86emit_operand(con, reg, adr._base, adr._index, adr._scale, adr._disp, fixed_length);}void CVMX86emit_farith(CVMJITCompilationContext* con, int b1, int b2, int i) { CVMassert(CVMX86isByte(b1) && CVMX86isByte(b2) /* wrong opcode */); CVMassert(0 <= i && i < 8 /* illegal stack offset */); CVMX86emit_byte(con, b1); CVMX86emit_byte(con, b2 + i);}void CVMX86pushad(CVMJITCompilationContext* con) { CVMtraceJITCodegenExec({ printPC(con); CVMconsolePrintf(" pushad"); }); CVMX86emit_byte(con, 0x60); CVMJITdumpCodegenComments(con);}void CVMX86popad(CVMJITCompilationContext* con) { CVMtraceJITCodegenExec({ printPC(con); CVMconsolePrintf(" popad"); }); CVMX86emit_byte(con, 0x61); CVMJITdumpCodegenComments(con);}void CVMX86pushfd(CVMJITCompilationContext* con) { CVMtraceJITCodegenExec({ printPC(con); CVMconsolePrintf(" pushfd"); }); CVMX86emit_byte(con, 0x9C); CVMJITdumpCodegenComments(con);}void CVMX86popfd(CVMJITCompilationContext* con) { CVMtraceJITCodegenExec({ printPC(con); CVMconsolePrintf(" popfd"); }); CVMX86emit_byte(con, 0x9D); CVMJITdumpCodegenComments(con);}void CVMX86pushl_imm32(CVMJITCompilationContext* con, int imm32) { /* InstructionMark im(this); */ CVMtraceJITCodegenExec({ printPC(con); CVMconsolePrintf(" pushl $%d", imm32); }); CVMX86emit_byte(con, 0x68); CVMX86emit_data(con, imm32); CVMJITdumpCodegenComments(con);}void CVMX86pushl_reg(CVMJITCompilationContext* con, CVMX86Register src) { CVMtraceJITCodegenExec({ char srcRegBuf[30]; printPC(con); getRegName(srcRegBuf, src); CVMconsolePrintf(" pushl %s", srcRegBuf); }); CVMX86emit_byte(con, 0x50 | CVMX86encoding(src)); CVMJITdumpCodegenComments(con);}void CVMX86pushl_mem(CVMJITCompilationContext* con, CVMX86Address src) { /* InstructionMark im(this); */ CVMtraceJITCodegenExec({ printPC(con); CVMconsolePrintf(" pushl"); }); CVMX86emit_byte(con, 0xFF); CVMX86emit_operand_wrapper(con, CVMX86esi, src, CVM_FALSE); CVMJITdumpCodegenComments(con);}void CVMX86popl_reg(CVMJITCompilationContext* con, CVMX86Register dst) { CVMtraceJITCodegenExec({ char dstRegBuf[30]; printPC(con); getRegName(dstRegBuf, dst); CVMconsolePrintf(" popl %s", dstRegBuf); }); CVMX86emit_byte(con, 0x58 | CVMX86encoding(dst)); CVMJITdumpCodegenComments(con);}void CVMX86popl_mem(CVMJITCompilationContext* con, CVMX86Address dst) { /* InstructionMark im(this); */ CVMtraceJITCodegenExec({ printPC(con); CVMconsolePrintf(" popl"); }); CVMX86emit_byte(con, 0x8F); CVMX86emit_operand_wrapper(con, CVMX86eax, dst, CVM_FALSE); CVMJITdumpCodegenComments(con);}void CVMX86prefix(CVMJITCompilationContext* con, CVMX86Prefix p) { CVMX86emit_byte(con, p);}/* CVMX86prefixMode: emits opcode to switch between 16 bit and 32 bit mode*/static void CVMX86prefixMode( CVMJITCompilationContext * con ) { CVMX86prefix( con, 0x66 );} /* CVMX86prefixMode */void CVMX86movb_reg_mem(CVMJITCompilationContext* con, CVMX86Register dst, CVMX86Address src) { CVMassert(CVMX86has_byte_register(dst) /* must have byte register */); /* InstructionMark im(this); */ CVMtraceJITCodegenExec({ char destRegBuf[30]; printPC(con); getRegName(destRegBuf, dst); CVMconsolePrintf(" movb %s, ", destRegBuf); printAddress(src); }); CVMX86emit_byte(con, 0x8A); CVMX86emit_operand_wrapper(con, dst, src, CVM_FALSE); CVMJITdumpCodegenComments(con);}void CVMX86movb_mem_imm8(CVMJITCompilationContext* con, CVMX86Address dst, int imm8) { /* InstructionMark im(this); */ CVMtraceJITCodegenExec({ printPC(con); CVMconsolePrintf(" movb "); printAddress(dst); CVMconsolePrintf(", $%d", imm8); }); CVMX86emit_byte(con, 0xC6); CVMX86emit_operand_wrapper(con, CVMX86eax, dst, CVM_FALSE); CVMX86emit_byte(con, imm8); CVMJITdumpCodegenComments(con);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?