]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Initial commit of the alpha port.
authorThomas Cort <linuxgeek@gmail.com>
Wed, 12 Jul 2006 03:06:49 +0000 (03:06 +0000)
committerThomas Cort <linuxgeek@gmail.com>
Wed, 12 Jul 2006 03:06:49 +0000 (03:06 +0000)
README.alpha [new file with mode: 0644]
jit/Makefile.am
jit/jit-apply-alpha.c [new file with mode: 0644]
jit/jit-apply-alpha.h [new file with mode: 0644]
jit/jit-elf-defs.h
jit/jit-gen-alpha.h [new file with mode: 0644]
jit/jit-rules-alpha.c [new file with mode: 0644]
jit/jit-rules-alpha.h [new file with mode: 0644]
jit/jit-rules-alpha.ins [new file with mode: 0644]
jit/jit-rules.h

diff --git a/README.alpha b/README.alpha
new file mode 100644 (file)
index 0000000..6815d31
--- /dev/null
@@ -0,0 +1,40 @@
+As part of Google's Summer of Code, I am porting libjit to the alpha 
+architecture for the GNU Project. Please be aware that this is still 
+very much a work in progress and isn't functional yet. You can follow my 
+progress via my blog: http://mediumbagel.org/nucleus/index.php?catid=6
+
+For the first iteration, the alpha port will not implement floating-
+point arithmetic. This is done to reduce complexity and to get libjit
+working on alpha sooner. Advanced features like prefetching, hints (for 
+jmp, jsr, ret, and jsrco), and branch elimination with cmov are 
+optimizations that will be implmented once the alpha port is functional.
+
+-Thomas Cort <linuxgeek@gmail.com>
+
+During the development of the alpha port, I found the following sources 
+of information to be very useful:
+
+       Alpha Architecture Handbook
+       ftp://ftp.compaq.com/pub/products/alphaCPUdocs/alpha_arch_ref.pdf
+       http://ftp.digital.com/pub/Digital/info/semiconductor/literature/alphaahb.pdf
+
+       Compiler Writer's Guide for the 21264/21364
+       ftp://ftp.compaq.com/pub/products/alphaCPUdocs/comp_guide_v2.pdf
+
+       Assembly Language Programmer's Guide
+       http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PS31D-TET1_html/TITLE.html
+
+       binutils source code
+       binutils-2.16.1/opcodes/alpha-opc.c
+
+       ffcall source code
+       ffcall-1.10/avcall/avcall-alpha.c
+
+       mono source code
+       mono-.1.1.15/mono/arch/alpha/*
+
+       gcc source code
+       gcc-3.4.6/gcc/config/alpha/*
+
+       ALPHA: Opcodes
+       http://www.cs.arizona.edu/alto/Doc/local/alpha.opcode.html
index b9aa47a081adf77c01c87760740cfe7c2ef7707d..8f84704adfdf1b91ea4b8782e1a8eb4ddc46c047 100644 (file)
@@ -5,6 +5,8 @@ libjit_la_SOURCES = \
                jit-alloc.c \
                jit-apply.c \
                jit-apply-func.h \
+               jit-apply-alpha.h \
+               jit-apply-alpha.c \
                jit-apply-arm.h \
                jit-apply-arm.c \
                jit-apply-x86.h \
@@ -23,6 +25,7 @@ libjit_la_SOURCES = \
                jit-elf-write.c \
                jit-except.c \
                jit-function.c \
+               jit-gen-alpha.h \
                jit-gen-arm.h \
                jit-gen-arm.c \
                jit-gen-x86.h \
@@ -43,6 +46,8 @@ libjit_la_SOURCES = \
                jit-rules.h \
                jit-rules.c \
                jit-rules-interp.c \
+               jit-rules-alpha.h \
+               jit-rules-alpha.c \
                jit-rules-arm.h \
                jit-rules-arm.c \
                jit-rules-x86.h \
@@ -82,4 +87,11 @@ jit-rules-arm.slc: jit-rules-arm.sel $(top_builddir)/tools/gen-sel$(EXEEXT)
        $(top_builddir)/tools/gen-sel$(EXEEXT) $(srcdir)/jit-rules-arm.sel \
                        >jit-rules-arm.slc
 
-CLEANFILES = jit-interp-labels.h jit-rules-x86.slc jit-rules-arm.slc
+jit-rules-alpha.lo: jit-rules-alpha.inc
+
+jit-rules-alpha.inc: jit-rules-alpha.ins $(top_builddir)/tools/gen-rules$(EXEEXT)
+       $(top_builddir)/tools/gen-rules$(EXEEXT) $(srcdir)/jit-rules-alpha.ins \
+                       >jit-rules-alpha.inc
+
+CLEANFILES = jit-interp-labels.h jit-rules-x86.slc jit-rules-arm.slc \
+               jit-rules-alpha.slc
diff --git a/jit/jit-apply-alpha.c b/jit/jit-apply-alpha.c
new file mode 100644 (file)
index 0000000..0cf7822
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * jit-apply-alpha.c - Apply support routines 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
+ */
+
+#include "jit-internal.h"
+
+#if defined(__alpha) || defined(__alpha__)
+
+#include "jit-gen-alpha.h"
+
+void _jit_create_closure(unsigned char *buf, void *func, void *closure, void *_type) {
+       alpha_inst inst = (alpha_inst) buf;
+
+       /* NOT IMPLEMENTED YET! */
+
+       /* Set up the local stack frame */
+       /* Create the apply argument block on the stack */
+       /* Push the arguments for calling "func" */
+       /* Call the closure handling function */
+
+}
+
+void *_jit_create_redirector(unsigned char *buf, void *func, void *user_data, int abi) {
+       alpha_inst inst = (alpha_inst) buf;
+
+       /* NOT IMPLEMENTED YET! */
+
+       /* Set up a new stack frame */
+
+       /* Push the user data onto the stack "(int)(jit_nint)user_data" */      
+
+       /* Call the redirector handling function */
+
+       /* Jump to the function that the redirector indicated */
+       alpha_jsr(inst,ALPHA_RA,ALPHA_R0,1);
+
+       return (void *)inst;
+}
+
+#endif /* alpha */
diff --git a/jit/jit-apply-alpha.h b/jit/jit-apply-alpha.h
new file mode 100644 (file)
index 0000000..f541ff0
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * jit-apply-alpha.h - Special definitions for alpha function application.
+ *
+ * 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_APPLY_ALPHA_H
+#define        _JIT_APPLY_ALPHA_H
+
+/* NOT IMPLEMENTED YET! */
+
+#endif /* _JIT_APPLY_ALPHA_H */
index 11cb6be7dece56f9939277b856562b8e44d281a1..0007be6df73bfc02d50cee135de4716a92bd38ab 100644 (file)
@@ -256,6 +256,10 @@ typedef struct
    pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
    chances of collision with official or non-GNU unofficial values.  */
 
+/*
+ * This is an interim value that will be used until the committee comes
+ * up with a final number. - include/linux/elf.h
+ */
 #define EM_ALPHA       0x9026
 
 /* Legal values for e_version (version).  */
diff --git a/jit/jit-gen-alpha.h b/jit/jit-gen-alpha.h
new file mode 100644 (file)
index 0000000..857f831
--- /dev/null
@@ -0,0 +1,693 @@
+/*
+ * 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 */
diff --git a/jit/jit-rules-alpha.c b/jit/jit-rules-alpha.c
new file mode 100644 (file)
index 0000000..3c5cca2
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * 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 */
diff --git a/jit/jit-rules-alpha.h b/jit/jit-rules-alpha.h
new file mode 100644 (file)
index 0000000..e2f116f
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * 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 */
diff --git a/jit/jit-rules-alpha.ins b/jit/jit-rules-alpha.ins
new file mode 100644 (file)
index 0000000..b3b6d2f
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * 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 */
index d2fa7536159f9106a00b220fd86e050e72f0be89..444a4e4b597e0544826c97500d83a828d6d20e3e 100644 (file)
@@ -37,6 +37,9 @@ extern        "C" {
 #elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
        #define JIT_BACKEND_X86                 1
        #define JIT_HAVE_BACKEND                1
+#elif defined(__alpha) || defined(__alpha__)
+       #define JIT_BACKEND_ALPHA               1
+       #define JIT_HAVE_BACKEND                1
 #endif
 /*#define      JIT_BACKEND_ARM         1*/
 #if !defined(JIT_HAVE_BACKEND)
@@ -83,6 +86,8 @@ typedef struct
        #include "jit-rules-x86.h"
 #elif defined(JIT_BACKEND_ARM)
        #include "jit-rules-arm.h"
+#elif defined(JIT_BACKEND_ALPHA)
+       #include "jit-rules-alpha.h"
 #else
        #error "unknown jit backend type"
 #endif