X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Farm%2Fcodegen.h;h=c18e324a9f6af1ea14d77d7470eb7a3dce93097a;hb=6adfad2e33417f2c885c460984cd150ca34bba9d;hp=5cca08322e78a37d9986d371280aeeeadc8913f6;hpb=e124e9a34bd8f6e16de7650f092eb941112d5f1a;p=cacao.git diff --git a/src/vm/jit/arm/codegen.h b/src/vm/jit/arm/codegen.h index 5cca08322..c18e324a9 100644 --- a/src/vm/jit/arm/codegen.h +++ b/src/vm/jit/arm/codegen.h @@ -1,9 +1,7 @@ /* src/vm/jit/arm/codegen.h - code generation macros and definitions for ARM - 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, 2008, 2010 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -22,13 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Contact: cacao@cacaojvm.org - - Authors: Michael Starzinger - Christian Thalinger - - $Id: codegen.h 6591 2007-01-02 19:14:25Z twisti $ - */ @@ -38,137 +29,64 @@ #include "config.h" -/* helper macros for generating code ******************************************/ - -/* load_var_to_reg_xxx: - 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 - tempnr: temporary register to be used if v is actually spilled to ram - regnr: the register number, where the operand can be found after - fetching (this wil be either tempregnum or the register - number allready given to v) -*/ +/******************************************************************************/ +/* register splitting stuff (ugly) ********************************************/ +/******************************************************************************/ #if defined(__ARMEL__) -#define load_var_to_reg_lng(regnr,v,tempnr) { \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - M_STACK_LOAD_LNG(tempnr, (v)->regoff); \ - regnr = tempnr; \ - } else if (GET_HIGH_REG((v)->regoff)==REG_SPLIT) { \ - M_LDR_INTERN(GET_HIGH_REG(tempnr), REG_SP, 0); /* TODO: where to load? */ \ - regnr = PACK_REGS(GET_LOW_REG((v)->regoff), GET_HIGH_REG(tempnr)); \ - } else regnr = (v)->regoff; \ -} -#else /* defined(__ARMEB__) */ -#define load_var_to_reg_lng(regnr,v,tempnr) { \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - M_STACK_LOAD_LNG(tempnr, (v)->regoff); \ - regnr = tempnr; \ - } else if (GET_LOW_REG((v)->regoff)==REG_SPLIT) { \ - M_LDR_INTERN(GET_LOW_REG(tempnr), REG_SP, 0); /* TODO: where to load? */ \ - regnr = PACK_REGS(GET_LOW_REG(tempnr), GET_HIGH_REG((v)->regoff)); \ - } else regnr = (v)->regoff; \ -} -#endif - -/* store_reg_to_var_xxx: - 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 - tempnr: Number of the temporary registers as returned by - reg_of_var. -*/ - -#if defined(__ARMEL__) -#define store_reg_to_var_lng(v,tempnr) { \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - M_STACK_STORE_LNG(tempnr, (v)->regoff); \ - } else if (GET_HIGH_REG((v)->regoff)==REG_SPLIT) { \ - M_STR_INTERN(GET_HIGH_REG(tempnr), REG_SP, 0); /* TODO: where to store? */ \ - } \ -} -#else /* defined(__ARMEB__) */ -#define store_reg_to_var_lng(v,tempnr) { \ - if ((v)->flags & INMEMORY) { \ - COUNT_SPILLS; \ - M_STACK_STORE_LNG(tempnr, (v)->regoff); \ - } else if (GET_LOW_REG((v)->regoff)==REG_SPLIT) { \ - M_STR_INTERN(GET_LOW_REG(tempnr), REG_SP, 0); /* TODO: where to store? */ \ - } \ -} -#endif - -#if defined(__ARMEL__) -#define SPLIT_OPEN(type, reg, tmpreg) \ +# define SPLIT_OPEN(type, reg, tmpreg) \ if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==REG_SPLIT) { \ /*dolog("SPLIT_OPEN({R%d;SPL} > {R%d;R%d})", GET_LOW_REG(reg), GET_LOW_REG(reg), tmpreg);*/ \ /*assert(GET_LOW_REG(reg) == 3);*/ \ (reg) = PACK_REGS(GET_LOW_REG(reg), tmpreg); \ } -#define SPLIT_LOAD(type, reg, offset) \ - if (IS_2_WORD_TYPE(type) && GET_LOW_REG(reg)==3) { \ - /*dolog("SPLIT_LOAD({R%d;R%d} from [%x])", GET_LOW_REG(reg), GET_HIGH_REG(reg), offset);*/ \ - M_LDR(GET_HIGH_REG(reg), REG_SP, 4 * (offset)); \ - } -#define SPLIT_STORE_AND_CLOSE(type, reg, offset) \ + +# define SPLIT_STORE_AND_CLOSE(type, reg, offset) \ if (IS_2_WORD_TYPE(type) && GET_LOW_REG(reg)==3) { \ /*dolog("SPLIT_STORE({R%d;R%d} to [%x])", GET_LOW_REG(reg), GET_HIGH_REG(reg), offset);*/ \ M_STR(GET_HIGH_REG(reg), REG_SP, 4 * (offset)); \ (reg) = PACK_REGS(GET_LOW_REG(reg), REG_SPLIT); \ } + #else /* defined(__ARMEB__) */ -#define SPLIT_OPEN(type, reg, tmpreg) \ + +# define SPLIT_OPEN(type, reg, tmpreg) \ if (IS_2_WORD_TYPE(type) && GET_LOW_REG(reg)==REG_SPLIT) { \ /*dolog("SPLIT_OPEN({SPL;R%d} > {R%d;R%d})", GET_HIGH_REG(reg), tmpreg, GET_HIGH_REG(reg));*/ \ /*assert(GET_HIGH_REG(reg) == 3);*/ \ (reg) = PACK_REGS(tmpreg, GET_HIGH_REG(reg)); \ } -#define SPLIT_LOAD(type, reg, offset) \ - if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==3) { \ - /*dolog("SPLIT_LOAD({R%d;R%d} from [%x])", GET_LOW_REG(reg), GET_HIGH_REG(reg), offset);*/ \ - M_LDR(GET_LOW_REG(reg), REG_SP, 4 * (offset)); \ - } -#define SPLIT_STORE_AND_CLOSE(type, reg, offset) \ + +# define SPLIT_STORE_AND_CLOSE(type, reg, offset) \ if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==3) { \ /*dolog("SPLIT_STORE({R%d;R%d} to [%x])", GET_LOW_REG(reg), GET_HIGH_REG(reg), offset);*/ \ M_STR(GET_LOW_REG(reg), REG_SP, 4 * (offset)); \ (reg) = PACK_REGS(REG_SPLIT, GET_HIGH_REG(reg)); \ } + #endif +/******************************************************************************/ +/* checking macros ************************************************************/ +/******************************************************************************/ + #define MCODECHECK(icnt) \ do { \ if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \ codegen_increase(cd); \ } while (0) +#define ALIGNCODENOP /* empty */ /* TODO: correct this! */ #define IS_IMM(val) ( ((val) >= 0) && ((val) <= 255) ) #define IS_OFFSET(off,max) ((s4)(off) <= (max) && (s4)(off) >= -(max)) -#if !defined(NDEBUG) -# define CHECK_INT_REG(r) if ((r)<0 || (r)>15) printf("CHECK_INT_REG: this is not an integer register: %d\n", r); assert((r)>=0 && (r)<=15) -# define CHECK_FLT_REG(r) if ((r)<0 || (r)>7) printf("CHECK_FLT_REG: this is not an float register: %d\n", r); assert((r)>=0 && (r)<=7) -# define CHECK_OFFSET(off,max) \ - if (!IS_OFFSET(off,max)) printf("CHECK_OFFSET: offset out of range: %x (>%x) SEVERE ERROR!!!\n", ((off)<0)?-(off):off, max); \ - assert(IS_OFFSET(off,max)) -#else -# define CHECK_INT_REG(r) -# define CHECK_FLT_REG(r) -# define CHECK_OFFSET(off,max) -#endif +#define CHECK_INT_REG(r) assert((r)>=0 && (r)<=15) +#define CHECK_FLT_REG(r) assert((r)>=0 && (r)<=7) +#define CHECK_OFFSET(off,max) assert(IS_OFFSET(off,max)) /* branch defines *************************************************************/ @@ -206,7 +124,9 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #endif +/******************************************************************************/ /* macros to create code ******************************************************/ +/******************************************************************************/ /* the condition field */ #define COND_EQ 0x0 /* Equal Z set */ @@ -259,6 +179,9 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); cd->mcodeptr += 4; \ } while (0) +#define M_MEM_GET_Rd(mcode) (((mcode) >> 12) & 0x0f) +#define M_MEM_GET_Rbase(mcode) (((mcode) >> 16) & 0x0f) + /* load and store instruction: M_MEM2 cond ... conditional execution @@ -339,6 +262,15 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); } while (0) +/* undefined instruction used for hardware exceptions */ + +#define M_UNDEFINED(cond,imm,n) \ + do { \ + *((u4 *) cd->mcodeptr) = ((cond) << 28) | (0x7f << 20) | (((imm) & 0x0fff) << 8) | (0x0f << 4) | (n); \ + cd->mcodeptr += 4; \ + } while (0) + + #if !defined(ENABLE_SOFTFLOAT) /* M_CPDO ********************************************************************** @@ -368,6 +300,13 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); } while (0) +#define M_CPDP(cond,p,q,r,s,cp_num,D,N,M,Fd,Fn,Fm) \ + do { \ + *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | ((p) << 23) | ((q) << 21) | ((r) << 20) | ((s) << 6) | ((cp_num) << 8) | ((D) << 22) | ((N) << 7) | ((M) << 5) | ((Fd) << 12) | ((Fn) << 16) | ((Fm) & 0x0f)); \ + cd->mcodeptr += 4; \ + } while (0) + + /* M_CPDT ********************************************************************** Floating-Point Coprocessor Data Transfer @@ -385,6 +324,12 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); cd->mcodeptr += 4; \ } while (0) +#define M_CPLS(cond,L,P,U,W,cp_num,D,Fd,n,off) \ + do { \ + *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0c << 24) | ((P) << 24) | ((U) << 23) | ((W) << 21) | ((L) << 20) | ((cp_num) << 8) | ((D) << 22) | ((Fd) << 12) | ((n) << 16) | ((off) & 0xff)); \ + cd->mcodeptr += 4; \ + } while (0) + /* M_CPRT ********************************************************************** @@ -394,6 +339,12 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); *******************************************************************************/ +#define M_CPRT(cond,op,L,cp_num,N,Fn,n) \ + do { \ + *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 4) | ((op) << 21) | ((L) << 20) | ((cp_num) << 8) | ((N) << 7) | ((Fn) << 16) | ((n) << 12)); \ + cd->mcodeptr += 4; \ + } while (0) + #define M_CPRTS(cond,L,d,Fn,Fm) \ do { \ *((u4 *) cd->mcodeptr) = (((cond) << 28) | (0x0e << 24) | (1 << 8) | (1 << 4) | ((L) << 20) | ((d) << 12) | ((Fn) << 16) | (Fm)); \ @@ -447,21 +398,25 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #define IMM_ROTR(imm, rot) ( ((imm) & 0xff) | (((rot) & 0x0f) << 8) ) #define IMM_ROTL(imm, rot) IMM_ROTR(imm, 16-(rot)) -/* macros for all arm instructions ********************************************/ + +/******************************************************************************/ +/* macros for all basic arm instructions **************************************/ +/******************************************************************************/ #define M_ADD(d,a,b) M_DAT(UNCOND,0x04,d,a,0,0,b) /* d = a + b */ #define M_ADC(d,a,b) M_DAT(UNCOND,0x05,d,a,0,0,b) /* d = a + b (with Carry) */ #define M_SUB(d,a,b) M_DAT(UNCOND,0x02,d,a,0,0,b) /* d = a - b */ #define M_SBC(d,a,b) M_DAT(UNCOND,0x06,d,a,0,0,b) /* d = a - b (with Carry) */ -#define M_AND(d,a,b) M_DAT(UNCOND,0x00,d,a,0,0,b) /* d = a & b */ -#define M_ORR(d,a,b) M_DAT(UNCOND,0x0c,d,a,0,0,b) /* d = a | b */ -#define M_EOR(d,a,b) M_DAT(UNCOND,0x01,d,a,0,0,b) /* d = a ^ b */ +#define M_AND(a,b,d) M_DAT(UNCOND,0x00,d,a,0,0,b) /* d = a & b */ +#define M_ORR(a,b,d) M_DAT(UNCOND,0x0c,d,a,0,0,b) /* d = a | b */ +#define M_EOR(a,b,d) M_DAT(UNCOND,0x01,d,a,0,0,b) /* d = a ^ b */ #define M_TST(a,b) M_DAT(UNCOND,0x08,0,a,1,0,b) /* TST a & b */ #define M_TEQ(a,b) M_DAT(UNCOND,0x09,0,a,1,0,b) /* TST a ^ b */ #define M_CMP(a,b) M_DAT(UNCOND,0x0a,0,a,1,0,b) /* TST a - b */ #define M_MOV(d,b) M_DAT(UNCOND,0x0d,d,0,0,0,b) /* d = b */ #define M_ADD_S(d,a,b) M_DAT(UNCOND,0x04,d,a,1,0,b) /* d = a + b (update Flags) */ #define M_SUB_S(d,a,b) M_DAT(UNCOND,0x02,d,a,1,0,b) /* d = a - b (update Flags) */ +#define M_ORR_S(a,b,d) M_DAT(UNCOND,0x0c,d,a,1,0,b) /* d = a | b (update flags) */ #define M_MOV_S(d,b) M_DAT(UNCOND,0x0d,d,0,1,0,b) /* d = b (update Flags) */ #define M_ADD_IMM(d,a,i) M_DAT(UNCOND,0x04,d,a,0,1,i) /* d = a + i */ @@ -470,7 +425,7 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #define M_SBC_IMM(d,a,i) M_DAT(UNCOND,0x06,d,a,0,1,i) /* d = a - i (with Carry) */ #define M_RSB_IMM(d,a,i) M_DAT(UNCOND,0x03,d,a,0,1,i) /* d = -a + i */ #define M_RSC_IMM(d,a,i) M_DAT(UNCOND,0x07,d,a,0,1,i) /* d = -a + i (with Carry) */ -#define M_AND_IMM(d,a,i) M_DAT(UNCOND,0x00,d,a,0,1,i) /* d = a & i */ +#define M_AND_IMM(a,i,d) M_DAT(UNCOND,0x00,d,a,0,1,i) /* d = a & i */ #define M_TST_IMM(a,i) M_DAT(UNCOND,0x08,0,a,1,1,i) /* TST a & i */ #define M_TEQ_IMM(a,i) M_DAT(UNCOND,0x09,0,a,1,1,i) /* TST a ^ i */ #define M_CMP_IMM(a,i) M_DAT(UNCOND,0x0a,0,a,1,1,i) /* TST a - i */ @@ -481,23 +436,56 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #define M_RSB_IMMS(d,a,i) M_DAT(UNCOND,0x03,d,a,1,1,i) /* d = -a + i (update Flags) */ #define M_ADDSUB_IMM(d,a,i) if((i)>=0) M_ADD_IMM(d,a,i); else M_SUB_IMM(d,a,-(i)) -#define M_MOVEQ(d,b) M_DAT(COND_EQ,0x0d,d,0,0,0,b) -#define M_MOVVS_IMM(d,i) M_DAT(COND_VS,0x0d,d,0,0,1,i) -#define M_MOVNE_IMM(d,i) M_DAT(COND_NE,0x0d,d,0,0,1,i) -#define M_MOVLS_IMM(d,i) M_DAT(COND_LS,0x0d,d,0,0,1,i) +#define M_MOVEQ(a,d) M_DAT(COND_EQ,0x0d,d,0,0,0,a) +#define M_EORLE(d,a,b) M_DAT(COND_LE,0x01,d,a,0,0,b) + +#define M_MOVVS_IMM(i,d) M_DAT(COND_VS,0x0d,d,0,0,1,i) +#define M_MOVEQ_IMM(i,d) M_DAT(COND_EQ,0x0d,d,0,0,1,i) +#define M_MOVNE_IMM(i,d) M_DAT(COND_NE,0x0d,d,0,0,1,i) +#define M_MOVLT_IMM(i,d) M_DAT(COND_LT,0x0d,d,0,0,1,i) +#define M_MOVGT_IMM(i,d) M_DAT(COND_GT,0x0d,d,0,0,1,i) +#define M_MOVLS_IMM(i,d) M_DAT(COND_LS,0x0d,d,0,0,1,i) + +#define M_ADDHI_IMM(d,a,i) M_DAT(COND_HI,0x04,d,a,0,1,i) #define M_ADDLT_IMM(d,a,i) M_DAT(COND_LT,0x04,d,a,0,1,i) #define M_ADDGT_IMM(d,a,i) M_DAT(COND_GT,0x04,d,a,0,1,i) +#define M_SUBLO_IMM(d,a,i) M_DAT(COND_CC,0x02,d,a,0,1,i) #define M_SUBLT_IMM(d,a,i) M_DAT(COND_LT,0x02,d,a,0,1,i) #define M_SUBGT_IMM(d,a,i) M_DAT(COND_GT,0x02,d,a,0,1,i) #define M_RSBMI_IMM(d,a,i) M_DAT(COND_MI,0x03,d,a,0,1,i) #define M_ADCMI_IMM(d,a,i) M_DAT(COND_MI,0x05,d,a,0,1,i) +#define M_CMPEQ(a,b) M_DAT(COND_EQ,0x0a,0,a,1,0,b) /* TST a - b */ +#define M_CMPLE(a,b) M_DAT(COND_LE,0x0a,0,a,1,0,b) /* TST a - b */ + +#define M_CMPEQ_IMM(a,i) M_DAT(COND_EQ,0x0a,0,a,1,1,i) + #define M_MUL(d,a,b) M_MULT(UNCOND,d,a,b,0,0,0x0) /* d = a * b */ +#define M_B(off) M_BRA(UNCOND,0,off) /* unconditional branch */ +#define M_BL(off) M_BRA(UNCOND,1,off) /* branch and link */ +#define M_BEQ(off) M_BRA(COND_EQ,0,off) /* conditional branches */ +#define M_BNE(off) M_BRA(COND_NE,0,off) +#define M_BGE(off) M_BRA(COND_GE,0,off) +#define M_BGT(off) M_BRA(COND_GT,0,off) +#define M_BLT(off) M_BRA(COND_LT,0,off) +#define M_BLE(off) M_BRA(COND_LE,0,off) +#define M_BHI(off) M_BRA(COND_HI,0,off) /* unsigned conditional */ +#define M_BHS(off) M_BRA(COND_CS,0,off) +#define M_BLO(off) M_BRA(COND_CC,0,off) +#define M_BLS(off) M_BRA(COND_LS,0,off) + + +/******************************************************************************/ +/* macros for load and store instructions *************************************/ +/******************************************************************************/ #define M_LDMFD(regs,base) M_MEM_MULTI(UNCOND,1,0,regs,base,0,1,1) #define M_STMFD(regs,base) M_MEM_MULTI(UNCOND,0,0,regs,base,1,0,1) +#define M_LDR_REG(d,base,offreg) M_MEM(UNCOND,1,0,d,base,offreg,1,1,1,0) +#define M_STR_REG(d,base,offreg) M_MEM(UNCOND,0,0,d,base,offreg,1,1,1,0) + #define M_LDR_INTERN(d,base,off) \ do { \ CHECK_OFFSET(off, 0x0fff); \ @@ -558,97 +546,14 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); M_MEM(UNCOND,0,1,d,base,off,0,1,1,0); \ } while (0) - -#if !defined(ENABLE_SOFTFLOAT) -#define M_LDFS_INTERN(d,base,off) \ - do { \ - CHECK_OFFSET(off, 0x03ff); \ - M_CPDT(UNCOND,1,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \ - } while (0) - -#define M_LDFD_INTERN(d,base,off) \ - do { \ - CHECK_OFFSET(off, 0x03ff); \ - M_CPDT(UNCOND,1,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \ - } while (0) - -#define M_STFS_INTERN(d,base,off) \ - do { \ - CHECK_OFFSET(off, 0x03ff); \ - M_CPDT(UNCOND,0,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \ - } while (0) - -#define M_STFD_INTERN(d,base,off) \ - do { \ - CHECK_OFFSET(off, 0x03ff); \ - M_CPDT(UNCOND,0,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \ - } while (0) - -#define M_LDFS_UPDATE(d,base,off) \ - do { \ - CHECK_OFFSET(off, 0x03ff); \ - M_CPDT(UNCOND,1,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),0,(((off) < 0) ? 0 : 1),1); \ - } while (0) - -#define M_LDFD_UPDATE(d,base,off) \ - do { \ - CHECK_OFFSET(off, 0x03ff); \ - M_CPDT(UNCOND,1,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),0,(((off) < 0) ? 0 : 1),1); \ - } while (0) - -#define M_STFS_UPDATE(d,base,off) \ - do { \ - CHECK_OFFSET(off, 0x03ff); \ - M_CPDT(UNCOND,0,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),1); \ - } while (0) - -#define M_STFD_UPDATE(d,base,off) \ - do { \ - CHECK_OFFSET(off, 0x03ff); \ - M_CPDT(UNCOND,0,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),1); \ - } while (0) - -#define M_ADFS(d,a,b) M_CPDOS(UNCOND,0x00,0,d,a,b) /* d = a + b */ -#define M_SUFS(d,a,b) M_CPDOS(UNCOND,0x02,0,d,a,b) /* d = a - b */ -#define M_RSFS(d,a,b) M_CPDOS(UNCOND,0x03,0,d,a,b) /* d = b - a */ -#define M_MUFS(d,a,b) M_CPDOS(UNCOND,0x01,0,d,a,b) /* d = a * b */ -#define M_DVFS(d,a,b) M_CPDOS(UNCOND,0x04,0,d,a,b) /* d = a / b */ -#define M_RMFS(d,a,b) M_CPDOS(UNCOND,0x08,0,d,a,b) /* d = a % b */ -#define M_ADFD(d,a,b) M_CPDOD(UNCOND,0x00,0,d,a,b) /* d = a + b */ -#define M_SUFD(d,a,b) M_CPDOD(UNCOND,0x02,0,d,a,b) /* d = a - b */ -#define M_RSFD(d,a,b) M_CPDOD(UNCOND,0x03,0,d,a,b) /* d = b - a */ -#define M_MUFD(d,a,b) M_CPDOD(UNCOND,0x01,0,d,a,b) /* d = a * b */ -#define M_DVFD(d,a,b) M_CPDOD(UNCOND,0x04,0,d,a,b) /* d = a / b */ -#define M_RMFD(d,a,b) M_CPDOD(UNCOND,0x08,0,d,a,b) /* d = a % b */ -#define M_MVFS(d,a) M_CPDOS(UNCOND,0x00,1,d,0,a) /* d = a */ -#define M_MVFD(d,a) M_CPDOD(UNCOND,0x00,1,d,0,a) /* d = a */ -#define M_MNFS(d,a) M_CPDOS(UNCOND,0x01,1,d,0,a) /* d = - a */ -#define M_MNFD(d,a) M_CPDOD(UNCOND,0x01,1,d,0,a) /* d = - a */ -#define M_CMF(a,b) M_CPRTX(UNCOND,1,0x0f,a,b) /* COMPARE a; b */ -#define M_FLTS(d,a) M_CPRTS(UNCOND,0,a,d,0) /* d = (float) a */ -#define M_FLTD(d,a) M_CPRTD(UNCOND,0,a,d,0) /* d = (float) a */ -#define M_FIX(d,a) M_CPRTI(UNCOND,1,d,0,a) /* d = (int) a */ - -#endif /* !defined(ENABLE_SOFTFLOAT) */ - - -#define M_B(off) M_BRA(UNCOND,0,off) /* unconditional branch */ -#define M_BL(off) M_BRA(UNCOND,1,off) /* branch and link */ -#define M_BEQ(off) M_BRA(COND_EQ,0,off) /* conditional branches */ -#define M_BNE(off) M_BRA(COND_NE,0,off) -#define M_BGE(off) M_BRA(COND_GE,0,off) -#define M_BGT(off) M_BRA(COND_GT,0,off) -#define M_BLT(off) M_BRA(COND_LT,0,off) -#define M_BLE(off) M_BRA(COND_LE,0,off) -#define M_BHI(off) M_BRA(COND_HI,0,off) /* unsigned conditional */ -#define M_BHS(off) M_BRA(COND_CS,0,off) -#define M_BLO(off) M_BRA(COND_CC,0,off) -#define M_BLS(off) M_BRA(COND_LS,0,off) - - -#define M_FMOV(a,b) M_MVFS(b,a) -#define M_DMOV(a,b) M_MVFD(b,a) +#define M_TRAP(a,i) M_UNDEFINED(UNCOND,i,a); +#define M_TRAPEQ(a,i) M_UNDEFINED(COND_EQ,i,a); +#define M_TRAPNE(a,i) M_UNDEFINED(COND_NE,i,a); +#define M_TRAPLT(a,i) M_UNDEFINED(COND_LT,i,a); +#define M_TRAPLE(a,i) M_UNDEFINED(COND_LE,i,a); +#define M_TRAPHI(a,i) M_UNDEFINED(COND_HI,i,a); +#define M_TRAPHS(a,i) M_UNDEFINED(COND_CS,i,a); /* if we do not have double-word load/store command, we can fake them */ @@ -732,6 +637,227 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #endif /* defined(__ARMEB__) */ +/******************************************************************************/ +/* macros for all floating point instructions *********************************/ +/******************************************************************************/ + +#if !defined(ENABLE_SOFTFLOAT) + +#if defined(__VFP_FP__) + +#define M_FADD(a,b,d) M_CPDP(UNCOND,0,1,1,0,10,0,0,0,d,a,b)/* d = a + b */ +#define M_FSUB(a,b,d) M_CPDP(UNCOND,0,1,1,1,10,0,0,0,d,a,b)/* d = a - b */ +#define M_FMUL(a,b,d) M_CPDP(UNCOND,0,1,0,0,10,0,0,0,d,a,b)/* d = a * b */ +#define M_FDIV(a,b,d) M_CPDP(UNCOND,1,0,0,0,10,0,0,0,d,a,b)/* d = a / b */ +#define M_DADD(a,b,d) M_CPDP(UNCOND,0,1,1,0,11,0,0,0,d,a,b)/* d = a + b */ +#define M_DSUB(a,b,d) M_CPDP(UNCOND,0,1,1,1,11,0,0,0,d,a,b)/* d = a - b */ +#define M_DMUL(a,b,d) M_CPDP(UNCOND,0,1,0,0,11,0,0,0,d,a,b)/* d = a * b */ +#define M_DDIV(a,b,d) M_CPDP(UNCOND,1,0,0,0,11,0,0,0,d,a,b)/* d = a / b */ + +#define M_FMOV(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,0,0,d,0x0,a) +#define M_DMOV(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,0,0,d,0x0,a) +#define M_FNEG(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,0,0,d,0x1,a) +#define M_DNEG(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,0,0,d,0x1,a) + +#define M_FCMP(a,b) M_CPDP(UNCOND,1,1,1,1,10,0,0,0,a,0x4,b) +#define M_DCMP(a,b) M_CPDP(UNCOND,1,1,1,1,11,0,0,0,a,0x4,b) + +#define M_CVTDF(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0x7,a) +#define M_CVTFD(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0x7,a) +#define M_CVTIF(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0x8,a) +#define M_CVTID(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0x8,a) +#define M_CVTFI(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0xd,a) // ftosis +#define M_CVTDI(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0xd,a) // ftosid + +#define M_FMSTAT M_CPRT(UNCOND,0x07,1,10,0,0x1,0xf) + +#define M_FMSR(a,Fb) M_CPRT(UNCOND,0x00,0,10,0,Fb,a) +#define M_FMRS(Fa,b) M_CPRT(UNCOND,0x00,1,10,0,Fa,b) +#define M_FMDLR(a,Fb) M_CPRT(UNCOND,0x00,0,11,0,Fb,a) +#define M_FMRDL(Fa,b) M_CPRT(UNCOND,0x00,1,11,0,Fa,b) +#define M_FMDHR(a,Fb) M_CPRT(UNCOND,0x01,0,11,0,Fb,a) +#define M_FMRDH(Fa,b) M_CPRT(UNCOND,0x01,1,11,0,Fa,b) + +#else + +#define M_FADD(a,b,d) M_CPDOS(UNCOND,0x00,0,d,a,b) /* d = a + b */ +#define M_FSUB(a,b,d) M_CPDOS(UNCOND,0x02,0,d,a,b) /* d = a - b */ +#define M_FMUL(a,b,d) M_CPDOS(UNCOND,0x01,0,d,a,b) /* d = a * b */ +#define M_FDIV(a,b,d) M_CPDOS(UNCOND,0x04,0,d,a,b) /* d = a / b */ +#define M_RMFS(d,a,b) M_CPDOS(UNCOND,0x08,0,d,a,b) /* d = a % b */ +#define M_DADD(a,b,d) M_CPDOD(UNCOND,0x00,0,d,a,b) /* d = a + b */ +#define M_DSUB(a,b,d) M_CPDOD(UNCOND,0x02,0,d,a,b) /* d = a - b */ +#define M_DMUL(a,b,d) M_CPDOD(UNCOND,0x01,0,d,a,b) /* d = a * b */ +#define M_DDIV(a,b,d) M_CPDOD(UNCOND,0x04,0,d,a,b) /* d = a / b */ +#define M_RMFD(d,a,b) M_CPDOD(UNCOND,0x08,0,d,a,b) /* d = a % b */ + +#define M_FMOV(a,d) M_CPDOS(UNCOND,0x00,1,d,0,a) /* d = a */ +#define M_DMOV(a,d) M_CPDOD(UNCOND,0x00,1,d,0,a) /* d = a */ +#define M_FNEG(a,d) M_CPDOS(UNCOND,0x01,1,d,0,a) /* d = - a */ +#define M_DNEG(a,d) M_CPDOD(UNCOND,0x01,1,d,0,a) /* d = - a */ + +#define M_FCMP(a,b) M_CPRTX(UNCOND,1,0x0f,a,b) /* COMPARE a; b */ +#define M_DCMP(a,b) M_CPRTX(UNCOND,1,0x0f,a,b) /* COMPARE a; b */ + +#define M_CVTDF(a,b) M_FMOV(a,b) +#define M_CVTFD(a,b) M_DMOV(a,b) +#define M_CVTIF(a,d) M_CPRTS(UNCOND,0,a,d,0) /* d = (float) a */ +#define M_CVTID(a,d) M_CPRTD(UNCOND,0,a,d,0) /* d = (float) a */ +#define M_CVTFI(a,d) M_CPRTI(UNCOND,1,d,0,a) /* d = (int) a */ +#define M_CVTDI(a,d) M_CPRTI(UNCOND,1,d,0,a) /* d = (int) a */ + +#endif + + +/* M_CAST_x2x: + loads the value of the integer-register a (argument or result) into + float-register Fb. (and vice versa) +*/ + +#if defined(__VFP_FP__) + +#define M_CAST_I2F(a,Fb) M_FMSR(a,Fb) + +#define M_CAST_F2I(Fa,b) M_FMRS(Fa,b) + +#define M_CAST_L2D(a,Fb) \ + do { \ + M_FMDLR(GET_LOW_REG(a), Fb); \ + M_FMDHR(GET_HIGH_REG(a), Fb); \ + } while (0) + +#define M_CAST_D2L(Fa,b) \ + do { \ + M_FMRDL(Fa, GET_LOW_REG(b)); \ + M_FMRDH(Fa, GET_HIGH_REG(b)); \ + } while (0) + +#else + +#define M_CAST_I2F(a,Fb) \ + do { \ + CHECK_FLT_REG(Fb); \ + CHECK_INT_REG(a); \ + M_STR_UPDATE(a, REG_SP, -4); \ + M_FLD_UPDATE(Fb, REG_SP, 4); \ + } while (0) + +#define M_CAST_L2D(a,Fb) \ + do { \ + CHECK_FLT_REG(Fb); \ + CHECK_INT_REG(GET_LOW_REG(a)); \ + CHECK_INT_REG(GET_HIGH_REG(a)); \ + M_STRD_UPDATE(a, REG_SP, -8); \ + M_DLD_UPDATE(Fb, REG_SP, 8); \ + } while (0) + +#define M_CAST_F2I(Fa,b) \ + do { \ + CHECK_FLT_REG(Fa); \ + CHECK_INT_REG(b); \ + M_FST_UPDATE(Fa, REG_SP, -4); \ + M_LDR_UPDATE(b, REG_SP, 4); \ + } while (0) + +#define M_CAST_D2L(Fa,b) \ + do { \ + CHECK_INT_REG(GET_LOW_REG(b)); \ + CHECK_INT_REG(GET_HIGH_REG(b)); \ + M_DST_UPDATE(Fa, REG_SP, -8); \ + M_LDRD_UPDATE(b, REG_SP, 8); \ + } while (0) + +#endif + +/* M_xLD_xx & M_xST_xx: + XXX document me! +*/ + +#if defined(__VFP_FP__) + +#define M_FLD_INTERN(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPLS(UNCOND,1,1,(((off) < 0) ? 0 : 1),0,10,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2)); \ + } while (0) + +#define M_DLD_INTERN(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPLS(UNCOND,1,1,(((off) < 0) ? 0 : 1),0,11,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2)); \ + } while (0) + +#define M_FST_INTERN(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPLS(UNCOND,0,1,(((off) < 0) ? 0 : 1),0,10,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2)); \ + } while (0) + +#define M_DST_INTERN(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPLS(UNCOND,0,1,(((off) < 0) ? 0 : 1),0,11,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2)); \ + } while (0) + +#else + +#define M_FLD_INTERN(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPDT(UNCOND,1,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \ + } while (0) + +#define M_DLD_INTERN(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPDT(UNCOND,1,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \ + } while (0) + +#define M_FST_INTERN(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPDT(UNCOND,0,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \ + } while (0) + +#define M_DST_INTERN(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPDT(UNCOND,0,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),0); \ + } while (0) + +#define M_FLD_UPDATE(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPDT(UNCOND,1,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),0,(((off) < 0) ? 0 : 1),1); \ + } while (0) + +#define M_DLD_UPDATE(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPDT(UNCOND,1,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),0,(((off) < 0) ? 0 : 1),1); \ + } while (0) + +#define M_FST_UPDATE(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPDT(UNCOND,0,0,0,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),1); \ + } while (0) + +#define M_DST_UPDATE(d,base,off) \ + do { \ + CHECK_OFFSET(off, 0x03ff); \ + M_CPDT(UNCOND,0,0,1,d,base,(((off) < 0) ? -(off) >> 2 : (off) >> 2),1,(((off) < 0) ? 0 : 1),1); \ + } while (0) + +#endif + +#endif /* !defined(ENABLE_SOFTFLOAT) */ + + +/******************************************************************************/ +/* wrapper macros for load and store instructions *****************************/ +/******************************************************************************/ + /* M_LDR/M_STR: these are replacements for the original LDR/STR instructions, which can handle longer offsets (up to 20bits). the original functions are now @@ -798,18 +924,19 @@ do { \ } while (0) #if !defined(ENABLE_SOFTFLOAT) + #define M_LDFS(d, base, offset) \ do { \ CHECK_OFFSET(offset, 0x03ffff); \ if (IS_OFFSET(offset, 0x03ff)) { \ - M_LDFS_INTERN(d, base, offset); \ + M_FLD_INTERN(d, base, offset); \ } else { \ if ((offset) > 0) { \ M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 10, 5)); \ - M_LDFS_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \ + M_FLD_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \ } else { \ M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 10, 5)); \ - M_LDFS_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \ + M_FLD_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \ } \ } \ } while (0) @@ -818,14 +945,14 @@ do { \ do { \ CHECK_OFFSET(offset, 0x03ffff); \ if (IS_OFFSET(offset, 0x03ff)) { \ - M_LDFD_INTERN(d, base, offset); \ + M_DLD_INTERN(d, base, offset); \ } else { \ if ((offset) > 0) { \ M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 10, 5)); \ - M_LDFD_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \ + M_DLD_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \ } else { \ M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 10, 5)); \ - M_LDFD_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \ + M_DLD_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \ } \ } \ } while (0) @@ -834,11 +961,11 @@ do { \ #define M_STR(d, base, offset) \ do { \ - assert((d) != REG_ITMP3); \ CHECK_OFFSET(offset, 0x0fffff); \ if (IS_OFFSET(offset, 0x000fff)) { \ M_STR_INTERN(d, base, offset); \ } else { \ + assert((d) != REG_ITMP3); \ if ((offset) > 0) { \ M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 12, 6)); \ M_STR_INTERN(d, REG_ITMP3, (offset) & 0x000fff); \ @@ -851,8 +978,6 @@ do { \ #define M_STRD(d, base, offset) \ do { \ - assert(GET_LOW_REG(d) != REG_ITMP3); \ - assert(GET_HIGH_REG(d) != REG_ITMP3); \ CHECK_OFFSET(offset, 0x0fffff - 4); \ if (IS_OFFSET(offset, 0x000fff - 4)) { \ M_STRD_INTERN(d,base,offset); \ @@ -860,6 +985,8 @@ do { \ dolog("M_STRD: this offset seems to be complicated (%d)", offset); \ assert(0); \ } else { \ + assert(GET_LOW_REG(d) != REG_ITMP3); \ + assert(GET_HIGH_REG(d) != REG_ITMP3); \ if ((offset) > 0) { \ M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 12, 6)); \ M_STRD_INTERN(d, REG_ITMP3, (offset) & 0x000fff); \ @@ -876,14 +1003,14 @@ do { \ do { \ CHECK_OFFSET(offset, 0x03ffff); \ if (IS_OFFSET(offset, 0x03ff)) { \ - M_STFS_INTERN(d, base, offset); \ + M_FST_INTERN(d, base, offset); \ } else { \ if ((offset) > 0) { \ M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 10, 5)); \ - M_STFS_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \ + M_FST_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \ } else { \ M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 10, 5)); \ - M_STFS_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \ + M_FST_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \ } \ } \ } while (0) @@ -892,36 +1019,47 @@ do { \ do { \ CHECK_OFFSET(offset, 0x03ffff); \ if (IS_OFFSET(offset, 0x03ff)) { \ - M_STFD_INTERN(d, base, offset); \ + M_DST_INTERN(d, base, offset); \ } else { \ if ((offset) > 0) { \ M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 10, 5)); \ - M_STFD_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \ + M_DST_INTERN(d, REG_ITMP3, (offset) & 0x03ff); \ } else { \ M_SUB_IMM(REG_ITMP3, base, IMM_ROTL((-(offset)) >> 10, 5)); \ - M_STFD_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \ + M_DST_INTERN(d, REG_ITMP3, -(-(offset) & 0x03ff)); \ } \ } \ } while (0) #endif /* !defined(ENABLE_SOFTFLOAT) */ + +/******************************************************************************/ +/* additional helper macros ***************************************************/ +/******************************************************************************/ + /* M_???_IMM_EXT_MUL4: extended immediate operations, to handle immediates lager than 8bit. ATTENTION: the immediate is rotatet left by 2 (multiplied by 4)!!! */ + #define M_ADD_IMM_EXT_MUL4(d,n,imm) \ - assert(d!=REG_PC); \ - assert((imm) >= 0 && (imm) <= 0x00ffffff); \ - M_ADD_IMM(d, n, IMM_ROTL(imm, 1)); \ - if ((imm) > 0x000000ff) M_ADD_IMM(d, d, IMM_ROTL((imm) >> 8, 5)); \ - if ((imm) > 0x0000ffff) M_ADD_IMM(d, d, IMM_ROTL((imm) >> 16, 9)); + do { \ + assert(d != REG_PC); \ + assert((imm) >= 0 && (imm) <= 0x00ffffff); \ + M_ADD_IMM(d, n, IMM_ROTL(imm, 1)); \ + if ((imm) > 0x000000ff) M_ADD_IMM(d, d, IMM_ROTL((imm) >> 8, 5)); \ + if ((imm) > 0x0000ffff) M_ADD_IMM(d, d, IMM_ROTL((imm) >> 16, 9)); \ + } while (0) + #define M_SUB_IMM_EXT_MUL4(d,n,imm) \ - assert(d!=REG_PC); \ - assert((imm) >= 0 && (imm) <= 0x00ffffff); \ - M_SUB_IMM(d, n, IMM_ROTL(imm, 1)); \ - if ((imm) > 0x000000ff) M_SUB_IMM(d, d, IMM_ROTL((imm) >> 8, 5)); \ - if ((imm) > 0x0000ffff) M_SUB_IMM(d, d, IMM_ROTL((imm) >> 16, 9)); + do { \ + assert(d != REG_PC); \ + assert((imm) >= 0 && (imm) <= 0x00ffffff); \ + M_SUB_IMM(d, n, IMM_ROTL(imm, 1)); \ + if ((imm) > 0x000000ff) M_SUB_IMM(d, d, IMM_ROTL((imm) >> 8, 5)); \ + if ((imm) > 0x0000ffff) M_SUB_IMM(d, d, IMM_ROTL((imm) >> 16, 9)); \ + } while (0) /* ICONST/LCONST: @@ -930,15 +1068,6 @@ do { \ #define ICONST(d,c) emit_iconst(cd, (d), (c)) -#define ICONST_CONDITIONAL(cond,d,const) \ - if (IS_IMM(const)) { \ - /* M_MOV_IMM */ M_DAT(cond,0x0d,d,0,0,1,const); \ - } else { \ - disp = dseg_adds4(cd, const); \ - /* TODO: implement this using M_DSEG_LOAD!!! */ \ - /* M_LDR_INTERN */ CHECK_OFFSET(disp,0x0fff); M_MEM(cond,1,0,d,REG_IP,(disp<0)?-disp:disp,0,1,(disp<0)?0:1,0); \ - } - #define LCONST(d,c) \ if (IS_IMM((c) >> 32)) { \ M_MOV_IMM(GET_HIGH_REG(d), (s4) ((s8) (c) >> 32)); \ @@ -948,7 +1077,7 @@ do { \ ICONST(GET_HIGH_REG(d), (s4) ((s8) (c) >> 32)); \ } else { \ disp = dseg_add_s8(cd, (c)); \ - M_LDRD(d, REG_IP, disp); \ + M_LDRD(d, REG_PV, disp); \ } @@ -957,127 +1086,18 @@ do { \ #define FCONST(d,c) \ do { \ disp = dseg_add_float(cd, (c)); \ - M_LDFS(d, REG_IP, disp); \ + M_LDFS(d, REG_PV, disp); \ } while (0) #define DCONST(d,c) \ do { \ disp = dseg_add_double(cd, (c)); \ - M_LDFD(d, REG_IP, disp); \ + M_LDFD(d, REG_PV, disp); \ } while (0) #endif /* !defined(ENABLE_SOFTFLOAT) */ -/* M_RECOMPUTE_IP: - used to recompute our IP (something like PV) out of the current PC - ATTENTION: if you change this, you have to look at other functions as well! - Following things depend on it: asm_call_jit_compiler(); codegen_findmethod(); -*/ -#define M_RECOMPUTE_IP(disp) \ - disp += 8; /* we use PC relative addr. */ \ - assert((disp & 0x03) == 0); \ - assert(disp >= 0 && disp <= 0x03ffffff); \ - M_SUB_IMM(REG_IP, REG_PC, IMM_ROTL(disp >> 2, 1)); \ - if (disp > 0x000003ff) M_SUB_IMM(REG_IP, REG_IP, IMM_ROTL(disp >> 10, 5)); \ - if (disp > 0x0003ffff) M_SUB_IMM(REG_IP, REG_IP, IMM_ROTL(disp >> 18, 9)); \ - -/* 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(b, a); \ - } while (0) - -#define M_LNGMOVE(a,b) \ - do { \ - if (GET_HIGH_REG(a) == GET_LOW_REG(b)) { \ - assert((GET_LOW_REG(a) != GET_HIGH_REG(b))); \ - M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \ - M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \ - } else { \ - M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \ - M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \ - } \ - } while (0) - - -#if !defined(ENABLE_SOFTFLOAT) - -/* 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) \ - do { \ - if ((a) != (b)) \ - M_FMOV(a, b); \ - } while (0) - -#define M_DBLMOVE(a,b) \ - do { \ - if ((a) != (b)) \ - M_DMOV(a, b); \ - } while (0) - -#endif - -#if !defined(ENABLE_SOFTFLOAT) -/* M_CAST_INT_TO_FLT_TYPED: - loads the value of the integer-register a (argument or result) into - float-register Fb. (and vice versa) -*/ -#define M_CAST_INT_TO_FLT_TYPED(t,a,Fb) \ - CHECK_FLT_REG(Fb); \ - if ((t) == TYPE_FLT) { \ - CHECK_INT_REG(a); \ - M_STR_UPDATE(a, REG_SP, -4); \ - M_LDFS_UPDATE(Fb, REG_SP, 4); \ - } else { \ - CHECK_INT_REG(GET_LOW_REG(a)); \ - CHECK_INT_REG(GET_HIGH_REG(a)); \ - M_STRD_UPDATE(a, REG_SP, -8); \ - M_LDFD_UPDATE(Fb, REG_SP, 8); \ - } -#define M_CAST_FLT_TO_INT_TYPED(t,Fa,b) \ - CHECK_FLT_REG(Fa); \ - if ((t) == TYPE_FLT) { \ - CHECK_INT_REG(b); \ - M_STFS_UPDATE(Fa, REG_SP, -4); \ - M_LDR_UPDATE(b, REG_SP, 4); \ - } else { \ - CHECK_INT_REG(GET_LOW_REG(b)); \ - CHECK_INT_REG(GET_HIGH_REG(b)); \ - M_STFD_UPDATE(Fa, REG_SP, -8); \ - M_LDRD_UPDATE(b, REG_SP, 8); \ - } -#endif /* !defined(ENABLE_SOFTFLOAT) */ - - -/* M_COMPARE: - generates the compare part of an if-sequece - uses M_CMP or M_CMP_IMM to do the compare - ATTENTION: uses REG_ITMP3 as intermediate register -*/ -/* TODO: improve this and add some comments! */ -#define M_COMPARE(reg, val, cond, overjump) \ - if (IS_IMM(val)) { \ - if (overjump) M_BNE(1); \ - /* M_CMP_IMM */ M_DAT(cond,0x0a,0,(reg),1,1,(val)); \ - } else if(IS_IMM(-(val))) { \ - if (overjump) M_BNE(1); \ - /* M_CMN_IMM */ M_DAT(cond,0x0b,0,(reg),1,1,-(val)); \ - } else { \ - ICONST(REG_ITMP3, (val)); \ - if (overjump) M_BNE(1); \ - /* M_CMP */ M_DAT(cond,0x0a,0,(reg),1,0,REG_ITMP3); \ - } - /* M_LONGBRANCH: performs a long branch to an absolute address with return address in LR takes up 3 bytes of code space; address is hard-coded into code @@ -1093,31 +1113,20 @@ do { \ ATTENTION: we use M_LDR, so the same restrictions apply to us! */ #define M_DSEG_LOAD(reg, offset) \ - M_LDR_NEGATIVE(reg, REG_IP, offset) + M_LDR_NEGATIVE(reg, REG_PV, offset) #define M_DSEG_BRANCH(offset) \ if (IS_OFFSET(offset, 0x0fff)) { \ M_MOV(REG_LR, REG_PC); \ - M_LDR_INTERN(REG_PC, REG_IP, offset); \ + M_LDR_INTERN(REG_PC, REG_PV, offset); \ } else { \ /*assert((offset) <= 0);*/ \ CHECK_OFFSET(offset,0x0fffff); \ - M_SUB_IMM(REG_ITMP3, REG_IP, ((-(offset) >> 12) & 0xff) | (((10) & 0x0f) << 8)); /*TODO: more to go*/ \ + M_SUB_IMM(REG_ITMP3, REG_PV, ((-(offset) >> 12) & 0xff) | (((10) & 0x0f) << 8)); /*TODO: more to go*/ \ M_MOV(REG_LR, REG_PC); \ M_LDR_INTERN(REG_PC, REG_ITMP3, -(-(offset) & 0x0fff)); /*TODO: this looks ugly*/ \ } -/* M_STACK_LOAD/STORE: - loads or stores integer values from register to stack or from stack to register - ATTENTION: we use M_LDR and M_STR, so the same restrictions apply to us! -*/ - -#define M_STACK_LOAD_LNG(reg, offset) { \ - CHECK_INT_REG(GET_LOW_REG(reg)); \ - CHECK_INT_REG(GET_HIGH_REG(reg)); \ - M_LDRD(reg, REG_SP, (offset) * 4); \ -} - #define M_ILD(a,b,c) M_LDR(a,b,c) #define M_LLD(a,b,c) M_LDRD(a,b,c) @@ -1127,6 +1136,7 @@ do { \ #define M_ALD(a,b,c) M_ILD(a,b,c) #define M_ALD_INTERN(a,b,c) M_ILD_INTERN(a,b,c) +#define M_ALD_DSEG(a,c) M_DSEG_LOAD(a,c) #define M_IST(a,b,c) M_STR(a,b,c) @@ -1139,92 +1149,32 @@ do { \ #define M_AST_INTERN(a,b,c) M_IST_INTERN(a,b,c) -#if !defined(ENABLE_SOFTFLOAT) +#define M_ACMP(a,b) M_CMP(a,b) +#define M_ICMP(a,b) M_CMP(a,b) -#define M_STACK_LOAD_FLT_TYPED(t, reg, offset) { \ - CHECK_FLT_REG(reg); \ - if (IS_2_WORD_TYPE(t)) { \ - M_LDFD(reg, REG_SP, (offset) * 4); \ - } else { \ - M_LDFS(reg, REG_SP, (offset) * 4); \ - } \ -} -#define M_FLD(a,b,c) M_LDFS(a,b,c) -#define M_DLD(a,b,c) M_LDFD(a,b,c) +#define M_TEST(a) M_TEQ_IMM(a, 0); -#define M_FLD_INTERN(a,b,c) M_LDFS_INTERN(a,b,c) -#define M_DLD_INTERN(a,b,c) M_LDFD_INTERN(a,b,c) +#if !defined(ENABLE_SOFTFLOAT) -#define M_STACK_STORE_FLT_TYPED(t, reg, offset) { \ - CHECK_FLT_REG(reg); \ - if (IS_2_WORD_TYPE(t)) { \ - M_STFD(reg, REG_SP, (offset) * 4); \ - } else { \ - M_STFS(reg, REG_SP, (offset) * 4); \ - } \ -} +#define M_FLD(a,b,c) M_LDFS(a,b,c) +#define M_DLD(a,b,c) M_LDFD(a,b,c) #define M_FST(a,b,c) M_STFS(a,b,c) #define M_DST(a,b,c) M_STFD(a,b,c) -#define M_FST_INTERN(a,b,c) M_STFS_INTERN(a,b,c) -#define M_DST_INTERN(a,b,c) M_STFD_INTERN(a,b,c) +#else /* !defined(ENABLE_SOFTFLOAT) */ -#endif /* !defined(ENABLE_SOFTFLOAT) */ - - -/* function gen_resolvebranch ************************************************** - 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) \ - assert((((s4*) (ip))[-1] & 0x0e000000) == 0x0a000000); \ - ((s4*) (ip))[-1] |= ((s4) (to) - (so) - 1) >> 2 & 0x0ffffff - - -/* function gen_nullptr_check *************************************************/ - -#define gen_nullptr_check_intern(objreg) { \ - M_TST((objreg), (objreg)); \ - M_BEQ(0); \ - codegen_add_nullpointerexception_ref(cd); \ -} - -#define gen_nullptr_check(objreg) \ - if (checknull) \ - gen_nullptr_check_intern(objreg) - - -/* function gen_div_check *****************************************************/ - -#define gen_div_check(type,reg) \ - do { \ - if (IS_2_WORD_TYPE(type)) { \ - M_TEQ_IMM(GET_LOW_REG(reg), 0); \ - /* M_TEQ_EQ_IMM(GET_HIGH_REG(reg), 0) */ M_DAT(COND_EQ,0x09,0,GET_HIGH_REG(reg),1,1,0); \ - M_BEQ(0); \ - } else { \ - M_TEQ_IMM((reg), 0); \ - M_BEQ(0); \ - } \ - codegen_add_arithmeticexception_ref(cd); \ - } while (0) - -/* function gen_bound_check *************************************************** - ATTENTION: uses REG_ITMP3 as intermediate register */ -/* TODO: maybe use another reg instead of REG_ITMP3! */ - -#define gen_bound_check(arrayref,index) \ - if (checkbounds) { \ - M_LDR_INTERN(REG_ITMP3, (arrayref), OFFSET(java_arrayheader, size)); \ - M_CMP((index), REG_ITMP3); \ - M_BHS(0); \ - codegen_add_arrayindexoutofboundsexception_ref(cd, index); \ +#define M_FMOV(s,d) M_MOV((d), (s)) +#define M_DMOV(s,d) \ + { \ + M_MOV(GET_LOW_REG(d), GET_LOW_REG(s)); \ + M_MOV(GET_HIGH_REG(d), GET_HIGH_REG(s)); \ } +#endif /* !defined(ENABLE_SOFTFLOAT) */ + #endif /* _CODEGEN_H */