--- /dev/null
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * 5-Oct-93 Alessandro Forin (af) at Carnegie-Mellon University
+ * First checkin.
+ *
+ * $Log$
+ * Revision 1.1 1994/01/28 01:36:59 raeburn
+ * New Alpha support files, based on files from CMU.
+ * Still to do:
+ * - fix floating-point handling
+ * - figure out if we can adapt to using ../opcodes/alpha-opc.h
+ * - gcc bootstrap testing
+ * - 32-bit mode support?
+ * - test cross-assembly
+ *
+ *
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: Jan 1993
+ */
+
+/* Table of opcodes for the alpha.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
+
+GAS/GDB 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 1, or (at your option)
+any later version.
+
+GAS/GDB 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 GAS or GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+struct alpha_opcode
+{
+ const char *name;
+ const unsigned int match; /* fixed encoding part of instruction */
+ const int isa_float;
+ const char *args;
+};
+
+/*
+ All alpha opcodes are 32 bits, except for the `set' instruction (really
+ a macro), which is 64 bits. It is handled as a special case.
+
+ The match component is a mask saying which bits must match a
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing one character
+ for each operand of the instruction.
+
+Kinds of operands:
+ 1 ra register
+ 2 rb register
+ 3 rc register
+ r same register for ra and rc
+ R same register for ra and rb
+ e fa floating point register.
+ f fb floating point register.
+ g fc floating point register.
+ I 26 bit immediate
+ l 16 low bits of immediate
+ h 16 high(er) bits of immediate [Never used. KR]
+ L 22 bit PC relative immediate.
+ i 14 bit immediate jmp/jsr/ret operand -- PC-rel or not,
+ dependent on opcode
+ b 8 bit literal, shifted left 13 bits (literal in `operate' fmt)
+ G Base-register GET at address, needs macro-expansion
+ P Base-register PUT at address, needs macro-expansion
+ Bn builtin macro
+ t twelve bit displacement
+ 8 eight bit index
+
+Syntactic elements
+ (
+ ) base register in "offset(base)" addressing
+ , separator
+
+Builtin functions (look like macros to the programmer)
+ %br the current base register
+ la %r,A load the (64bit) address in register %r
+ li %r,N load the constant N in register %r
+#if 0
+ lo(A) low 16 bits of Address (relocatable)
+ uml(A) med-low 16 bits, unchanged
+ umh(A) med-high 16 bits, unchanged
+ uhi(A) high 16 bits, unchanged
+ ml(A) med-low, adjusted viz sign of lo(A)
+ mh(A) med-high, adjusted viz sign of ml(A)
+ hi(A) high, adjusted viz sign of mh(A)
+#endif
+
+*/
+
+/* The order of the opcodes in this table is significant:
+
+ * The assembler requires that all instances of the same mnemonic must be
+ consecutive. If they aren't, the assembler will bomb at runtime.
+
+ * The disassembler should not care about the order of the opcodes. */
+
+static const struct alpha_opcode alpha_opcodes[] =
+{
+
+{ "ldgp", 0x00000000, 0, "3,l(1)Ba" }, /* builtin */
+{ "setgp", 0x00000000, 0, "0(1)Bb" }, /* builtin */
+
+{ "reml", 0x00000000, 0, "1,2,3B0" }, /* builtin */
+{ "divl", 0x00000000, 0, "1,2,3B1" }, /* builtin */
+{ "remq", 0x00000000, 0, "1,2,3B2" }, /* builtin */
+{ "divq", 0x00000000, 0, "1,2,3B3" }, /* builtin */
+{ "remlu", 0x00000000, 0, "1,2,3B4" }, /* builtin */
+{ "divlu", 0x00000000, 0, "1,2,3B5" }, /* builtin */
+{ "remqu", 0x00000000, 0, "1,2,3B6" }, /* builtin */
+{ "divqu", 0x00000000, 0, "1,2,3B7" }, /* builtin */
+
+{ "lda", 0x20000000, 0, "1,l(2)" }, /* 6o+5a+5b+16d */
+{ "lda", 0x20000000, 0, "1,G" }, /* regbase macro */
+{ "ldi", 0x201F0000, 0, "1,l"}, /* ldi ra,lit == lda ra,lit(r31) */
+{ "ldah", 0x24000000, 0, "1,l(2)" },
+{ "ldah", 0x24000000, 0, "1,G" }, /* regbase macro */
+{ "lui", 0x241F0000, 0, "1,l"}, /* lui ra,lit == ldah ra,lit(r31) */
+{ "ldil", 0x20000000, 0, "1,G" }, /* macro */
+{ "ldiq", 0x20000000, 0, "1,G" }, /* (broken) macro */
+
+{ "ldl", 0xa0000000, 0, "1,l(2)" },
+{ "ldl", 0xa0000000, 0, "1,G" }, /* regbase macro */
+{ "ldl_l", 0xa8000000, 0, "1,l(2)" },
+{ "ldl_l", 0xa8000000, 0, "1,G" }, /* regbase macro */
+{ "ldq", 0xa4000000, 0, "1,l(2)" },
+{ "ldq", 0xa4000000, 0, "1,G" }, /* regbase macro */
+{ "ldq_u", 0x2c000000, 0, "1,l(2)" },
+{ "ldq_u", 0x2c000000, 0, "1,G" }, /* regbase macro */
+{ "ldq_l", 0xac000000, 0, "1,l(2)" },
+{ "ldq_l", 0xac000000, 0, "1,G" }, /* regbase macro */
+
+{ "stl", 0xb0000000, 0, "1,l(2)" },
+{ "stl", 0xb0000000, 0, "1,P" }, /* regbase macro */
+{ "stl_c", 0xb8000000, 0, "1,l(2)" },
+{ "stl_c", 0xb8000000, 0, "1,P" }, /* regbase macro */
+{ "stq", 0xb4000000, 0, "1,l(2)" },
+{ "stq", 0xb4000000, 0, "1,P" }, /* regbase macro */
+{ "stq_u", 0x3c000000, 0, "1,l(2)" },
+{ "stq_u", 0x3c000000, 0, "1,P" }, /* regbase macro */
+{ "stq_c", 0xbc000000, 0, "1,l(2)" },
+{ "stq_c", 0xbc000000, 0, "1,P" }, /* regbase macro */
+
+{ "beq", 0xe4000000, 0, "1,L" }, /* 6o+5a+21d */
+{ "bne", 0xf4000000, 0, "1,L" },
+{ "blt", 0xe8000000, 0, "1,L" },
+{ "ble", 0xec000000, 0, "1,L" },
+{ "bgt", 0xfc000000, 0, "1,L" },
+{ "bge", 0xf8000000, 0, "1,L" },
+{ "blbc", 0xe0000000, 0, "1,L" },
+{ "blbs", 0xf0000000, 0, "1,L" },
+
+{ "br", 0xc0000000, 0, "1,L" },
+{ "br", 0xc3e00000, 0, "L" }, /* macro: br zero,disp */
+{ "bsr", 0xd0000000, 0, "1,L" },
+{ "bsr", 0xd3500000, 0, "L" }, /* macro: bsr $ra,L */
+
+{ "jmp", 0x68000000, 0, "1,(2),i" }, /* 6o+5a+5b+2A+14d */
+{ "jmp", 0x68000000, 0, "1,(2)" },
+{ "jsr", 0x68004000, 0, "1,(2),i" },
+{ "jsr", 0x68004000, 0, "1,(2)" },
+{ "jsr", 0x68004000, 0, "1,Bc" }, /* macro: lda $pv,L;jsr .. */
+{ "ret", 0x68008000, 0, "1,(2),i" },
+{ "ret", 0x68008000, 0, "1,(2)" },
+{ "ret", 0x6b5a8000, 0, "" }, /* macro: ret ra,(ra) */
+{ "ret", 0x6be08000, 0, "(2)" }, /* macro: ret zero,(2) */
+{ "ret", 0x681a8000, 0, "1" }, /* macro: ret 1,(ra) */
+{ "jcr", 0x6800c000, 0, "1,(2)" },
+{ "jsr_coroutine", 0x6800c000, 0, "1,(2)" },
+
+{ "addl", 0x40000000, 0, "1,2,3" }, /* 6o+5a+5b+4z+7f+5c */
+{ "addl", 0x40001000, 0, "1,b,3" }, /* 6o+5a+8n+1+7f+5c */
+{ "addl/v", 0x40000800, 0, "1,2,3" },
+{ "addl/v", 0x40001800, 0, "1,b,3" },
+{ "s4addl", 0x40000040, 0, "1,2,3" },
+{ "s4addl", 0x40001040, 0, "1,b,3" },
+{ "s8addl", 0x40000240, 0, "1,2,3" },
+{ "s8addl", 0x40001240, 0, "1,b,3" },
+{ "addq", 0x40000400, 0, "1,2,3" },
+{ "addq", 0x40001400, 0, "1,b,3" },
+{ "addq/v", 0x40000c00, 0, "1,2,3" },
+
+{ "addq/v", 0x40001c00, 0, "1,b,3" },
+{ "s4addq", 0x40000440, 0, "1,2,3" },
+{ "s4addq", 0x40001440, 0, "1,b,3" },
+{ "s8addq", 0x40000640, 0, "1,2,3" },
+{ "s8addq", 0x40001640, 0, "1,b,3" },
+{ "cmpeq", 0x400005a0, 0, "1,2,3" },
+{ "cmpeq", 0x400015a0, 0, "1,b,3" },
+{ "cmplt", 0x400009a0, 0, "1,2,3" },
+{ "cmplt", 0x400019a0, 0, "1,b,3" },
+{ "cmple", 0x40000da0, 0, "1,2,3" },
+{ "cmple", 0x40001da0, 0, "1,b,3" },
+{ "cmpult", 0x400003a0, 0, "1,2,3" },
+{ "cmpult", 0x400013a0, 0, "1,b,3" },
+{ "cmpule", 0x400007a0, 0, "1,2,3" },
+{ "cmpule", 0x400017a0, 0, "1,b,3" },
+{ "subl", 0x40000120, 0, "1,2,3" },
+{ "subl", 0x40001120, 0, "1,b,3" },
+{ "subl/v", 0x40000920, 0, "1,2,3" },
+{ "subl/v", 0x40001920, 0, "1,b,3" },
+{ "s4subl", 0x40000160, 0, "1,2,3" },
+{ "s4subl", 0x40001160, 0, "1,b,3" },
+{ "s8subl", 0x40000360, 0, "1,2,3" },
+{ "s8subl", 0x40001360, 0, "1,b,3" },
+{ "subq", 0x40000520, 0, "1,2,3" },
+{ "subq", 0x40001520, 0, "1,b,3" },
+{ "subq/v", 0x40000d20, 0, "1,2,3" },
+{ "subq/v", 0x40001d20, 0, "1,b,3" },
+{ "s4subq", 0x40000560, 0, "1,2,3" },
+{ "s4subq", 0x40001560, 0, "1,b,3" },
+{ "s8subq", 0x40000760, 0, "1,2,3" },
+{ "s8subq", 0x40001760, 0, "1,b,3" },
+{ "cmpbge", 0x400001e0, 0, "1,2,3" },
+{ "cmpbge", 0x400011e0, 0, "1,b,3" },
+
+{ "mull", 0x4c000000, 0, "1,2,3" },
+{ "mull", 0x4c001000, 0, "1,b,3" },
+{ "mull/v", 0x4c000800, 0, "1,2,3" },
+{ "mull/v", 0x4c001800, 0, "1,b,3" },
+{ "mulq", 0x4c000400, 0, "1,2,3" },
+{ "mulq", 0x4c001400, 0, "1,b,3" },
+{ "mulq/v", 0x4c000c00, 0, "1,2,3" },
+{ "mulq/v", 0x4c001c00, 0, "1,b,3" },
+{ "umulh", 0x4c000600, 0, "1,2,3" },
+{ "umulh", 0x4c001600, 0, "1,b,3" },
+
+{ "clr", 0x47ff0400, 0, "3" }, /* macro: or zero,zero,rc */
+{ "negl", 0x43e00120, 0, "2,3" }, /* macro: subl zero,rb,rc */
+{ "negl_v", 0x43e00920, 0, "2,3" }, /* macro: subl_v zero,rb,rc */
+{ "negq", 0x43e00520, 0, "2,3" }, /* macro: subq zero,rb,rc */
+{ "negq_v", 0x43e00d20, 0, "2,3" }, /* macro: subq_v zero,rb,rc */
+{ "sextl", 0x43e00000, 0, "2,3" }, /* macro: addl zero,rb,rc */
+
+{ "and", 0x44000000, 0, "1,2,3" },
+{ "and", 0x44001000, 0, "1,b,3" },
+{ "and", 0x44000000, 0, "r,2" }, /* macro: and ra,rb,ra */
+{ "and", 0x44001000, 0, "r,b" }, /* macro: and ra,#,ra */
+{ "or", 0x44000400, 0, "1,2,3" },
+{ "or", 0x44001400, 0, "1,b,3" },
+{ "or", 0x44000400, 0, "r,2" }, /* macro: or ra,rb,ra */
+{ "or", 0x44001400, 0, "r,b" }, /* macro: or ra,#,ra */
+{ "bis", 0x44000400, 0, "1,2,3" },
+{ "bis", 0x44001400, 0, "1,b,3" },
+{ "bis", 0x44000400, 0, "r,2" }, /* macro: or ra,rb,ra */
+{ "bis", 0x44001400, 0, "r,b" }, /* macro: or ra,#,ra */
+{ "movi", 0x47E01400, 0, "b,3"}, /* movi lit,rc == bis r31,lit,rc */
+{ "xor", 0x44000800, 0, "1,2,3" },
+{ "xor", 0x44001800, 0, "1,b,3" },
+{ "xor", 0x44000800, 0, "r,2" }, /* macro: ra,rb,ra */
+{ "xor", 0x44001800, 0, "r,b" }, /* macro: ra,#,ra */
+{ "andnot", 0x44000100, 0, "1,2,3" },
+{ "andnot", 0x44001100, 0, "1,b,3" },
+{ "andnot", 0x44000100, 0, "r,2" }, /* macro: ra,#,ra */
+{ "andnot", 0x44001100, 0, "r,b" }, /* macro: ra,#,ra */
+{ "bic", 0x44000100, 0, "1,2,3" },
+{ "bic", 0x44001100, 0, "1,b,3" },
+{ "bic", 0x44000100, 0, "r,2" }, /* macro: ra,#,ra */
+{ "bic", 0x44001100, 0, "r,b" }, /* macro: ra,#,ra */
+{ "ornot", 0x44000500, 0, "1,2,3" },
+{ "ornot", 0x44001500, 0, "1,b,3" },
+{ "ornot", 0x44000500, 0, "r,2" }, /* macro: ra,#,ra */
+{ "ornot", 0x44001500, 0, "r,b" }, /* macro: ra,#,ra */
+{ "not", 0x47e00500, 0, "2,3" }, /* macro: ornot zero,.. */
+{ "not", 0x47e01500, 0, "b,3" },
+{ "xornot", 0x44000900, 0, "1,2,3" },
+{ "xornot", 0x44001900, 0, "1,b,3" },
+{ "xornot", 0x44000900, 0, "r,2" }, /* macro: ra,#,ra */
+{ "xornot", 0x44001900, 0, "r,b" }, /* macro: ra,#,ra */
+{ "eqv", 0x44000900, 0, "1,2,3" },
+{ "eqv", 0x44001900, 0, "1,b,3" },
+{ "eqv", 0x44000900, 0, "r,2" }, /* macro: ra,#,ra */
+{ "eqv", 0x44001900, 0, "r,b" }, /* macro: ra,#,ra */
+
+{ "cmoveq", 0x44000480, 0, "1,2,3" },
+{ "cmoveq", 0x44001480, 0, "1,b,3" },
+{ "cmovne", 0x440004c0, 0, "1,2,3" },
+{ "cmovne", 0x440014c0, 0, "1,b,3" },
+{ "cmovlt", 0x44000880, 0, "1,2,3" },
+{ "cmovlt", 0x44001880, 0, "1,b,3" },
+{ "cmovle", 0x44000c80, 0, "1,2,3" },
+{ "cmovle", 0x44001c80, 0, "1,b,3" },
+{ "cmovgt", 0x44000cc0, 0, "1,2,3" },
+{ "cmovgt", 0x44001cc0, 0, "1,b,3" },
+{ "cmovge", 0x440008c0, 0, "1,2,3" },
+{ "cmovge", 0x440018c0, 0, "1,b,3" },
+{ "cmovlbc", 0x440002c0, 0, "1,2,3" },
+{ "cmovlbc", 0x440012c0, 0, "1,b,3" },
+{ "cmovlbs", 0x44000280, 0, "1,2,3" },
+{ "cmovlbs", 0x44001280, 0, "1,b,3" },
+
+{ "sll", 0x48000720, 0, "1,2,3" },
+{ "sll", 0x48001720, 0, "1,b,3" },
+{ "srl", 0x48000680, 0, "1,2,3" },
+{ "srl", 0x48001680, 0, "1,b,3" },
+{ "sra", 0x48000780, 0, "1,2,3" },
+{ "sra", 0x48001780, 0, "1,b,3" },
+
+{ "extbl", 0x480000c0, 0, "1,2,3" },
+{ "extbl", 0x480010c0, 0, "1,b,3" },
+{ "extwl", 0x480002c0, 0, "1,2,3" },
+{ "extwl", 0x480012c0, 0, "1,b,3" },
+{ "extll", 0x480004c0, 0, "1,2,3" },
+{ "extll", 0x480014c0, 0, "1,b,3" },
+{ "extql", 0x480006c0, 0, "1,2,3" },
+{ "extql", 0x480016c0, 0, "1,b,3" },
+{ "extwh", 0x48000b40, 0, "1,2,3" },
+{ "extwh", 0x48001b40, 0, "1,b,3" },
+{ "extlh", 0x48000d40, 0, "1,2,3" },
+{ "extlh", 0x48001d40, 0, "1,b,3" },
+{ "extqh", 0x48000f40, 0, "1,2,3" },
+{ "extqh", 0x48001f40, 0, "1,b,3" },
+{ "insbl", 0x48000160, 0, "1,2,3" },
+{ "insbl", 0x48001160, 0, "1,b,3" },
+{ "inswl", 0x48000360, 0, "1,2,3" },
+{ "inswl", 0x48001360, 0, "1,b,3" },
+{ "insll", 0x48000560, 0, "1,2,3" },
+{ "insll", 0x48001560, 0, "1,b,3" },
+{ "insql", 0x48000760, 0, "1,2,3" },
+{ "insql", 0x48001760, 0, "1,b,3" },
+{ "inswh", 0x48000ae0, 0, "1,2,3" },
+{ "inswh", 0x48001ae0, 0, "1,b,3" },
+{ "inslh", 0x48000ce0, 0, "1,2,3" },
+{ "inslh", 0x48001ce0, 0, "1,b,3" },
+{ "insqh", 0x48000ee0, 0, "1,2,3" },
+{ "insqh", 0x48001ee0, 0, "1,b,3" },
+{ "mskbl", 0x48000040, 0, "1,2,3" },
+{ "mskbl", 0x48001040, 0, "1,b,3" },
+{ "mskwl", 0x48000240, 0, "1,2,3" },
+{ "mskwl", 0x48001240, 0, "1,b,3" },
+{ "mskll", 0x48000440, 0, "1,2,3" },
+{ "mskll", 0x48001440, 0, "1,b,3" },
+{ "mskql", 0x48000640, 0, "1,2,3" },
+{ "mskql", 0x48001640, 0, "1,b,3" },
+{ "mskwh", 0x48000a40, 0, "1,2,3" },
+{ "mskwh", 0x48001a40, 0, "1,b,3" },
+{ "msklh", 0x48000c40, 0, "1,2,3" },
+{ "msklh", 0x48001c40, 0, "1,b,3" },
+{ "mskqh", 0x48000e40, 0, "1,2,3" },
+{ "mskqh", 0x48001e40, 0, "1,b,3" },
+{ "zap", 0x48000600, 0, "1,2,3" },
+{ "zap", 0x48001600, 0, "1,b,3" },
+{ "zapnot", 0x48000620, 0, "1,2,3" },
+{ "zapnot", 0x48001620, 0, "1,b,3" },
+
+/*
+ * Floating point instructions
+ */
+{ "ldf", 0x80000000, 1, "e,l(2)" }, /* 6o+5a+5b+16d */
+{ "ldf", 0x80000000, 1, "e,G" }, /* regbase macro */
+{ "ldg", 0x84000000, 1, "e,l(2)" },
+{ "ldg", 0x84000000, 1, "e,G" }, /* regbase macro */
+{ "lds", 0x88000000, 1, "e,l(2)" },
+{ "lds", 0x88000000, 1, "e,G" }, /* regbase macro */
+{ "ldt", 0x8c000000, 1, "e,l(2)" },
+{ "ldt", 0x8c000000, 1, "e,G" }, /* regbase macro */
+{ "stf", 0x90000000, 1, "e,l(2)" },
+{ "stf", 0x90000000, 1, "e,P" }, /* regbase macro */
+{ "stg", 0x94000000, 1, "e,l(2)" },
+{ "stg", 0x94000000, 1, "e,P" }, /* regbase macro */
+{ "sts", 0x98000000, 1, "e,l(2)" },
+{ "sts", 0x98000000, 1, "e,P" }, /* regbase macro */
+{ "stt", 0x9c000000, 1, "e,l(2)" },
+{ "stt", 0x9c000000, 1, "e,P" }, /* regbase macro */
+
+{ "fbeq", 0xc4000000, 1, "e,L" }, /* 6o+5a+21d */
+{ "fbne", 0xd4000000, 1, "e,L" },
+{ "fblt", 0xc8000000, 1, "e,L" },
+{ "fble", 0xcc000000, 1, "e,L" },
+{ "fbgt", 0xdc000000, 1, "e,L" },
+{ "fbge", 0xd8000000, 1, "e,L" },
+
+/* All subsets (opcode 0x17) */
+{ "cpys", 0x5c000400, 1, "e,f,g" }, /* 6o+5a+5b+11f+5c */
+{ "cpysn", 0x5c000420, 1, "e,f,g" },
+{ "cpyse", 0x5c000440, 1, "e,f,g" },
+
+{ "cvtlq", 0x5fe00200, 1, "f,g" },
+{ "cvtql", 0x5fe00600, 1, "f,g" },
+{ "cvtql/v", 0x5fe02600, 1, "f,g" },
+{ "cvtql/sv", 0x5fe06600, 1, "f,g" },
+
+{ "fcmoveq", 0x5c000540, 1, "e,f,g" },
+{ "fcmovne", 0x5c000560, 1, "e,f,g" },
+{ "fcmovlt", 0x5c000580, 1, "e,f,g" },
+{ "fcmovle", 0x5c0005c0, 1, "e,f,g" },
+{ "fcmovgt", 0x5c0005e0, 1, "e,f,g" },
+{ "fcmovge", 0x5c0005a0, 1, "e,f,g" },
+
+{ "mf_fpcr", 0x5c0004a0, 1, "E" },
+{ "mt_fpcr", 0x5c000480, 1, "E" },
+
+/* Vax subset (opcode 0x15) */
+{ "addf", 0x54001000, 1, "e,f,g" },
+{ "addf/c", 0x54000000, 1, "e,f,g" },
+{ "addf/u", 0x54003000, 1, "e,f,g" },
+{ "addf/uc", 0x54002000, 1, "e,f,g" },
+{ "addf/s", 0x54009000, 1, "e,f,g" },
+{ "addf/sc", 0x54008000, 1, "e,f,g" },
+{ "addf/su", 0x5400b000, 1, "e,f,g" },
+{ "addf/suc", 0x5400a000, 1, "e,f,g" },
+{ "addg", 0x54001400, 1, "e,f,g" },
+{ "addg/c", 0x54000400, 1, "e,f,g" },
+{ "addg/u", 0x54003400, 1, "e,f,g" },
+{ "addg/uc", 0x54002400, 1, "e,f,g" },
+{ "addg/s", 0x54009400, 1, "e,f,g" },
+{ "addg/sc", 0x54008400, 1, "e,f,g" },
+{ "addg/su", 0x5400b400, 1, "e,f,g" },
+{ "addg/suc", 0x5400a400, 1, "e,f,g" },
+{ "subf", 0x54001020, 1, "e,f,g" },
+{ "subf/c", 0x54000020, 1, "e,f,g" },
+{ "subf/u", 0x54003020, 1, "e,f,g" },
+{ "subf/uc", 0x54002020, 1, "e,f,g" },
+{ "subf/s", 0x54009020, 1, "e,f,g" },
+{ "subf/sc", 0x54008020, 1, "e,f,g" },
+{ "subf/su", 0x5400b020, 1, "e,f,g" },
+{ "subf/suc", 0x5400a020, 1, "e,f,g" },
+{ "subg", 0x54001420, 1, "e,f,g" },
+{ "subg/c", 0x54000420, 1, "e,f,g" },
+{ "subg/u", 0x54003420, 1, "e,f,g" },
+{ "subg/uc", 0x54002420, 1, "e,f,g" },
+{ "subg/s", 0x54009420, 1, "e,f,g" },
+{ "subg/sc", 0x54008420, 1, "e,f,g" },
+{ "subg/su", 0x5400b420, 1, "e,f,g" },
+{ "subg/suc", 0x5400a420, 1, "e,f,g" },
+
+{ "cmpgeq", 0x540014a0, 1, "e,f,g" },
+{ "cmpgeq/s", 0x540094a0, 1, "e,f,g" },
+{ "cmpglt", 0x540014c0, 1, "e,f,g" },
+{ "cmpglt/s", 0x540094c0, 1, "e,f,g" },
+{ "cmpgle", 0x540014e0, 1, "e,f,g" },
+{ "cmpgle/s", 0x540094e0, 1, "e,f,g" },
+
+{ "cvtgq", 0x57e015e0, 1, "f,g" },
+{ "cvtgq/c", 0x57e005e0, 1, "f,g" },
+{ "cvtgq/v", 0x57e035e0, 1, "f,g" },
+{ "cvtgq/vc", 0x57e025e0, 1, "f,g" },
+{ "cvtgq/s", 0x57e095e0, 1, "f,g" },
+{ "cvtgq/sc", 0x57e085e0, 1, "f,g" },
+{ "cvtgq/sv", 0x57e0b5e0, 1, "f,g" },
+{ "cvtgq/svc", 0x57e0a5e0, 1, "f,g" },
+{ "cvtqf", 0x57e01780, 1, "f,g" },
+{ "cvtqf/c", 0x57e00780, 1, "f,g" },
+{ "cvtqf/s", 0x57e09780, 1, "f,g" },
+{ "cvtqf/sc", 0x57e08780, 1, "f,g" },
+{ "cvtqg", 0x57e017c0, 1, "f,g" },
+{ "cvtqg/c", 0x57e007c0, 1, "f,g" },
+{ "cvtqg/s", 0x57e097c0, 1, "f,g" },
+{ "cvtqg/sc", 0x57e087c0, 1, "f,g" },
+{ "cvtdg", 0x57e013c0, 1, "f,g" },
+{ "cvtdg/c", 0x57e003c0, 1, "f,g" },
+{ "cvtdg/u", 0x57e033c0, 1, "f,g" },
+{ "cvtdg/uc", 0x57e023c0, 1, "f,g" },
+{ "cvtdg/s", 0x57e093c0, 1, "f,g" },
+{ "cvtdg/sc", 0x57e083c0, 1, "f,g" },
+{ "cvtdg/su", 0x57e0b3c0, 1, "f,g" },
+{ "cvtdg/suc", 0x57e0a3c0, 1, "f,g" },
+{ "cvtgd", 0x57e015a0, 1, "f,g" },
+{ "cvtgd/c", 0x57e005a0, 1, "f,g" },
+{ "cvtgd/u", 0x57e035a0, 1, "f,g" },
+{ "cvtgd/uc", 0x57e025a0, 1, "f,g" },
+{ "cvtgd/s", 0x57e095a0, 1, "f,g" },
+{ "cvtgd/sc", 0x57e085a0, 1, "f,g" },
+{ "cvtgd/su", 0x57e0b5a0, 1, "f,g" },
+{ "cvtgd/suc", 0x57e0a5a0, 1, "f,g" },
+{ "cvtgf", 0x57e01580, 1, "f,g" },
+{ "cvtgf/c", 0x57e00580, 1, "f,g" },
+{ "cvtgf/u", 0x57e03580, 1, "f,g" },
+{ "cvtgf/uc", 0x57e02580, 1, "f,g" },
+{ "cvtgf/s", 0x57e09580, 1, "f,g" },
+{ "cvtgf/sc", 0x57e08580, 1, "f,g" },
+{ "cvtgf/su", 0x57e0b580, 1, "f,g" },
+{ "cvtgf/suc", 0x57e0a580, 1, "f,g" },
+
+{ "divf", 0x54001060, 1, "e,f,g" },
+{ "divf/c", 0x54000060, 1, "e,f,g" },
+{ "divf/u", 0x54003060, 1, "e,f,g" },
+{ "divf/uc", 0x54002060, 1, "e,f,g" },
+{ "divf/s", 0x54009060, 1, "e,f,g" },
+{ "divf/sc", 0x54008060, 1, "e,f,g" },
+{ "divf/su", 0x5400b060, 1, "e,f,g" },
+{ "divf/suc", 0x5400a060, 1, "e,f,g" },
+{ "divg", 0x54001460, 1, "e,f,g" },
+{ "divg/c", 0x54000460, 1, "e,f,g" },
+{ "divg/u", 0x54003460, 1, "e,f,g" },
+{ "divg/uc", 0x54002460, 1, "e,f,g" },
+{ "divg/s", 0x54009460, 1, "e,f,g" },
+{ "divg/sc", 0x54008460, 1, "e,f,g" },
+{ "divg/su", 0x5400b460, 1, "e,f,g" },
+{ "divg/suc", 0x5400a460, 1, "e,f,g" },
+{ "mulf", 0x54001040, 1, "e,f,g" },
+{ "mulf/c", 0x54000040, 1, "e,f,g" },
+{ "mulf/u", 0x54003040, 1, "e,f,g" },
+{ "mulf/uc", 0x54002040, 1, "e,f,g" },
+{ "mulf/s", 0x54009040, 1, "e,f,g" },
+{ "mulf/sc", 0x54008040, 1, "e,f,g" },
+{ "mulf/su", 0x5400b040, 1, "e,f,g" },
+{ "mulf/suc", 0x5400a040, 1, "e,f,g" },
+{ "mulg", 0x54001440, 1, "e,f,g" },
+{ "mulg/c", 0x54000440, 1, "e,f,g" },
+{ "mulg/u", 0x54003440, 1, "e,f,g" },
+{ "mulg/uc", 0x54002440, 1, "e,f,g" },
+{ "mulg/s", 0x54009440, 1, "e,f,g" },
+{ "mulg/sc", 0x54008440, 1, "e,f,g" },
+{ "mulg/su", 0x5400b440, 1, "e,f,g" },
+{ "mulg/suc", 0x5400a440, 1, "e,f,g" },
+
+/* IEEE subset (opcode 0x16) */
+{ "adds", 0x58001000, 1, "e,f,g" },
+{ "adds/c", 0x58000000, 1, "e,f,g" },
+{ "adds/m", 0x58000800, 1, "e,f,g" },
+{ "adds/d", 0x58001800, 1, "e,f,g" },
+{ "adds/u", 0x58003000, 1, "e,f,g" },
+{ "adds/uc", 0x58002000, 1, "e,f,g" },
+{ "adds/um", 0x58002800, 1, "e,f,g" },
+{ "adds/ud", 0x58003800, 1, "e,f,g" },
+{ "adds/su", 0x5800b000, 1, "e,f,g" },
+{ "adds/suc", 0x5800a000, 1, "e,f,g" },
+{ "adds/sum", 0x5800a800, 1, "e,f,g" },
+{ "adds/sud", 0x5800b800, 1, "e,f,g" },
+{ "adds/sui", 0x5800f000, 1, "e,f,g" },
+{ "adds/suic", 0x5800e000, 1, "e,f,g" },
+{ "adds/suim", 0x5800e800, 1, "e,f,g" },
+{ "adds/suid", 0x5800f800, 1, "e,f,g" },
+{ "addt", 0x58001400, 1, "e,f,g" },
+{ "addt/c", 0x58000400, 1, "e,f,g" },
+{ "addt/m", 0x58000c00, 1, "e,f,g" },
+{ "addt/d", 0x58001c00, 1, "e,f,g" },
+{ "addt/u", 0x58003400, 1, "e,f,g" },
+{ "addt/uc", 0x58002400, 1, "e,f,g" },
+{ "addt/um", 0x58002c00, 1, "e,f,g" },
+{ "addt/ud", 0x58003c00, 1, "e,f,g" },
+{ "addt/su", 0x5800b400, 1, "e,f,g" },
+{ "addt/suc", 0x5800a400, 1, "e,f,g" },
+{ "addt/sum", 0x5800ac00, 1, "e,f,g" },
+{ "addt/sud", 0x5800bc00, 1, "e,f,g" },
+{ "addt/sui", 0x5800f400, 1, "e,f,g" },
+{ "addt/suic", 0x5800e400, 1, "e,f,g" },
+{ "addt/suim", 0x5800ec00, 1, "e,f,g" },
+{ "addt/suid", 0x5800fc00, 1, "e,f,g" },
+{ "subs", 0x58001020, 1, "e,f,g" },
+{ "subs/c", 0x58000020, 1, "e,f,g" },
+{ "subs/m", 0x58000820, 1, "e,f,g" },
+{ "subs/d", 0x58001820, 1, "e,f,g" },
+{ "subs/u", 0x58003020, 1, "e,f,g" },
+{ "subs/uc", 0x58002020, 1, "e,f,g" },
+{ "subs/um", 0x58002820, 1, "e,f,g" },
+{ "subs/ud", 0x58003820, 1, "e,f,g" },
+{ "subs/su", 0x5800b020, 1, "e,f,g" },
+{ "subs/suc", 0x5800a020, 1, "e,f,g" },
+{ "subs/sum", 0x5800a820, 1, "e,f,g" },
+{ "subs/sud", 0x5800b820, 1, "e,f,g" },
+{ "subs/sui", 0x5800f020, 1, "e,f,g" },
+{ "subs/suic", 0x5800e020, 1, "e,f,g" },
+{ "subs/suim", 0x5800e820, 1, "e,f,g" },
+{ "subs/suid", 0x5800f820, 1, "e,f,g" },
+{ "subt", 0x58001420, 1, "e,f,g" },
+{ "subt/c", 0x58000420, 1, "e,f,g" },
+{ "subt/m", 0x58000c20, 1, "e,f,g" },
+{ "subt/d", 0x58001c20, 1, "e,f,g" },
+{ "subt/u", 0x58003420, 1, "e,f,g" },
+{ "subt/uc", 0x58002420, 1, "e,f,g" },
+{ "subt/um", 0x58002c20, 1, "e,f,g" },
+{ "subt/ud", 0x58003c20, 1, "e,f,g" },
+{ "subt/su", 0x5800b420, 1, "e,f,g" },
+{ "subt/suc", 0x5800a420, 1, "e,f,g" },
+{ "subt/sum", 0x5800ac20, 1, "e,f,g" },
+{ "subt/sud", 0x5800bc20, 1, "e,f,g" },
+{ "subt/sui", 0x5800f420, 1, "e,f,g" },
+{ "subt/suic", 0x5800e420, 1, "e,f,g" },
+{ "subt/suim", 0x5800ec20, 1, "e,f,g" },
+{ "subt/suid", 0x5800fc20, 1, "e,f,g" },
+
+{ "cmpteq", 0x580014a0, 1, "e,f,g" },
+{ "cmpteq/su", 0x5800b4a0, 1, "e,f,g" },
+{ "cmptlt", 0x580014c0, 1, "e,f,g" },
+{ "cmptlt/su", 0x5800b4c0, 1, "e,f,g" },
+{ "cmptle", 0x580014e0, 1, "e,f,g" },
+{ "cmptle/su", 0x5800b4e0, 1, "e,f,g" },
+{ "cmptun", 0x58001480, 1, "e,f,g" },
+{ "cmptun/su", 0x5800b480, 1, "e,f,g" },
+
+{ "cvttq", 0x5be015e0, 1, "f,g" },
+{ "cvttq/c", 0x5be005e0, 1, "f,g" },
+{ "cvttq/v", 0x5be035e0, 1, "f,g" },
+{ "cvttq/vc", 0x5be025e0, 1, "f,g" },
+{ "cvttq/sv", 0x5be0b5e0, 1, "f,g" },
+{ "cvttq/svc", 0x5be0a5e0, 1, "f,g" },
+{ "cvttq/svi", 0x5be0f5e0, 1, "f,g" },
+{ "cvttq/svic", 0x5be0e5e0, 1, "f,g" },
+{ "cvtqs", 0x5be01780, 1, "f,g" },
+{ "cvtqs/c", 0x5be00780, 1, "f,g" },
+{ "cvtqs/m", 0x5be00f80, 1, "f,g" },
+{ "cvtqs/d", 0x5be01f80, 1, "f,g" },
+{ "cvtqs/sui", 0x5be0f780, 1, "f,g" },
+{ "cvtqs/suic", 0x5be0e780, 1, "f,g" },
+{ "cvtqs/suim", 0x5be0ef80, 1, "f,g" },
+{ "cvtqs/suid", 0x5be0ff80, 1, "f,g" },
+{ "cvtqt", 0x5be017c0, 1, "f,g" },
+{ "cvtqt/c", 0x5be007c0, 1, "f,g" },
+{ "cvtqt/m", 0x5be00fc0, 1, "f,g" },
+{ "cvtqt/d", 0x5be01fc0, 1, "f,g" },
+{ "cvtqt/sui", 0x5be0f7c0, 1, "f,g" },
+{ "cvtqt/suic", 0x5be0e7c0, 1, "f,g" },
+{ "cvtqt/suim", 0x5be0efc0, 1, "f,g" },
+{ "cvtqt/suid", 0x5be0ffc0, 1, "f,g" },
+{ "cvtts", 0x5be01580, 1, "f,g" },
+{ "cvtts/c", 0x5be00580, 1, "f,g" },
+{ "cvtts/m", 0x5be00d80, 1, "f,g" },
+{ "cvtts/d", 0x5be01d80, 1, "f,g" },
+{ "cvtts/u", 0x5be03580, 1, "f,g" },
+{ "cvtts/uc", 0x5be02580, 1, "f,g" },
+{ "cvtts/um", 0x5be02d80, 1, "f,g" },
+{ "cvtts/ud", 0x5be03d80, 1, "f,g" },
+{ "cvtts/su", 0x5be0b580, 1, "f,g" },
+{ "cvtts/suc", 0x5be0a580, 1, "f,g" },
+{ "cvtts/sum", 0x5be0ad80, 1, "f,g" },
+{ "cvtts/sud", 0x5be0bd80, 1, "f,g" },
+{ "cvtts/sui", 0x5be0f580, 1, "f,g" },
+{ "cvtts/suic", 0x5be0e580, 1, "f,g" },
+{ "cvtts/suim", 0x5be0ed80, 1, "f,g" },
+{ "cvtts/suid", 0x5be0fd80, 1, "f,g" },
+
+{ "divs", 0x58001060, 1, "e,f,g" },
+{ "divs/c", 0x58000060, 1, "e,f,g" },
+{ "divs/m", 0x58000860, 1, "e,f,g" },
+{ "divs/d", 0x58001860, 1, "e,f,g" },
+{ "divs/u", 0x58003060, 1, "e,f,g" },
+{ "divs/uc", 0x58002060, 1, "e,f,g" },
+{ "divs/um", 0x58002860, 1, "e,f,g" },
+{ "divs/ud", 0x58003860, 1, "e,f,g" },
+{ "divs/su", 0x5800b060, 1, "e,f,g" },
+{ "divs/suc", 0x5800a060, 1, "e,f,g" },
+{ "divs/sum", 0x5800a860, 1, "e,f,g" },
+{ "divs/sud", 0x5800b860, 1, "e,f,g" },
+{ "divs/sui", 0x5800f060, 1, "e,f,g" },
+{ "divs/suic", 0x5800e060, 1, "e,f,g" },
+{ "divs/suim", 0x5800e860, 1, "e,f,g" },
+{ "divs/suid", 0x5800f860, 1, "e,f,g" },
+{ "divt", 0x58001460, 1, "e,f,g" },
+{ "divt/c", 0x58000460, 1, "e,f,g" },
+{ "divt/m", 0x58000c60, 1, "e,f,g" },
+{ "divt/d", 0x58001c60, 1, "e,f,g" },
+{ "divt/u", 0x58003460, 1, "e,f,g" },
+{ "divt/uc", 0x58002460, 1, "e,f,g" },
+{ "divt/um", 0x58002c60, 1, "e,f,g" },
+{ "divt/ud", 0x58003c60, 1, "e,f,g" },
+{ "divt/su", 0x5800b460, 1, "e,f,g" },
+{ "divt/suc", 0x5800a460, 1, "e,f,g" },
+{ "divt/sum", 0x5800ac60, 1, "e,f,g" },
+{ "divt/sud", 0x5800bc60, 1, "e,f,g" },
+{ "divt/sui", 0x5800f460, 1, "e,f,g" },
+{ "divt/suic", 0x5800e460, 1, "e,f,g" },
+{ "divt/suim", 0x5800ec60, 1, "e,f,g" },
+{ "divt/suid", 0x5800fc60, 1, "e,f,g" },
+{ "muls", 0x58001040, 1, "e,f,g" },
+{ "muls/c", 0x58000040, 1, "e,f,g" },
+{ "muls/m", 0x58000840, 1, "e,f,g" },
+{ "muls/d", 0x58001840, 1, "e,f,g" },
+{ "muls/u", 0x58003040, 1, "e,f,g" },
+{ "muls/uc", 0x58002040, 1, "e,f,g" },
+{ "muls/um", 0x58002840, 1, "e,f,g" },
+{ "muls/ud", 0x58003840, 1, "e,f,g" },
+{ "muls/su", 0x5800b040, 1, "e,f,g" },
+{ "muls/suc", 0x5800a040, 1, "e,f,g" },
+{ "muls/sum", 0x5800a840, 1, "e,f,g" },
+{ "muls/sud", 0x5800b840, 1, "e,f,g" },
+{ "muls/sui", 0x5800f040, 1, "e,f,g" },
+{ "muls/suic", 0x5800e040, 1, "e,f,g" },
+{ "muls/suim", 0x5800e840, 1, "e,f,g" },
+{ "muls/suid", 0x5800f840, 1, "e,f,g" },
+{ "mult", 0x58001440, 1, "e,f,g" },
+{ "mult/c", 0x58000440, 1, "e,f,g" },
+{ "mult/m", 0x58000c40, 1, "e,f,g" },
+{ "mult/d", 0x58001c40, 1, "e,f,g" },
+{ "mult/u", 0x58003440, 1, "e,f,g" },
+{ "mult/uc", 0x58002440, 1, "e,f,g" },
+{ "mult/um", 0x58002c40, 1, "e,f,g" },
+{ "mult/ud", 0x58003c40, 1, "e,f,g" },
+{ "mult/su", 0x5800b440, 1, "e,f,g" },
+{ "mult/suc", 0x5800a440, 1, "e,f,g" },
+{ "mult/sum", 0x5800ac40, 1, "e,f,g" },
+{ "mult/sud", 0x5800bc40, 1, "e,f,g" },
+{ "mult/sui", 0x5800f440, 1, "e,f,g" },
+{ "mult/suic", 0x5800e440, 1, "e,f,g" },
+{ "mult/suim", 0x5800ec40, 1, "e,f,g" },
+{ "mult/suid", 0x5800fc40, 1, "e,f,g" },
+
+/*
+ * Miscellaneous
+ */
+{ "pal", 0x00000000, 0, "I" }, /* 6o+26f */
+{ "call_pal", 0x00000000, 0, "I" }, /* alias */
+{ "bpt", 0x00000080, 0, "" },
+{ "chmk", 0x00000083, 0, "" },
+{ "imb", 0x00000086, 0, "" },
+
+{ "draint", 0x60000000, 0, "" }, /* 6o+5a+5b+16d */
+{ "trapb", 0x60000000, 0, "" }, /* 6o+5a+5b+16d */
+{ "fetch", 0x60008000, 0, "0(2)" },
+{ "fetch_m", 0x6000a000, 0, "0(2)" },
+{ "mb", 0x60004000, 0, "" },
+{ "rpcc", 0x6000c000, 0, "1" },
+{ "rc", 0x6000e000, 0, "1" },
+{ "rs", 0x6000f000, 0, "1" },
+
+/*
+ * PAL instructions
+ */
+{ "hw_ld", 0x6c000000, 0, "1,t(2)" },
+{ "hw_ld/p", 0x6c008000, 0, "1,t(2)" },
+{ "hw_ld/a", 0x6c004000, 0, "1,t(2)" },
+{ "hw_ld/r", 0x6c002000, 0, "1,t(2)" },
+{ "hw_ld/q", 0x6c001000, 0, "1,t(2)" },
+{ "hw_ld/pa", 0x6c00C000, 0, "1,t(2)" },
+{ "hw_ld/pr", 0x6c00A000, 0, "1,t(2)" },
+{ "hw_ld/pq", 0x6c009000, 0, "1,t(2)" },
+{ "hw_ld/ar", 0x6c006000, 0, "1,t(2)" },
+{ "hw_ld/aq", 0x6c005000, 0, "1,t(2)" },
+{ "hw_ld/rq", 0x6c003000, 0, "1,t(2)" },
+{ "hw_ld/par", 0x6c00e000, 0, "1,t(2)" },
+{ "hw_ld/paq", 0x6c00d000, 0, "1,t(2)" },
+{ "hw_ld/prq", 0x6c00b000, 0, "1,t(2)" },
+{ "hw_ld/arq", 0x6c007000, 0, "1,t(2)" },
+{ "hw_ld/parq", 0x6c00f000, 0, "1,t(2)" },
+
+{ "hw_ldq", 0x6c001000, 0, "1,t(2)" }, /* ldq/ldl variants for Eric */
+{ "hw_ldq/p", 0x6c009000, 0, "1,t(2)" },
+{ "hw_ldq/a", 0x6c005000, 0, "1,t(2)" },
+{ "hw_ldq/r", 0x6c003000, 0, "1,t(2)" },
+{ "hw_ldq/pa", 0x6c00d000, 0, "1,t(2)" },
+{ "hw_ldq/pr", 0x6c00b000, 0, "1,t(2)" },
+{ "hw_ldq/ar", 0x6c007000, 0, "1,t(2)" },
+{ "hw_ldq/par", 0x6c00f000, 0, "1,t(2)" },
+{ "hw_ldl", 0x6c000000, 0, "1,t(2)" },
+{ "hw_ldl/p", 0x6c008000, 0, "1,t(2)" },
+{ "hw_ldl/a", 0x6c004000, 0, "1,t(2)" },
+{ "hw_ldl/r", 0x6c002000, 0, "1,t(2)" },
+{ "hw_ldl/pa", 0x6c00C000, 0, "1,t(2)" },
+{ "hw_ldl/pr", 0x6c00A000, 0, "1,t(2)" },
+{ "hw_ldl/ar", 0x6c006000, 0, "1,t(2)" },
+{ "hw_ldl/par", 0x6c00e000, 0, "1,t(2)" },
+
+{ "hw_st/paq", 0x7c00c000, 0, "1,t(2)" },
+{ "hw_st/pa", 0x7c00b000, 0, "1,t(2)" },
+{ "hw_st/pq", 0x7c009000, 0, "1,t(2)" },
+{ "hw_st/aq", 0x7c005000, 0, "1,t(2)" },
+{ "hw_st/p", 0x7c008000, 0, "1,t(2)" },
+{ "hw_st/a", 0x7c004000, 0, "1,t(2)" },
+{ "hw_st/q", 0x7c001000, 0, "1,t(2)" },
+{ "hw_st", 0x7c000000, 0, "1,t(2)" },
+
+{ "hw_stq/pa", 0x7c00c000, 0, "1,t(2)" }, /* stq/stl variants for Eric */
+{ "hw_stq/p", 0x7c009000, 0, "1,t(2)" },
+{ "hw_stq", 0x7c001000, 0, "1,t(2)" },
+{ "hw_stq/a", 0x7c005000, 0, "1,t(2)" },
+{ "hw_stl/pa", 0x7c00b000, 0, "1,t(2)" },
+{ "hw_stl/p", 0x7c008000, 0, "1,t(2)" },
+{ "hw_stl/a", 0x7c004000, 0, "1,t(2)" },
+{ "hw_stl", 0x7c000000, 0, "1,t(2)" },
+
+{ "hw_mfpr/p", 0x64000080, 0, "R,3" },
+{ "hw_mfpr/a", 0x64000040, 0, "R,3" },
+{ "hw_mfpr/i", 0x64000020, 0, "R,3" },
+{ "hw_mfpr/pa", 0x640000c0, 0, "R,3" },
+{ "hw_mfpr/pi", 0x640000a0, 0, "R,3" },
+{ "hw_mfpr/ai", 0x64000060, 0, "R,3" },
+{ "hw_mfpr/pai",0x640000e0, 0, "R,3" },
+{ "hw_mfpr", 0x64000000, 0, "R,8" },
+
+{ "hw_mtpr/p", 0x74000080, 0, "R,3" },
+{ "hw_mtpr/a", 0x74000040, 0, "R,3" },
+{ "hw_mtpr/i", 0x74000020, 0, "R,3" },
+{ "hw_mtpr/pa", 0x740000c0, 0, "R,3" },
+{ "hw_mtpr/pi", 0x740000a0, 0, "R,3" },
+{ "hw_mtpr/ai", 0x74000060, 0, "R,3" },
+{ "hw_mtpr/pai",0x740000e0, 0, "R,3" },
+{ "hw_mtpr", 0x74000000, 0, "R,8" },
+
+{ "hw_rei", 0x7bff8000, 0, "" },
+/*
+ * More macros
+ */
+{ "nop", 0x47ff041f, 0, "" }, /* or zero,zero,zero */
+{ "mov", 0x47e00400, 0, "2,3" }, /* or zero,r2,r3 */
+};
+
+#define NUMOPCODES ((sizeof alpha_opcodes)/(sizeof alpha_opcodes[0]))
--- /dev/null
+/* tc-alpha.c - Processor-specific code for the DEC Alpha CPU.
+ Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Carnegie Mellon University, 1993.
+ Written by Alessandro Forin, based on earlier gas-1.38 target CPU files.
+ Modified by Ken Raeburn for gas-2.x and ECOFF support.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * 5-Oct-93 Alessandro Forin (af) at Carnegie-Mellon University
+ * First Checkin
+ *
+ * $Log$
+ * Revision 1.1 1994/01/28 01:36:53 raeburn
+ * New Alpha support files, based on files from CMU.
+ * Still to do:
+ * - fix floating-point handling
+ * - figure out if we can adapt to using ../opcodes/alpha-opc.h
+ * - gcc bootstrap testing
+ * - 32-bit mode support?
+ * - test cross-assembly
+ *
+ *
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: Jan 1993
+ */
+
+#include "as.h"
+#include "alpha-opcode.h"
+#include "subsegs.h"
+
+/* These are exported to relaxing code, even though we don't do any
+ relaxing on this processor currently. */
+const relax_typeS md_relax_table[1];
+int md_short_jump_size = 4;
+int md_long_jump_size = 4;
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash;
+
+/* sections we'll want to keep track of */
+static segT lita_sec, rdata, sdata;
+
+/* setting for ".set [no]{at,macro}" */
+static int at_ok = 1, macro_ok = 1;
+
+/* Keep track of global pointer. */
+static valueT gp_value;
+static symbolS *gp;
+
+/* We'll probably be using this relocation frequently, and we
+ will want to compare for it. */
+static reloc_howto_type *gpdisp_hi16_howto;
+
+/* These are exported to ECOFF code. */
+unsigned long alpha_gprmask, alpha_fprmask;
+
+/* Used for LITUSE relocations. */
+static expressionS lituse_basereg, lituse_byteoff, lituse_jsr;
+
+/* Imported functions -- they should be defined in header files somewhere. */
+extern segT subseg_get ();
+extern PTR bfd_alloc_by_size_t ();
+extern void s_globl (), s_long (), s_short (), s_space (), cons (), s_text (),
+ s_data (), float_cons ();
+
+static void s_mask (), s_base (), s_proc (), s_alpha_set ();
+static void s_gprel32 (), s_rdata (), s_sdata (), s_alpha_comm ();
+static int alpha_ip ();
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"common", s_comm, 0}, /* is this used? */
+ {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */
+ {"rdata", s_rdata, 0},
+ {"sdata", s_sdata, 0},
+ {"gprel32", s_gprel32, 0},
+ {"t_floating", float_cons, 'd'},
+ {"s_floating", float_cons, 'f'},
+ {"f_floating", float_cons, 'F'},
+ {"g_floating", float_cons, 'G'},
+ {"d_floating", float_cons, 'D'},
+
+ {"proc", s_proc, 0},
+ {"aproc", s_proc, 1},
+ {"set", s_alpha_set, 0},
+ {"reguse", s_ignore, 0},
+ {"livereg", s_ignore, 0},
+ {"extern", s_ignore, 0}, /*??*/
+ {"base", s_base, 0}, /*??*/
+ {"option", s_ignore, 0},
+ {"prologue", s_ignore, 0},
+ {"aent", s_ignore, 0},
+ {"ugen", s_ignore, 0},
+
+/* We don't do any optimizing, so we can safely ignore these. */
+ {"noalias", s_ignore, 0},
+ {"alias", s_ignore, 0},
+
+ {NULL, 0, 0},
+};
+
+#define SA 21 /* shift for register Ra */
+#define SB 16 /* shift for register Rb */
+#define SC 0 /* shift for register Rc */
+#define SN 13 /* shift for 8 bit immediate # */
+
+#define T9 23
+#define T10 24
+#define T11 25
+#define RA 26
+#define PV 27
+#define AT 28
+#define GP 29
+#define SP 30
+#define ZERO 31
+
+#define OPCODE(X) (((X) >> 26) & 0x3f)
+#define OP_FCN(X) (((X) >> 5) & 0x7f)
+
+#ifndef FIRST_32BIT_QUADRANT
+#define FIRST_32BIT_QUADRANT 0
+#endif
+
+int first_32bit_quadrant = FIRST_32BIT_QUADRANT;
+int base_register = FIRST_32BIT_QUADRANT ? ZERO : GP;
+
+int no_mixed_code = 0;
+int nofloats = 0;
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = "#";
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that '/*' will always start a comment */
+const char line_comment_chars[] = "#";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+const char line_separator_chars[1];
+
+/* Chars that mean this number is a floating point constant, as in
+ "0f12.456" or "0d1.2345e12". */
+char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here. */
+
+struct reloc_data {
+ expressionS exp;
+ int pcrel;
+ bfd_reloc_code_real_type code;
+};
+
+/* Occasionally, two relocations will be desired for one address.
+ Mainly only in cases like "jsr $r,foo" where we want both a LITUSE
+ and a HINT reloc. */
+#define MAX_RELOCS 2
+
+struct alpha_it {
+ unsigned long opcode; /* need at least 32 bits */
+ struct reloc_data reloc[MAX_RELOCS];
+};
+
+static int getExpression (char *str, struct alpha_it *insn);
+static char *expr_end;
+
+#define note_gpreg(R) (alpha_gprmask |= (1 << (R)))
+#define note_fpreg(R) (alpha_fprmask |= (1 << (R)))
+
+int
+tc_get_register (frame)
+ int frame;
+{
+ int reg;
+ int framereg = SP;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '$')
+ {
+ input_line_pointer++;
+ if (input_line_pointer[0] == 's'
+ && input_line_pointer[1] == 'p')
+ {
+ input_line_pointer += 2;
+ framereg = SP;
+ }
+ else
+ framereg = get_absolute_expression ();
+ framereg &= 31; /* ? */
+ }
+ else
+ as_warn ("frame reg expected, using $%d.", framereg);
+
+ note_gpreg (framereg);
+ return framereg;
+}
+
+static void
+s_rdata (ignore)
+ int ignore;
+{
+ int temp;
+
+ temp = get_absolute_expression ();
+#if 0
+ if (!rdata)
+ rdata = subseg_get (".rdata", 0);
+ subseg_set (rdata, (subsegT) temp);
+#else
+ rdata = subseg_new (".rdata", 0);
+#endif
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_sdata (ignore)
+ int ignore;
+{
+ int temp;
+
+ temp = get_absolute_expression ();
+#if 0
+ if (!sdata)
+ sdata = subseg_get (".sdata", 0);
+ subseg_set (sdata, (subsegT) temp);
+#else
+ sdata = subseg_new (".sdata", 0);
+#endif
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_alpha_comm (ignore)
+ int ignore;
+{
+ register char *name;
+ register char c;
+ register char *p;
+ offsetT temp;
+ register symbolS *symbolP;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ }
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp);
+ ignore_rest_of_line ();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ if (S_IS_DEFINED (symbolP))
+ {
+ as_bad ("Ignoring attempt to re-define symbol");
+ ignore_rest_of_line ();
+ return;
+ }
+ if (S_GET_VALUE (symbolP))
+ {
+ if (S_GET_VALUE (symbolP) != (valueT) temp)
+ as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.",
+ S_GET_NAME (symbolP),
+ (long) S_GET_VALUE (symbolP),
+ (long) temp);
+ }
+ else
+ {
+ S_SET_VALUE (symbolP, (valueT) temp);
+ S_SET_EXTERNAL (symbolP);
+ }
+
+ know (symbolP->sy_frag == &zero_address_frag);
+ demand_empty_rest_of_line ();
+}
+
+int
+alpha_local_label (name)
+ const char *name;
+{
+ if (name[0] == 'L' /* || name[0] == '$' */)
+ return 1;
+ return 0;
+}
+
+arelent *
+tc_gen_reloc (sec, fixp)
+ asection *sec;
+ fixS *fixp;
+{
+ arelent *reloc;
+ bfd_reloc_code_real_type code;
+
+ reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ if (fixp->fx_r_type > BFD_RELOC_UNUSED || fixp->fx_r_type < 0)
+ abort ();
+
+ if (fixp->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16)
+ {
+ if (!gpdisp_hi16_howto)
+ gpdisp_hi16_howto = bfd_reloc_type_lookup (stdoutput,
+ fixp->fx_r_type);
+ reloc->howto = gpdisp_hi16_howto;
+ }
+ else
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ assert (reloc->howto != 0);
+ if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
+ {
+ as_fatal ("bug in handling type-%d relocs", fixp->fx_r_type);
+ abort ();
+ }
+ assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
+
+ if (reloc->howto->pc_relative
+ && reloc->howto->pcrel_offset
+#if 1
+ && code != BFD_RELOC_ALPHA_GPDISP_HI16
+ && code != BFD_RELOC_ALPHA_GPDISP_LO16
+#endif
+ )
+ {
+ reloc->addend = fixp->fx_offset - reloc->address;
+ }
+ else
+ reloc->addend = fixp->fx_offset;
+ return reloc;
+}
+
+static void
+s_base ()
+{
+ if (first_32bit_quadrant)
+ {
+ /* not fatal, but it might not work in the end */
+ as_warn ("File overrides no-base-register option.");
+ first_32bit_quadrant = 0;
+ }
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '$')
+ { /* $rNN form */
+ input_line_pointer++;
+ if (*input_line_pointer == 'r')
+ input_line_pointer++;
+ }
+
+ base_register = get_absolute_expression ();
+ if (base_register < 0 || base_register > 31)
+ {
+ base_register = GP;
+ as_warn ("Bad base register, using $r.", base_register);
+ }
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_gprel32 ()
+{
+ expressionS e;
+ char *p;
+
+ SKIP_WHITESPACE ();
+ expression (&e);
+ switch (e.X_op)
+ {
+ case O_constant:
+ e.X_add_symbol = section_symbol (absolute_section);
+ /* fall through */
+ case O_symbol:
+ e.X_op = O_subtract;
+ e.X_op_symbol = gp;
+ break;
+ default:
+ abort ();
+ }
+ p = frag_more (4);
+ memset (p, 0, 4);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &e, 0,
+ BFD_RELOC_GPREL32);
+}
+
+static void
+create_lita_section ()
+{
+ segT current_section = now_seg;
+ int current_subsec = now_subseg;
+
+ lita_sec = subseg_new (".lita", 0);
+ subseg_set (current_section, current_subsec);
+ bfd_set_section_flags (stdoutput, lita_sec,
+ SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_DATA);
+ bfd_set_section_alignment (stdoutput, lita_sec, 3);
+}
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc. that the MD part of the assembler will need. */
+void
+md_begin ()
+{
+ const char *retval;
+ int lose = 0;
+ unsigned int i = 0;
+
+ op_hash = hash_new ();
+
+ for (i = 0; i < NUMOPCODES; )
+ {
+ const char *name = alpha_opcodes[i].name;
+ retval = hash_insert (op_hash, name, (PTR) & alpha_opcodes[i]);
+ if (retval)
+ {
+ as_bad ("internal error: can't hash opcode `%s': %s",
+ alpha_opcodes[i].name, retval);
+ lose = 1;
+ }
+ do
+ ++i;
+ while (i < NUMOPCODES
+ && (alpha_opcodes[i].name == name
+ || !strcmp (alpha_opcodes[i].name, name)));
+ }
+ /* Some opcodes include modifiers of various sorts with a "/mod"
+ syntax, like the architecture documentation suggests. However,
+ for use with gcc at least, we also need to access those same
+ opcodes without the "/". */
+ for (i = 0; i < NUMOPCODES; )
+ {
+ const char *name = alpha_opcodes[i].name;
+ if (strchr (name, '/'))
+ {
+ char *p = xmalloc (strlen (name));
+ const char *q = name;
+ char *q2 = p;
+
+ for (; *q; q++)
+ if (*q != '/')
+ *q2++ = *q;
+
+ *q2++ = 0;
+ retval = hash_insert (op_hash, p, (PTR) & alpha_opcodes[i]);
+ if (retval)
+ {
+ /* Ignore failures -- the opcode table does duplicate
+ some variants in different forms, like "hw_st/q" and
+ "hw_stq". */
+#if 0
+ as_bad ("internal error: can't hash opcode variant `%s': %s",
+ p, retval);
+ lose = 1;
+#endif
+ }
+ }
+ do
+ ++i;
+ while (i < NUMOPCODES
+ && (alpha_opcodes[i].name == name
+ || !strcmp (alpha_opcodes[i].name, name)));
+ }
+
+
+
+ if (lose)
+ as_fatal ("Broken assembler. No assembly attempted.");
+
+ lituse_basereg.X_op = O_constant;
+ lituse_basereg.X_add_number = 1;
+ lituse_byteoff.X_op = O_constant;
+ lituse_byteoff.X_add_number = 2;
+ lituse_jsr.X_op = O_constant;
+ lituse_jsr.X_add_number = 3;
+
+ /* So .sbss will get used for tiny objects. */
+ bfd_set_gp_size (stdoutput, 8);
+ create_lita_section ();
+ /* For handling the GP, create a symbol that won't be output in the
+ symbol table. We'll edit it out of relocs later. */
+ gp = symbol_new ("<GP value>", lita_sec, 0x8000, &zero_address_frag);
+ symbol_remove (gp, &symbol_rootP, &symbol_lastP);
+}
+
+int optnum = 1;
+
+void
+md_assemble (str)
+ char *str;
+{
+ char *toP;
+ int i, j, count;
+#define MAX_INSNS 5
+ struct alpha_it insns[MAX_INSNS];
+
+ count = alpha_ip (str, insns);
+ if (count <= 0)
+ return;
+
+ for (i = 0; i < count; i++)
+ {
+ toP = frag_more (4);
+
+ /* put out the opcode */
+ md_number_to_chars (toP, insns[i].opcode, 4);
+
+ /* put out the symbol-dependent stuff */
+ for (j = 0; j < MAX_RELOCS; j++)
+ {
+ struct reloc_data *r = &insns[i].reloc[j];
+ fixS *f;
+
+ if (r->code != BFD_RELOC_NONE)
+ {
+ if (r->exp.X_op == O_constant)
+ {
+ r->exp.X_add_symbol = section_symbol (absolute_section);
+ r->exp.X_op = O_symbol;
+ }
+ f = fix_new_exp (frag_now, (toP - frag_now->fr_literal), 4,
+ &r->exp, r->pcrel, r->code);
+ }
+ if (r->code == BFD_RELOC_ALPHA_GPDISP_LO16)
+ {
+ static bit_fixS cookie;
+ /* This'll make the range checking in write.c shut up. */
+ f->fx_bit_fixP = &cookie;
+ }
+ }
+ }
+}
+
+/* @@ Will a simple 0x8000 work here? If not, why not? */
+#define GP_ADJUSTMENT (0x8000 - 0x10)
+
+static void
+select_gp_value ()
+{
+ if (gp_value == 0)
+ /* Must be first time through -- pick a GP to use for this file. */
+ {
+ bfd_vma lita_vma, sdata_vma;
+ if (lita_sec)
+ lita_vma = bfd_get_section_vma (abfd, lita_sec);
+ else
+ lita_vma = 0;
+#if 0
+ if (sdata)
+ sdata_vma = bfd_get_section_vma (abfd, sdata);
+ else
+#endif
+ sdata = 0;
+
+ if (lita_vma == 0
+ /* Who knows which order they'll get laid out in? */
+ || (sdata_vma != 0 && sdata_vma < lita_vma))
+ gp_value = sdata_vma;
+ else
+ gp_value = lita_vma;
+
+ gp_value += GP_ADJUSTMENT;
+
+ S_SET_VALUE (gp, gp_value);
+
+#ifdef DEBUG1
+ printf ("Chose GP value of %lx\n", gp_value);
+#endif
+ bfd_set_gp_value (stdoutput, gp_value);
+ }
+}
+
+int
+alpha_force_relocation (f)
+ fixS *f;
+{
+ switch (f->fx_r_type)
+ {
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ case BFD_RELOC_ALPHA_LITERAL:
+ case BFD_RELOC_ALPHA_LITUSE:
+ case BFD_RELOC_GPREL32:
+ return 1;
+ case BFD_RELOC_ALPHA_HINT:
+ case BFD_RELOC_64:
+ case BFD_RELOC_32:
+ case BFD_RELOC_16:
+ case BFD_RELOC_8:
+ case BFD_RELOC_23_PCREL_S2:
+ case BFD_RELOC_14:
+ return 0;
+ default:
+ abort ();
+ return 0;
+ }
+}
+
+int
+alpha_fix_adjustable (f)
+ fixS *f;
+{
+ /* Are there any relocation types for which we must generate a reloc
+ but we can adjust the values contained within it? */
+ switch (f->fx_r_type)
+ {
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ return 0;
+ case BFD_RELOC_GPREL32:
+ return 1;
+ }
+ return !alpha_force_relocation (f);
+}
+
+int
+alpha_validate_fix (fixp, seg)
+ fixS *fixp;
+ segT seg;
+{
+ /* We must make sure we've got a good GP value if any relocations might
+ use it... */
+ if (gp_value == 0)
+ select_gp_value ();
+ return 0;
+}
+
+int
+alpha_frob_symbol (s)
+ symbolS *s;
+{
+ return 0;
+}
+
+unsigned long
+md_section_align (seg, size)
+ segT seg;
+ unsigned long size;
+{
+#ifdef OBJ_ECOFF
+ /* This should probably be handled within BFD, or by pulling the
+ number from BFD at least. */
+#define MIN 15
+ size += MIN;
+ size &= ~MIN;
+#endif
+ return size;
+}
+
+/* Add this thing to the .lita section and produce a LITERAL reloc referring
+ to it.
+
+ TODO:
+ Remove duplicates.
+ Set GP value properly, and have values in LITERAL references set
+ accordingly.
+ */
+
+static void
+load_symbol_address (reg, insn)
+ int reg;
+ struct alpha_it *insn;
+{
+ static symbolS *lita_sym;
+
+ int x;
+ addressT reloc_addr;
+ valueT retval;
+ char *p;
+ symbolS *sym;
+ valueT addend;
+
+ if (!lita_sym)
+ {
+ lita_sym = section_symbol (lita_sec);
+ S_CLEAR_EXTERNAL (lita_sym);
+ }
+
+ retval = add_to_literal_pool (insn->reloc[0].exp.X_add_symbol,
+ insn->reloc[0].exp.X_add_number,
+ lita_sec, 8);
+
+ /* @@ Get these numbers from GP setting. */
+ retval -= GP_ADJUSTMENT;
+
+ /* Now emit a LITERAL relocation for the original section. */
+ insn->reloc[0].exp.X_op = O_symbol;
+ insn->reloc[0].exp.X_add_symbol = lita_sym;
+ insn->reloc[0].exp.X_add_number = retval;
+ insn->reloc[0].code = BFD_RELOC_ALPHA_LITERAL;
+
+ if (retval == 0x8000)
+ /* Overflow? */
+ as_fatal ("overflow in literal (.lita) table");
+ x = retval;
+ insn->opcode = (0xa4000000 /* ldq */
+ | (reg << SA)
+ | (base_register << SB)
+ | (x & 0xffff));
+ note_gpreg (base_register);
+}
+
+/* To load an address with a single instruction,
+ emit a LITERAL reloc in this section, and a REFQUAD
+ for the .lita section, so that we'll be able to access
+ it via $gp:
+ lda REG, xx -> ldq REG, -32752(gp)
+ lda REG, xx+4 -> ldq REG, -32752(gp)
+ lda REG, 4(REG)
+
+ The offsets need to start near -0x8000, and the generated LITERAL
+ relocations should negate the offset. I don't completely grok the
+ scheme yet. */
+
+static int
+load_expression (reg, insn)
+ int reg;
+ struct alpha_it *insn;
+{
+ valueT addend;
+ int num_insns = 1;
+
+ addend = insn->reloc[0].exp.X_add_number;
+ insn->reloc[0].exp.X_add_number = 0;
+ load_symbol_address (reg, insn);
+ if (addend)
+ {
+ num_insns++;
+ {
+ valueT x = addend;
+ if (x & ~0x7fff != 0
+ && (x & ~0x7fff) + 0x8000 != 0)
+ {
+ as_bad ("assembler not prepared to handle constants >16 bits yet");
+ addend = 0;
+ }
+ }
+ insn[1].opcode = (0x20000000 /* lda */
+ | (reg << SA)
+ | (reg << SB)
+ | (addend & 0xffff));
+ insn[1].reloc[0].code = BFD_RELOC_ALPHA_LITUSE;
+ insn[1].reloc[0].exp = lituse_basereg;
+ }
+ return num_insns;
+}
+
+static inline int
+getExpression (str, this_insn)
+ char *str;
+ struct alpha_it *this_insn;
+{
+ char *save_in;
+ segT seg;
+
+#if 0 /* Not converted to bfd yet, and I don't think we need them
+ for ECOFF. Re-adding a.out support will probably require
+ them though. */
+ static const struct am {
+ char *name;
+ bfd_reloc_code_real_type reloc;
+ } macro[] = {
+ { "hi", RELOC_48_63 },
+ { "lo", RELOC_0_15 },
+ { "ml", RELOC_16_31 },
+ { "mh", RELOC_32_47 },
+ { "uhi", RELOC_U_48_63 },
+ { "uml", RELOC_U_16_31 },
+ { "umh", RELOC_U_32_47 },
+ { 0, }
+ };
+
+ /* Handle macros: "%macroname(expr)" */
+ if (*str == '%')
+ {
+ struct am *m;
+ char *p, *q;
+
+ str++;
+ m = ¯o[0];
+ while (q = m->name)
+ {
+ p = str;
+ while (*q && *p == *q)
+ p++, q++;
+ if (*q == 0)
+ break;
+ m++;
+ }
+ if (q)
+ {
+ str = p; /* keep the '(' */
+ this_insn->reloc = m->reloc;
+ }
+ }
+#endif
+
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+
+ seg = expression (&this_insn->reloc[0].exp);
+ /* XXX validate seg and exp, make sure they're reasonable */
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+
+ return 0;
+}
+
+/* Note that for now, this function is called recursively. Some of the
+ macros defined as part of the assembly language are currently
+ rewritten as sequences of strings to be assembled. See, for example,
+ the handling of "divq".
+
+ For efficiency, this should be fixed someday. */
+static int
+alpha_ip (str, insns)
+ char *str;
+ struct alpha_it insns[];
+{
+ char *s;
+ const char *args;
+ char c;
+ unsigned long i;
+ struct alpha_opcode *pattern;
+ char *argsStart;
+ unsigned int opcode;
+ unsigned int mask;
+ int match = 0, num_gen = 1;
+ int comma = 0;
+
+ for (s = str;
+ islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8';
+ ++s)
+ ;
+ switch (*s)
+ {
+
+ case '\0':
+ break;
+
+ case ',':
+ comma = 1;
+
+ /*FALLTHROUGH*/
+
+ case ' ':
+ *s++ = '\0';
+ break;
+
+ default:
+ as_warn ("Unknown opcode: `%s'", str);
+ exit (1);
+ }
+ if ((pattern = (struct alpha_opcode *) hash_find (op_hash, str)) == NULL)
+ {
+ as_warn ("Unknown opcode: `%s'", str);
+ return -1;
+ }
+ if (comma)
+ *--s = ',';
+
+ argsStart = s;
+ for (;;)
+ {
+ opcode = pattern->match;
+ num_gen = 1;
+ memset (insns, 0, sizeof (*insns));
+ for (i = 0; i < MAX_RELOCS; i++)
+ insns[0].reloc[i].code = BFD_RELOC_NONE;
+ for (i = 1; i < MAX_INSNS; i++)
+ insns[i] = insns[0];
+
+ /* Build the opcode, checking as we go to make sure that the
+ operands match. */
+ for (args = pattern->args;; ++args)
+ {
+ switch (*args)
+ {
+
+ case '\0': /* end of args */
+ if (*s == '\0')
+ {
+ match = 1;
+ }
+ break;
+
+ case '+':
+ if (*s == '+')
+ {
+ ++s;
+ continue;
+ }
+ if (*s == '-')
+ {
+ continue;
+ }
+ break;
+
+ case '(': /* these must match exactly */
+ case ')':
+ case ',':
+ case ' ':
+ case '0':
+ if (*s++ == *args)
+ continue;
+ break;
+
+ case '1': /* next operand must be a register */
+ case '2':
+ case '3':
+ case 'r':
+ case 'R':
+ if (*s++ == '$')
+ {
+ switch (c = *s++)
+ {
+
+ case 'a': /* $at: as temporary */
+ if (*s++ != 't')
+ goto error;
+ mask = AT;
+ break;
+
+ case 'g': /* $gp: base register */
+ if (*s++ != 'p')
+ goto error;
+ mask = base_register;
+ break;
+
+ case 's': /* $sp: stack pointer */
+ if (*s++ != 'p')
+ goto error;
+ mask = SP;
+ break;
+
+
+ case 'r': /* any register */
+ if (!isdigit (c = *s++))
+ {
+ goto error;
+ }
+ /* FALLTHROUGH */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (isdigit (*s))
+ {
+ if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
+ {
+ goto error;
+ }
+ }
+ else
+ {
+ c -= '0';
+ }
+ if ((c == GP) && first_32bit_quadrant)
+ c = ZERO;
+
+ mask = c;
+ break;
+
+ default:
+ goto error;
+ }
+ note_gpreg (mask);
+ /* Got the register, now figure out where it goes in
+ the opcode. */
+ doregister:
+ switch (*args)
+ {
+
+ case '1':
+ case 'e':
+ opcode |= mask << SA;
+ continue;
+
+ case '2':
+ case 'f':
+ opcode |= mask << SB;
+ continue;
+
+ case '3':
+ case 'g':
+ opcode |= mask;
+ continue;
+
+ case 'r':
+ opcode |= (mask << SA) | mask;
+ continue;
+
+ case 'R': /* ra and rb are the same */
+ opcode |= (mask << SA) | (mask << SB);
+ continue;
+
+ case 'E':
+ opcode |= (mask << SA) | (mask << SB) | (mask);
+ continue;
+ }
+ }
+ break;
+
+ case 'e': /* next operand is a floating point register */
+ case 'f':
+ case 'g':
+ case 'E':
+ if (*s++ == '$' && *s++ == 'f' && isdigit (*s))
+ {
+ mask = *s++;
+ if (isdigit (*s))
+ {
+ mask = 10 * (mask - '0') + (*s++ - '0');
+ if (mask >= 32)
+ {
+ break;
+ }
+ }
+ else
+ {
+ mask -= '0';
+ }
+ note_fpreg (mask);
+ /* same encoding as gp registers */
+ goto doregister;
+ }
+ break;
+
+#if 0
+ case 'h': /* bits 16..31 */
+ insns[0].reloc = RELOC_16_31;
+ goto immediate;
+#endif
+
+ case 'l': /* bits 0..15 */
+ insns[0].reloc[0].code = BFD_RELOC_16;
+ goto immediate;
+
+ case 'L': /* 21 bit PC relative immediate */
+ insns[0].reloc[0].code = BFD_RELOC_23_PCREL_S2;
+ insns[0].reloc[0].pcrel = 1;
+ goto immediate;
+
+ case 'i': /* 14 bit immediate */
+ if (OPCODE (opcode) != 0x1a)
+ /* Not a jmp variant?? */
+ abort ();
+ else if (opcode & 0x8000)
+ /* ret or jsr_coroutine */
+ {
+ insns[0].reloc[0].code = BFD_RELOC_14;
+ insns[0].reloc[0].pcrel = 0;
+ }
+ else
+ /* jmp or jsr */
+ {
+ insns[0].reloc[0].code = BFD_RELOC_ALPHA_HINT;
+ insns[0].reloc[0].pcrel = 1;
+ }
+ goto immediate;
+
+ case 'b': /* 8 bit immediate */
+ insns[0].reloc[0].code = BFD_RELOC_8;
+ goto immediate;
+
+#if 0
+ case 't': /* 12 bit 0...11 */
+ insns[0].reloc = RELOC_0_12;
+ goto immediate;
+
+ case '8': /* 8 bit 0...7 */
+ insns[0].reloc = RELOC_0_8;
+ goto immediate;
+
+ case 'I': /* 26 bit immediate */
+ insns[0].reloc = RELOC_0_25;
+#else
+ case 't':
+ case '8':
+ case 'I':
+ abort ();
+#endif
+ /*FALLTHROUGH*/
+
+ immediate:
+ if (*s == ' ')
+ s++;
+ (void) getExpression (s, &insns[0]);
+ s = expr_end;
+ /* Handle overflow in certain instructions by converting
+ to other instructions. */
+ if (insns[0].reloc[0].code == BFD_RELOC_8
+ && insns[0].reloc[0].exp.X_op == O_constant
+ && (insns[0].reloc[0].exp.X_add_number < 0
+ || insns[0].reloc[0].exp.X_add_number > 0xff))
+ {
+ if (OPCODE (opcode) == 0x10
+ && (OP_FCN (opcode) == 0x00 /* addl */
+ || OP_FCN (opcode) == 0x40 /* addl/v */
+ || OP_FCN (opcode) == 0x20 /* addq */
+ || OP_FCN (opcode) == 0x60 /* addq/v */
+ || OP_FCN (opcode) == 0x09 /* subl */
+ || OP_FCN (opcode) == 0x49 /* subl/v */
+ || OP_FCN (opcode) == 0x29 /* subq */
+ || OP_FCN (opcode) == 0x69 /* subq/v */
+ || OP_FCN (opcode) == 0x02 /* s4addl */
+ || OP_FCN (opcode) == 0x22 /* s4addq */
+ || OP_FCN (opcode) == 0x0b /* s4subl */
+ || OP_FCN (opcode) == 0x2b /* s4subq */
+ || OP_FCN (opcode) == 0x12 /* s8addl */
+ || OP_FCN (opcode) == 0x32 /* s8addq */
+ || OP_FCN (opcode) == 0x1b /* s8subl */
+ || OP_FCN (opcode) == 0x3b /* s8subq */
+ )
+ /* Can we make it fit by negating? */
+ && -insns[0].reloc[0].exp.X_add_number < 0xff
+ && -insns[0].reloc[0].exp.X_add_number > 0)
+ {
+ opcode ^= 0x120; /* convert add<=>sub */
+ insns[0].reloc[0].exp.X_add_number *= -1;
+ }
+ else if (at_ok && macro_ok)
+ {
+ /* Constant value supplied, but it's too large. */
+ char expansion[64];
+ sprintf (expansion, "lda $%d,%d($%d)", AT,
+ insns[0].reloc[0].exp.X_add_number, ZERO);
+ md_assemble (expansion);
+ opcode |= 0x1000 /* use reg */ | (AT << SB);
+ insns[0].reloc[0].code = BFD_RELOC_NONE;
+ }
+ else
+ as_bad ("overflow in 8-bit literal field in `operate' format insn");
+ }
+ continue;
+
+ /* The following two.. take advantage of the fact that
+ opcode already contains most of what we need to know.
+ We just prepend to the instr an "ldah
+ $r,%ml(expr)($base)" and turn this one (done later
+ after we return) into something like "stq
+ $r,%lo(expr)(at)" or "ldq $r,%lo(expr)($r)".
+
+ NOTE: This can fail later on at link time if the
+ offset from $base actually turns out to be more than
+ 2**31 or 2**47 if use_large_offsets is set. */
+ case 'P': /* Addressing macros: PUT */
+ mask = AT; /* register 'at' */
+ /* fall through */
+
+ case 'G': /* Addressing macros: GET */
+ get_macro:
+ /* All it is missing is the expression, which is what we
+ will get now */
+
+ if (*s == ' ')
+ s++;
+ (void) getExpression (s, &insns[0]);
+ s = expr_end;
+
+ /* Must check for "lda ..,number" too */
+ if (insns[0].reloc[0].exp.X_op == O_big)
+ {
+ as_warn ("Sorry, not yet. Put bignums in .data section yourself.");
+ return -1;
+ }
+ if (insns[0].reloc[0].exp.X_op == O_constant)
+ {
+ /* This only handles 32bit numbers */
+ register int val = insns[0].reloc[0].exp.X_add_number;
+ register short sval;
+
+ insns[0].reloc[0].code = BFD_RELOC_NONE;
+ insns[1].reloc[0].code = BFD_RELOC_NONE;
+
+ sval = val;
+ if (0)
+ fprintf (stderr, "val %lx sval %lx\n", val, sval);
+ if ((sval != val) && (val & 0x8000))
+ {
+ val += 0x10000;
+ sval = val;
+ }
+
+ if (optnum && (sval == val))
+ {
+ /* optimize away the ldah */
+ num_gen = 1;
+ opcode |= (ZERO << SB) | (val & 0xffff);
+ }
+ else
+ {
+ num_gen = 2;
+ insns[1].opcode = opcode | (mask << SB) | (val & 0xffff);
+ opcode = 0x24000000 /*ldah*/ |
+ mask << SA | (ZERO << SB) |
+ ((val >> 16) & 0xffff);
+ }
+ }
+ else if (insns[0].reloc[0].exp.X_op == O_symbol)
+ {
+ unsigned long old_opcode = opcode;
+ int tmp_reg;
+
+ if (!macro_ok)
+ as_bad ("insn requires expansion but `nomacro' specified");
+ else if (*args == 'G')
+ tmp_reg = mask;
+ else if (!at_ok)
+ as_bad ("insn expansion requires AT use, but `noat' specified");
+ else
+ tmp_reg = AT;
+ num_gen = load_expression (tmp_reg, insns);
+ opcode = insns[0].opcode;
+ /* lda is opcode 8, 0x20000000 */
+ if (OPCODE (old_opcode) != 0x08)
+ {
+ struct alpha_it *i;
+ i = &insns[num_gen++];
+ i->reloc[0].code = BFD_RELOC_NONE;
+ i->opcode = old_opcode | (tmp_reg << SB);
+ }
+ }
+ else
+ {
+ /* Not a number */
+ num_gen = 2;
+ insns[1].reloc[0].exp = insns[0].reloc[0].exp;
+
+ /* Generate: ldah REG,x1(GP); OP ?,x0(REG) */
+
+ abort (); /* relocs need fixing */
+#if 0
+ insns[1].reloc = RELOC_0_15;
+ insns[1].opcode = opcode | mask << SB;
+
+ insns[0].reloc = RELOC_16_31;
+ opcode = 0x24000000 /*ldah*/ | mask << SA | (base_register << SB);
+#endif
+ }
+
+ continue;
+
+ /* Same failure modes as above, actually most of the
+ same code shared. */
+ case 'B': /* Builtins */
+ args++;
+ switch (*args)
+ {
+
+ case 'a': /* ldgp */
+
+ if (first_32bit_quadrant || no_mixed_code)
+ return -1;
+ switch (OUTPUT_FLAVOR)
+ {
+ case bfd_target_aout_flavour:
+ /* this is cmu's a.out version */
+ insns[0].reloc[0].code = BFD_RELOC_NONE;
+ /* generate "zap %r,0xf,%r" to take high 32 bits */
+ opcode |= 0x48001600 /* zap ?,#,?*/ | (0xf << SN);
+ break;
+ case bfd_target_ecoff_flavour:
+ /* Given "ldgp R1,N(R2)", turn it into something
+ like "ldah R1,###(R2) ; lda R1,###(R1)" with
+ appropriate constants and relocations. */
+ {
+ unsigned long r1, r2;
+ unsigned long addend = 0;
+
+ num_gen = 2;
+ r2 = mask;
+ r1 = opcode & 0x3f;
+ insns[0].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_HI16;
+ insns[0].reloc[0].pcrel = 1;
+ insns[0].reloc[0].exp.X_op = O_symbol;
+ insns[0].reloc[0].exp.X_add_symbol = gp;
+ insns[0].reloc[0].exp.X_add_number = 0;
+ insns[0].opcode = (0x24000000 /* ldah */
+ | (r1 << SA)
+ | (r2 << SB));
+ insns[1].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_LO16;
+ insns[1].reloc[0].exp.X_op = O_symbol;
+ insns[1].reloc[0].exp.X_add_symbol = gp;
+ insns[1].reloc[0].exp.X_add_number = 4;
+ insns[1].reloc[0].pcrel = 1;
+ insns[1].opcode = 0x20000000 | (r1 << SA) | (r1 << SB);
+ opcode = insns[0].opcode;
+ /* merge in addend */
+ insns[1].opcode |= addend & 0xffff;
+ insns[0].opcode |= ((addend >> 16)
+ + (addend & 0x8000 ? 1 : 0));
+ ecoff_set_gp_prolog_size (0);
+ }
+ break;
+ default:
+ abort ();
+ }
+ continue;
+
+
+ case 'b': /* setgp */
+ switch (OUTPUT_FLAVOR)
+ {
+ case bfd_target_aout_flavour:
+ /* generate "zap %r,0xf,$gp" to take high 32 bits */
+ opcode |= 0x48001600 /* zap ?,#,?*/
+ | (0xf << SN) | (base_register);
+ break;
+ default:
+ abort ();
+ }
+ continue;
+
+ case 'c': /* jsr $r,foo becomes
+ lda $27,foo
+ jsr $r,($27),foo
+ Register 27, t12, is used by convention
+ here. */
+ {
+ struct alpha_it *jsr;
+ expressionS etmp;
+ struct reloc_data *r;
+
+ /* We still have to parse the function name */
+ if (*s == ' ')
+ s++;
+ (void) getExpression (s, &insns[0]);
+ etmp = insns[0].reloc[0].exp;
+ s = expr_end;
+ num_gen = load_expression (PV, &insns[0]);
+ note_gpreg (PV);
+
+ jsr = &insns[num_gen++];
+ jsr->opcode = (0x68004000 /* jsr */
+ | (mask << SA)
+ | (PV << SB)
+ | 0);
+ if (num_gen == 2)
+ {
+ /* LITUSE wasn't emitted yet */
+ jsr->reloc[0].code = BFD_RELOC_ALPHA_LITUSE;
+ jsr->reloc[0].exp = lituse_jsr;
+ r = &jsr->reloc[1];
+ }
+ else
+ r = &jsr->reloc[0];
+ r->exp = etmp;
+ r->code = BFD_RELOC_ALPHA_HINT;
+ r->pcrel = 1;
+ opcode = insns[0].opcode;
+ }
+ continue;
+
+ /* DIVISION and MODULUS. Yech.
+ Convert OP x,y,result
+ to mov x,t10
+ mov y,t11
+ jsr t9, __OP
+ mov t12,result
+
+ with appropriate optimizations if t10,t11,t12
+ are the registers specified by the compiler.
+ We are missing an obvious optimization
+ opportunity here; if the ldq generated by the
+ jsr assembly requires a cycle or two to make
+ the value available, initiating it before one
+ or two of the mov instructions would result in
+ faster execution. */
+ case '0': /* reml */
+ case '1': /* divl */
+ case '2': /* remq */
+ case '3': /* divq */
+ case '4': /* remlu */
+ case '5': /* divlu */
+ case '6': /* remqu */
+ case '7': /* divqu */
+ {
+ static char func[8][6] = {
+ "reml", "divl", "remq", "divq",
+ "remlu", "divlu", "remqu", "divqu"
+ };
+ char expansion[64];
+ int reg;
+
+ /* All regs parsed, in opcode */
+
+ /* Do the expansions, one instr at a time */
+
+ reg = (opcode >> SA) & 31;
+ if (reg != T10)
+ {
+ /* x->t10 */
+ sprintf (expansion, "mov $%d,$%d", reg, T10);
+ md_assemble (expansion);
+ }
+ reg = (opcode >> SB) & 31;
+ if (reg == T10)
+ /* we already overwrote it! */
+ abort ();
+ else if (reg != T11)
+ {
+ /* y->t11 */
+ sprintf (expansion, "mov $%d,$%d", reg, T11);
+ md_assemble (expansion);
+ }
+ sprintf (expansion, "lda $%d,__%s", PV, func[*args - '0']);
+ md_assemble (expansion);
+ sprintf (expansion, "jsr $%d,($%d),__%s", T9, PV,
+ func[*args - '0']);
+ md_assemble (expansion);
+#if 0 /* huh? */
+ if (!first_32bit_quadrant)
+ {
+ sprintf (expansion,
+ "zap $%d,0xf,$%d",
+ T9, base_register);
+ md_assemble (expansion);
+ }
+#endif
+ sprintf (expansion, "ldgp $%d,0($%d)",
+ base_register, T9);
+ md_assemble (expansion);
+
+ /* Use insns[0] to get at the result */
+ if ((reg = (opcode & 31)) != PV)
+ opcode = (0x47e00400 /* or zero,zero,zero */
+ | (PV << SB)
+ | reg /* Rc */ ); /* pv->z */
+ else
+ num_gen = 0;
+ }
+ continue;
+ }
+ /* fall through */
+
+ default:
+ abort ();
+ }
+ break;
+ }
+ error:
+ if (match == 0)
+ {
+ /* Args don't match. */
+ if (&pattern[1] - alpha_opcodes < NUMOPCODES
+ && !strcmp (pattern->name, pattern[1].name))
+ {
+ ++pattern;
+ s = argsStart;
+ continue;
+ }
+ else
+ {
+ as_warn ("Illegal operands");
+ return -1;
+ }
+ }
+ else
+ {
+ /* Args match, see if a float instructions and -nofloats */
+ if (nofloats && pattern->isa_float)
+ return -1;
+ }
+ break;
+ }
+
+ insns[0].opcode = opcode;
+ return num_gen;
+}
+
+/* Turn a string in input_line_pointer into a floating point constant
+ of type type, and store the appropriate bytes in *litP. The number
+ of LITTLENUMS emitted is stored in *sizeP. An error message is
+ returned, or NULL on OK. */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee (), *vax_md_atof ();
+
+ switch (type)
+ {
+ /* VAX floats */
+ case 'G':
+ type = 'g';
+ case 'F':
+ case 'D':
+ return vax_md_atof (type, litP, sizeP);
+
+ /* IEEE floats */
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return "Bad call to MD_ATOF()";
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ for (wordP = words + prec - 1; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+
+ return 0;
+}
+
+void
+md_bignum_to_chars (buf, bignum, nchars)
+ char *buf;
+ LITTLENUM_TYPE *bignum;
+ int nchars;
+{
+ while (nchars)
+ {
+ LITTLENUM_TYPE work = *bignum++;
+ int nb = CHARS_PER_LITTLENUM;
+
+ do
+ {
+ *buf++ = work & ((1 << BITS_PER_CHAR) - 1);
+ if (--nchars == 0)
+ return;
+ work >>= BITS_PER_CHAR;
+ }
+ while (--nb);
+ }
+}
+
+int
+md_parse_option (argP, cntP, vecP)
+ char **argP;
+ int *cntP;
+ char ***vecP;
+{
+ if (**argP == 'F')
+ {
+ nofloats = 1;
+ return 1;
+ }
+#if 0 /* I have no idea if this stuff would work any more. And it's
+ probably not right for ECOFF anyways. */
+ /* Use base-register addressing, e.g. PIC code */
+ if (**argP == 'B')
+ {
+ if (first_32bit_quadrant)
+ {
+ first_32bit_quadrant = 0;
+ base_register = GP;
+ }
+ else
+ {
+ first_32bit_quadrant = 1;
+ base_register = ZERO;
+ }
+ if (argP[0][1] == 'k')
+ no_mixed_code = 1;
+ argP[0][1] = 0;
+ return 1;
+ }
+#endif
+ if (!strcmp (*argP, "nocpp"))
+ {
+ *argP += 5;
+ return 1;
+ }
+ return 0;
+}
+
+static void
+s_proc (is_static)
+{
+ /* XXXX Align to cache linesize XXXXX */
+ char *name;
+ char c;
+ char *p;
+ symbolS *symbolP;
+ int temp;
+
+ /* Takes ".proc name,nargs" */
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ *p = 0;
+ as_warn ("Expected comma after name \"%s\"", name);
+ *p = c;
+ temp = 0;
+ ignore_rest_of_line ();
+ }
+ else
+ {
+ input_line_pointer++;
+ temp = get_absolute_expression ();
+ }
+ /* symbolP->sy_other = (signed char) temp; */
+ as_warn ("unhandled: .proc %s,%d", name, temp);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_alpha_set (x)
+ int x;
+{
+ char *name = input_line_pointer, ch, *s;
+ int yesno = 1;
+
+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
+ input_line_pointer++;
+ ch = *input_line_pointer;
+ *input_line_pointer = '\0';
+
+ s = name;
+ if (s[0] == 'n' && s[1] == 'o')
+ {
+ yesno = 0;
+ s += 2;
+ }
+ if (!strcmp ("reorder", s))
+ /* ignore */ ;
+ else if (!strcmp ("at", s))
+ at_ok = yesno;
+ else if (!strcmp ("macro", s))
+ macro_ok = yesno;
+ else
+ as_warn ("Tried to set unrecognized symbol: %s", name);
+ *input_line_pointer = ch;
+ demand_empty_rest_of_line ();
+}
+
+/* @@ Is this right?? */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ return addr;
+ default:
+ return fixP->fx_size + addr;
+ }
+}
+
+int
+alpha_do_align (n, fill)
+ int n;
+ char *fill;
+{
+ if (!fill
+ && (now_seg == text_section
+ || !strcmp (now_seg->name, ".init")
+ || !strcmp (now_seg->name, ".fini")))
+ {
+ static const char nop_pattern[] = { 0x1f, 0x04, 0xff, 0x47 };
+ frag_align_pattern (n, nop_pattern, sizeof (nop_pattern));
+ return 1;
+ }
+ return 0;
+}
+
+int
+md_apply_fix (fixP, valueP)
+ fixS *fixP;
+ valueT *valueP;
+{
+ valueT value;
+ int size;
+ valueT addend;
+ char *p = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+ value = *valueP;
+
+ switch (fixP->fx_r_type)
+ {
+ /* The GPDISP relocations are processed internally with a symbol
+ referring to the current function; we need to drop in a value
+ which, when added to the address of the start of the function,
+ gives the desired GP. */
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ addend = value;
+ if (fixP->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16)
+ {
+ assert (fixP->fx_next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16);
+#ifdef DEBUG1
+ printf ("hi16: ");
+ fprintf_vma (stdout, addend);
+ printf ("\n");
+#endif
+ if (addend & 0x8000)
+ addend += 0x10000;
+ addend >>= 16;
+ fixP->fx_offset = 4; /* @@ Compute this using fx_next. */
+ }
+ else
+ {
+#ifdef DEBUG1
+ printf ("lo16: ");
+ fprintf_vma (stdout, addend);
+ printf ("\n");
+#endif
+ addend &= 0xffff;
+ fixP->fx_offset = 0;
+ }
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ addend, 2);
+ fixP->fx_addsy = section_symbol (absolute_section);
+ fixP->fx_offset += fixP->fx_frag->fr_address + fixP->fx_where;
+ break;
+
+ case BFD_RELOC_8:
+ /* Write 8 bits, shifted left 13 bit positions. */
+ value &= 0xff;
+ p++;
+ *p &= 0x1f;
+ *p |= (value << 5) & 0xe0;
+ value >>= 3;
+ p++;
+ *p &= 0xe0;
+ *p |= value;
+ value >>= 5;
+ fixP->fx_done = 1;
+ check_zov:
+ if (value != 0)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "overflow in type-%d reloc", (int) fixP->fx_r_type);
+ return 3;
+
+ case BFD_RELOC_32:
+ case BFD_RELOC_64:
+ return 42;
+ case BFD_RELOC_16:
+ /* Don't want overflow checking. */
+ size = 2;
+ do_it:
+ if (fixP->fx_pcrel == 0
+ && fixP->fx_addsy == 0)
+ {
+ md_number_to_chars (p, value, size);
+ /* @@ Overflow checks?? */
+ goto done;
+ }
+ break;
+
+ case BFD_RELOC_14:
+ if (fixP->fx_addsy != 0
+ && fixP->fx_addsy->bsym->section != absolute_section)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "ret/jsr_coroutine requires constant in displacement field");
+ else if (value >> 14 != 0)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "overflow in 14-bit operand field of ret or jsr_coroutine");
+ *p++ = value & 0xff;
+ value >>= 8;
+ *p = (*p & 0xc0) | (value & 0x3f);
+ goto done;
+
+ case BFD_RELOC_23_PCREL_S2:
+ /* Write 21 bits only. */
+ value >>= 2;
+ *p++ = value & 0xff;
+ value >>= 8;
+ *p++ = value & 0xff;
+ value >>= 8;
+ *p &= 0xe0;
+ *p |= (value & 0x1f);
+ goto done;
+
+ case BFD_RELOC_ALPHA_LITERAL:
+ case BFD_RELOC_ALPHA_LITUSE:
+ return 2;
+
+ case BFD_RELOC_GPREL32:
+ assert (fixP->fx_subsy == gp);
+ value = - gp_value; /* huh? this works... */
+ fixP->fx_subsy = 0;
+ md_number_to_chars (p, value, 4);
+ break;
+
+ case BFD_RELOC_ALPHA_HINT:
+ if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
+ {
+ size = 2;
+ goto do_it;
+ }
+ return 2;
+
+ default:
+ as_fatal ("unknown relocation type %d?", fixP->fx_r_type);
+ return 9;
+ }
+
+ if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
+ {
+ printf ("type %d reloc done?\n", fixP->fx_r_type);
+ done:
+ fixP->fx_done = 1;
+ return 42;
+ }
+
+ return 0x12345678;
+}
+
+void
+alpha_end ()
+{
+ /* $zero and $f31 are read-only */
+ alpha_gprmask &= ~(1L << 31);
+ alpha_fprmask &= ~(1L << 31);
+}
+
+/* The Alpha has support for some VAX floating point types, as well as for
+ IEEE floating point. We consider IEEE to be the primary floating point
+ format, and sneak in the VAX floating point support here. */
+#define md_atof vax_md_atof
+#include "config/atof-vax.c"