New Alpha support files, based on files from CMU.
authorKen Raeburn <raeburn@cygnus>
Fri, 28 Jan 1994 01:37:02 +0000 (01:37 +0000)
committerKen Raeburn <raeburn@cygnus>
Fri, 28 Jan 1994 01:37:02 +0000 (01:37 +0000)
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

gas/config/.Sanitize
gas/config/alpha-opcode.h [new file with mode: 0644]
gas/config/tc-alpha.c [new file with mode: 0644]
gas/config/tc-alpha.h [new file with mode: 0644]

index d70a821..1894973 100644 (file)
@@ -30,6 +30,7 @@ fi
 Things-to-keep:
 
 aout_gnu.h
+alpha-opcode.h
 atof-ieee.c
 atof-ns32k.c
 atof-tahoe.c
@@ -93,6 +94,8 @@ sh.mt
 sparc.mt
 tc-a29k.c
 tc-a29k.h
+tc-alpha.c
+tc-alpha.h
 tc-generic.c
 tc-generic.h
 tc-h8300.c
diff --git a/gas/config/alpha-opcode.h b/gas/config/alpha-opcode.h
new file mode 100644 (file)
index 0000000..d6b85b3
--- /dev/null
@@ -0,0 +1,831 @@
+/* 
+ * 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]))
diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c
new file mode 100644 (file)
index 0000000..f14e5e9
--- /dev/null
@@ -0,0 +1,1918 @@
+/* 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 = &macro[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"
diff --git a/gas/config/tc-alpha.h b/gas/config/tc-alpha.h
new file mode 100644 (file)
index 0000000..4994cf9
--- /dev/null
@@ -0,0 +1,67 @@
+/* This file is tc-alpha.h
+   Copyright (C) 1994 Free Software Foundation, Inc.
+   Written by Ken Raeburn <raeburn@cygnus.com>.
+
+   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.  */
+
+#define TC_ALPHA
+
+#define TARGET_ARCH                    bfd_arch_alpha
+
+#define TARGET_FORMAT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour       \
+                      ? "ecoff-littlealpha"                            \
+                      : OUTPUT_FLAVOR == bfd_target_elf_flavour        \
+                      ? "elf64-alpha"                                  \
+                      : "unknown-format")
+
+#define NEED_LITERAL_POOL
+#define TC_HANDLES_FX_DONE
+#define REPEAT_CONS_EXPRESSIONS
+
+extern int alpha_force_relocation PARAMS ((struct fix *));
+extern int alpha_fix_adjustable PARAMS ((struct fix *));
+extern int alpha_frob_symbol PARAMS ((struct symbol *));
+extern int alpha_validate_fix PARAMS ((struct fix *, segT));
+
+extern unsigned long alpha_gprmask, alpha_fprmask;
+
+#define TC_FORCE_RELOCATION(FIXP)      alpha_force_relocation (FIXP)
+#define tc_fix_adjustable(FIXP)                alpha_fix_adjustable (FIXP)
+#define RELOC_REQUIRES_SYMBOL
+#define tc_frob_symbol(S,P)            ((P) = alpha_frob_symbol (S))
+#define TC_VALIDATE_FIX(F,S,L)         if(alpha_validate_fix(F,S))goto L;
+
+#define md_convert_frag(b,s,f)         {as_fatal ("alpha convert_frag\n");}
+#define md_create_long_jump(p,f,t,fr,s)        as_fatal("alpha_create_long_jump")
+#define md_create_short_jump(p,f,t,fr,s) as_fatal("alpha_create_short_jump")
+#define md_estimate_size_before_relax(f,s) \
+                       (as_fatal("estimate_size_before_relax called"),1)
+#define md_operand(x)                  0
+
+extern unsigned long md_section_align PARAMS ((segT, unsigned long));
+
+#define md_undefined_symbol(name)      (0)
+extern void alpha_end ();
+#define md_end()                       alpha_end ()
+
+extern int alpha_local_label PARAMS ((const char *));
+#define LOCAL_LABEL(name)              alpha_local_label (name)
+
+#define md_number_to_chars             number_to_chars_littleendian
+
+extern int alpha_do_align ();
+#define md_do_align(n,fill,l)  if (alpha_do_align(n,fill)) goto l