-/* vm/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-2005, 2006 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
+ Copyright (C) 1996-2005, 2006, 2007
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
- Reinhard Grafl
-
- Changes: Christian Thalinger
-
- $Id: codegen.h 4722 2006-04-03 15:36:00Z twisti $
-
*/
#include "config.h"
#include "vm/types.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* additional functions and macros to generate code ***************************/
-/* gen_nullptr_check(objreg) */
-
-#define gen_nullptr_check(objreg) \
- if (checknull) { \
- M_BEQZ((objreg), 0); \
- codegen_add_nullpointerexception_ref(cd, mcodeptr); \
- }
-
#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, mcodeptr, s2); \
+ codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
}
/* MCODECHECK(icnt) */
#define MCODECHECK(icnt) \
- if ((mcodeptr + (icnt)) > cd->mcodeend) \
- mcodeptr = codegen_increase(cd, (u1 *) mcodeptr)
+ do { \
+ if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
+ codegen_increase(cd); \
+ } while (0)
#define ALIGNCODENOP \
- if ((s4) ((ptrint) mcodeptr & 7)) { \
+ 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) if (a != b) { M_MOV(a, b); }
-
+#define ICONST(d,c) emit_iconst(cd, (d), (c))
+#define LCONST(d,c) emit_lconst(cd, (d), (c))
-/* 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 M_FLTMOVE(a,b) if (a != b) { M_FMOV(a, b); }
+/* branch defines *************************************************************/
-/* var_to_reg_xxx **************************************************************
+#define BRANCH_NOPS \
+ do { \
+ M_NOP; \
+ } while (0)
- This function generates code to fetch data from a pseudo-register
- into a real register. If the pseudo-register has actually been
- assigned to a real register, no code will be emitted, since
- following operations can use this register directly.
-
- v: pseudoregister to be fetched from
- tempregnum: temporary register to be used if v is actually spilled to ram
- return: the register number, where the operand can be found after
- fetching (this wil be either tempregnum or the register
- number allready given to v)
+/* patcher defines ************************************************************/
-*******************************************************************************/
+#define PATCHER_CALL_SIZE 1 * 4 /* an instruction is 4-bytes long */
-#define var_to_reg_int(regnr,v,tempnr) \
+#define PATCHER_NOPS \
do { \
- if ((v)->flags & INMEMORY) { \
- COUNT_SPILLS; \
- M_LLD(tempnr, REG_SP, (v)->regoff * 8); \
- regnr = tempnr; \
- } else { \
- regnr = (v)->regoff; \
- } \
+ M_NOP; \
} while (0)
-#define var_to_reg_flt(regnr,v,tempnr) \
- do { \
- if ((v)->flags & INMEMORY) { \
- COUNT_SPILLS; \
- M_DLD(tempnr, REG_SP, (v)->regoff * 8); \
- regnr = tempnr; \
- } else { \
- regnr = (v)->regoff; \
- } \
- } while (0)
-
+/* macros to create code ******************************************************/
-/* store_reg_to_var_xxx ********************************************************
+/* M_MEM - memory instruction format *******************************************
- This function generates the code to store the result of an
- operation back into a spilled pseudo-variable. If the
- pseudo-variable has not been spilled in the first place, this
- function will generate nothing.
-
- v ............ Pseudovariable
- tempregnum ... Number of the temporary registers as returned by
- reg_of_var.
+ 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 store_reg_to_var_int(sptr, tempregnum) \
+#define M_MEM(Opcode,Ra,Rb,Memory_disp) \
do { \
- if ((sptr)->flags & INMEMORY) { \
- COUNT_SPILLS; \
- M_LST(tempregnum, REG_SP, (sptr)->regoff * 8); \
- } \
+ *((uint32_t *) cd->mcodeptr) = ((((Opcode)) << 26) | ((Ra) << 21) | ((Rb) << 16) | ((Memory_disp) & 0xffff)); \
+ cd->mcodeptr += 4; \
} while (0)
-#define store_reg_to_var_flt(sptr, tempregnum) \
- do { \
- if ((sptr)->flags & INMEMORY) { \
- COUNT_SPILLS; \
- M_DST(tempregnum, REG_SP, (sptr)->regoff * 8); \
- } \
- } 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))
-#define M_COPY(from,to) \
- d = codegen_reg_of_var(rd, iptr->opc, (to), REG_IFTMP); \
- if ((from->regoff != to->regoff) || \
- ((from->flags ^ to->flags) & INMEMORY)) { \
- if (IS_FLT_DBL_TYPE(from->type)) { \
- var_to_reg_flt(s1, from, d); \
- M_FLTMOVE(s1,d); \
- store_reg_to_var_flt(to, d); \
- } else { \
- var_to_reg_int(s1, from, d); \
- M_INTMOVE(s1,d); \
- store_reg_to_var_int(to, d); \
- } \
- }
-
-#define ICONST(r,c) \
- if ((c) >= -32768 && (c) <= 32767) { \
- M_LDA_INTERN((r), REG_ZERO, c); \
- } else { \
- disp = dseg_adds4(cd, (c)); \
- M_ILD((r), REG_PV, disp); \
- }
+/* M_BRA - branch instruction format *******************************************
-#define LCONST(r,c) \
- if ((c) >= -32768 && (c) <= 32767) { \
- M_LDA_INTERN((r), REG_ZERO, (c)); \
- } else { \
- disp = dseg_adds8(cd, (c)); \
- M_LLD((r), REG_PV, disp); \
- }
+ 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)
-/* macros to create code ******************************************************/
#define REG 0
#define CONST 1
*/
#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)
+
+#define M_OP3_GET_Opcode(x) ( (((x) >> 26) & 0x3f ))
/* 3-address-floating-point-operation: M_FOP3
*/
#define M_FOP3(op,fu,a,b,c) \
- *(mcodeptr++) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << 16) | ((fu) << 5) | (c))
-
-
-/* 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))
-
-
-/* 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))
+ do { \
+ *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << 16) | ((fu) << 5) | (c)); \
+ cd->mcodeptr += 4; \
+ } while (0)
/* macros for all used commands (see an Alpha-manual for description) *********/
} \
} 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_ALD_DSEG(a,disp) M_LLD(a,REG_PV,disp)
#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_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_FCMPLTS(a,b,c) M_FOP3 (0x16, 0x5a6, a,b,c) /* c = a<b */
#define M_FMOV(fa,fb) M_FOP3 (0x17, 0x020, fa,fa,fb) /* b = a */
+#define M_DMOV(fa,fb) M_FMOV (fa,fb)
#define M_FMOVN(fa,fb) M_FOP3 (0x17, 0x021, fa,fa,fb) /* b = -a */
#define M_FNOP M_FMOV (31,31)
#define M_FBEQZ(fa,disp) M_BRA (0x31,fa,disp) /* br a == 0.0*/
-/* macros for special commands (see an Alpha-manual for description) **********/
+/* macros for special commands (see an Alpha-manual for description) **********/
#define M_TRAPB M_MEM (0x18,0,0,0x0000) /* trap barrier*/
#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) ***********/
+// 0x04 seems to be the first undefined instruction which does not
+// call PALcode.
+#define M_UNDEFINED M_OP3(0x04, 0, 0, 0, 0, 0)
+
+/* 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 */
#define M_JMP_CO(a,b) M_MEM (0x1a,a,b,0xc000) /* call cosub */
-
-/* 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
-
#endif /* _CODEGEN_H */