#include "vm/jit/jit.h"
+#include "md-abi.h" /* for INT_NATARG_CNT */
-/* additional functions and macros to generate code ***************************/
+#include <assert.h>
-#define gen_nullptr_check(objreg) \
- if (checknull) { \
- M_BEQZ(objreg, 0); \
- codegen_add_nullpointerexception_ref(cd); \
- M_NOP; \
- }
+/* from md-abi.c */
+s4 nat_argintregs[INT_NATARG_CNT];
+
+/* branch defines *************************************************************/
-#define gen_bound_check \
- if (checkbounds) { \
- M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
- M_CMP(s2, REG_ITMP3); \
- M_XBUGE(0); \
- codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
+#define BRANCH_NOPS \
+ do { \
M_NOP; \
- }
+ M_NOP; \
+ } while (0)
+
+
+/* patcher defines ************************************************************/
+
+#define PATCHER_CALL_INSTRUCTIONS 2 /* number of instructions */
+#define PATCHER_CALL_SIZE 2 * 4 /* size in bytes of a patcher call */
-#define gen_div_check(r) \
+#define EXCEPTION_CHECK_INSTRUCTIONS 3 /* number of instructions */
+#define EXCEPTION_CHECK_SIZE 3 * 4 /* byte size of an exception check */
+
+#define PATCHER_NOPS \
do { \
- M_BEQZ((r), 0); \
- codegen_add_arithmeticexception_ref(cd); \
+ M_NOP; \
M_NOP; \
} while (0)
+
+/* additional functions and macros to generate code ***************************/
+
+
/* MCODECHECK(icnt) */
#define MCODECHECK(icnt) \
#define ALIGNCODENOP \
- if ((s4) ((ptrint) mcodeptr & 7)) { \
+ if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
M_NOP; \
}
#define M_COPY(s,d) emit_copy(jd, iptr, (s), (d))
+#define ICONST(d,c) emit_iconst(cd, (d), (c))
+#define LCONST(d,c) emit_lconst(cd, (d), (c))
/********************** instruction formats ***********************************/
-#define REG 0
-#define IMM 1
+#define REG 0
+#define IMM 1
/* 3-address-operations: M_OP3
* op ..... opcode
* imm ..... switch to use rs2 as constant 13bit integer
* (REG means: use b as register number)
* (IMM means: use b as signed immediate value)
- * */
-
+ */
#define M_OP3(op,op3,rd,rs1,rs2,imm) \
- *(mcodeptr++) = ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | (imm?((rs2)&0x1fff):(rs2)) )
+ do { \
+ *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | (imm?((rs2)&0x1fff):(rs2)) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+
+
+#define M_OP3_GET_RD(x) (((x) >> 25) & 0x1f)
+#define M_OP3_GET_RS(x) (((x) >> 14) & 0x1f)
+#define M_OP3_GET_IMM(x) ( (x) & 0x1fff)
/* 3-address-operations: M_OP3C
* rcond ... condition opcode
* rs2 ..... register number or 10bit signed immediate
*
*/
-
#define M_OP3C(op,op3,rcond,rd,rs1,rs2,imm) \
- *(mcodeptr++) = ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | \
- ((rcond) << 10) | (imm?((rs2)&0x3ff):(rs2)) )
-
+ do { \
+ *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | \
+ ((rcond) << 10) | (imm?((rs2)&0x3ff):(rs2)) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
/* shift Format 3
* op ..... opcode
* op3..... op3 code
- * rs1 .... source 1
- * rs2 .... source 2 or constant
+ * rs1 .... source reg 1
+ * rs2 .... source reg 2 or immediate shift count (5 or 6 bits long depending whether 32 or 64 bit shift)
* rd ..... dest reg
* imm .... switch for constant
* x ...... 0 => 32, 1 => 64 bit shift
*/
#define M_SHFT(op,op3,rs1,rs2,rd,imm,x) \
- *(mcodeptr++) = ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((rs2) << 0) | \
- ((imm) << 13) | ((x) << 12) )
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((imm) << 13) | \
+ ((x) << 12) | (((imm) && (x))?((rs2) & 0x3f):((rs2) & 0x1f)) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+
/* Format 4
* op ..... opcode
* imm .... switch for constant
* cc{0-2} 32-bit 64-bit or fp condition
*/
-
#define M_FMT4(op,op3,rd,rs2,cond,cc2,cc1,cc0,imm) \
- *(mcodeptr++) = ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((cc2) << 18) | ((cond) << 14) | \
- ((imm) << 13) | ((cc1) << 12) | ((cc0) << 11) | ((rs2) << 0) )
-
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((cc2) << 18) | ((cond) << 14) | \
+ ((imm) << 13) | ((cc1) << 12) | ((cc0) << 11) | ((rs2) & 0x7ff) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+#define FR_X(r) (((r)<<1) + 1) /* transpose macro for floats which reside in upper half of double word */
+#define DR_X(r) ((((r)*2)|(((r)*2)>>5)) & 0x1f) /* transpose & pack double, see SPARC spec. */
/* 3-address-floating-point-operation
- op .... opcode
- op3,opf .... function-number
- XXX
-*/
+ * op .... opcode
+ * op3,opf .... function-number
+ * rd .... dest reg
+ * rs1 ... source reg (-1 signals unused)
+ * rs2 ... source reg
+ *
+ *
+ */
#define M_FOP3(op,op3,opf,rd,rs1,rs2) \
- *(mcodeptr++) = ( (((s4)(op))<<30) | ((rd)<<25) | ((op3)<<19) | ((rs1) << 14) | ((opf)<<5) | (rs2) )
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:(rs1)) << 14) | \
+ ((opf)<<5) | (rs2) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+/* float addressing */
+#define M_FOP3_FX(op,op3,opf,rd,rs1,rs2) \
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | (FR_X(rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:FR_X(rs1)) << 14) | \
+ ((opf)<<5) | FR_X(rs2) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+/* double addressing */
+#define M_FOP3_DX(op,op3,opf,rd,rs1,rs2) \
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | (DR_X(rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:DR_X(rs1)) << 14) | \
+ ((opf)<<5) | DR_X(rs2) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+/* 3-address-floating-point-compare-operation
+ * op .... opcode
+ * op3,opf .... function-number
+ * fcc ... floating point condition code (fcc0 - fcc3)
+ * rs1 ... source reg
+ * rs2 ... source reg
+ *
+ *
+ */
+#define M_FCMP_DX(op,op3,opf,fcc,rs1,rs2) \
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((fcc)<<25) | ((op3)<<19) | (DR_X(rs1) << 14) | \
+ ((opf)<<5) | DR_X(rs2) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+
+#define M_FCMP_FX(op,op3,opf,fcc,rs1,rs2) \
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((fcc)<<25) | ((op3)<<19) | (FR_X(rs1) << 14) | \
+ ((opf)<<5) | FR_X(rs2) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
/**** format 2 operations ********/
anul .... annullment bit
*/
#define M_BRAREG(op,rcond,rs1,disp16,p,anul) \
- *(mcodeptr++) = ( (((s4)(op))<<30) | ((anul)<<29) | (0<<28) | ((rcond)<<25) | (3<<22) | \
- ( ((disp16)& 0xC000) << 6 ) | (p << 19) | ((rs1) << 14) | ((disp16)&0x3fff) )
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((anul)<<29) | (0<<28) | ((rcond)<<25) | (3<<22) | \
+ ( ((disp16)& 0xC000) << 6 ) | (p << 19) | ((rs1) << 14) | ((disp16)&0x3fff) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+
/* branch on integer reg instruction
op,op2 .... opcodes
anul .... annullment bit
*/
#define M_BRACC(op,op2,cond,disp19,ccx,p,anul) \
- *(mcodeptr++) = ( (((s4)(op))<<30) | ((anul)<<29) | ((cond)<<25) | (op2<<22) | (ccx<<20) | \
- (p << 19 ) | (disp19) )
-
-/************** end-user instructions (try to follow asm style) ***************/
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((anul)<<29) | ((cond)<<25) | (op2<<22) | (ccx<<20) | \
+ (p << 19 ) | ((disp19) & 0x007ffff) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+
+/************** end-user instructions (see a SPARC asm manual) ***************/
#define M_SETHI(imm22, rd) \
- *(mcodeptr++) = ((((s4)(0x00)) << 30) | ((rd) << 25) | ((0x04)<<22) | ((imm22)&0x3FFFFF) )
-
+ do { \
+ *((u4 *) cd->mcodeptr) = ((((s4)(0x00)) << 30) | ((rd) << 25) | ((0x04)<<22) | ((imm22)&0x3FFFFF) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
-#define M_NOP (M_SETHI(0,0)) /* nop */
+#define M_NOP M_SETHI(0,0) /* nop */
#define M_AND(rs1,rs2,rd) M_OP3(0x02,0x01,rd,rs1,rs2,REG) /* 64b c = a & b */
#define M_AND_IMM(rs1,rs2,rd) M_OP3(0x02,0x01,rd,rs1,rs2,IMM)
#define M_OR(rs1,rs2,rd) M_OP3(0x02,0x02,rd,rs1,rs2,REG) /* rd = rs1 | rs2 */
#define M_OR_IMM(rs1,rs2,rd) M_OP3(0x02,0x02,rd,rs1,rs2,IMM)
-#define M_XOR(rs1,rs2,rd) M_OP3(0x02,0x03,rs1,rs2,rd,REG) /* rd = rs1 ^ rs2 */
-#define M_XOR_IMM(rs1,rs2,rd) M_OP3(0x02,0x03,rs1,rs2,rd,IMM)
+#define M_XOR(rs1,rs2,rd) M_OP3(0x02,0x03,rd,rs1,rs2,REG) /* rd = rs1 ^ rs2 */
+#define M_XOR_IMM(rs1,rs2,rd) M_OP3(0x02,0x03,rd,rs1,rs2,IMM)
#define M_MOV(rs,rd) M_OR(REG_ZERO, rs, rd) /* rd = rs */
+#define M_CLR(rd) M_OR(REG_ZERO,REG_ZERO,rd) /* rd = 0 */
#define M_SLLX(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,REG,1) /* 64b rd = rs << rs2 */
#define M_SLLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,1)
+#define M_SLL(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,REG,0) /* 32b rd = rs << rs2 */
+#define M_SLL_IMM(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,0)
#define M_SRLX(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,REG,1) /* 64b rd = rs >>>rs2 */
#define M_SRLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,1)
#define M_SRL(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,REG,0) /* 32b rd = rs >>>rs2 */
#define M_SRL_IMM(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,0)
#define M_SRAX(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,REG,1) /* 64b rd = rs >> rs2 */
#define M_SRAX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,1)
-#define M_SRA(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0) /* 32b rd = rs >> rs2 */
+#define M_SRA(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0) /* 32b rd = rs >> rs2 */
#define M_SRA_IMM(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,0)
-#define M_ISEXT(rs,rd) M_SRA_IMM(rs,0,rd) /* sign extend 32 bits*/
+#define M_ISEXT(rs,rd) M_SRA(rs,REG_ZERO,rd) /* sign extend 32 bits*/
#define M_ADD(rs1,rs2,rd) M_OP3(0x02,0x00,rd,rs1,rs2,REG) /* 64b rd = rs1 + rs2 */
#define M_MULX_IMM(rs1,rs2,rd) M_OP3(0x02,0x09,rd,rs1,rs2,IMM)
#define M_DIVX(rs1,rs2,rd) M_OP3(0x02,0x2d,rd,rs1,rs2,REG) /* 64b rd = rs1 / rs2 */
+#define M_SUBcc(rs1,rs2,rd) M_OP3(0x02,0x14,rd,rs1,rs2,REG) /* sets xcc and icc */
+#define M_SUBcc_IMM(rs1,rs2,rd) M_OP3(0x02,0x14,rd,rs1,rs2,IMM) /* sets xcc and icc */
+
/**** compare and conditional ALU operations ***********/
-#define M_CMP(rs1,rs2) M_SUB(rs1,rs2,REG_ZERO) /* sets xcc and icc */
-#define M_CMP_IMM(rs1,rs2) M_SUB_IMM(rs1,rs2,REG_ZERO)
+#define M_CMP(rs1,rs2) M_SUBcc(rs1,rs2,REG_ZERO)
+#define M_CMP_IMM(rs1,rs2) M_SUBcc_IMM(rs1,rs2,REG_ZERO)
+
/* move integer register on (64-bit) condition */
#define M_XCMOVGE(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,REG) /* a>=b ? rd=rs */
#define M_XCMOVLE(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,REG) /* a<=b ? rd=rs */
#define M_XCMOVGT(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,REG) /* a>b ? rd=rs */
+#define M_XCMOVULE(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x4,1,1,0,REG) /* a<=b ? rd=rs (u)*/
#define M_XCMOVEQ_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,IMM) /* a==b ? rd=rs */
#define M_XCMOVNE_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,IMM) /* a!=b ? rd=rs */
#define M_XCMOVGE_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,IMM) /* a>=b ? rd=rs */
#define M_XCMOVLE_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,IMM) /* a<=b ? rd=rs */
#define M_XCMOVGT_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,IMM) /* a>b ? rd=rs */
+#define M_XCMOVULE_IMM(rs,rd) M_FMT4(0x2,0x2c,rd,rs,0x4,1,1,0,IMM) /* a<=b ? rd=rs (u)*/
/* move integer register on (fcc0) floating point condition */
#define M_CMOVRGE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,IMM) /* rs1>=0 ? rd=rs2 */
+/**** big constant helpers *********/
+
+/* #define FITS_13BIT_IMM(x) ((x >= -4096) && (x <= 4095)) */
+
+bool fits_13(s4 disp);
+s4 get_lopart_disp(s4 disp);
+
+#define abs(x) ((x) < 0 ? (-(x)) : (x))
+
+#define sethi_part(x) ((x)>>10)
+#define setlo_part(x) ((x) & 0x3ff)
+
+#define DO_SETHI_REG(c,rd) \
+ do { \
+ if (c > 0) { \
+ M_SETHI(sethi_part(c), rd); \
+ if (setlo_part(c)) { \
+ M_OR_IMM(rd, setlo_part(c), rd); \
+ } \
+ } \
+ else { \
+ M_SETHI(sethi_part(~c), rd); \
+ M_XOR_IMM(rd, setlo_part(c) | 0xffffffffffff1c00, rd); \
+ } \
+ } while (0)
+
+#define DO_SETHI_PART(c,rs,rd) \
+ do { \
+ if (c > 0) { \
+ M_SETHI(sethi_part(c), rd); \
+ M_ADD(rs,rd,rd); \
+ } \
+ else { \
+ M_SETHI(sethi_part(-c), rd); \
+ M_SUB(rs,rd,rd); \
+ assert(sethi_part(c) != 0xf); \
+ } \
+ } while (0)
+
+
+
+
+#define M_LDA(rd,rs,disp) \
+ do { \
+ if (fits_13(disp)) { \
+ M_AADD_IMM(rs,disp,rd); \
+ } \
+ else { \
+ DO_SETHI_REG(disp,rd); \
+ M_AADD(rd,rs,rd); \
+ } \
+ } while (0)
+
/**** load/store operations ********/
#define M_SLDU(rd,rs,disp) M_OP3(0x03,0x02,rd,rs,disp,IMM) /* 16-bit load, uns*/
#define M_LDX_INTERN(rd,rs,disp) M_OP3(0x03,0x0b,rd,rs,disp,IMM) /* 64-bit load, sig*/
#define M_LDX(rd,rs,disp) \
do { \
- s4 lo = (short) (disp); \
- s4 hi = (short) (((disp) - lo) >> 13); \
- if (hi == 0) { \
- M_LDX_INTERN(rd,rs,lo); \
- } else { \
- M_SETHI(hi&0x3ffff8,rd); \
- M_AADD(rs,rd,rd); \
- M_LDX_INTERN(rd,rd,lo); \
+ if (fits_13(disp)) { \
+ M_LDX_INTERN(rd,rs,disp); \
+ } \
+ else { \
+ DO_SETHI_PART(disp,rs,rd); \
+ M_LDX_INTERN(rd,rd,get_lopart_disp(disp)); \
} \
} while (0)
#define M_ILD_INTERN(rd,rs,disp) M_OP3(0x03,0x08,rd,rs,disp,IMM) /* 32-bit load, sig */
#define M_ILD(rd,rs,disp) \
do { \
- s4 lo = (short) (disp); \
- s4 hi = (short) (((disp) - lo) >> 13); \
- if (hi == 0) { \
- M_ILD_INTERN(rd,rs,lo); \
- } else { \
- M_SETHI(hi&0x3ffff8,rd); \
- M_AADD(rs,rd,rd); \
- M_ILD_INTERN(rd,rd,lo); \
+ if (fits_13(disp)) { \
+ M_ILD_INTERN(rd,rs,disp); \
+ } \
+ else { \
+ DO_SETHI_PART(disp,rs,rd); \
+ M_ILD_INTERN(rd,rd,get_lopart_disp(disp)); \
} \
} while (0)
#define M_STX_INTERN(rd,rs,disp) M_OP3(0x03,0x0e,rd,rs,disp,IMM) /* 64-bit store */
#define M_STX(rd,rs,disp) \
do { \
- s4 lo = (short) (disp); \
- s4 hi = (short) (((disp) - lo) >> 13); \
- if (hi == 0) { \
- M_STX_INTERN(rd,rs,lo); \
- } else { \
- M_SETHI(hi&0x3ffff8,REG_ITMP3); /* sethi has a 22bit imm, only set upper 19 bits */ \
- M_AADD(rs,REG_ITMP3,REG_ITMP3); \
- M_STX_INTERN(rd,REG_ITMP3,lo); \
+ if (fits_13(disp)) { \
+ M_STX_INTERN(rd,rs,disp); \
+ } \
+ else { \
+ DO_SETHI_PART(disp,rs,REG_ITMP3); \
+ M_STX_INTERN(rd,REG_ITMP3,setlo_part(disp)); \
+ assert(0); \
} \
} while (0)
#define M_IST_INTERN(rd,rs,disp) M_OP3(0x03,0x04,rd,rs,disp,IMM) /* 32-bit store */
#define M_IST(rd,rs,disp) \
do { \
- s4 lo = (short) (disp); \
- s4 hi = (short) (((disp) - lo) >> 13); \
- if (hi == 0) { \
- M_IST_INTERN(rd,rs,lo); \
- } else { \
- M_SETHI(hi&0x3ffff8,REG_ITMP3); /* sethi has a 22bit imm, only set upper 19 bits */ \
- M_AADD(rs,REG_ITMP3,REG_ITMP3); \
- M_IST_INTERN(rd,REG_ITMP3,lo); \
+ if (fits_13(disp)) { \
+ M_IST_INTERN(rd,rs,disp); \
+ } \
+ else { \
+ DO_SETHI_PART(disp,rs,REG_ITMP3); \
+ M_IST_INTERN(rd,REG_ITMP3,setlo_part(disp)); \
+ assert(0); \
} \
} while (0)
/* branch on (64-bit) integer condition codes */
#define M_XBEQ(disp) M_BRACC(0x00,0x1,0x1,disp,2,1,0) /* branch a==b */
-#define M_XBNEQ(disp) M_BRACC(0x00,0x1,0x9,disp,2,1,0) /* branch a!=b */
+#define M_XBNE(disp) M_BRACC(0x00,0x1,0x9,disp,2,1,0) /* branch a!=b */
#define M_XBGT(disp) M_BRACC(0x00,0x1,0xa,disp,2,1,0) /* branch a>b */
#define M_XBLT(disp) M_BRACC(0x00,0x1,0x3,disp,2,1,0) /* branch a<b */
#define M_XBGE(disp) M_BRACC(0x00,0x1,0xb,disp,2,1,0) /* branch a>=b */
#define M_XBLE(disp) M_BRACC(0x00,0x1,0x2,disp,2,1,0) /* branch a<=b */
#define M_XBUGE(disp) M_BRACC(0x00,0x1,0xd,disp,2,1,0) /* br uns a>=b */
+#define M_XBUGT(disp) M_BRACC(0x00,0x1,0xc,disp,2,1,0) /* br uns a>b */
+#define M_XBULT(disp) M_BRACC(0x00,0x1,0x5,disp,2,1,0) /* br uns a<b */
/* branch on (32-bit) integer condition codes */
#define M_BR(disp) M_BRACC(0x00,0x1,0x8,disp,0,1,0) /* branch */
#define M_BEQ(disp) M_BRACC(0x00,0x1,0x1,disp,0,1,0) /* branch a==b */
-#define M_BNEQ(disp) M_BRACC(0x00,0x1,0x9,disp,0,1,0) /* branch a!=b */
+#define M_BNE(disp) M_BRACC(0x00,0x1,0x9,disp,0,1,0) /* branch a!=b */
#define M_BGT(disp) M_BRACC(0x00,0x1,0xa,disp,0,1,0) /* branch a>b */
#define M_BLT(disp) M_BRACC(0x00,0x1,0x3,disp,0,1,0) /* branch a<b */
#define M_BGE(disp) M_BRACC(0x00,0x1,0xb,disp,0,1,0) /* branch a>=b */
#define M_BLE(disp) M_BRACC(0x00,0x1,0x2,disp,0,1,0) /* branch a<=b */
+#define M_BULE(disp) M_BRACC(0x00,0x1,0x4,disp,0,1,0) /* br uns a<=b */
+#define M_BUGT(disp) M_BRACC(0x00,0x1,0xc,disp,0,1,0) /* br uns a>b */
+#define M_BULT(disp) M_BRACC(0x00,0x1,0x5,disp,0,1,0) /* br uns a<b */
-
+#define M_SAVE(rs1,rs2,rd) M_OP3(0x02,0x3c,rd,rs1,rs2,IMM)
+#define M_RESTORE(rs1,rs2,rd) M_OP3(0x02,0x3d,rd,rs1,rs2,IMM)
#define M_JMP(rd,rs1,rs2) M_OP3(0x02,0x38,rd, rs1,rs2,REG) /* jump to rs1+rs2, adr of instr. saved to rd */
#define M_JMP_IMM(rd,rs1,rs2) M_OP3(0x02,0x38,rd, rs1,rs2,IMM)
-#define M_RET(rs) M_OP3(0x02,0x38,REG_ZERO,rs,REG_ZERO,REG)
+#define M_RET(rs1,imm) M_OP3(0x02,0x38,REG_ZERO,rs1,imm,IMM) /* a jump which discards the current pc */
-#define M_RETURN(rs) M_OP3(0x02,0x39,0,rs,REG_ZERO,REG) /* like ret, does window restore */
+#define M_RETURN(rs1,imm) M_OP3(0x02,0x39,0,rs1,imm,IMM) /* like ret, but does window restore */
/**** floating point operations **/
-#define M_DMOV(rs,rd) M_FOP3(0x02,0x34,0x02,rd,0,rs) /* rd = rs */
-#define M_FMOV(rs,rd) M_FOP3(0x02,0x34,0x01,rd*2,0,rs*2) /* rd = rs */
+#define M_DMOV(rs,rd) M_FOP3_DX(0x02,0x34,0x02,rd,-1,rs) /* rd = rs */
+#define M_FMOV(rs,rd) M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs) /* rd = rs */
-#define M_FNEG(rs,rd) M_FOP3(0x02,0x34,0x05,rd,0,rs) /* rd = -rs */
-#define M_DNEG(rs,rd) M_FOP3(0x02,0x34,0x06,rd,0,rs) /* rd = -rs */
+#define M_FNEG(rs,rd) M_FOP3_FX(0x02,0x34,0x05,rd,-1,rs) /* rd = -rs */
+#define M_DNEG(rs,rd) M_FOP3_DX(0x02,0x34,0x06,rd,-1,rs) /* rd = -rs */
-#define M_FADD(rs1,rs2,rd) M_FOP3(0x02,0x34,0x41,rd,rs1,rs2) /* float add */
-#define M_DADD(rs1,rs2,rd) M_FOP3(0x02,0x34,0x42,rd,rs1,rs2) /* double add */
-#define M_FSUB(rs1,rs2,rd) M_FOP3(0x02,0x34,0x045,rd,rs1,rs2) /* float sub */
-#define M_DSUB(rs1,rs2,rd) M_FOP3(0x02,0x34,0x046,rd,rs1,rs2) /* double sub */
-#define M_FMUL(rs1,rs2,rd) M_FOP3(0x02,0x34,0x049,rd,rs1,rs2) /* float mul */
-#define M_DMUL(rs1,rs2,rd) M_FOP3(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul */
-#define M_FDIV(rs1,rs2,rd) M_FOP3(0x02,0x34,0x04d,rd,rs1,rs2) /* float div */
-#define M_DDIV(rs1,rs2,rd) M_FOP3(0x02,0x34,0x04e,rd,rs1,rs2) /* double div */
+#define M_FADD(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x41,rd,rs1,rs2) /* float add */
+#define M_DADD(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x42,rd,rs1,rs2) /* double add */
+#define M_FSUB(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x045,rd,rs1,rs2) /* float sub */
+#define M_DSUB(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x046,rd,rs1,rs2) /* double sub */
+#define M_FMUL(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x049,rd,rs1,rs2) /* float mul */
+#define M_DMUL(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul */
+#define M_FDIV(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x04d,rd,rs1,rs2) /* float div */
+#define M_DDIV(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x04e,rd,rs1,rs2) /* double div */
/**** compare and conditional FPU operations ***********/
/* rd field 0 ==> fcc target unit is fcc0 */
-#define M_FCMP(rs1,rs2) M_FOP3(0x02,0x35,0x051,0,rs1*2,rs2*2) /* set fcc flt */
-#define M_DCMP(rs1,rs2) M_FOP3(0x02,0x35,0x052,0,rs1,rs2) /* set fcc dbl */
+#define M_FCMP(rs1,rs2) M_FCMP_FX(0x02,0x35,0x051,0,rs1,rs2) /* compare flt */
+#define M_DCMP(rs1,rs2) M_FCMP_DX(0x02,0x35,0x052,0,rs1,rs2) /* compare dbl */
/* conversion functions */
-#define M_CVTIF(rs,rd) M_FOP3(0x02,0x34,0x0c4,rd*2,0,rs*2)/* int2flt */
-#define M_CVTID(rs,rd) M_FOP3(0x02,0x34,0x0c8,rd,0,rs*2) /* int2dbl */
-#define M_CVTLF(rs,rd) M_FOP3(0x02,0x34,0x084,rd*2,0,rs) /* long2flt */
-#define M_CVTLD(rs,rd) M_FOP3(0x02,0x34,0x088,rd,0,rs) /* long2dbl */
+#define M_CVTIF(rs,rd) M_FOP3_FX(0x02,0x34,0x0c4,rd,-1,rs)/* int2flt */
+#define M_CVTID(rs,rd) M_FOP3(0x02,0x34,0x0c8,DR_X(rd),-1,FR_X(rs)) /* int2dbl */
+#define M_CVTLF(rs,rd) M_FOP3(0x02,0x34,0x084,FR_X(rd),-1,DR_X(rs)) /* long2flt */
+#define M_CVTLD(rs,rd) M_FOP3_DX(0x02,0x34,0x088,rd,-1,rs) /* long2dbl */
+
+#define M_CVTFI(rs,rd) M_FOP3_FX(0x02,0x34,0x0d1,rd,-1,rs) /* flt2int */
+#define M_CVTDI(rs,rd) M_FOP3(0x02,0x34,0x0d2,FR_X(rd),-1,DR_X(rs)) /* dbl2int */
+#define M_CVTFL(rs,rd) M_FOP3(0x02,0x34,0x081,DR_X(rd),-1,FR_X(rs)) /* flt2long */
+#define M_CVTDL(rs,rd) M_FOP3_DX(0x02,0x34,0x082,rd,-1,rs) /* dbl2long */
-#define M_CVTFI(rs,rd) M_FOP3(0x02,0x34,0x0d1,rd*2,0,rs*2) /* flt2int */
-#define M_CVTDI(rs,rd) M_FOP3(0x02,0x34,0x0d2,rd*2,0,rs) /* dbl2int */
-#define M_CVTFL(rs,rd) M_FOP3(0x02,0x34,0x081,rd,0,rs*2) /* flt2long */
-#define M_CVTDL(rs,rd) M_FOP3(0x02,0x34,0x082,rd,0,rs) /* dbl2long */
+#define M_CVTFD(rs,rd) M_FOP3(0x02,0x34,0x0c9,DR_X(rd),-1,FR_X(rs)) /* flt2dbl */
+#define M_CVTDF(rs,rd) M_FOP3(0x02,0x34,0x0c6,FR_X(rd),-1,DR_X(rs)) /* dbl2float */
-#define M_CVTFD(rs,rd) M_FOP3(0x02,0x34,0x0c9,rd,0,rs*2) /* flt2dbl */
-#define M_CVTDF(rs,rd) M_FOP3(0x02,0x34,0x0c6,rd*2,0,rs) /* dbl2float */
-/* translate logical double register index to float index. (e.g. %d1 -> %f2, %d2 -> %f4, etc.) */
-/* we don't have to pack the 6-bit register number, since we are not using the upper 16 doubles */
-/* floats reside in lower register of a double pair, use same translation as above */
-#define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,rd*2,rs1,disp,IMM) /* double (64-bit) load */
+#define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,DR_X(rd),rs1,disp,IMM) /* double (64-bit) load */
#define M_DLD(rd,rs,disp) \
do { \
s4 lo = (short) (disp); \
} while (0)
/* Note for SETHI: sethi has a 22bit imm, only set upper 19 bits */
-#define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,rd*2,rs1,disp,IMM) /* float (32-bit) load */
+#define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,FR_X(rd),rs1,disp,IMM) /* float (32-bit) load */
#define M_FLD(rd,rs,disp) \
do { \
s4 lo = (short) (disp); \
} while (0)
-#define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,rd*2,rs,disp,IMM) /* float (32-bit) store */
+#define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,FR_X(rd),rs,disp,IMM) /* float (32-bit) store */
#define M_FST(rd,rs,disp) \
do { \
s4 lo = (short) (disp); \
} while (0)
-#define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,rd,rs1,disp,IMM) /* double (64-bit) store */
+#define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,DR_X(rd),rs1,disp,IMM) /* double (64-bit) store */
#define M_DST(rd,rs,disp) \
do { \
s4 lo = (short) (disp); \
#define M_ALD_INTERN(a,b,disp) M_LDX_INTERN(a,b,disp)
-#define M_ALD(a,b,disp) M_LDX(a,b,disp)
+#define M_ALD(rd,rs,disp) M_LDX(rd,rs,disp)
#define M_AST_INTERN(a,b,disp) M_STX_INTERN(a,b,disp)
#define M_AST(a,b,disp) M_STX(a,b,disp)
#define M_AADD(a,b,c) M_ADD(a,b,c)
} while (0)
-/* gen_resolvebranch ***********************************************************
- *
- * backpatches a branch instruction
- * On Sparc all there is to do, is replace the 22bit disp at the end of the
- * instruction.
- * THIS APPLIES TO THE (V8) BICC INSTRUCTION ONLY.
- *
- * 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 */