--- /dev/null
+/*
+ * jit-gen-alpha.h - Code generation macros for the alpha processor.
+ *
+ * Copyright (C) 2006 Southern Storm Software, Pty Ltd.
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _JIT_GEN_ALPHA_H
+#define _JIT_GEN_ALPHA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * enumerate the 32 integer registers.
+ *
+ * See JIT_REG_INFO in jit-rules-alpha.h for details about registers
+ */
+typedef enum {
+ ALPHA_R0 = 0, ALPHA_V0 = ALPHA_R0, /* Function result */
+
+ ALPHA_R1 = 1, ALPHA_T0 = ALPHA_R1, /* Temp registers */
+ ALPHA_R2 = 2, ALPHA_T1 = ALPHA_R2,
+ ALPHA_R3 = 3, ALPHA_T2 = ALPHA_R3,
+ ALPHA_R4 = 4, ALPHA_T3 = ALPHA_R4,
+ ALPHA_R5 = 5, ALPHA_T4 = ALPHA_R5,
+ ALPHA_R6 = 6, ALPHA_T5 = ALPHA_R6,
+ ALPHA_R7 = 7, ALPHA_T6 = ALPHA_R7,
+ ALPHA_R8 = 8, ALPHA_T7 = ALPHA_R8,
+
+ ALPHA_R9 = 9, ALPHA_S0 = ALPHA_R9, /* Saved registers */
+ ALPHA_R10 = 10, ALPHA_S1 = ALPHA_R10,
+ ALPHA_R11 = 11, ALPHA_S2 = ALPHA_R11,
+ ALPHA_R12 = 12, ALPHA_S3 = ALPHA_R12,
+ ALPHA_R13 = 13, ALPHA_S4 = ALPHA_R13,
+ ALPHA_R14 = 14, ALPHA_S5 = ALPHA_R14,
+
+ ALPHA_R15 = 15, ALPHA_S6 = ALPHA_R15, /* ALPHA_R15 can hold either a saved value */
+ ALPHA_FP = ALPHA_R15, /* or the frame pointer */
+
+ ALPHA_R16 = 16, ALPHA_A0 = ALPHA_R16, /* First 6 arguments */
+ ALPHA_R17 = 17, ALPHA_A1 = ALPHA_R17,
+ ALPHA_R18 = 18, ALPHA_A2 = ALPHA_R18,
+ ALPHA_R19 = 19, ALPHA_A3 = ALPHA_R19,
+ ALPHA_R20 = 20, ALPHA_A4 = ALPHA_R20,
+ ALPHA_R21 = 21, ALPHA_A5 = ALPHA_R21,
+
+ ALPHA_R22 = 22, ALPHA_T8 = ALPHA_R22, /* More temp registers */
+ ALPHA_R23 = 23, ALPHA_T9 = ALPHA_R23,
+ ALPHA_R24 = 24, ALPHA_T10 = ALPHA_R24,
+ ALPHA_R25 = 25, ALPHA_T11 = ALPHA_R25,
+
+ ALPHA_R26 = 26, ALPHA_RA = ALPHA_R26, /* Return address */
+
+ ALPHA_R27 = 27, ALPHA_T12 = ALPHA_R27, /* ALPHA_R27 can hold either a temp value */
+ ALPHA_PV = ALPHA_R27,
+
+ ALPHA_R28 = 28, ALPHA_AT = ALPHA_R28, /* Reeserved for the assembler */
+
+ ALPHA_R29 = 29, ALPHA_GP = ALPHA_R29, /* Global pointer */
+
+ ALPHA_R30 = 30, ALPHA_SP = ALPHA_R30, /* Stack pointer */
+
+ ALPHA_R31 = 31, ALPHA_ZERO = ALPHA_R31 /* Contains the value 0 */
+} ALPHA_REG;
+
+/*
+ * enumerate the 32 floating-point registers.
+ *
+ * See JIT_REG_INFO in jit-rules-alpha.h for details about registers
+ */
+typedef enum {
+ /* Function result */
+ ALPHA_F0 = 0, ALPHA_FV0 = ALPHA_F0, /* real part */
+ ALPHA_F1 = 1, ALPHA_FV1 = ALPHA_F1, /* complex part */
+
+ ALPHA_F2 = 2, ALPHA_FS0 = ALPHA_F2, /* Saved registers */
+ ALPHA_F3 = 3, ALPHA_FS1 = ALPHA_F3,
+ ALPHA_F4 = 4, ALPHA_FS2 = ALPHA_F4,
+ ALPHA_F5 = 5, ALPHA_FS3 = ALPHA_F5,
+ ALPHA_F6 = 6, ALPHA_FS4 = ALPHA_F6,
+ ALPHA_F7 = 7, ALPHA_FS5 = ALPHA_F7,
+ ALPHA_F8 = 8, ALPHA_FS6 = ALPHA_F8,
+ ALPHA_F9 = 9, ALPHA_FS7 = ALPHA_F9,
+
+ ALPHA_F10 = 10, ALPHA_FT0 = ALPHA_F10, /* Temp registers */
+ ALPHA_F11 = 11, ALPHA_FT1 = ALPHA_F11,
+ ALPHA_F12 = 12, ALPHA_FT2 = ALPHA_F12,
+ ALPHA_F13 = 13, ALPHA_FT3 = ALPHA_F13,
+ ALPHA_F14 = 14, ALPHA_FT4 = ALPHA_F14,
+ ALPHA_F15 = 15, ALPHA_FT5 = ALPHA_F15,
+
+ ALPHA_F16 = 16, ALPHA_FA0 = ALPHA_F16, /* First 6 arguments */
+ ALPHA_F17 = 17, ALPHA_FA1 = ALPHA_F17,
+ ALPHA_F18 = 18, ALPHA_FA2 = ALPHA_F18,
+ ALPHA_F19 = 19, ALPHA_FA3 = ALPHA_F19,
+ ALPHA_F20 = 20, ALPHA_FA4 = ALPHA_F20,
+ ALPHA_F21 = 21, ALPHA_FA5 = ALPHA_F21,
+
+ ALPHA_F22 = 22, ALPHA_FE0 = ALPHA_F22, /* Temp registers for expression evaluation. */
+ ALPHA_F23 = 23, ALPHA_FE1 = ALPHA_F23,
+ ALPHA_F24 = 24, ALPHA_FE2 = ALPHA_F24,
+ ALPHA_F25 = 25, ALPHA_FE3 = ALPHA_F25,
+ ALPHA_F26 = 26, ALPHA_FE4 = ALPHA_F26,
+ ALPHA_F27 = 27, ALPHA_FE5 = ALPHA_F27,
+ ALPHA_F28 = 28, ALPHA_FE6 = ALPHA_F28,
+ ALPHA_F29 = 29, ALPHA_FE7 = ALPHA_F29,
+ ALPHA_F30 = 30, ALPHA_FE8 = ALPHA_F30,
+
+ ALPHA_F31 = 31, ALPHA_FZERO = ALPHA_F31 /*Contains the value 0.0 */
+} ALPHA_FREG;
+
+/*
+ * Number of registers that are used for parameters.
+ *
+ * 6 registers a0-a5 (i.e. $16-$21) to pass integer parameters
+ * 6 registers fa0-fa5 (i.e. $f16-$f21) to pass floating-point parameters
+ * Additional parameters are stored on the stack.
+ */
+#define ALPHA_NUM_PARAM_REGS 6
+
+/*
+ * each alpha machine code instruction is 32-bits long.
+ */
+
+typedef unsigned int * alpha_inst;
+
+#define ALPHA_REG_MASK 0x1f
+#define ALPHA_REGA_SHIFT 0x15
+#define ALPHA_REGB_SHIFT 0x10
+#define ALPHA_REGC_SHIFT 0x00
+
+#define ALPHA_OP_MASK 0x3f
+#define ALPHA_OP_SHIFT 0x1a
+
+#define ALPHA_LIT_MASK 0x7f
+#define ALPHA_LIT_SHIFT 0x0d
+
+#define ALPHA_FUNC_MASK 0x7f
+#define ALPHA_FUNC_SHIFT 0x5
+
+#define ALPHA_FUNC_MEM_BRANCH_MASK 0x3
+#define ALPHA_FUNC_MEM_BRANCH_SHIFT 0xe
+#define ALPHA_HINT_MASK 0x3fff
+
+#define ALPHA_OFFSET_MASK 0xffff
+#define ALPHA_BRANCH_OFFSET_MASK 0x1fffff
+
+/*
+ * Define opcodes
+ */
+
+#define ALPHA_OP_LDA 0x08
+#define ALPHA_OP_LDAH 0x09
+#define ALPHA_OP_LDBU 0x0a
+#define ALPHA_OP_LDQ_U 0x0b
+#define ALPHA_OP_LDWU 0x0c
+#define ALPHA_OP_STW 0x0d
+#define ALPHA_OP_STB 0x0e
+#define ALPHA_OP_STQ_U 0x0f
+#define ALPHA_OP_ADDL 0x10
+#define ALPHA_OP_S4ADDL 0x10
+#define ALPHA_OP_SUBL 0x10
+#define ALPHA_OP_S4SUBL 0x10
+#define ALPHA_OP_CMPBGE 0x10
+#define ALPHA_OP_S8ADDL 0x10
+#define ALPHA_OP_S8SUBL 0x10
+#define ALPHA_OP_CMPULT 0x10
+#define ALPHA_OP_ADDQ 0x10
+#define ALPHA_OP_S4ADDQ 0x10
+#define ALPHA_OP_SUBQ 0x10
+#define ALPHA_OP_S4SUBQ 0x10
+#define ALPHA_OP_CMPEQ 0x10
+#define ALPHA_OP_S8ADDQ 0x10
+#define ALPHA_OP_S8SUBQ 0x10
+#define ALPHA_OP_CMPULE 0x10
+#define ALPHA_OP_ADDLV 0x10
+#define ALPHA_OP_SUBLV 0x10
+#define ALPHA_OP_ADDQV 0x10
+#define ALPHA_OP_SUBQV 0x10
+#define ALPHA_OP_CMPLE 0x10
+#define ALPHA_OP_AND 0x11
+#define ALPHA_OP_BIC 0x11
+#define ALPHA_OP_CMOVLBS 0x11
+#define ALPHA_OP_CMOVLBC 0x11
+#define ALPHA_OP_NOP 0x11
+#define ALPHA_OP_CLR 0x11
+#define ALPHA_OP_MOV 0x11
+#define ALPHA_OP_OR 0x11
+#define ALPHA_OP_BIS 0x11
+#define ALPHA_OP_CMOVEQ 0x11
+#define ALPHA_OP_CMOVNE 0x11
+#define ALPHA_OP_NOT 0x11
+#define ALPHA_OP_ORNOT 0x11
+#define ALPHA_OP_XOR 0x11
+#define ALPHA_OP_CMOVLT 0x11
+#define ALPHA_OP_CMOVGE 0x11
+#define ALPHA_OP_EQV 0x11
+#define ALPHA_OP_XORNOT 0x11
+#define ALPHA_OP_AMASK 0x11
+#define ALPHA_OP_CMOVLE 0x11
+#define ALPHA_OP_CMOVLE 0x11
+#define ALPHA_OP_CMOVGT 0x11
+#define ALPHA_OP_IMPLVER 0x11
+#define ALPHA_OP_MSKBL 0x12
+#define ALPHA_OP_EXTBL 0x12
+#define ALPHA_OP_INSBL 0x12
+#define ALPHA_OP_MSKWL 0x12
+#define ALPHA_OP_EXTWL 0x12
+#define ALPHA_OP_INSWL 0x12
+#define ALPHA_OP_MSKLL 0x12
+#define ALPHA_OP_EXTLL 0x12
+#define ALPHA_OP_INSLL 0x12
+#define ALPHA_OP_ZAP 0x12
+#define ALPHA_OP_ZAPNOT 0x12
+#define ALPHA_OP_MSKQL 0x12
+#define ALPHA_OP_SRL 0x12
+#define ALPHA_OP_EXTQA 0x12
+#define ALPHA_OP_SLL 0x12
+#define ALPHA_OP_INSQL 0x12
+#define ALPHA_OP_SRA 0x12
+#define ALPHA_OP_MSKWH 0x12
+#define ALPHA_OP_INSWH 0x12
+#define ALPHA_OP_EXTWH 0x12
+#define ALPHA_OP_MSKLH 0x12
+#define ALPHA_OP_INSLH 0x12
+#define ALPHA_OP_EXTLH 0x12
+#define ALPHA_OP_MSKQH 0x12
+#define ALPHA_OP_INSQH 0x12
+#define ALPHA_OP_EXTQH 0x12
+#define ALPHA_OP_MULL 0x13
+#define ALPHA_OP_MULQ 0x13
+#define ALPHA_OP_UMULH 0x13
+#define ALPHA_OP_MULLV 0x13
+#define ALPHA_OP_MULLQV 0x13
+#define ALPHA_OP_JMP 0x1a
+#define ALPHA_OP_JSR 0x1a
+#define ALPHA_OP_RET 0x1a
+#define ALPHA_OP_JSRCO 0x1a
+#define ALPHA_OP_LDF 0x20
+#define ALPHA_OP_LDG 0x21
+#define ALPHA_OP_LDS 0x22
+#define ALPHA_OP_LDT 0x23
+#define ALPHA_OP_LDQF 0x23
+#define ALPHA_OP_STF 0x24
+#define ALPHA_OP_STG 0x25
+#define ALPHA_OP_STS 0x26
+#define ALPHA_OP_STT 0x27
+#define ALPHA_OP_LDL 0x28
+#define ALPHA_OP_LDQ 0x29
+#define ALPHA_OP_LDL_L 0x2a
+#define ALPHA_OP_LDQ_L 0x2b
+#define ALPHA_OP_STL 0x2c
+#define ALPHA_OP_STQ 0x2d
+#define ALPHA_OP_STL_C 0x2e
+#define ALPHA_OP_STQ_C 0x2f
+#define ALPHA_OP_BR 0x30
+#define ALPHA_OP_FBEQ 0x31
+#define ALPHA_OP_FBLT 0x32
+#define ALPHA_OP_FBLE 0x33
+#define ALPHA_OP_BSR 0x34
+#define ALPHA_OP_FBNE 0x35
+#define ALPHA_OP_FBGE 0x36
+#define ALPHA_OP_FBGT 0x37
+#define ALPHA_OP_BLBC 0x38
+#define ALPHA_OP_BEQ 0x39
+#define ALPHA_OP_BLT 0x3a
+#define ALPHA_OP_BLE 0x3b
+#define ALPHA_OP_BLBS 0x3c
+#define ALPHA_OP_BNE 0x3d
+#define ALPHA_OP_BGE 0x3e
+#define ALPHA_OP_BGT 0x3f
+
+/*
+ * Define functions
+ */
+
+/* register operations -- use with ALPHA_OP_* == 0x10 */
+#define ALPHA_FUNC_ADDL 0x00
+#define ALPHA_FUNC_S4ADDL 0x02
+#define ALPHA_FUNC_SUBL 0x09
+#define ALPHA_FUNC_S4SUBL 0x0b
+#define ALPHA_FUNC_CMPBGE 0x0f
+#define ALPHA_FUNC_S8ADDL 0x12
+#define ALPHA_FUNC_S8SUBL 0x1b
+#define ALPHA_FUNC_CMPULT 0x1d
+#define ALPHA_FUNC_ADDQ 0x20
+#define ALPHA_FUNC_S4ADDQ 0x22
+#define ALPHA_FUNC_SUBQ 0x29
+#define ALPHA_FUNC_S4SUBQ 0x2b
+#define ALPHA_FUNC_CMPEQ 0x2d
+#define ALPHA_FUNC_S9ADDQ 0x32
+#define ALPHA_FUNC_S9SUBQ 0x3b
+#define ALPHA_FUNC_CMPULE 0x3d
+#define ALPHA_FUNC_ADDLV 0x40
+#define ALPHA_FUNC_SUBLV 0x49
+#define ALPHA_FUNC_CMPLT 0x4d
+#define ALPHA_FUNC_ADDQV 0x60
+#define ALPHA_FUNC_SUBQV 0x69
+#define ALPHA_FUNC_CMPLE 0x6d
+
+/* bitwise operations -- use with ALPHA_OP_* == 0x11 */
+#define ALPHA_FUNC_AND 0x00
+#define ALPHA_FUNC_BIC 0x08
+#define ALPHA_FUNC_CMOVLBS 0x14
+#define ALPHA_FUNC_CMOVLBC 0x16
+#define ALPHA_FUNC_NOOP 0x20
+#define ALPHA_FUNC_CLR 0x20
+#define ALPHA_FUNC_MOV 0x20
+#define ALPHA_FUNC_OR 0x20
+#define ALPHA_FUNC_CMOVEQ 0x24
+#define ALPHA_FUNC_CMOVNE 0x2C
+#define ALPHA_FUNC_NOT 0x28
+#define ALPHA_FUNC_ORNOT 0x28
+#define ALPHA_FUNC_XOR 0x40
+#define ALPHA_FUNC_CMOVLT 0x44
+#define ALPHA_FUNC_COMVGE 0x46
+#define ALPHA_FUNC_EQV 0x48
+#define ALPHA_FUNC_AMASK 0x61
+#define ALPHA_FUNC_CMOVLE 0x64
+#define ALPHA_FUNC_CMOVGT 0x66
+#define ALPHA_FUNC_IMPLVER 0x6c
+#define ALPHA_FUNC_CMOVGT 0x66
+
+/* byte manipulation operations -- use with ALPHA_OP_* == 0x12 */
+#define ALPHA_FUNC_MSKBL 0x02
+#define ALPHA_FUNC_EXTBL 0x06
+#define ALPHA_FUNC_INSBL 0x0b
+#define ALPHA_FUNC_MSKWL 0x12
+#define ALPHA_FUNC_EXTWL 0x16
+#define ALPHA_FUNC_INSWL 0x1b
+#define ALPHA_FUNC_MSKLL 0x22
+#define ALPHA_FUNC_EXTLL 0x26
+#define ALPHA_FUNC_INSLL 0x2b
+#define ALPHA_FUNC_ZAP 0x30
+#define ALPHA_FUNC_ZAPNOT 0x31
+#define ALPHA_FUNC_MSKQL 0x32
+#define ALPHA_FUNC_SRL 0x34
+#define ALPHA_FUNC_EXTQL 0x36
+#define ALPHA_FUNC_SLL 0x39
+#define ALPHA_FUNC_INSQL 0x3b
+#define ALPHA_FUNC_SRA 0x3c
+#define ALPHA_FUNC_MSKWH 0x52
+#define ALPHA_FUNC_INSWH 0x57
+#define ALPHA_FUNC_EXTWH 0x5a
+#define ALPHA_FUNC_MSKLH 0x62
+#define ALPHA_FUNC_INSLH 0x67
+#define ALPHA_FUNC_EXTLH 0x6a
+#define ALPHA_FUNC_MSKQH 0x72
+#define ALPHA_FUNC_INSQH 0x77
+#define ALPHA_FUNC_EXTQH 0x7a
+
+/* multiplication operations -- use with ALPHA_OP_* == 0x13 */
+#define ALPHA_FUNC_MULL 0x00
+#define ALPHA_FUNC_MULQ 0x20
+#define ALPHA_FUNC_UMULH 0x30
+#define ALPHA_FUNC_MULLV 0x40
+#define ALPHA_FUNC_MULQV 0x60
+
+/* branching operations -- use with ALPHA_OP_* == 0x1a */
+#define ALPHA_FUNC_JMP 0x0
+#define ALPHA_FUNC_JSR 0x1
+#define ALPHA_FUNC_RET 0x2
+#define ALPHA_FUNC_JSRCO 0x3
+
+
+/* encode registers */
+#define alpha_encode_reg_a(reg) \
+ ((reg & ALPHA_REG_MASK) << ALPHA_REGA_SHIFT)
+
+#define alpha_encode_reg_b(reg) \
+ ((reg & ALPHA_REG_MASK) << ALPHA_REGB_SHIFT)
+
+#define alpha_encode_reg_c(reg) \
+ ((reg & ALPHA_REG_MASK) << ALPHA_REGC_SHIFT)
+
+/* encode literals */
+#define alpha_encode_lit(lit) \
+ ((lit & ALPHA_LIT_MASK) << ALPHA_LIT_SHIFT)
+
+/* encode opcodes */
+#define alpha_encode_op(op) \
+ ((op & ALPHA_OP_MASK) << ALPHA_OP_SHIFT)
+
+/* encode function codes */
+#define alpha_encode_func(func) \
+ ((func & ALPHA_FUNC_MASK) << ALPHA_FUNC_SHIFT)
+
+#define alpha_encode_func_mem_branch(func,hint) \
+ (((func & ALPHA_FUNC_MEM_BRANCH_MASK) << ALPHA_FUNC_MEM_BRANCH_SHIFT) | \
+ (hint & ALPHA_HINT_MASK))
+
+/*
+ * instruction encoding
+ */
+
+#define alpha_encode_mem(inst,op,dreg,sreg,offset) \
+ *(inst)++ = (alpha_encode_op(op) | alpha_encode_reg_a(dreg) | \
+ alpha_encode_reg_b(sreg) | (offset & ALPHA_OFFSET_MASK))
+
+#define alpha_encode_regops(inst,op,func,sreg0,sreg1,dreg) \
+ *(inst)++ = (alpha_encode_op(op) | alpha_encode_reg_a(sreg0) | \
+ alpha_encode_reg_b(sreg1)| alpha_encode_reg_c(dreg) | \
+ alpha_encode_func(func))
+
+#define alpha_encode_mem_branch(inst,op,func,dreg,sreg,hint) \
+ *(inst)++ = (alpha_encode_op(op) | alpha_encode_reg_a(dreg) | \
+ alpha_encode_reg_b(sreg) | \
+ alpha_encode_func_mem_branch(func,hint))
+
+#define alpha_encode_branch(inst,op,reg,offset) \
+ *(inst)++ = (alpha_encode_op(op) | alpha_encode_reg_a(reg) | \
+ (offset & ALPHA_BRANCH_OFFSET_MASK))
+
+#define alpha_encode_regops_lit(inst,op,func,sreg,lit,dreg) \
+ *(inst)++ = (alpha_encode_op(op) | alpha_encode_reg_a(sreg) | \
+ alpha_encode_lit(lit) | alpha_encode_reg_c(dreg) | \
+ alpha_encode_func(func) | 0x1000)
+
+/*
+ * define pneumonics
+ *
+ * A note about the naming convention...
+ *
+ * Some pneumonics can be used to operate on literals (aka immediate
+ * values) and registers. For example, the operands for 'addl' can be
+ * "sreg1, sreg2, dreg" or "sreg, lit, dreg". Since the opcodes are the
+ * same and the encoding of the literal is different than the encoding
+ * of the register, we need more than one alpha_addl macro.
+ *
+ * The naming convention I picked is: 'alpha_addl' will operate on
+ * registers and 'alpha_addli' will operate on registers and a literal.
+ * The 'i' suffix stands for immediate. It is the convention used in
+ * MIPS assembly. So when you want to use one of these macros for an
+ * immediate value, just use the pneumonic with the 'i' suffix.
+ *
+ * TODO: implement the missing macros!
+ *
+ * floating-point arithmetic, PAL (Privileged Architecture Library), and
+ * some special instructions (like those used for prefetching data and halting the system)
+ * have not been implmented yet.
+ */
+
+/* load and store operations */
+#define alpha_lda(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDA,dreg,sreg,offset)
+#define alpha_ldah(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDAH,dreg,sreg,offset)
+#define alpha_ldbu(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDBU,dreg,sreg,offset)
+#define alpha_ldq_u(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDQ_U,dreg,sreg,offset)
+#define alpha_ldwu(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDWU,dreg,sreg,offset)
+#define alpha_stw(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STW,dreg,sreg,offset)
+#define alpha_stb(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STB,dreg,sreg,offset)
+#define alpha_stq_u(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STQ_U,dreg,sreg,offset)
+
+/* arithmetic operations */
+#define alpha_addl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_ADDL,ALPHA_FUNC_ADDL,sreg0,sreg1,dreg)
+#define alpha_s4addl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_S4ADDL,ALPHA_FUNC_S4ADDL,sreg0,sreg1,dreg)
+#define alpha_subl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_SUBL,ALPHA_FUNC_SUBL,sreg0,sreg1,dreg)
+#define alpha_s4subl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_S4SUBL,ALPHA_FUNC_S4SUBL,sreg0,sreg1,dreg)
+#define alpha_cmpbge(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMPBGE,ALPHA_FUNC_CMPBGE,sreg0,sreg1,dreg)
+#define alpha_s8addl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_S8ADDL,ALPHA_FUNC_S8ADDL,sreg0,sreg1,dreg)
+#define alpha_s8subl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_S8SUBL,ALPHA_FUNC_S8SUBL,sreg0,sreg1,dreg)
+#define alpha_cmpult(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMPULT,ALPHA_FUNC_CMPULT,sreg0,sreg1,dreg)
+#define alpha_addq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_ADDQ,ALPHA_FUNC_ADDQ,sreg0,sreg1,dreg)
+#define alpha_s4addq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_S4ADDQ,ALPHA_FUNC_S4ADDQ,sreg0,sreg1,dreg)
+#define alpha_subq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_SUBQ,ALPHA_FUNC_SUBQ,sreg0,sreg1,dreg)
+#define alpha_s4subq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_S4SUBQ,ALPHA_FUNC_S4SUBQ,sreg0,sreg1,dreg)
+#define alpha_cmpeq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMPEQ,ALPHA_FUNC_CMPEQ,sreg0,sreg1,dreg)
+#define alpha_s8addq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_S8ADDQ,ALPHA_FUNC_S8ADDQ,sreg0,sreg1,dreg)
+#define alpha_s8subq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_S8SUBQ,ALPHA_FUNC_S8SUBQ,sreg0,sreg1,dreg)
+#define alpha_cmpule(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMPULE,ALPHA_FUNC_CMPULE,sreg0,sreg1,dreg)
+#define alpha_addlv(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_ADDLV,ALPHA_FUNC_ADDLV,sreg0,sreg1,dreg)
+#define alpha_sublv(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_SUBLV,ALPHA_FUNC_SUBLV,sreg0,sreg1,dreg)
+#define alpha_cmplt(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMPLT,ALPHA_FUNC_CMPLT,sreg0,sreg1,dreg)
+#define alpha_addqv(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_ADDQV,ALPHA_FUNC_ADDQV,sreg0,sreg1,dreg)
+#define alpha_subqv(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_SUBQV,ALPHA_FUNC_SUBQV,sreg0,sreg1,dreg)
+#define alpha_cmple(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMPLE,ALPHA_FUNC_CMPLE,sreg0,sreg1,dreg)
+
+/* bitwise / move operations */
+#define alpha_and(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_AND,ALPHA_FUNC_AND,sreg0,sreg1,dreg)
+#define alpha_bic(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_BIC,ALPHA_FUNC_BIC,sreg0,sreg1,dreg)
+#define alpha_cmovlbs(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMOVLBS,ALPHA_FUNC_CMOVLBS,sreg0,sreg1,dreg)
+#define alpha_cmovlbc(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMOVLBC,ALPHA_FUNC_CMOVLBC,sreg0,sreg1,dreg)
+#define alpha_bis(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_BIS,ALPHA_FUNC_BIS,sreg0,sreg1,dreg)
+#define alpha_cmoveq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMOVEQ,ALPHA_FUNC_CMOVEQ,sreg0,sreg1,dreg)
+#define alpha_cmovne(inst,sreg,dreg) alpha_encode_regops(inst,ALPHA_OP_CMOVNE,ALPHA_FUNC_CMOVNE,ALPHA_ZERO,sreg,dreg)
+#define alpha_ornot(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_ORNOT,ALPHA_FUNC_ORNOT,sreg0,sreg1,dreg)
+#define alpha_xor(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_XOR,ALPHA_FUNC_XOR,sreg0,sreg1,dreg)
+#define alpha_cmovlt(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMOVLT,ALPHA_FUNC_CMOVLT,sreg0,sreg1,dreg)
+#define alpha_cmovge(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMOVGE,ALPHA_FUNC_CMOVGE,sreg0,sreg1,dreg)
+#define alpha_eqv(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_EQV,ALPHA_FUNC_EQV,sreg0,sreg1,dreg)
+#define alpha_amask(inst,sreg,dreg) alpha_encode_regops(inst,ALPHA_OP_AMASK,ALPHA_FUNC_AMASK,ALPHA_ZERO,sreg,dreg)
+#define alpha_cmovle(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMOVLE,ALPHA_FUNC_CMOVLE,sreg0,sreg1,dreg)
+#define alpha_cmovgt(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_CMOVGT,ALPHA_FUNC_CMOVGT,sreg0,sreg1,dreg)
+#define alpha_implver(inst,dreg) alpha_encode_regops_lit(inst,ALPHA_OP_IMPLVER,ALPHA_FUNC_IMPLVER,ALPHA_ZERO,1,dreg)
+
+/* pseudo bitwise / move instructions */
+#define alpha_mov(inst,sreg,dreg) alpha_encode_regops(inst,ALPHA_OP_MOV,ALPHA_FUNC_MOV,ALPHA_ZERO,sreg,dreg)
+#define alpha_nop(inst) alpha_mov(inst,ALPHA_ZERO,ALPHA_ZERO)
+#define alpha_unop(inst) alpha_nop(inst)
+#define alpha_clr(inst,dreg) alpha_mov(inst,ALPHA_ZERO,dreg)
+#define alpha_or(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_OR,ALPHA_FUNC_OR,sreg0,sreg1,dreg)
+#define alpha_ori(inst,sreg,lit,dreg) alpha_encode_regops_lit(inst,ALPHA_OP_OR,ALPHA_FUNC_OR,sreg,lit,dreg)
+
+/* byte manipulation instructions */
+#define alpha_mskbl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MSKBL,ALPHA_FUNC_MSKBL,sreg0,sreg1,dreg)
+#define alpha_extbl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_EXTBL,ALPHA_FUNC_EXTBL,sreg0,sreg1,dreg)
+#define alpha_insbl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_INSBL,ALPHA_FUNC_INSBL,sreg0,sreg1,dreg)
+#define alpha_mskwl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MSKWL,ALPHA_FUNC_MSKWL,sreg0,sreg1,dreg)
+#define alpha_extwl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_EXTWL,ALPHA_FUNC_EXTWL,sreg0,sreg1,dreg)
+#define alpha_inswl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_INSWL,ALPHA_FUNC_INSWL,sreg0,sreg1,dreg)
+#define alpha_mskll(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MSKLL,ALPHA_FUNC_MSKLL,sreg0,sreg1,dreg)
+#define alpha_extll(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_EXTLL,ALPHA_FUNC_EXTLL,sreg0,sreg1,dreg)
+#define alpha_insll(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_INSLL,ALPHA_FUNC_INSLL,sreg0,sreg1,dreg)
+#define alpha_zap(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_ZAP,ALPHA_FUNC_ZAP,sreg0,sreg1,dreg)
+#define alpha_zapnot(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_ZAPNOT,ALPHA_FUNC_ZAPNOT,sreg0,sreg1,dreg)
+#define alpha_mskql(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MSKQL,ALPHA_FUNC_MSKQL,sreg0,sreg1,dreg)
+#define alpha_srl(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_SRL,ALPHA_FUNC_SRL,sreg0,sreg1,dreg)
+#define alpha_srli(inst,sreg,lit,dreg) alpha_encode_regops_lit(inst,ALPHA_OP_SRL,ALPHA_FUNC_SRL,sreg,lit,dreg)
+#define alpha_extql(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_EXTQL,ALPHA_FUNC_EXTQL,sreg0,sreg1,dreg)
+#define alpha_sll(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_SLL,ALPHA_FUNC_SLL,sreg0,sreg1,dreg)
+#define alpha_slli(inst,sreg,lit,dreg) alpha_encode_regops_lit(inst,ALPHA_OP_SLL,ALPHA_FUNC_SLL,sreg,lit,dreg)
+#define alpha_insql(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_INSQL,ALPHA_FUNC_INSQL,sreg0,sreg1,dreg)
+#define alpha_sra(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_SRA,ALPHA_FUNC_SRA,sreg0,sreg1,dreg)
+#define alpha_srai(inst,sreg,lit,dreg) alpha_encode_regops_lit(inst,ALPHA_OP_SRA,ALPHA_FUNC_SRA,sreg,lit,dreg)
+#define alpha_mskwh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MSKWH,ALPHA_FUNC_MSKWH,sreg0,sreg1,dreg)
+#define alpha_inswh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_INSWH,ALPHA_FUNC_INSWH,sreg0,sreg1,dreg)
+#define alpha_extwh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_EXTWH,ALPHA_FUNC_EXTWH,sreg0,sreg1,dreg)
+#define alpha_msklh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MSKLH,ALPHA_FUNC_MSKLH,sreg0,sreg1,dreg)
+#define alpha_inslh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_INSLH,ALPHA_FUNC_INSLH,sreg0,sreg1,dreg)
+#define alpha_extlh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_EXTLH,ALPHA_FUNC_EXTLH,sreg0,sreg1,dreg)
+#define alpha_mskqh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MSKQH,ALPHA_FUNC_MSKQH,sreg0,sreg1,dreg)
+#define alpha_insqh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_INSQH,ALPHA_FUNC_INSQH,sreg0,sreg1,dreg)
+#define alpha_extqh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_EXTQH,ALPHA_FUNC_EXTQH,sreg0,sreg1,dreg)
+
+/* multiplication operations */
+#define alpha_mull(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MULL,ALPHA_FUNC_MULL,sreg0,sreg1,dreg)
+#define alpha_mulq(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MULQ,ALPHA_FUNC_MULQ,sreg0,sreg1,dreg)
+#define alpha_umulh(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_UMULH,ALPHA_FUNC_UMULH,sreg0,sreg1,dreg)
+#define alpha_mullv(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MULLV,ALPHA_FUNC_MULLV,sreg0,sreg1,dreg)
+#define alpha_mulqv(inst,sreg0,sreg1,dreg) alpha_encode_regops(inst,ALPHA_OP_MULQV,ALPHA_FUNC_MULQV,sreg0,sreg1,dreg)
+
+/* memory branch operations */
+#define alpha_jmp(inst,dreg,sreg,hint) alpha_encode_mem_branch(inst,ALPHA_OP_JMP,ALPHA_FUNC_JMP,dreg,sreg,hint)
+#define alpha_jsr(inst,dreg,sreg,hint) alpha_encode_mem_branch(inst,ALPHA_OP_JSR,ALPHA_FUNC_JSR,dreg,sreg,hint)
+#define alpha_ret(inst,sreg,hint) alpha_encode_mem_branch(inst,ALPHA_OP_RET,ALPHA_FUNC_RET,ALPHA_ZERO,sreg,hint)
+#define alpha_jsrco(inst,dreg,sreg,hint) alpha_encode_mem_branch(inst,ALPHA_OP_JSRCO,ALPHA_FUNC_JSRCO,dreg,sreg,hint)
+
+/* memory operations */
+#define alpha_ldf(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDF,dreg,sreg,offset)
+#define alpha_ldg(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDG,dreg,sreg,offset)
+#define alpha_lds(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDS,dreg,sreg,offset)
+#define alpha_ldt(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDT,dreg,sreg,offset)
+#define alpha_stf(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STF,dreg,sreg,offset)
+#define alpha_stg(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STG,dreg,sreg,offset)
+#define alpha_sts(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STS,dreg,sreg,offset)
+#define alpha_stt(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STT,dreg,sreg,offset)
+#define alpha_ldl(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDL,dreg,sreg,offset)
+#define alpha_ldq(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDQ,dreg,sreg,offset)
+#define alpha_ldl_l(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDL_L,dreg,sreg,offset)
+#define alpha_ldq_l(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDQ_L,dreg,sreg,offset)
+#define alpha_ldqf(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_LDQF,dreg,sreg,offset)
+#define alpha_stl(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STL,dreg,sreg,offset)
+#define alpha_stq(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STQ,dreg,sreg,offset)
+#define alpha_stl_c(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STL_C,dreg,sreg,offset)
+#define alpha_stq_c(inst,dreg,sreg,offset) alpha_encode_mem(inst,ALPHA_OP_STQ_C,dreg,sreg,offset)
+#define alpha_br(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BR,reg,offset)
+#define alpha_fbeq(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_FBEQ,reg,offset)
+#define alpha_fblt(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_FBLT,reg,offset)
+#define alpha_fble(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_FBLE,reg,offset)
+#define alpha_bsr(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BSR,reg,offset)
+#define alpha_fbne(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_FBNE,reg,offset)
+#define alpha_fbge(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_FBGE,reg,offset)
+#define alpha_fbgt(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_FBGT,reg,offset)
+#define alpha_blbc(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BLBC,reg,offset)
+#define alpha_beq(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BEQ,reg,offset)
+#define alpha_blt(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BLT,reg,offset)
+#define alpha_ble(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BLE,reg,offset)
+#define alpha_blbs(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BLBS,reg,offset)
+#define alpha_bne(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BNE,reg,offset)
+#define alpha_bge(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BGE,reg,offset)
+#define alpha_bgt(inst,reg,offset) alpha_encode_branch(inst,ALPHA_OP_BGT,reg,offset)
+
+/*
+ * load immediate pseudo instruction.
+ */
+
+#define _alpha_li64(code,dreg,val) \
+do { \
+ unsigned long c1 = val; \
+ unsigned int d1,d2,d3,d4; \
+ \
+ /* This little bit of code deals with the sign bit */ \
+ /* It can be found in alpha_emit_set_long_const(...) */ \
+ /* from gcc-3.4.6/gcc/config/alpha/alpha.c */ \
+ \
+ d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000; \
+ c1 -= d1; \
+ d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000; \
+ c1 = (c1 - d2) >> 32; \
+ d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000; \
+ c1 -= d3; \
+ d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000; \
+ \
+ alpha_ldah(code,dreg,ALPHA_ZERO,d4>>16); \
+ alpha_lda(code,dreg,dreg,d3); \
+ alpha_slli(code,dreg,32,dreg); \
+ alpha_ldah(code,dreg,dreg,d2>>16); \
+ alpha_lda(code,dreg,dreg,d1); \
+ \
+} while (0)
+
+#define _alpha_li32(code,dreg,val) \
+do { \
+ unsigned int c1 = val; \
+ unsigned int d1,d2; \
+ \
+ d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000; \
+ c1 -= d1; \
+ d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000; \
+ \
+ alpha_ldah(code,dreg,ALPHA_ZERO,d2>>16); \
+ alpha_lda(code,dreg,dreg,d1); \
+ alpha_slli(code,dreg,32,dreg); \
+ alpha_srli(code,dreg,32,dreg); \
+ \
+} while (0)
+
+#define _alpha_li16(code,dreg,val) \
+do { \
+ alpha_lda(code,dreg,ALPHA_ZERO,(((val & 0xffff) ^ 0x8000) - 0x8000)); \
+ alpha_slli(code,dreg,48,dreg); \
+ alpha_srli(code,dreg,48,dreg); \
+ \
+} while (0)
+
+#define _alpha_li8(code,dreg,val) \
+do { \
+ alpha_lda(code,dreg,ALPHA_ZERO,(((val & 0xff) ^ 0x80) - 0x80)); \
+ alpha_slli(code,dreg,56,dreg); \
+ alpha_srli(code,dreg,56,dreg); \
+ \
+} while (0)
+
+#define alpha_li(code,dreg,val) \
+do { \
+ switch (sizeof(val)) { \
+ case 1: \
+ _alpha_li8(code,dreg,val); \
+ break; \
+ case 2: \
+ _alpha_li16(code,dreg,val); \
+ break; \
+ case 4: \
+ _alpha_li32(code,dreg,val); \
+ break; \
+ case 8: \
+ _alpha_li64(code,dreg,val); \
+ break; \
+ default: \
+ _alpha_li64(code,dreg,val); \
+ break; \
+ } \
+} while (0)
+
+/*
+ * Call a subroutine at a specific target location.
+ */
+
+#define alpha_call(inst,target) \
+do { \
+ int __call_offset = target - (inst+4); \
+ alpha_bsr(inst,ALPHA_RA,__call_offset); \
+} while (0)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _JIT_GEN_ALPHA_H */
--- /dev/null
+/*
+ * jit-rules-alpha.c - Rules that define the characteristics of the alpha.
+ *
+ * Copyright (C) 2006 Southern Storm Software, Pty Ltd.
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "jit-internal.h"
+#include "jit-rules.h"
+#include "jit-apply-rules.h"
+
+#if defined(JIT_BACKEND_ALPHA)
+
+#include "jit-elf-defs.h"
+#include "jit-gen-alpha.h"
+#include "jit-reg-alloc.h"
+#include "jit-setjmp.h"
+#include <stdio.h>
+
+/*
+ * _alpha_has_ieeefp()
+ *
+ * When the Alpha architecture's floating point unit was first designed,
+ * the designers traded performance for functionality. As a result, all
+ * Alpha systems below EV6 do not fully implement the IEEE floating
+ * point standard. For those earlier systems, there is no hardware
+ * support for denormalized numbers or exceptional IEEE values like not
+ * a number and positive/negative infinity. For systems without hardware
+ * support, the kernal can assist, but more you'll need to add
+ * instructions to trap into the kernel. Use this function to determine
+ * if hardware ieeefp is available.
+ *
+ * To get the kernel to assist when needed, use the following code:
+ *
+ * if (!_alpha_has_ieeefp())
+ * alpha_trapb(inst);
+ *
+ * RETURN VALUE:
+ * - TRUE if the CPU fully supports IEEE floating-point (i.e. >=ev6)
+ * - FALSE if the CPU needs kernel assistance
+ */
+int _alpha_has_ieeefp() {
+ unsigned long __implver;
+
+ /*
+ * __implver - major version number of the processor
+ *
+ * (__implver == 0) ev4 class processors
+ * (__implver == 1) ev5 class processors
+ * (__implver == 2) ev6 class processors
+ */
+ __asm__ ("implver %0" : "=r"(__implver));
+ return (__implver >= 2);
+}
+
+/*
+ * Setup or teardown the alpha code output process.
+ */
+#define jit_cache_setup_output(needed) \
+ alpha_inst inst = (alpha_inst) gen->posn.ptr; \
+ if(!jit_cache_check_for_n(&(gen->posn), (needed))) { \
+ jit_cache_mark_full(&(gen->posn)); \
+ return; \
+ } \
+
+#define jit_cache_end_output() \
+ gen->posn.ptr = (char*) inst
+
+/*
+ * Initialize the backend. This is normally used to configure registers
+ * that may not appear on all CPU's in a given family. For example, only
+ * some ARM cores have floating-point registers.
+ */
+void _jit_init_backend(void) {
+ /* Nothing to do here */;
+}
+
+/*
+ * Get the ELF machine and ABI type information for this platform. The
+ * machine field should be set to one of the EM_* values in
+ * jit-elf-defs.h. The abi field should be set to one of the ELFOSABI_*
+ * values in jit-elf-defs.h (ELFOSABI_SYSV will normally suffice if you
+ * are unsure). The abi_version field should be set to the ABI version,
+ * which is usually zero.
+ */
+void _jit_gen_get_elf_info(jit_elf_info_t *info) {
+ info->machine = EM_ALPHA;
+ info->abi = ELFOSABI_SYSV;
+ info->abi_version = 0;
+}
+
+/*
+ * Generate the prolog for a function into a previously-prepared buffer
+ * area of JIT_PROLOG_SIZE bytes in size. Returns the start of the
+ * prolog, which may be different than buf.
+ *
+ * This function is called at the end of the code generation process,
+ * not the beginning. At this point, it is known which callee save
+ * registers must be preserved, allowing the back end to output the
+ * most compact prolog possible.
+ */
+void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) {
+ unsigned int prolog[JIT_PROLOG_SIZE];
+ alpha_inst inst = prolog;
+ short int savereg_space = 0;
+ unsigned char reg;
+
+ /* NOT IMPLEMENTED YET */
+
+ /* Determine which registers need to be preserved and push them onto the stack */
+ for (reg = 0; reg < 32; reg++) {
+ if(jit_reg_is_used(gen->touched, reg) && (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) {
+ /* store the register value on the stack */
+ alpha_stq(inst,ALPHA_SP,reg,savereg_space);
+ savereg_space -= 8;
+ }
+ }
+
+ /* adjust the stack pointer to point to the 'top' of the stack */
+ alpha_li(inst,ALPHA_AT,savereg_space);
+ alpha_addq(inst,ALPHA_SP,ALPHA_AT,ALPHA_SP);
+
+ /* TODO see if ALPHA_RA needs to be saved or was saved above -----^ */
+
+ /* Copy the prolog into place and return the adjusted entry position */
+ reg = (int)(inst - prolog);
+ jit_memcpy(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg, prolog, reg);
+ return (void *)(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg);
+}
+
+/*
+ * Generate a function epilog, restoring the registers that were saved on entry to the
+ * function, and then returning.
+ *
+ * Only one epilog is generated per function. Functions with multiple jit_insn_return
+ * instructions will all jump to the common epilog. This is needed because the code
+ * generator may not know which callee save registers need to be restored by the
+ * epilog until the full function has been processed.
+ */
+void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) {
+ short int savereg_space = 0;
+ unsigned char reg;
+
+ alpha_inst inst;
+ void **fixup, **next;
+
+ /* NOT IMPLEMENTED YET */;
+
+ inst = (alpha_inst) gen->posn.ptr;
+
+ /* Determine which registers need to be restored when we return and restore them */
+ for (reg = 0; reg < 32; reg++) {
+ if (jit_reg_is_used(gen->touched, reg) && (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) {
+ /* store the register value on the stack */
+ alpha_ldq(inst,reg,ALPHA_SP,savereg_space);
+ savereg_space += 8;
+ }
+ }
+
+ /* adjust the stack pointer to point to the 'top' of the stack */
+ alpha_li(inst,ALPHA_AT,savereg_space);
+ alpha_addq(inst,ALPHA_SP,ALPHA_AT,ALPHA_SP);
+
+ fixup = (void **)(gen->epilog_fixup);
+ while (fixup) {
+ next = (void **)(fixup[0]);
+ fixup[0] = (void*) ((jit_nint) inst - (jit_nint) fixup - 4);
+ fixup = next;
+ }
+
+ /* Return from the current function */
+ alpha_ret(inst,ALPHA_RA,1);
+}
+
+/*
+ * Create instructions within func to clean up after a function call and
+ * to place the function's result into return_value. This should use
+ * jit_insn_pop_stack to pop values off the system stack and
+ * jit_insn_return_reg to tell libjit which register contains the return
+ * value. In the case of a void function, return_value will be NULL.
+ *
+ * Note: the argument values are passed again because it may not be
+ * possible to determine how many bytes to pop from the stack from the
+ * signature alone; especially if the called function is vararg.
+ */
+int _jit_create_call_return_insns(jit_function_t func, jit_type_t signature, jit_value_t *args, unsigned int num_args, jit_value_t return_value, int is_nested) {
+ /* NOT IMPLEMENTED YET */
+ return 0;
+}
+
+/*
+ * Place the indirect function pointer value into a suitable register or
+ * stack location for a subsequent indirect call.
+ */
+int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value) {
+ /* NOT IMPLEMENTED YET */
+ return 0;
+}
+
+/*
+ * TODO: write what this function is supposed to do
+ */
+void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop) {
+ /* NOT IMPLEMENTED YET */;
+}
+
+/*
+ * TODO: write what this function is supposed to do
+ */
+void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value) {
+ /* NOT IMPLEMENTED YET */;
+}
+
+/*
+ * Generate instructions to spill a pseudo register to the local variable frame. If
+ * other_reg is not -1, then it indicates the second register in a 64-bit register pair.
+ *
+ * This function will typically call _jit_gen_fix_value to fix the value's frame
+ * position, and will then generate the appropriate spill instructions.
+ */
+void _jit_gen_spill_reg(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) {
+ /* NOT IMPLEMENTED YET */;
+}
+
+/*
+ * Generate instructions to free a register without spilling its value. This is called
+ * when a register's contents become invalid, or its value is no longer required. If
+ * value_used is set to a non-zero value, then it indicates that the register's value
+ * was just used. Otherwise, there is a value in the register but it was never used.
+ *
+ * On most platforms, this function won't need to do anything to free the register.
+ * But some do need to take explicit action. For example, x86 needs an explicit
+ * instruction to remove a floating-point value from the FPU's stack if its value has
+ * not been used yet.
+ */
+void _jit_gen_free_reg(jit_gencode_t gen, int reg, int other_reg, int value_used) {
+ /* Nothing to do here */;
+}
+
+/*
+ * Not all CPU's support all arithmetic, conversion, bitwise, or comparison operators
+ * natively. For example, most ARM platforms need to call out to helper functions to
+ * perform floating-point.
+ *
+ * If this function returns zero, then jit-insn.c will output a call to an intrinsic
+ * function that is equivalent to the desired opcode. This is how you tell libjit that
+ * you cannot handle the opcode natively.
+ *
+ * This function can also help you develop your back end incrementally. Initially, you
+ * can report that only integer operations are supported, and then once you have them
+ * working you can move on to the floating point operations.
+ *
+ * Since alpha processors below ev6 need help with floating-point, we'll use the
+ * intrinsic floating-point functions on this systems.
+ */
+int _jit_opcode_is_supported(int opcode) {
+
+ switch(opcode) {
+ #define JIT_INCLUDE_SUPPORTED
+ #include "jit-rules-alpha.inc"
+ #undef JIT_INCLUDE_SUPPORTED
+ }
+
+ return 0;
+}
+
+/*
+ * Determine if type is a candidate for allocation within global registers.
+ */
+int _jit_gen_is_global_candidate(jit_type_t type) {
+
+ switch(jit_type_remove_tags(type)->kind) {
+ case JIT_TYPE_INT:
+ case JIT_TYPE_UINT:
+ case JIT_TYPE_NINT:
+ case JIT_TYPE_NUINT:
+ case JIT_TYPE_PTR:
+ case JIT_TYPE_SIGNATURE:
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Called to notify the back end that the start of a basic block has been reached.
+ */
+void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block) {
+ void **fixup, **next;
+
+ /* Set the address of this block */
+ block->address = (void *)(gen->posn.ptr);
+
+ /* If this block has pending fixups, then apply them now */
+ fixup = (void **)(block->fixup_list);
+
+ while (fixup) {
+ next = (void **)(fixup[0]);
+ fixup[0] = (void*) ((jit_nint) block->address - (jit_nint) fixup - 4);
+ fixup = next;
+ }
+
+ block->fixup_list = 0;
+}
+
+/*
+ * Called to notify the back end that the end of a basic block has been reached.
+ */
+void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block) {
+ /* Nothing to do here */;
+}
+
+/*
+ * Generate instructions to load a value into a register. The value will either be a
+ * constant or a slot in the frame. You should fix frame slots with
+ * _jit_gen_fix_value.
+ */
+void _jit_gen_load_value(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) {
+
+ /* Make sure that we have sufficient space */
+ jit_cache_setup_output(32);
+
+ if (value->is_constant) {
+
+ /* Determine the type of constant to be loaded */
+ switch(jit_type_normalize(value->type)->kind) {
+
+ case JIT_TYPE_SBYTE:
+ case JIT_TYPE_UBYTE:
+ case JIT_TYPE_SHORT:
+ case JIT_TYPE_USHORT:
+ case JIT_TYPE_INT:
+ case JIT_TYPE_UINT:
+ case JIT_TYPE_LONG:
+ case JIT_TYPE_ULONG:
+ alpha_li(inst,_jit_reg_info[reg].cpu_reg,(jit_nint)(value->address));
+ break;
+
+ /*
+ TODO (needs floating-point
+ case JIT_TYPE_FLOAT32:
+ case JIT_TYPE_FLOAT64:
+ case JIT_TYPE_NFLOAT:
+ break;
+ */
+
+ default:
+ break;
+
+ }
+ } else if (value->in_register || value->in_global_register) {
+
+ /* mov from value->reg to _jit_reg_info[reg].cpu_reg */
+ alpha_mov(inst,value->reg,_jit_reg_info[reg].cpu_reg);
+
+ } /* TODO else load from mem */
+
+ jit_cache_end_output();
+}
+
+void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value) {
+/*
+ NOT IMPLEMENTED YET!
+ jit_cache_setup_output();
+ jit_cache_end_output();
+*/
+}
+
+
+/*
+ * Generate code for a redirector, which makes an indirect jump to the contents of
+ * func->entry_point. Redirectors are used on recompilable functions in place of the
+ * regular entry point. This allows libjit to redirect existing calls to the new
+ * version after recompilation.
+ */
+void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) {
+ /* NOT IMPLEMENTED YET */
+ return NULL;
+}
+
+/*
+ * Generate native code for the specified insn. This function should call the
+ * appropriate register allocation routines, output the instruction, and then arrange
+ * for the result to be placed in an appropriate register or memory destination.
+ */
+void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, jit_block_t block, jit_insn_t insn) {
+ /* NOT IMPLEMENTED YET */;
+}
+
+/*
+ * TODO: write what this function is supposed to do
+ */
+void _jit_gen_exch_top(jit_gencode_t gen, int reg, int pop) {
+ /* NOT IMPLEMENTED YET */;
+}
+
+/*
+ * Output a branch instruction.
+ */
+void alpha_output_branch(jit_function_t func, alpha_inst inst, int opcode, jit_insn_t insn, int reg) {
+ jit_block_t block;
+ short int offset;
+
+ if (!(block = jit_block_from_label(func, (jit_label_t)(insn->dest))))
+ return;
+
+ if (block->address) {
+ /* We already know the address of the block */
+
+ offset = ((unsigned long) block->address - (unsigned long) inst);
+ alpha_encode_branch(inst,opcode,reg,offset);
+
+ } else {
+ /* Output a placeholder and record on the block's fixup list */
+
+ if(block->fixup_list) {
+ offset = (short int) ((unsigned long int) inst - (unsigned long int) block->fixup_list);
+ } else {
+ offset = 0;
+ }
+
+ alpha_encode_branch(inst,opcode,reg,offset);
+ block->fixup_list = inst - 4;
+ }
+}
+
+/*
+ * Jump to the current function's epilog.
+ */
+void alpha_jump_to_epilog(jit_gencode_t gen, alpha_inst inst, jit_block_t block) {
+ short int offset;
+
+ /*
+ * If the epilog is the next thing that we will output,
+ * then fall through to the epilog directly.
+ */
+
+ block = block->next;
+
+ while (!block && block->first_insn > block->last_insn)
+ block = block->next;
+
+ if (!block)
+ return;
+
+ /* Output a placeholder for the jump and add it to the fixup list */
+ if (gen->epilog_fixup) {
+ offset = (short int) ((unsigned long int) inst - (unsigned long int) gen->epilog_fixup);
+ } else {
+ offset = 0;
+ }
+
+ alpha_br(inst, ALPHA_ZERO, offset);
+ gen->epilog_fixup = inst - 4;
+}
+
+#endif /* JIT_BACKEND_ALPHA */
--- /dev/null
+/*
+ * jit-rules-alpha.h - Rules that define the characteristics of the alpha.
+ *
+ * Copyright (C) 2006 Southern Storm Software, Pty Ltd.
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _JIT_RULES_ALPHA_H
+#define _JIT_RULES_ALPHA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * alpha has 32 64-bit floating-point registers. Each can hold either
+ * 1 32-bit float or 1 64-bit double.
+ */
+#define JIT_REG_ALPHA_FLOAT \
+ (JIT_REG_FLOAT32 | JIT_REG_FLOAT64 | JIT_REG_NFLOAT)
+
+/*
+ * alpha has 32 64-bit integer registers that can hold WORD and LONG values
+ */
+#define JIT_REG_ALPHA_INT \
+ (JIT_REG_WORD | JIT_REG_LONG)
+
+/*
+ * Integer registers
+ *
+ * $0 - function results.
+ * $1..$8 - Temp registers.
+ * $9..$14 - Saved registers.
+ * $15/$fp - Frame pointer or saved register.
+ * $16-$21 - First 6 arguments.
+ * $22-$25 - Temp registers.
+ * $26 - Return address.
+ * $27 - Procedure value or temp register.
+ * $28/$at - Reserved for the assembler.
+ * $29/$gp - Global pointer.
+ * $30/$sp - Stack pointer.
+ * $31 - Contains the value 0.
+ *
+ * Floating-point registers
+ *
+ * $f0,$f1 - function results. $f0 = real component $f1 = imaginary component
+ * $f2..$f9 - Saved registers.
+ * $f10..$f15 - Temp registers.
+ * $f16..$f21 - First 6 arguments.
+ * $f22..$f30 - Temp registers for expression evaluation.
+ * $f31 - Contains the value 0.0.
+ */
+#define JIT_REG_INFO \
+ { "v0", 0, -1, JIT_REG_FIXED}, \
+ { "t0", 1, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t1", 2, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t2", 3, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t3", 4, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t4", 5, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t5", 6, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t6", 7, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t7", 8, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "s0", 9, -1, JIT_REG_ALPHA_INT | JIT_REG_GLOBAL}, \
+ { "s1", 10, -1, JIT_REG_ALPHA_INT | JIT_REG_GLOBAL}, \
+ { "s2", 11, -1, JIT_REG_ALPHA_INT | JIT_REG_GLOBAL}, \
+ { "s3", 12, -1, JIT_REG_ALPHA_INT | JIT_REG_GLOBAL}, \
+ { "s4", 13, -1, JIT_REG_ALPHA_INT | JIT_REG_GLOBAL}, \
+ { "s5", 14, -1, JIT_REG_ALPHA_INT | JIT_REG_GLOBAL}, \
+ { "fp", 15, -1, JIT_REG_FIXED | JIT_REG_FRAME}, \
+ { "a0", 16, -1, JIT_REG_FIXED}, \
+ { "a1", 17, -1, JIT_REG_FIXED}, \
+ { "a2", 18, -1, JIT_REG_FIXED}, \
+ { "a3", 19, -1, JIT_REG_FIXED}, \
+ { "a4", 20, -1, JIT_REG_FIXED}, \
+ { "a5", 21, -1, JIT_REG_FIXED}, \
+ { "t8", 22, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t9", 23, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t10", 24, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "t11", 25, -1, JIT_REG_ALPHA_INT | JIT_REG_CALL_USED}, \
+ { "ra", 26, -1, JIT_REG_FIXED}, \
+ { "pv", 27, -1, JIT_REG_FIXED}, \
+ { "at", 28, -1, JIT_REG_FIXED}, \
+ { "gp", 29, -1, JIT_REG_FIXED}, \
+ { "sp", 30, -1, JIT_REG_FIXED | JIT_REG_STACK_PTR}, \
+ { "zero", 31, -1, JIT_REG_FIXED}, \
+ { "fv0", 0, -1, JIT_REG_FIXED}, \
+ { "fv1", 1, -1, JIT_REG_FIXED}, \
+ { "fs0", 2, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_GLOBAL}, \
+ { "fs1", 3, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_GLOBAL}, \
+ { "fs2", 4, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_GLOBAL}, \
+ { "fs3", 5, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_GLOBAL}, \
+ { "fs4", 6, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_GLOBAL}, \
+ { "fs5", 7, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_GLOBAL}, \
+ { "fs6", 8, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_GLOBAL}, \
+ { "fs7", 9, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_GLOBAL}, \
+ { "ft0", 10, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_CALL_USED}, \
+ { "ft1", 11, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_CALL_USED}, \
+ { "ft2", 12, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_CALL_USED}, \
+ { "ft3", 13, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_CALL_USED}, \
+ { "ft4", 14, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_CALL_USED}, \
+ { "ft5", 15, -1, JIT_REG_ALPHA_FLOAT | JIT_REG_CALL_USED}, \
+ { "fa0", 16, -1, JIT_REG_FIXED}, \
+ { "fa1", 17, -1, JIT_REG_FIXED}, \
+ { "fa2", 18, -1, JIT_REG_FIXED}, \
+ { "fa3", 19, -1, JIT_REG_FIXED}, \
+ { "fa4", 20, -1, JIT_REG_FIXED}, \
+ { "fa5", 21, -1, JIT_REG_FIXED}, \
+ { "fe0", 22, -1, JIT_REG_FIXED}, \
+ { "fe1", 23, -1, JIT_REG_FIXED}, \
+ { "fe2", 24, -1, JIT_REG_FIXED}, \
+ { "fe3", 25, -1, JIT_REG_FIXED}, \
+ { "fe4", 26, -1, JIT_REG_FIXED}, \
+ { "fe5", 27, -1, JIT_REG_FIXED}, \
+ { "fe6", 28, -1, JIT_REG_FIXED}, \
+ { "fe7", 29, -1, JIT_REG_FIXED}, \
+ { "fe8", 30, -1, JIT_REG_FIXED}, \
+ {"fzero", 31, -1, JIT_REG_FIXED},
+
+/* 32 floating-point registers + 32 integer registers */
+#define JIT_NUM_REGS 64
+
+/*
+ * The number of registers that are used for global register
+ * allocation. Set to zero if global register allocation should not be
+ * used.
+ */
+#define JIT_NUM_GLOBAL_REGS 14
+
+/*
+ * Define to 1 if we should always load values into registers
+ * before operating on them. i.e. the CPU does not have reg-mem
+ * and mem-reg addressing modes.
+ *
+ * The maximum number of operands for an alpha instruction is 3,
+ * all of which must be registers.
+ */
+#define JIT_ALWAYS_REG_REG 1
+
+/*
+ * The maximum number of bytes to allocate for the prolog.
+ * This may be shortened once we know the true prolog size.
+ *
+ * Use the prolog size mono uses. See mono/arch/alpha/tramp.c
+ */
+#define JIT_PROLOG_SIZE 24
+
+/*
+ * Preferred alignment for the start of functions.
+ *
+ * Use the alignment that gcc uses. See gcc/config/alpha/alpha.h
+ */
+#define JIT_FUNCTION_ALIGNMENT 32
+
+/*
+ * Define this to 1 if the platform allows reads and writes on
+ * any byte boundary. Define to 0 if only properly-aligned
+ * memory accesses are allowed.
+ *
+ * All memory access on alpha must be naturally aligned. There are
+ * unaligned load and store instructions to operate on arbitrary byte
+ * boundaries. However sometimes compilers don't always spot where
+ * to use them due to programming tricks with pointers. The kernel will
+ * do the fetch transparently if the access is unaligned and not done
+ * with the proper instructions. Kernel assisted unaligned accesses
+ * don't change the behavior of the program.
+ *
+ * TODO: benchmark this to determine what is more costly... setting
+ * up everything to be aligned or dealing with the unaligned accesses.
+ */
+#define JIT_ALIGN_OVERRIDES 1
+
+/*
+ * The jit_extra_gen_state macro can be supplied to add extra fields to
+ * the struct jit_gencode type in jit-rules.h, for extra CPU-specific
+ * code generation state information.
+ */
+#define jit_extra_gen_state /* empty */;
+
+/*
+ * The jit_extra_gen_init macro initializes this extra information, and
+ * the jit_extra_gen_cleanup macro cleans it up when code generation is
+ * complete.
+ */
+#define jit_extra_gen_init(gen) do { ; } while (0)
+#define jit_extra_gen_cleanup(gen) do { ; } while (0)
+
+/*
+ * Parameter passing rules.
+ */
+#define JIT_CDECL_WORD_REG_PARAMS {9,10,11,12,13,14,-1}
+#define JIT_MAX_WORD_REG_PARAMS 6
+
+/* TODO: find the proper values for these */
+#define JIT_INITIAL_STACK_OFFSET 0
+#define JIT_INITIAL_FRAME_SIZE 0
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _JIT_RULES_ALPHA_H */
--- /dev/null
+/*
+ * jit-rules-alpha.ins - Instruction selector for alpha.
+ *
+ * Copyright (C) 2006 Southern Storm Software, Pty Ltd.
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+%inst_type alpha_inst
+
+/*
+ * Conversion opcodes.
+ */
+
+JIT_OP_TRUNC_SBYTE: unary
+ [reg] -> {
+ alpha_slli(code,$1,56,$1);
+ alpha_srai(code,$1,56,$1);
+ }
+
+JIT_OP_TRUNC_UBYTE: unary
+ [reg] -> {
+ alpha_li8(code,ALPHA_AT,0xff);
+ alpha_and(code,$1,ALPHA_AT,$1);
+ }
+
+JIT_OP_TRUNC_SHORT: unary
+ [reg] -> {
+ alpha_slli(code,$1,56,$1);
+ alpha_srai(code,$1,56,$1);
+ }
+
+JIT_OP_TRUNC_USHORT: unary
+ [reg] -> {
+ alpha_slli(code,$1,56,$1);
+ alpha_srli(code,$1,56,$1);
+ }
+
+/*
+ * TODO: JIT_OP_NFLOAT_TO_FLOAT32 JIT_OP_NFLOAT_TO_FLOAT64
+ * TODO: JIT_OP_FLOAT32_TO_NFLOAT JIT_OP_FLOAT64_TO_NFLOAT
+ *
+ * Requires floating-point opcodes
+ */
+
+/*
+ * Arithmetic opcodes.
+ *
+ * These operations take the two parameters [$1, $2] and perform the
+ * operation on them and store the result in $1. The format of most of
+ * the alpha arithmetic operations is alpha_opl(inst,sreg0,sreg1,dreg).
+ * For operations with imediate values we use alpha_liN to load the
+ * value into ALPHA_AT, a register reserved for the assembler, before
+ * doing any operations on it.
+ *
+ * Perform an arithmetic operation on signed 32-bit integers.
+ */
+
+/* return value1 + value2; */
+JIT_OP_IADD: binary
+ [=reg, reg, imm, if("$3 == 0")] -> {
+ alpha_mov(inst,$2,$1);
+ }
+ [=reg, reg, reg] -> {
+ alpha_addl(inst,$3,$2,$1);
+ }
+
+/* return value1 - value2; */
+JIT_OP_ISUB: binary
+ [=reg, reg, imm, if("$3 == 0")] -> {
+ alpha_mov(inst,$2,$1);
+ }
+ [=reg, reg, reg] -> {
+ alpha_subl(inst,$3,$2,$1);
+ }
+
+/* return value1 * value2; */
+/* TODO add more trivial IMUL imm rules */
+JIT_OP_IMUL: binary
+ [=reg, reg, imm, if("$3 == 1")] -> {
+ alpha_mov(inst,$2,$1);
+ }
+ [=reg, reg, imm, if("$3 == 0")] -> {
+ alpha_clr(inst,$1);
+ }
+ [=reg, reg, imm, if("$3 == -1")] -> {
+ alpha_subl(inst,$1,ALPHA_ZERO,$2);
+ }
+ [=reg, reg, reg] -> {
+ alpha_mull(inst,$3,$2,$1);
+ }
+
+
+/*
+ * TODO: JIT_OP_IDIV, JIT_OP_IDIV_UN, JIT_OP_IREM, JIT_OP_IREM_UN
+ *
+ * alpha has no integer division instruction, so you have to convert the
+ * value to a float, do floating-point division, and convert the result
+ * back to an integer. This depends on adding floating-point instructions
+ * to jit-gen-alpha.h
+ */
+
+/* return -value1; */
+JIT_OP_INEG: unary
+ [reg] -> {
+ /* Alpha has no neg operation, do $1 = 0 - $1; instead */
+ alpha_subl(inst,ALPHA_ZERO,$1,$1);
+ }
+
+/* return value1 + value2 */
+JIT_OP_LADD: binary
+ [=lreg, lreg, lreg] -> {
+ alpha_addq(inst,$3,$2,$1);
+ }
+
+/* return value1 - value2 */
+JIT_OP_LSUB: binary
+ [=lreg, lreg, lreg] -> {
+ alpha_subq(inst,$3,$2,$1);
+ }
+
+/* return value1 * value2 */
+/* TODO add more trivial LMUL imm rules */
+JIT_OP_LMUL: binary
+ [=lreg, lreg, imm, if("$3 == 1")] -> {
+ alpha_mov(inst,$2,$1);
+ }
+ [=lreg, lreg, imm, if("$3 == 0")] -> {
+ alpha_clr(inst,$1);
+ }
+ [=lreg, lreg, imm, if("$3 == -1")] -> {
+ alpha_subq(inst,$1,ALPHA_ZERO,$2);
+ }
+ [=lreg, lreg, lreg] -> {
+ alpha_mulq(inst,$3,$2,$1);
+ }
+
+JIT_OP_LNEG: unary
+ [lreg] -> {
+ /* Alpha has no neg operation, do $1 = 0 - $1; instead */
+ alpha_subq(inst,ALPHA_ZERO,$1,$1);
+ }
+
+/*
+ * TODO: JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD, JIT_OP_FSUB
+ * TODO: JIT_OP_DSUB, JIT_OP_NFSUB, JIT_OP_FMUL, JIT_OP_DMUL
+ * TODO: JIT_OP_NFMUL, JIT_OP_FDIV, JIT_OP_DDIV, JIT_OP_NFDIV
+ * TODO: JIT_OP_FREM, JIT_OP_DREM, JIT_OP_NFREM, JIT_OP_FREM,
+ * TODO: JIT_OP_DREM, JIT_OP_NFREM, JIT_OP_FNEG, JIT_OP_DNEG,
+ * TODO: JIT_OP_NFNEG
+ *
+ * This depends on adding floating-point instructions to jit-gen-alpha.h
+ */
+
+/*
+ * Bitwise opcodes.
+ */
+JIT_OP_IAND: binary
+ [=reg, reg, reg] -> {
+ alpha_and(inst,$3,$2,$1);
+ }
+
+JIT_OP_IOR: binary
+ [=reg, reg, reg] -> {
+ alpha_or(inst,$3,$2,$1);
+ }
+
+JIT_OP_IXOR: binary
+ [=reg, reg, reg] -> {
+ alpha_xor(inst,$3,$2,$1);
+ }
+
+JIT_OP_INOT: unary
+ [reg] -> {
+ alpha_li32(inst,ALPHA_AT,0xffffffff);
+ alpha_xor(inst,ALPHA_AT,$1,$1);
+ }
+
+/*
+ * TODO: JIT_OP_ISHL JIT_OP_ISHR JIT_OP_ISHR_UN
+ *
+ * The machine instructions operate on 64-bit values.
+ * Some extra masking and clean up will need to be done to get
+ * these to work properly.
+ */
+
+JIT_OP_LAND: binary
+ [=reg, reg, reg] -> {
+ alpha_and(inst,$3,$2,$1);
+ }
+
+JIT_OP_LOR: binary
+ [=reg, reg, reg] -> {
+ alpha_or(inst,$3,$2,$1);
+ }
+
+JIT_OP_LXOR: binary
+ [=reg, reg, reg] -> {
+ alpha_xor(inst,$3,$2,$1);
+ }
+
+JIT_OP_LNOT: unary
+ [reg] -> {
+ alpha_li64(inst,ALPHA_AT,0xffffffff);
+ alpha_xor(inst,ALPHA_AT,$1,$1);
+ }
+
+JIT_OP_LSHL: binary
+ [=reg, reg, reg] -> {
+ alpha_sll(inst,$3,$2,$1);
+ }
+
+JIT_OP_LSHR: binary
+ [=reg, reg, reg] -> {
+ alpha_srl(inst,$3,$2,$1);
+ }
+
+JIT_OP_LSHR_UN: binary
+ [=reg, reg, reg] -> {
+ alpha_sra(inst,$3,$2,$1);
+ }
+
+/*
+ * Branch opcodes
+ */
+
+JIT_OP_BR: spill_before
+ [] -> {
+ /* branch if ALPHA_ZERO is zero (this is always true) */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_ZERO);
+ }
+
+JIT_OP_BR_IFALSE: unary_branch
+ [reg] -> {
+ /* banch if $1 == 0 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, $1);
+ }
+
+JIT_OP_BR_ITRUE: unary_branch
+ [reg] -> {
+ /* branch if $1 != 0 */
+ alpha_output_branch(func, inst, ALPHA_OP_BNE, insn, $1);
+ }
+
+JIT_OP_BR_IEQ: binary_branch
+ [reg, reg] -> {
+ /* $1 == $2 -> $at */
+ alpha_cmpeq(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+JIT_OP_BR_INE: binary_branch
+ [reg, reg] -> {
+ /* $1 == $2 -> $at */
+ alpha_cmpeq(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 0 */
+ alpha_output_branch(func, inst, ALPHA_OP_BNE, insn, ALPHA_AT);
+ }
+JIT_OP_BR_ILT: binary_branch
+ [reg, reg] -> {
+ /* $1 < $2 -> $at */
+ alpha_cmplt(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+JIT_OP_BR_ILT_UN: binary_branch
+ [reg, reg] -> {
+ /* $1 < $2 -> $at */
+ alpha_cmpult(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+JIT_OP_BR_ILE: binary_branch
+ [reg, reg] -> {
+ /* $1 <= $2 -> $at */
+ alpha_cmple(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+JIT_OP_BR_ILE_UN: binary_branch
+ [reg, reg] -> {
+ /* $1 <= $2 -> $at */
+ alpha_cmpule(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+
+JIT_OP_BR_IGT: binary_branch
+ [reg, reg] -> {
+ /* $1 > $2 -> $at */
+ alpha_cmpgt(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+JIT_OP_BR_IGT_UN: binary_branch
+ [reg, reg] -> {
+ /* $1 > $2 -> $at */
+ alpha_cmpugt(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+JIT_OP_BR_IGE: binary_branch
+ [reg, reg] -> {
+ /* $1 >= $2 -> $at */
+ alpha_cmpge(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+JIT_OP_BR_IGE_UN: binary_branch
+ [reg, reg] -> {
+ /* $1 => $2 -> $at */
+ alpha_cmpugt(inst, $1, $2, ALPHA_AT);
+
+ /* branch if $at == 1 */
+ alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
+ }
+
+
+/*
+ * Comparison opcodes.
+ */
+
+JIT_OP_IEQ: binary
+ [=reg, reg, reg] -> {
+ alpha_cmpeq(inst,$3,$2,$1);
+ }
+
+JIT_OP_INE: binary
+ [=reg, reg, reg] -> {
+ alpha_cmpeq(inst,$3,$2,$1);
+ alpha_cmpeq(inst,$1,ALPHA_ZERO,$1);
+ }
+
+JIT_OP_ILT: binary
+ [=reg, reg, reg] -> {
+ alpha_cmplt(inst,$3,$2,$1);
+ }
+
+
+JIT_OP_ILT_UN: binary
+ [=reg, reg, reg] -> {
+ alpha_cmpult(inst,$3,$2,$1);
+ }
+
+JIT_OP_ILE: binary
+ [=reg, reg, reg] -> {
+ alpha_cmple(inst,$3,$2,$1);
+ }
+
+JIT_OP_ILE_UN: binary
+ [=reg, reg, reg] -> {
+ alpha_cmpule(inst,$3,$2,$1);
+ }
+
+JIT_OP_IGT: binary
+ [=reg, reg, reg] -> {
+ alpha_cmpgt(inst,$3,$2,$1);
+ }
+
+JIT_OP_IGT_UN: binary
+ [=reg, reg, reg] -> {
+ alpha_cmpugt(inst,$3,$2,$1);
+ }
+
+JIT_OP_IGE: binary
+ [=reg, reg, reg] -> {
+ alpha_cmpge(inst,$3,$2,$1);
+ }
+
+JIT_OP_IGE_UN: binary
+ [=reg, reg, reg] -> {
+ alpha_cmpuge(inst,$3,$2,$1);
+ }
+
+/*
+ * Mathematical opcodes.
+ *
+ * TODO: JIT_OP_FATAN, JIT_OP_DATAN, JIT_OP_NFATAN JIT_OP_FCOS, JIT_OP_DCOS, JIT_OP_NFCOS
+ * TODO: JIT_OP_FSIN, JIT_OP_DSIN, JIT_OP_NFSIN JIT_OP_FSQRT, JIT_OP_DSQRT, JIT_OP_NFSQRT
+ * TODO: JIT_OP_FABS, JIT_OP_DABS, JIT_OP_NFABS
+ *
+ * Requires floating-point opcodes
+ */
+
+/*
+ * Pointer check opcodes.
+ */
+
+/* TODO: JIT_OP_CHECK_NULL: unary_note */
+
+/*
+ * Function calls.
+ */
+
+JIT_OP_CALL:
+ [] -> {
+ jit_function_t func = (jit_function_t)(insn->dest);
+ alpha_call(inst, func->closure_entry);
+ }
+
+/* TODO: JIT_OP_CALL_TAIL, JIT_OP_CALL_INDIRECT, JIT_OP_CALL_VTABLE_PTR */
+
+JIT_OP_RETURN:
+ [] -> {
+ jump_to_epilog(gen, inst, block);
+ }
+
+JIT_OP_RETURN_INT: unary_branch
+ [reg] -> {
+ alpha_mov(inst,$1,ALPHA_V0);
+ jump_to_epilog(gen, inst, block);
+ }
+
+JIT_OP_RETURN_LONG: unary_branch
+ [reg] -> {
+ alpha_mov(inst,$1,ALPHA_V0);
+ jump_to_epilog(gen, inst, block);
+ }
+
+/* TODO: JIT_OP_RETURN_FLOAT32 JIT_OP_RETURN_FLOAT64 JIT_OP_RETURN_NFLOAT */