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 + -
显示快捷键?