From: Thomas Cort Date: Wed, 12 Jul 2006 03:06:49 +0000 (+0000) Subject: Initial commit of the alpha port. X-Git-Tag: before.move.to.git~223 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=ef26ecd2cdbe2904f7a85304b6b42ff34ea6cd8f;p=francis%2Flibjit.git Initial commit of the alpha port. --- diff --git a/README.alpha b/README.alpha new file mode 100644 index 0000000..6815d31 --- /dev/null +++ b/README.alpha @@ -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 + +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 diff --git a/jit/Makefile.am b/jit/Makefile.am index b9aa47a..8f84704 100644 --- a/jit/Makefile.am +++ b/jit/Makefile.am @@ -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 index 0000000..0cf7822 --- /dev/null +++ b/jit/jit-apply-alpha.c @@ -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 index 0000000..f541ff0 --- /dev/null +++ b/jit/jit-apply-alpha.h @@ -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 */ diff --git a/jit/jit-elf-defs.h b/jit/jit-elf-defs.h index 11cb6be..0007be6 100644 --- a/jit/jit-elf-defs.h +++ b/jit/jit-elf-defs.h @@ -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 index 0000000..857f831 --- /dev/null +++ b/jit/jit-gen-alpha.h @@ -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 index 0000000..3c5cca2 --- /dev/null +++ b/jit/jit-rules-alpha.c @@ -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 + +/* + * _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 index 0000000..e2f116f --- /dev/null +++ b/jit/jit-rules-alpha.h @@ -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 index 0000000..b3b6d2f --- /dev/null +++ b/jit/jit-rules-alpha.ins @@ -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 */ diff --git a/jit/jit-rules.h b/jit/jit-rules.h index d2fa753..444a4e4 100644 --- a/jit/jit-rules.h +++ b/jit/jit-rules.h @@ -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