X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Falpha%2Fcodegen.h;h=c43ba7b6d56574ea5e20fd3e402a99be17f594a3;hb=3a349bb476c3a52fa3271f8582488efb2c9aec20;hp=1de6507bbc5d95324f0c5203455a2e5c266d22dd;hpb=d9ffca83d2dd62603d14b9973cc3008b98e1aa0d;p=cacao.git diff --git a/src/vm/jit/alpha/codegen.h b/src/vm/jit/alpha/codegen.h index 1de6507bb..c43ba7b6d 100644 --- a/src/vm/jit/alpha/codegen.h +++ b/src/vm/jit/alpha/codegen.h @@ -1,10 +1,9 @@ -/* jit/alpha/codegen.h - code generation macros and definitions for alpha +/* src/vm/jit/alpha/codegen.h - code generation macros and definitions for Alpha - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 - Institut f. Computersprachen, TU Wien - R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, - M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, - P. Tomsich, J. Wenninger + Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, + C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, + E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, + J. Wenninger, Institut f. Computersprachen - TU Wien This file is part of CACAO. @@ -20,15 +19,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. - - Contact: cacao@complang.tuwien.ac.at - - Authors: Andreas Krall - Reinhard Grafl - - $Id: codegen.h 899 2004-01-22 13:24:36Z twisti $ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ @@ -36,50 +28,127 @@ #ifndef _CODEGEN_H #define _CODEGEN_H -#include "jit.h" +#include "config.h" +#include "vm/types.h" + +#include "vm/jit/jit.h" + + +/* additional functions and macros to generate code ***************************/ + +#define gen_bound_check \ + if (checkbounds) { \ + M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\ + M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\ + M_BEQZ(REG_ITMP3, 0);\ + codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \ + } -/* see also file calling.doc for explanation of calling conventions */ +/* MCODECHECK(icnt) */ -/* preallocated registers *****************************************************/ +#define MCODECHECK(icnt) \ + do { \ + if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \ + codegen_increase(cd); \ + } while (0) -/* integer registers */ - -#define REG_RESULT 0 /* to deliver method results */ -#define REG_RA 26 /* return address */ -#define REG_PV 27 /* procedure vector, must be provided by caller */ -#define REG_METHODPTR 28 /* pointer to the place from where the procedure */ - /* vector has been fetched */ -#define REG_ITMP1 25 /* temporary register */ -#define REG_ITMP2 28 /* temporary register and method pointer */ -#define REG_ITMP3 29 /* temporary register */ +#define ALIGNCODENOP \ + if ((s4) ((ptrint) cd->mcodeptr & 7)) { \ + M_NOP; \ + } + + +/* M_INTMOVE: + generates an integer-move from register a to b. + if a and b are the same int-register, no code will be generated. +*/ + +#define M_INTMOVE(a,b) \ + do { \ + if ((a) != (b)) \ + M_MOV(a, b); \ + } while (0) + + +/* M_FLTMOVE: + generates a floating-point-move from register a to b. + if a and b are the same float-register, no code will be generated +*/ -#define REG_ITMP1_XPTR 25 /* exception pointer = temporary register 1 */ -#define REG_ITMP2_XPC 28 /* exception pc = temporary register 2 */ +#define M_FLTMOVE(a,b) \ + do { \ + if ((a) != (b)) \ + M_FMOV(a, b); \ + } while (0) -#define REG_SP 30 /* stack pointer */ -#define REG_ZERO 31 /* allways zero */ -/* floating point registers */ +#define ICONST(d,c) emit_iconst(cd, (d), (c)) +#define LCONST(d,c) emit_lconst(cd, (d), (c)) -#define REG_FRESULT 0 /* to deliver floating point method results */ -#define REG_FTMP1 28 /* temporary floating point register */ -#define REG_FTMP2 29 /* temporary floating point register */ -#define REG_FTMP3 30 /* temporary floating point register */ -#define REG_IFTMP 28 /* temporary integer and floating point register */ +/* branch defines *************************************************************/ +#define BRANCH_NOPS \ + do { \ + M_NOP; \ + } while (0) -#define INT_SAV_CNT 7 /* number of int callee saved registers */ -#define INT_ARG_CNT 6 /* number of int argument registers */ -#define FLT_SAV_CNT 8 /* number of flt callee saved registers */ -#define FLT_ARG_CNT 6 /* number of flt argument registers */ +/* patcher defines ************************************************************/ + +#define PATCHER_CALL_SIZE 1 * 4 /* an instruction is 4-bytes long */ + +#define PATCHER_NOPS \ + do { \ + M_NOP; \ + } while (0) + + +/* stub defines ***************************************************************/ + +#define COMPILERSTUB_CODESIZE 1 * 4 /* macros to create code ******************************************************/ +/* M_MEM - memory instruction format ******************************************* + + Opcode ........ opcode + Ra ............ source/target register for memory access + Rb ............ base register + Memory_disp ... memory displacement (16 bit signed) to be added to Rb + +*******************************************************************************/ + +#define M_MEM(Opcode,Ra,Rb,Memory_disp) \ + do { \ + *((uint32_t *) cd->mcodeptr) = ((((Opcode)) << 26) | ((Ra) << 21) | ((Rb) << 16) | ((Memory_disp) & 0xffff)); \ + cd->mcodeptr += 4; \ + } while (0) + +#define M_MEM_GET_Opcode(x) ( (((x) >> 26) & 0x3f )) +#define M_MEM_GET_Ra(x) ( (((x) >> 21) & 0x1f )) +#define M_MEM_GET_Rb(x) ( (((x) >> 16) & 0x1f )) +#define M_MEM_GET_Memory_disp(x) ((int16_t) ( (x) & 0xffff)) + + +/* M_BRA - branch instruction format ******************************************* + + Opcode ........ opcode + Ra ............ register to be tested + Branch_disp ... relative address to be jumped to (divided by 4) + +*******************************************************************************/ + +#define M_BRA(Opcode,Ra,Branch_disp) \ + do { \ + *((uint32_t *) cd->mcodeptr) = ((((Opcode)) << 26) | ((Ra) << 21) | ((Branch_disp) & 0x1fffff)); \ + cd->mcodeptr += 4; \ + } while (0) + + #define REG 0 #define CONST 1 @@ -93,9 +162,13 @@ (REG means: use b as register number) (CONST means: use b as constant 8-bit-integer) */ + #define M_OP3(op,fu,a,b,c,const) \ - *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \ - ((const)<<12)|((fu)<<5)|((c)) ) + do { \ + *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << (16 - 3 * (const))) | ((const) << 12) | ((fu) << 5) | ((c))); \ + cd->mcodeptr += 4; \ + } while (0) + /* 3-address-floating-point-operation: M_FOP3 op .... opcode @@ -103,42 +176,100 @@ a,b ... source floating-point registers c ..... destination register */ + #define M_FOP3(op,fu,a,b,c) \ - *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) ) + do { \ + *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << 16) | ((fu) << 5) | (c)); \ + cd->mcodeptr += 4; \ + } while (0) -/* branch instructions: M_BRA - op ..... opcode - a ...... register to be tested - disp ... relative address to be jumped to (divided by 4) -*/ -#define M_BRA(op,a,disp) \ - *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) ) +/* macros for all used commands (see an Alpha-manual for description) *********/ -/* memory operations: M_MEM - op ..... opcode - a ...... source/target register for memory access - b ...... base register - disp ... displacement (16 bit signed) to be added to b -*/ -#define M_MEM(op,a,b,disp) \ - *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) ) - +#define M_LDA_INTERN(a,b,disp) M_MEM(0x08,a,b,disp) /* low const */ -/* macros for all used commands (see an Alpha-manual for description) *********/ +#define M_LDA(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_LDA_INTERN(a,b,lo); \ + } else { \ + M_LDAH(a,b,hi); \ + M_LDA_INTERN(a,a,lo); \ + } \ + } while (0) -#define M_LDA(a,b,disp) M_MEM (0x08,a,b,disp) /* low const */ #define M_LDAH(a,b,disp) M_MEM (0x09,a,b,disp) /* high const */ + #define M_BLDU(a,b,disp) M_MEM (0x0a,a,b,disp) /* 8 load */ #define M_SLDU(a,b,disp) M_MEM (0x0c,a,b,disp) /* 16 load */ -#define M_ILD(a,b,disp) M_MEM (0x28,a,b,disp) /* 32 load */ -#define M_LLD(a,b,disp) M_MEM (0x29,a,b,disp) /* 64 load */ -#define M_ALD(a,b,disp) M_MEM (0x29,a,b,disp) /* addr load */ -#define M_BST(a,b,disp) M_MEM (0x0e,a,b,disp) /* 8 store */ -#define M_SST(a,b,disp) M_MEM (0x0d,a,b,disp) /* 16 store */ -#define M_IST(a,b,disp) M_MEM (0x2c,a,b,disp) /* 32 store */ -#define M_LST(a,b,disp) M_MEM (0x2d,a,b,disp) /* 64 store */ -#define M_AST(a,b,disp) M_MEM (0x2d,a,b,disp) /* addr store */ + +#define M_ILD_INTERN(a,b,disp) M_MEM(0x28,a,b,disp) /* 32 load */ +#define M_LLD_INTERN(a,b,disp) M_MEM(0x29,a,b,disp) /* 64 load */ + +#define M_ILD(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_ILD_INTERN(a,b,lo); \ + } else { \ + M_LDAH(a,b,hi); \ + M_ILD_INTERN(a,a,lo); \ + } \ + } while (0) + +#define M_LLD(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_LLD_INTERN(a,b,lo); \ + } else { \ + M_LDAH(a,b,hi); \ + M_LLD_INTERN(a,a,lo); \ + } \ + } while (0) + +#define M_ALD_INTERN(a,b,disp) M_LLD_INTERN(a,b,disp) +#define M_ALD(a,b,disp) M_LLD(a,b,disp) /* addr load */ + +#define M_BST(a,b,disp) M_MEM(0x0e,a,b,disp) /* 8 store */ +#define M_SST(a,b,disp) M_MEM(0x0d,a,b,disp) /* 16 store */ + +#define M_IST_INTERN(a,b,disp) M_MEM(0x2c,a,b,disp) /* 32 store */ +#define M_LST_INTERN(a,b,disp) M_MEM(0x2d,a,b,disp) /* 64 store */ + +/* Stores with displacement overflow should only happen with PUTFIELD or on */ +/* the stack. The PUTFIELD instruction does not use REG_ITMP3 and a */ +/* reg_of_var call should not use REG_ITMP3!!! */ + +#define M_IST(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_IST_INTERN(a,b,lo); \ + } else { \ + M_LDAH(REG_ITMP3,b,hi); \ + M_IST_INTERN(a,REG_ITMP3,lo); \ + } \ + } while (0) + +#define M_LST(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_LST_INTERN(a,b,lo); \ + } else { \ + M_LDAH(REG_ITMP3,b,hi); \ + M_LST_INTERN(a,REG_ITMP3,lo); \ + } \ + } while (0) + +#define M_AST(a,b,disp) M_LST(a,b,disp) /* addr store */ #define M_BSEXT(b,c) M_OP3 (0x1c,0x0,REG_ZERO,b,c,0) /* 8 signext */ #define M_SSEXT(b,c) M_OP3 (0x1c,0x1,REG_ZERO,b,c,0) /* 16 signext */ @@ -170,6 +301,9 @@ #define M_IMUL_IMM(a,b,c) M_OP3 (0x13,0x00, a,b,c,1) /* 32 mul */ #define M_LMUL_IMM(a,b,c) M_OP3 (0x13,0x20, a,b,c,1) /* 64 mul */ +#define M_AADD_IMM(a,b,c) M_LADD_IMM(a,b,c) +#define M_ASUB_IMM(a,b,c) M_LSUB_IMM(a,b,c) + #define M_CMPEQ(a,b,c) M_OP3 (0x10,0x2d, a,b,c,0) /* c = a == b */ #define M_CMPLT(a,b,c) M_OP3 (0x10,0x4d, a,b,c,0) /* c = a < b */ #define M_CMPLE(a,b,c) M_OP3 (0x10,0x6d, a,b,c,0) /* c = a <= b */ @@ -204,10 +338,64 @@ #define M_SRA_IMM(a,b,c) M_OP3 (0x12,0x3c, a,b,c,1) /* c = a >> b */ #define M_SRL_IMM(a,b,c) M_OP3 (0x12,0x34, a,b,c,1) /* c = a >>>b */ -#define M_FLD(a,b,disp) M_MEM (0x22,a,b,disp) /* load flt */ -#define M_DLD(a,b,disp) M_MEM (0x23,a,b,disp) /* load dbl */ -#define M_FST(a,b,disp) M_MEM (0x26,a,b,disp) /* store flt */ -#define M_DST(a,b,disp) M_MEM (0x27,a,b,disp) /* store dbl */ +#define M_FLD_INTERN(a,b,disp) M_MEM(0x22,a,b,disp) /* load flt */ +#define M_DLD_INTERN(a,b,disp) M_MEM(0x23,a,b,disp) /* load dbl */ + +#define M_FLD(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_FLD_INTERN(a,b,lo); \ + } else { \ + M_LDAH(REG_ITMP3,b,hi); \ + M_FLD_INTERN(a,REG_ITMP3,lo); \ + } \ + } while (0) + +#define M_DLD(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_DLD_INTERN(a,b,lo); \ + } else { \ + M_LDAH(REG_ITMP3,b,hi); \ + M_DLD_INTERN(a,REG_ITMP3,lo); \ + } \ + } while (0) + +#define M_FST_INTERN(a,b,disp) M_MEM(0x26,a,b,disp) /* store flt */ +#define M_DST_INTERN(a,b,disp) M_MEM(0x27,a,b,disp) /* store dbl */ + +/* Stores with displacement overflow should only happen with PUTFIELD or on */ +/* the stack. The PUTFIELD instruction does not use REG_ITMP3 and a */ +/* reg_of_var call should not use REG_ITMP3!!! */ + +#define M_FST(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_FST_INTERN(a,b,lo); \ + } else { \ + M_LDAH(REG_ITMP3,b,hi); \ + M_FST_INTERN(a,REG_ITMP3,lo); \ + } \ + } while (0) + +#define M_DST(a,b,disp) \ + do { \ + s4 lo = (short) (disp); \ + s4 hi = (short) (((disp) - lo) >> 16); \ + if (hi == 0) { \ + M_DST_INTERN(a,b,lo); \ + } else { \ + M_LDAH(REG_ITMP3,b,hi); \ + M_DST_INTERN(a,REG_ITMP3,lo); \ + } \ + } while (0) + #define M_FADD(a,b,c) M_FOP3 (0x16, 0x080, a,b,c) /* flt add */ #define M_DADD(a,b,c) M_FOP3 (0x16, 0x0a0, a,b,c) /* dbl add */ @@ -351,7 +539,7 @@ #define M_CMOVLE_IMM(a,b,c) M_OP3 (0x11,0x64, a,b,c,1) /* a<=0 ? c=b */ #define M_CMOVGT_IMM(a,b,c) M_OP3 (0x11,0x66, a,b,c,1) /* a> 0 ? c=b */ -/* macros for unused commands (see an Alpha-manual for description) ***********/ +/* macros for unused commands (see an Alpha-manual for description) ***********/ #define M_ANDNOT(a,b,c,const) M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b */ #define M_ORNOT(a,b,c,const) M_OP3 (0x11,0x28, a,b,c,const) /* c = a |~ b */ @@ -370,31 +558,6 @@ #define M_JMP_CO(a,b) M_MEM (0x1a,a,b,0xc000) /* call cosub */ - -/* function gen_resolvebranch ************************************************** - - backpatches a branch instruction; Alpha branch instructions are very - regular, so it is only necessary to overwrite some fixed bits in the - instruction. - - parameters: ip ... pointer to instruction after branch (void*) - so ... offset of instruction after branch (s4) - to ... offset of branch target (s4) - -*******************************************************************************/ - -#define gen_resolvebranch(ip,so,to) ((s4*)(ip))[-1]|=((s4)(to)-(so))>>2&0x1fffff - -#define SOFTNULLPTRCHECK /* soft null pointer check supportet as option */ - -/* function prototypes */ - -void codegen_init(); -void init_exceptions(); -void codegen(); -void codegen_close(); -void dseg_display(s4 *s4ptr); - #endif /* _CODEGEN_H */