/* src/vm/jit/s390/codegen.h - code generation macros for s390 Copyright (C) 1996-2005, 2006, 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. 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 for more details. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _CODEGEN_H #define _CODEGEN_H #include "config.h" #include #include "vm/types.h" #include "vm/jit/jit.hpp" /* MCODECHECK(icnt) */ #define MCODECHECK(icnt) \ do { \ if ((cd->mcodeptr + (icnt)) > cd->mcodeend) \ codegen_increase(cd); \ } while (0) /* some patcher defines *******************************************************/ #define PATCHER_CALL_SIZE 2 /* size in bytes of a patcher call */ #define PATCHER_NOPS M_NOP3 /* branch defines ************************************************************/ #define BRANCH_NOPS \ do { \ if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \ M_NOP2; M_NOP2; /* brc */ \ M_NOP2; M_NOP2; M_NOP2; M_NOP2; M_NOP2; M_NOP2; M_NOP2; M_NOP2; /* ild */ \ M_NOP2; /* ar, bcr */ \ } else { \ M_NOP; /* brc */ \ } \ } while (0) /* *** BIG TODO *** * Make all this inline functions !!!!!!!!!! */ /* macros to create code ******************************************************/ /* Conventions: * N_foo: defines the instrucition foo as in `ESA/390 Principles of operations' * SZ_foo: defines the size of the instruction N_foo * DD_foo: defines a condition code as used by s390 GCC * M_foo: defines the alpha like instruction used in cacao * the instruction is defined by an equivalent N_ instruction * CC_foo: defines a condition code as used * the instruction is defined as an equivalent DD_ condition code */ /* S390 specific code */ /* Argument checks for debug mode */ /* Some instructions with register arguments treat %r0 as "value not given". * To prevent bugs, in debug mode we use a special value RN (reg none) with * the meaning "value not given". * In debug mode, the instructions assert that %r0 was not given as argument. */ #if !defined(NDEBUG) # include /* register none */ # define RN 16 static inline int _OR_IMPL(const char *file, int line, int r) { if(!( ((0 < r) && (r < 16)) || (r == RN) )) { fprintf(stdout, "%d is not a valid register at %s:%d.\n", r, file, line); abort(); } return ((r == RN) ? 0 : r); } # define _OR(r) _OR_IMPL(__FILE__, __LINE__, r) # define _SMIN(b) (-(1 << (bits - 1))) # define _SMAX(b) ((1 << (b - 1)) - 1) # define _UMIN(b) 0 # define _UMAX(b) ((1 << b) - 1) static inline int _UBITS_IMPL(const char *file, int line, int i, int bits) { if (!((_UMIN(bits) <= i) && (i <= _UMAX(bits)))) { fprintf(stdout, "%d (0x%X) is not an unsigned %d bit integer at %s:%d.\n", i, i, bits, file, line); abort(); } return i; } # define _UBITS(i, bits) _UBITS_IMPL(__FILE__, __LINE__, i, bits) static inline int _SBITS_IMPL(const char *file, int line, int i, int bits) { if(!((_SMIN(bits) <= i) && (i <= _SMAX(bits)))) { fprintf(stdout, "%d (0x%X) is not an signed %d bit integer at %s:%d.\n", i, i, bits, file, line); abort(); } return i; } # define _SBITS(i, bits) _SBITS_IMPL(__FILE__, __LINE__, i, bits) static inline int _BITS_IMPL(const char *file, int line, int i, int bits) { if (!( ((_UMIN(bits) <= i) && (i <= _UMAX(bits))) || ((_SMIN(bits) <= i) && (i <= _SMAX(bits))) )) { fprintf(stdout, "%d (0x%X) is not an %d bit integer at %s:%d.\n", i, i, bits, file, line); abort(); } return i; } # define _BITS(i, bits) _BITS_IMPL(__FILE__, __LINE__, i, bits) #else # define RN 0 # define _OR(x) (x) # define _BITS(x, b) (x) # define _UBITS(x, b) (x) # define _SBITS(x, b) (x) #endif /* Register */ #define _R(x) _UBITS((x), 4) /* Displacement */ #define _D(x) _UBITS((x), 12) /* 4 bit Immediate */ #define _I4(x) _BITS((x), 4) #define _UI4(x) _UBITS((x), 4) #define _SI4(x) _SBITS((x), 4) /* 8 bit Immediate */ #define _I8(x) _BITS((x), 8) #define _UI8(x) _UBITS((x), 8) #define _SI8(x) _SBITS((x), 8) /* 12 bit Immediate */ #define _I12(x) _BITS((x), 12) #define _UI12(x) _UBITS((x), 12) #define _SI12(x) _SBITS((x), 12) /* 16 bit Immediate */ #define _I16(x) _BITS((x), 16) #define _UI16(x) _UBITS((x), 16) #define _SI16(x) _SBITS((x), 16) /* Opcode */ #define _OP(x) _UBITS((x), 8) /* Second part of opcode */ #define _OP4(x) _UBITS((x), 4) /* Extended opcode */ #define _OP16(x) _UBITS((x), 16) /* Instruction formats */ #define _CODE(t, code) \ do { \ *((t *) cd->mcodeptr) = (code); \ cd->mcodeptr += sizeof(t); \ } while (0) #define _CODE2(code) _CODE(u2, code) #define _CODE4(code) _CODE(u4, code) #define _IF(cond, t, f) \ do { if (cond) { t ; } else { f ; } } while (0) #define _IFNEG(val, neg, pos) _IF((val) < 0, neg, pos) #define N_RR(op, r1, r2) \ _CODE2( (_OP(op) << 8) | (_R(r1) << 4) | _R(r2) ) #define SZ_RR 2 static inline uint8_t N_RR_GET_OPC(uint8_t *instrp) { return instrp[0]; } static inline uint8_t N_RR_GET_REG1(uint8_t *instrp) { return (instrp[1] >> 4) & 0xF; } static inline uint8_t N_RR_GET_REG2(uint8_t *instrp) { return (instrp[1] & 0xF); } #define N_RR2(op, i) \ _CODE2( (_OP(op) << 8) | _I8(i) ) #define N_RX(op, r1, d2, x2, b2) \ _CODE4( (_OP(op) << 24) | (_R(r1) << 20) | (_OR(x2) << 16) | (_OR(b2) << 12) | (_D(d2) << 0) ) #define SZ_RX 4 static inline uint8_t N_RX_GET_OPC(uint8_t *instrp) { return instrp[0]; } static inline uint8_t N_RX_GET_REG(uint8_t *instrp) { return (instrp[1] >> 4) & 0xF; } static inline uint8_t N_RX_GET_INDEX(uint8_t *instrp) { return (instrp[1] & 0xF); } static inline uint8_t N_RX_GET_BASE(uint8_t *instrp) { return (instrp[2] >> 4) & 0xF; } static inline uint16_t N_RX_GET_DISP(uint8_t *instrp) { return *(uint16_t *)(instrp + 2) & 0xFFF; } static inline void N_RX_SET_DISP(uint8_t *instrp, uint16_t disp) { *(uint16_t *)(instrp + 2) |= (disp & 0xFFF); } #define N_RI(op1, op2, r1, i2) \ _CODE4( (_OP(op1) << 24) | (_R(r1) << 20) | (_OP4(op2) << 16) | (u2)_SI16(i2) ) static inline int16_t N_RI_GET_IMM(uint8_t *instrp) { return *(int16_t *)(instrp + 2); } static inline void N_RI_SET_IMM(uint8_t *instrp, int16_t imm) { *(int16_t *)(instrp + 2) = imm; } #define N_RI2(op1, op2, r1, i2) \ _CODE4( (_OP(op1) << 24) | (_R(r1) << 20) | (_OP4(op2) << 16) | (u2)_UI16(i2) ) #define SZ_RI 4 #define N_SI(op, d1, b1, i2) \ _CODE4( (_OP(op) << 24) | (_OR(i2) << 16) | (_OR(b1) << 12) | _D(d1) ) #define SZ_SI 4 #define N_SS(op, d1, l, b1, d2, b2) \ do { \ _CODE4( (_OP(op) << 24) | (_I8(l) << 16) | (_OR(b1) << 12) | _D(d1) ); \ _CODE2( (_OR(b2) << 12) | _D(d2) ); \ } while (0) #define SZ_SS 6 #define N_SS2(op, d1, l1, b1, d2, l2, b2) \ N_SS(op, d1, (_I4(l1) << 4) | _I4(l2), b1, d2, l2) #define N_RS(op, r1, r3, d2, b2) \ _CODE4( (_OP(op) << 24) | (_R(r1) << 20) | (_R(r3) << 16) | (_OR(b2) << 12) | _D(d2) ) #define SZ_RS 4 #define N_RSI(op, r1, r2, i2) \ _CODE4( ((op) << 24) | (_R(r1) << 20) | (_R(r3) << 16) | (u2)_16(i2) ) #define SZ_RSI 4 #define N_RRE(op, r1, r2) \ _CODE4( (_OP16(op) << 16) | (_R(r1) << 4) | _R(r2) ) #define SZ_RRE 4 #define N_S2(d2, b2) \ _CODE4( (_OP16(op) << 16) | (_OR(b2) << 12) | _D(d2) ) #define SZ_S2 4 #define N_E(op) \ _CODE2( _OP16(op) ) #define SZ_E 2 #define N_RXE(op, r1, d2, x2, b2) \ do { \ _CODE4( ((_OP16(op) >> 8) << 24) | (_R(r1) << 20) | \ (_R(x2) << 16) | (_R(b2) << 12) | _UI12(d2) ); \ _CODE2( _OP16(op) & 0xFF ); \ } while (0) #define S_RXE 6 #define N_RRF(op, r1, m3, r2) \ _CODE4( (_OP16(op) << 16) | (_R(m3) << 12) | (_R(r1) << 4) | _R(r2) ) #define S_RRF 4 #define N_IMM_MIN -32768 #define N_IMM_MAX 32767 #define N_VALID_IMM(x) ((N_IMM_MIN <= (x)) && ((x) <= N_IMM_MAX)) #define ASSERT_VALID_IMM(x) assert(N_VALID_IMM(x)) #define N_DISP_MIN 0 #define N_DISP_MAX 0xFFF #define N_VALID_DISP(x) ((N_DISP_MIN <= (x)) && ((x) <= N_DISP_MAX)) #define ASSERT_VALID_DISP(x) assert(N_VALID_DISP(x)) #define N_PV_OFFSET (-0xFFC) #define N_DSEG_DISP(x) ((x) - N_PV_OFFSET) #define N_VALID_DSEG_DISP(x) N_VALID_DISP(N_DSEG_DISP(x)) #define N_BRANCH_MIN (-32768 * 2) #define N_BRANCH_MAX (32767 * 2) #define N_VALID_BRANCH(x) ((N_BRANCH_MIN <= (x)) && ((x) <= N_BRANCH_MAX)) #define ASSERT_VALID_BRANCH(x) assert(N_VALID_BRANCH(x)) #define N_IS_EVEN_ODD(x) \ (((GET_HIGH_REG(x) % 2) == 0) && (GET_LOW_REG(x) == (GET_HIGH_REG(x) + 1))) /* Condition codes */ #define DD_O 1 #define DD_H 2 #define DD_NLE 3 #define DD_L 4 #define DD_NHE 5 #define DD_LH 6 #define DD_NE 7 #define DD_E 8 #define DD_NLH 9 #define DD_HE 10 #define DD_NL 11 #define DD_LE 12 #define DD_NH 13 #define DD_NO 14 #define DD_ANY 15 #define DD_0 8 #define DD_1 4 #define DD_2 2 #define DD_3 1 /* Misc */ /* Trap instruction. * If most significant bits of first opcode byte are 00, then * format is RR (1 byte opcode) or E (2 bytes opcode). * There seems to be no opcode 0x02 or 0x02**, so we'll define * our trap instruction as: * +--------+--------+ * | 0x02 | data | * +--------+--------+ * 0 15 */ #define N_ILL(data) _CODE2(0x0200 | _UBITS(data, 8)) # define OPC_ILL 0x02 # define SZ_ILL 2 static inline uint8_t N_ILL_GET_REG(uint8_t *instrp) { return (instrp[1] >> 4) & 0xF; } static inline uint8_t N_ILL_GET_TYPE(uint8_t *instrp) { return (instrp[1] & 0xF); } #define N_LONG(l) _CODE4(l) #define SZ_LONG 4 /* Chapter 7. General instructions */ #define N_AR(r1, r2) N_RR(0x1A, r1, r2) #define N_A(r1, d2, x2, b2) N_RX(0x5A, r1, d2, x2, b2) #define N_AH(r1, d2, x2, b2) N_RX(0x4A, r1, d2, x2, b2) #define N_AHI(r1, i2) N_RI(0xA7, 0xA, r1, i2) # define SZ_AHI SZ_RI #define N_ALR(r1, r2) N_RR(0x1E, r1, r2) #define N_AL(r1, d2, x2, b2) N_RX(0x5E, r1, d2, x2, b2) #define N_NR(r1, r2) N_RR(0x14, r1, r2) # define SZ_NR SZ_RR #define N_N(r1, d2, x2, b2) N_RX(0x54, r1, d2, x2, b2) #define N_NI(d1, b1, i2) N_SI(0x94, d1, b1, i2) #define N_NC(d1, l, b1, d2, b2) N_SS(0xD4, (l - 1), b1, d1, b2, d2) #define N_BALR(r1, r2) N_RR(0x05, r1, _OR(r2)) #define N_BAL(r1, d2, x2, b2) N_RX(0x45, r1, d2, x2, b2) #define N_BASR(r1, r2) N_RR(0x0D, r1, _OR(r2)) # define SZ_BASR SZ_RR #define N_BAS(r1, d2, x2, b2) N_RX(0x4D, r1, d2, x2, b2) #define N_BASSM(r1, r2) N_RR(0x0C, r1, _OR(r2)) #define N_BSM(r1, r2) N_RR(0x0B, r1, _OR(r2)) #define N_BCR(m1, r2) N_RR(0x07, m1, _OR(r2)) # define SZ_BCR SZ_RR # define N_BR(r2) N_BCR(DD_ANY, r2) #define N_BC(m1, d2, x2, b2) N_RX(0x47, m1, d2, x2, b2) # define SZ_BC SZ_RS #define N_BCTR(r1, r2) N_RR(0x06, r1, _OR(r2)) #define N_BCT(r1, d2, x2, b2) N_RX(0x46, r1, d2, x2, b2) #define N_BHX(r1, r2, d2, b2) N_RS(0xB6, r1, r3, d2, b2) #define N_BXLE(r1, r3, d2, b2) N_RS(0xB7, r1, r3, d2, b2) #define N_BRAS(r1, i2) N_RI(0xA7, 0x5, r1, (i2) / 2) # define SZ_BRAS SZ_RI #define N_BRC(m1, i2) N_RI(0xA7, 0x4, m1, (i2) / 2) # define N_J(i2) N_BRC(DD_ANY, i2) # define SZ_BRC SZ_RI # define SZ_J SZ_RI # define N_BRC_BACK_PATCH(brc_pos) \ do { \ *(u4 *)(brc_pos) |= (u4)(cd->mcodeptr - (brc_pos)) / 2; \ } while (0) #define N_BRCT(r1, i2) N_RI(0xA7, 0x6, r1, (i2) / 2) #define N_BRXH(r1, r3, i2) N_RSI(0x84, r1, r3, (i2) / 2) #define N_BRXLE(r1, r3, i2) N_RSI(0x85, r1, r2, (i2) / 2) #define N_CKSM(r1, r2) N_RRE(0xB241, r1, r2) #define N_CR(r1, r2) N_RR(0x19, r1, r2) # define SZ_CR SZ_RR #define N_C(r1, d2, x2, b2) N_RX(0x59, r1, d2, x2, b2) #define N_CFC(d2, b2) N_S2(0xB21A, d2, b2) #define N_CS(r1, r3, d2, b2) N_RS(0xBA, r1, r3, d2, b2) #define N_CDS(r1, r3, d2, b2) N_RS(0xBB, r1, r3, d2, b2) #define N_CH(r1, d2, x2, b2) N_CH(0x49, r1, d2, x2, b2) #define N_CHI(r1, i2) N_RI(0xA7, 0xE, r1, i2) #define N_CLR(r1, r2) N_RR(0x15, r1, r2) #define N_CL(r1, d2, x2, b2) N_RX(0x55, r1, d2, x2, b2) # define OPC_CL 0x55 #define N_CLI(d1, b1, i2) N_SI(0x95, d1, b1, i2) #define N_CLC(d1, l, b1, d2, b2) N_SS(0xD5, d1, (l - 1), b1, d2, b2) #define N_CLM(r1, m3, d2, b2) N_RS(0xBD, r1, m3, d2, b2) #define N_CLCL(r1, r2) N_RR(0x0F, r1, r2) #define N_CLCLE(r1, r3, d2, b2) N_RS(0xA9, r1, r3, d2, b2) #define N_CLST(r1, r2) N_RRE(0xB25D, r1, r2) #define N_CUSE(r1, r2) N_RRE(0xB257, r1, r2) #define N_CVB(r1, d2, x2, b2) N_RX(0x4F, r1, r2, x2, b2) #define N_CVD(r1, d2, x2, b2) N_RX(0x4E, r1, d2, x2, b2) #define N_CUUTF(r1, r2) N_RRE(0xB2A6, r1, r2) #define N_CUTFU(r1, r2) N_RRE(0xB2A7, r1, r2) #define N_CPYA(r1, r2) N_RRE(0xB240, r1, r2) #define N_DR(r1, r2) N_RR(0x1D, r1, r2) # define OPC_DR 0x1D #define N_D(r1, d2, x2, b2) N_RX(0x5D, r1, d2, x2, b2) #define N_XR(r1, r2) N_RR(0x17, r1, r2) #define N_X(r1, d2, x2, b2) N_RX(0x57, r1, d2, x2, b2) #define N_XI(d1, b1, i2) N_SI(0x97, d1, b1, i2) #define N_XC(d1, l, b1, d2, b2) N_SS(0xD7, d1, (l - 1), b1, d2, b2) #define N_EX(r1, d2, x2, b2) N_RX(0x44, r1, d2, x2, b2) #define N_EAR(r1, r2) N_RRE(0xB24F, r1, r2) #define N_IC(r1, d2, x2, b2) N_RX(0x43, r1, d2, x2, b2) #define N_ICM(r1, m3, d2, b2) N_RS(0xBF, r1, m3, d2, b2) #define N_IPM(r1) N_RRE(0xB222, r1, 0) #define N_LR(r1, r2) N_RR(0x18, r1, r2) #define N_L(r1, d2, x2, b2) N_RX(0x58, r1, d2, x2, b2) # define SZ_L SZ_RX # define OPC_L 0x58 #define N_LAM(r1, r3, d2, b2) N_RS(0x9A, r1, r3, d2, b2) #define N_LA(r1, d2, x2, b2) N_RX(0x41, r1, d2, x2, b2) #define N_LAE(r1, d2, x2, b2) N_RX(0x51, r1, d2, x2, b2) #define N_LTR(r1, r2) N_RR(0x12, r1, r2) #define N_LCR(r1, r2) N_RR(0x13, r1, r2) # define SZ_LCR SZ_RR #define N_LH(r1, d2, x2, b2) N_RX(0x48, r1, d2, x2, b2) #define N_LHI(r1, i2) N_RI(0xA7, 0x8, r1, i2) # define SZ_LHI SZ_RI #define N_LM(r1, r3, d2, b2) N_RS(0x98, r1, r3, d2, b2) #define N_LNR(r1, r2) N_RR(0x11, r1, r2) #define N_LPR(r1, r2) N_RR(0x10, r1, r2) #define N_MC(d1, b1, i2) N_SI(0xAF, d1, b1, i2) #define N_MVI(d1, b1, i2) N_SI(0x92, d1, b1, i2) #define N_MVC(d1, l, b1, d2, b2) N_SS(0xD2, d1, (l - 1), b1, d2, b2) #define N_MVCIN(d1, l, b1, d2, b2) N_SS(0xEB, d1, (l - 1), b1, d2, b2) #define N_MVCL(r1, r2) N_RR(0x0E, r1, r2) #define N_MVCLE(r1, r3, d2, b2) N_RS(0xAB, r1, r3, d2, b2) #define N_MVN(d1, l, b1, d2, b2) N_SS(0xD1, d1, (l - 1), b1, d2, b2) #define N_MVPG(r1, r2) N_RRE(0xB254, r1, r2) #define N_MVST(r1, r2) N_RRE(0xB255, r1, r2) #define N_MVO(d1, l1, b1, d2, l2, b2) N_SS2(0xF1, d1, (l1 - 1), b1, d2, (l2 - 1), b2) #define N_MVZ(d1, l, b1, d2, b2) N_SS(0xD3, d1, (l - 1), b1, d2, b2) #define N_MR(r1, r2) N_RR(0x1C, r1, r2) #define N_M(r1, d2, x2, b2) N_RX(0x5C, r1, d2, x2, b2) #define N_MH(r1, d2, x2, b2) N_RX(0x4C, r1, d2, x2, b2) #define N_MHI(r1, i2) N_RI(0xA7, 0xC, r1, i2) #define N_MSR(r1, r2) N_RRE(0xB252, r1, r2) #define N_MS(r1, d2, x2, b2) N_RX(0x71, r1, d2, x2, b2) #define N_OR(r1, r2) N_RR(0x16, r1, r2) #define N_O(r1, d2, x2, b2) N_RX(0x56, r1, d2, x2, b2) #define N_OI(d1, b1, i2) N_SI(0x96, d1, b1, i2) #define N_OC(d1, l, b1, d2, b2) N_SS(0xD6, d1, (l - 1), b1, d2, b2) #define N_PACK(d1, l1, b1, d2, l2, b2) N_SS2(0xF2, d1, (l1 - 1), b1, d2, (l2 - 1), b2) #define N_PLO(r1, d2, b2, r3, d4, b4) N_SS2(0xEE, d2, r1, b2, d4, r3, b4) #define N_SRST(r1, r2) N_RRE(0xB25E, r1, r2) #define N_SAR(r1, r2) N_RRE(0xB24E, r1, r2) #define N_SPM(r1) N_RR(0x04, r1, 0x00) #define N_SLDA(r1, d2, b2) N_RS(0x8F, r1, 0x00, d2, b2) #define N_SLDL(r1, d2, b2) N_RS(0x8D, r1, 0x00, d2, b2) #define N_SLA(r1, d2, b2) N_RS(0x8B, r1, 0x00, d2, b2) #define N_SLL(r1, d2, b2) N_RS(0x89, r1, 0x00, d2, b2) #define N_SRDA(r1, d2, b2) N_RS(0x8E, r1, 0x00, d2, b2) #define N_SRDL(r1, d2, b2) N_RS(0x8C, r1, 0x00, d2, b2) #define N_SRA(r1, d2, b2) N_RS(0x8A, r1, 0x00, d2, b2) #define N_SRL(r1, d2, b2) N_RS(0x88, r1, 0x00, d2, b2) #define N_ST(r1, d2, x2, b2) N_RX(0x50, r1, d2, x2, b2) # define OPC_ST 0x50 #define N_STAM(r1, r3, d2, b2) N_RS(0x9B, r1, r3, d2, b2) #define N_STC(r1, d2, x2, b2) N_RX(0x42, r1, d2, x2, b2) #define N_STCM(r1, m3, d2, b2) N_RS(0xBE, r1, m3, d2, b2) #define N_STCK(d2, b2) N_S2(0xB205, d2, b2) #define N_STCKE(d2, b2) N_S2(0xB278, d2, b2) #define N_STH(r1, d2, x2, b2) N_RX(0x40, r1, d2, x2, b2) #define N_STM(r1, r3, d2, b2) N_RS(0x90, r1, r3, d2, b2) #define N_SR(r1, r2) N_RR(0x1B, r1, r2) #define N_S(r1, d2, x2, b2) N_RX(0x5B, r1, d2, x2, b2) #define N_SH(r1, d2, x2, b2) N_RX(0x4B, r1, d2, x2, b2) #define N_SLR(r1, r2) N_RR(0x1F, r1, r2) #define N_SL(r1, d2, x2, b2) N_RX(0x5F, r1, d2, x2, b2) #define N_SVC(i) N_RR2(0x0A, i) #define N_TS(d2, b2) N_S2(0x93, d2, b2) #define N_TM(d1, b1, i2) N_SI(0x91, d1, b1, i2) #define N_TMH(r1, i2) N_RI2(0xA7, 0x00, r1, i2) #define N_TML(r1, i2) N_RI2(0xA7, 0x01, r1, i2) #define N_TR(d1, l, b1, d2, b2) N_SS(0xDC, d1, (l - 1), b1, d2, b2) #define N_TRT(d1, l, b1, d2, b2) N_SS(0xDD, d1, (l - 1), b1, d2, b2) #define N_TRE(r1, r2) N_RRE(0xB2A5, r1, r2) #define N_UNPK(d1, l1, b1, d2, l2, b2) N_SS2(0xF3, d1, (l1 - 1), b1, d2, (l2 - 2), b2) #define N_UPT() N_E(0x0102) /* Chapter 9. Floating point instructions */ #define N_LER(r1, r2) N_RR(0x38, r1, r2) #define N_LDR(r1, r2) N_RR(0x28, r1, r2) #define N_LXR(r1, r2) N_RRE(0xB365, r1, r2) #define N_LE(r1, d2, x2, b2) N_RX(0x78, r1, d2, x2, b2) #define N_LD(r1, d2, x2, b2) N_RX(0x68, r1, d2, x2, b2) #define N_LZER(r1) N_RRE(0xB374, r1, 0x0) #define N_LZDR(r1) N_RRE(0xB375, r1, 0x0) #define N_LZXR(r1) N_RRE(0xB376, r1, 0x0) #define N_STE(r1, d2, x2, b2) N_RX(0x70, r1, d2, x2, b2) #define N_STD(r1, d2, x2, b2) N_RX(0x60, r1, d2, x2, b2) /* chapter 19. Binary floating point instructions */ #define N_AEBR(r1, r2) N_RRE(0xB30A, r1, r2) #define N_ADBR(r1, r2) N_RRE(0xB31A, r1, r2) #define N_AXBR(r1, r2) N_RRE(0xB34A, r1, r2) #define N_AEB(r1, d2, x2, b2) N_RXE(0xED0A, r1, d2, x2, b2) #define N_ADB(r1, d2, x2, b2) N_RXE(0xED1A, r1, d2, x2, b2) #define N_CEBR(r1, r2) N_RRE(0xB309, r1, r2) #define N_CDBR(r1, r2) N_RRE(0xB319, r1, r2) #define N_CXBR(r1, r2) N_RRE(0xB349, r1, r2) #define N_CEB(r1, d2, x2, b2) N_RXE(0xED09, r1, d2, x2, b2) #define N_CDB(r1, d2, x2, b2) N_RXE(0xED19, r1, d2, x2, b2) #define N_CEFBR(r1, r2) N_RRE(0xB394, r1, r2) #define N_CDFBR(r1, r2) N_RRE(0xB395, r1, r2) #define N_CXFBR(r1, r2) N_RRE(0xB396, r1, r2) #define N_CFEBR(r1, m3, r2) N_RRF(0xB398, r1, m3, r2) #define N_CFDBR(r1, m3, r2) N_RRF(0xB399, r1, m3, r2) #define N_CFXBR(r1, m3, r2) N_RRF(0xB39A, r1, m3, r2) #define N_DEBR(r1, r2) N_RRE(0xB30D, r1, r2) #define N_DDBR(r1, r2) N_RRE(0xB31D, r1, r2) #define N_DXBR(r1, r2) N_RRE(0xB34D, r1, r2) #define N_DEB(r1, d2, x2, b2) N_RXE(0xED0D, r1, d2, x2, b2) #define N_DDB(r1, d2, x2, b2) N_RXE(0xED1D, r1, d2, x2, b2) #define N_LCEBR(r1, r2) N_RRE(0xB303, r1, r2) #define N_LCDBR(r1, r2) N_RRE(0xB313, r1, r2) #define N_LCXBR(r1, r2) N_RRE(0xB343, r1, r2) #define N_LDEBR(r1, r2) N_RRE(0xB304, r1, r2) # define SZ_LDEBR SZ_RRE #define N_LXDBR(r1, r2) N_RRE(0xB305, r1, r2) #define N_LXEBR(r1, r2) N_RRE(0xB306, r1, r2) #define N_LEDBR(r1, r2) N_RRE(0xB344, r1, r2) #define N_LDXBR(r1, r2) N_RRE(0xB345, r1, r2) #define N_LEXBR(r1, r2) N_RRE(0xB346, r1, r2) #define N_LTEBR(r1, r2) N_RRE(0xB302, r1, r2) #define N_LTDBR(r1, r2) N_RRE(0xB312, r1, r2) #define N_LTXBR(r1, r2) N_RRE(0xB342, r1, r2) #define N_MEEBR(r1, r2) N_RRE(0xB317, r1, r2) #define N_MDBR(r1, r2) N_RRE(0xB31C, r1, r2) #define N_MXBR(r1, r2) N_RRE(0xB34C, r1, r2) #define N_MDEBR(r1, r2) N_RRE(0xB30C, r1, r2) #define N_MXDBR(r1, r2) N_RRE(0xB307, r1, r2) #define N_SEBR(r1, r2) N_RRE(0xB30B, r1, r2) #define N_SDBR(r1, r2) N_RRE(0xB31B, r1, r2) #define N_SXBR(r1, r2) N_RRE(0xB34B, r1, r2) #define N_SEB(r1, d2, x2, b2) N_RXE(0xED0B, r1, d2, x2, b2) #define N_SDB(r1, d2, x2, b2) N_RXE(0xED1B, r1, d2, x2, b2) /* Alpha like instructions */ #define M_CALL(r2) N_BASR(R14, r2) #define M_ILL(data) N_ILL(data) #define M_ILL2(data1, data2) N_ILL((_UBITS(data1, 4) << 4) | _UBITS(data2, 4)) #define M_LONG(l) N_LONG(l) #define M_ILD(r, b, d) \ do { \ if (N_VALID_DISP(d)) { \ N_L(r, d, RN, b); \ } else if ((r == R0) && N_VALID_IMM(d)) { \ N_LR(R0, R1); \ N_LHI(R1, d); \ N_L(R1, 0, R1, b); \ N_XR(R1, R0); \ N_XR(R0, R1); \ N_XR(R1, R0); \ } else if ((r != R0) && N_VALID_IMM(d)) { \ N_LHI(r, d); N_L(r, 0, r, b); \ } else { \ N_BRAS(r, SZ_BRAS + SZ_LONG); \ N_LONG(d); \ N_L(r, 0, RN, r); \ N_L(r, 0, r, b); \ } \ } while (0) #define M_ILD_DSEG(r, d) M_ILD(r, REG_PV, N_DSEG_DISP(d)) #define M_ALD(r, b, d) M_ILD(r, b, d) #define M_ALD_DSEG(r, d) M_ALD(r, REG_PV, N_DSEG_DISP(d)) #define M_LDA(r, b, d) \ do { \ if (N_VALID_DISP(d)) { \ N_LA(r, d, RN, b); \ } else if (N_VALID_IMM(d)) { \ N_LHI(r, d); \ N_LA(r, 0, r, b); \ } else { \ N_BRAS(r, SZ_BRAS + SZ_LONG); \ N_LONG(d); \ N_L(r, 0, RN, r); \ N_LA(r, 0, r, b); \ } \ } while (0) #define M_LDA_DSEG(r, d) M_LDA(r, REG_PV, N_DSEG_DISP(d)) #define M_FLD(r, b, d) N_LE(r, d, RN, b) #define M_FLDN(r, b, d, t) _IFNEG( \ d, \ N_LHI(t, d); N_LE(r, 0, t, b), \ N_LE(r, d, RN, b) \ ) #define M_FLD_DSEG(r, d, t) M_FLDN(r, REG_PV, N_DSEG_DISP(d), t) #define M_DLD(r, b, d) N_LD(r, d, RN, b) #define M_DLDN(r, b, d, t) _IFNEG( \ d, \ N_LHI(t, d); N_LD(r, 0, t, b), \ N_LD(r, d, RN, b) \ ) #define M_DLD_DSEG(r, d, t) M_DLDN(r, REG_PV, N_DSEG_DISP(d), t) #define M_LLD(r, b, d) _IFNEG( \ d, \ N_LHI(GET_LOW_REG(r), d); \ N_L(GET_HIGH_REG(r), 0, GET_LOW_REG(r), b); \ N_L(GET_LOW_REG(r), 4, GET_LOW_REG(r), b), \ N_L(GET_HIGH_REG(r), (d) + 0, RN, b); N_L(GET_LOW_REG(r), (d) + 4, RN, b) \ ) #define M_LLD_DSEG(r, d) M_LLD(r, REG_PV, N_DSEG_DISP(d) /* MOV(a, b) -> mov from A to B */ #define M_MOV(a, b) N_LR(b, a) #define M_FMOV(a, b) N_LDR(b, a) #define M_DST(r, b, d) _IFNEG(d, assert(0), N_STD(r, d, RN, b)) #define M_FST(r, b, d) _IFNEG(d, assert(0), N_STE(r, d, RN, b)) #define M_IST(r, b, d) _IFNEG( \ d, \ assert(0), \ N_ST(r, d, RN, b) \ ) #define M_AST(r, b, d) M_IST(r, b, d) #define M_LST(r, b, d) _IFNEG( \ d, \ assert(0), \ N_ST(GET_HIGH_REG(r), (d) + 0, RN, b); N_ST(GET_LOW_REG(r), (d) + 4, RN, b) \ ) #define M_TEST(r) N_LTR(r, r) #define M_BEQ(off) N_BRC(DD_E, off) #define M_BNE(off) N_BRC(DD_NE, off) #define M_BLE(off) N_BRC(DD_LE, off) #define M_BGT(off) N_BRC(DD_H, off) #define M_BLT(off) N_BRC(DD_L, off) #define M_BGE(off) N_BRC(DD_HE, off) #define M_BO(off) N_BRC(DD_O, off) #define M_CMP(r1, r2) N_CR(r1, r2) #define M_CMPU(r1, r2) N_CLR(r1, r2) #define M_CLR(r) N_LHI(r, 0) #define M_AADD_IMM(val, reg) N_AHI(reg, val) #define M_IADD_IMM(val, reg) N_AHI(reg, val) #define M_ISUB_IMM(val, reg) N_AHI(reg, -(val)) #define M_ASUB_IMM(val, reg) N_AHI(reg, -(val)) #define M_RET N_BCR(DD_ANY, R14) #define M_BSR(ret_reg, disp) N_BRAS(ret_reg, disp) #define M_BR(disp) N_BRC(DD_ANY, disp) #define M_JMP(rs, rd) _IF(rs == RN, N_BCR(DD_ANY, rd), N_BASR(rs, rd)) #define M_NOP N_BC(0, 0, RN, RN) #define M_NOP2 N_BCR(0, RN) #define M_NOP3 N_BCR(0, 1) #define M_JSR(reg_ret, reg_addr) N_BASR(reg_ret, reg_addr) #define M_ICMP(a, b) N_CR(a, b) #define M_ICMPU(a, b) N_CLR(a, b) #define M_ICMP_IMM(a, b) N_CHI(a, b) #define M_CVTIF(src, dst) N_CEFBR(dst, src) #define M_CVTID(src, dst) N_CDFBR(dst, src) #define M_FMUL(a, dest) N_MEEBR(dest, a) #define M_FSUB(a, dest) N_SEBR(dest, a) #define M_FADD(a, dest) N_AEBR(dest, a) #define M_FDIV(a, dest) N_DEBR(dest, a) #define M_DMUL(a, dest) N_MDBR(dest, a) #define M_DSUB(a, dest) N_SDBR(dest, a) #define M_DADD(a, dest) N_ADBR(dest, a) #define M_DDIV(a, dest) N_DDBR(dest, a) #define M_CVTFI(src, dst) N_CFEBR(dst, 5, src) #define M_CVTDI(src, dst) N_CFDBR(dst, 5, src) #define M_IADD(a, dest) N_AR(dest, a) #define M_AADD(a, dest) N_AR(dest, a) #define M_ISUB(a, dest) N_SR(dest, a) #define M_ASUB(a, dest) N_SR(dest, a) #define M_IAND(a, dest) N_NR(dest, a) #define M_IOR(a, dest) N_OR(dest, a) #define M_IXOR(a, dest) N_XR(dest, a) #define M_CVTFD(src,dst) N_LDEBR(dst, src) #define M_CVTDF(src,dst) N_LEDBR(dst, src) #define M_SLL_IMM(imm, reg) N_SLL(reg, imm, RN) #define M_SLA_IMM(imm, reg) N_SLA(reg, imm, RN) #define M_SLDL_IMM(imm, reg) N_SLDL(reg, imm, RN) #define M_SLDA_IMM(imm, reg) N_SLDA(reg, imm, RN) #define M_SRL_IMM(imm, reg) N_SRL(reg, imm, RN) #define M_SRA_IMM(imm, reg) N_SRA(reg, imm, RN) #define M_SRDL_IMM(imm, reg) N_SRDL(reg, imm, RN) #define M_SRDA_IMM(imm, reg) N_SRDA(reg, imm, RN) #define M_SLL(op, dst) N_SLL(dst, 0, op) #define M_SLA(op, dst) N_SLA(dst, 0, op) #define M_SLDL(op, dst) N_SLDL(dst, 0, op) #define M_SLDA(op, dst) N_SLDA(dst, 0, op) #define M_SRL(op, dst) N_SRL(dst, 0, op) #define M_SRA(op, dst) N_SRA(dst, 0, op) #define M_SRDL(op, dst) N_SRDL(dst, 0, op) #define M_SRDA(op, dst) N_SRDA(dst, 0, op) #define M_IMUL_IMM(val, reg) N_MHI(reg, val) #define M_IMUL(a, dest) N_MSR(dest, a) #define M_INEG(a, dest) N_LCR(dest, a) #define M_FCMP(a, b) N_CEBR(a, b) #define M_DCMP(a, b) N_CDBR(a, b) #define M_FMOVN(r, dst) N_LCEBR(dst, r) #define M_DMOVN(r, dst) N_LCDBR(dst, r) #define ICONST(reg, i) \ do { \ if (N_VALID_IMM(i)) { \ N_LHI(reg, i); \ } else { \ disp = dseg_add_s4(cd, (i)); \ M_ILD_DSEG(reg, disp); \ } \ } while (0) #define LCONST(reg,c) \ do { \ ICONST(GET_HIGH_REG((reg)), (s4) ((s8) (c) >> 32)); \ ICONST(GET_LOW_REG((reg)), (s4) ((s8) (c))); \ } while (0) /* 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(reg,dreg) \ do { \ if ((reg) != (dreg)) { \ M_MOV(reg, dreg); \ } \ } 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) /* 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(reg,dreg) \ do { \ if ((reg) != (dreg)) { \ M_FMOV(reg, dreg); \ } \ } while (0) #define M_ISUB_IMM32(imm, tmpreg, reg) \ do { \ if (N_VALID_IMM(imm)) { \ M_ISUB_IMM(imm, reg); \ } else { \ ICONST(tmpreg, imm); \ M_ISUB(tmpreg, reg); \ } \ } while (0) #define M_ASUB_IMM32(imm, tmpreg, reg) M_ISUB_IMM32(imm, tmpreg, reg) #define PROFILE_CYCLE_START #define PROFILE_CYCLE_STOP #endif /* _CODEGEN_H */ /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where * Emacs will automagically detect them. * --------------------------------------------------------------------- * Local variables: * mode: c * indent-tabs-mode: t * c-basic-offset: 4 * tab-width: 4 * End: */