From 5749c4970051e6f4149c9a52e11b530c70d50f19 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Fri, 28 Jan 1994 01:37:02 +0000 Subject: [PATCH] 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 --- gas/config/.Sanitize | 3 + gas/config/alpha-opcode.h | 831 ++++++++++++++++ gas/config/tc-alpha.c | 1918 +++++++++++++++++++++++++++++++++++++ gas/config/tc-alpha.h | 67 ++ 4 files changed, 2819 insertions(+) create mode 100644 gas/config/alpha-opcode.h create mode 100644 gas/config/tc-alpha.c create mode 100644 gas/config/tc-alpha.h diff --git a/gas/config/.Sanitize b/gas/config/.Sanitize index d70a821609..1894973e7e 100644 --- a/gas/config/.Sanitize +++ b/gas/config/.Sanitize @@ -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 index 0000000000..d6b85b3ebb --- /dev/null +++ b/gas/config/alpha-opcode.h @@ -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 index 0000000000..f14e5e9d82 --- /dev/null +++ b/gas/config/tc-alpha.c @@ -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 ("", lita_sec, 0x8000, &zero_address_frag); + symbol_remove (gp, &symbol_rootP, &symbol_lastP); +} + +int optnum = 1; + +void +md_assemble (str) + char *str; +{ + char *toP; + int i, j, count; +#define MAX_INSNS 5 + struct alpha_it insns[MAX_INSNS]; + + count = alpha_ip (str, insns); + if (count <= 0) + return; + + for (i = 0; i < count; i++) + { + toP = frag_more (4); + + /* put out the opcode */ + md_number_to_chars (toP, insns[i].opcode, 4); + + /* put out the symbol-dependent stuff */ + for (j = 0; j < MAX_RELOCS; j++) + { + struct reloc_data *r = &insns[i].reloc[j]; + fixS *f; + + if (r->code != BFD_RELOC_NONE) + { + if (r->exp.X_op == O_constant) + { + r->exp.X_add_symbol = section_symbol (absolute_section); + r->exp.X_op = O_symbol; + } + f = fix_new_exp (frag_now, (toP - frag_now->fr_literal), 4, + &r->exp, r->pcrel, r->code); + } + if (r->code == BFD_RELOC_ALPHA_GPDISP_LO16) + { + static bit_fixS cookie; + /* This'll make the range checking in write.c shut up. */ + f->fx_bit_fixP = &cookie; + } + } + } +} + +/* @@ Will a simple 0x8000 work here? If not, why not? */ +#define GP_ADJUSTMENT (0x8000 - 0x10) + +static void +select_gp_value () +{ + if (gp_value == 0) + /* Must be first time through -- pick a GP to use for this file. */ + { + bfd_vma lita_vma, sdata_vma; + if (lita_sec) + lita_vma = bfd_get_section_vma (abfd, lita_sec); + else + lita_vma = 0; +#if 0 + if (sdata) + sdata_vma = bfd_get_section_vma (abfd, sdata); + else +#endif + sdata = 0; + + if (lita_vma == 0 + /* Who knows which order they'll get laid out in? */ + || (sdata_vma != 0 && sdata_vma < lita_vma)) + gp_value = sdata_vma; + else + gp_value = lita_vma; + + gp_value += GP_ADJUSTMENT; + + S_SET_VALUE (gp, gp_value); + +#ifdef DEBUG1 + printf ("Chose GP value of %lx\n", gp_value); +#endif + bfd_set_gp_value (stdoutput, gp_value); + } +} + +int +alpha_force_relocation (f) + fixS *f; +{ + switch (f->fx_r_type) + { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + case BFD_RELOC_ALPHA_LITERAL: + case BFD_RELOC_ALPHA_LITUSE: + case BFD_RELOC_GPREL32: + return 1; + case BFD_RELOC_ALPHA_HINT: + case BFD_RELOC_64: + case BFD_RELOC_32: + case BFD_RELOC_16: + case BFD_RELOC_8: + case BFD_RELOC_23_PCREL_S2: + case BFD_RELOC_14: + return 0; + default: + abort (); + return 0; + } +} + +int +alpha_fix_adjustable (f) + fixS *f; +{ + /* Are there any relocation types for which we must generate a reloc + but we can adjust the values contained within it? */ + switch (f->fx_r_type) + { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + return 0; + case BFD_RELOC_GPREL32: + return 1; + } + return !alpha_force_relocation (f); +} + +int +alpha_validate_fix (fixp, seg) + fixS *fixp; + segT seg; +{ + /* We must make sure we've got a good GP value if any relocations might + use it... */ + if (gp_value == 0) + select_gp_value (); + return 0; +} + +int +alpha_frob_symbol (s) + symbolS *s; +{ + return 0; +} + +unsigned long +md_section_align (seg, size) + segT seg; + unsigned long size; +{ +#ifdef OBJ_ECOFF + /* This should probably be handled within BFD, or by pulling the + number from BFD at least. */ +#define MIN 15 + size += MIN; + size &= ~MIN; +#endif + return size; +} + +/* Add this thing to the .lita section and produce a LITERAL reloc referring + to it. + + TODO: + Remove duplicates. + Set GP value properly, and have values in LITERAL references set + accordingly. + */ + +static void +load_symbol_address (reg, insn) + int reg; + struct alpha_it *insn; +{ + static symbolS *lita_sym; + + int x; + addressT reloc_addr; + valueT retval; + char *p; + symbolS *sym; + valueT addend; + + if (!lita_sym) + { + lita_sym = section_symbol (lita_sec); + S_CLEAR_EXTERNAL (lita_sym); + } + + retval = add_to_literal_pool (insn->reloc[0].exp.X_add_symbol, + insn->reloc[0].exp.X_add_number, + lita_sec, 8); + + /* @@ Get these numbers from GP setting. */ + retval -= GP_ADJUSTMENT; + + /* Now emit a LITERAL relocation for the original section. */ + insn->reloc[0].exp.X_op = O_symbol; + insn->reloc[0].exp.X_add_symbol = lita_sym; + insn->reloc[0].exp.X_add_number = retval; + insn->reloc[0].code = BFD_RELOC_ALPHA_LITERAL; + + if (retval == 0x8000) + /* Overflow? */ + as_fatal ("overflow in literal (.lita) table"); + x = retval; + insn->opcode = (0xa4000000 /* ldq */ + | (reg << SA) + | (base_register << SB) + | (x & 0xffff)); + note_gpreg (base_register); +} + +/* To load an address with a single instruction, + emit a LITERAL reloc in this section, and a REFQUAD + for the .lita section, so that we'll be able to access + it via $gp: + lda REG, xx -> ldq REG, -32752(gp) + lda REG, xx+4 -> ldq REG, -32752(gp) + lda REG, 4(REG) + + The offsets need to start near -0x8000, and the generated LITERAL + relocations should negate the offset. I don't completely grok the + scheme yet. */ + +static int +load_expression (reg, insn) + int reg; + struct alpha_it *insn; +{ + valueT addend; + int num_insns = 1; + + addend = insn->reloc[0].exp.X_add_number; + insn->reloc[0].exp.X_add_number = 0; + load_symbol_address (reg, insn); + if (addend) + { + num_insns++; + { + valueT x = addend; + if (x & ~0x7fff != 0 + && (x & ~0x7fff) + 0x8000 != 0) + { + as_bad ("assembler not prepared to handle constants >16 bits yet"); + addend = 0; + } + } + insn[1].opcode = (0x20000000 /* lda */ + | (reg << SA) + | (reg << SB) + | (addend & 0xffff)); + insn[1].reloc[0].code = BFD_RELOC_ALPHA_LITUSE; + insn[1].reloc[0].exp = lituse_basereg; + } + return num_insns; +} + +static inline int +getExpression (str, this_insn) + char *str; + struct alpha_it *this_insn; +{ + char *save_in; + segT seg; + +#if 0 /* Not converted to bfd yet, and I don't think we need them + for ECOFF. Re-adding a.out support will probably require + them though. */ + static const struct am { + char *name; + bfd_reloc_code_real_type reloc; + } macro[] = { + { "hi", RELOC_48_63 }, + { "lo", RELOC_0_15 }, + { "ml", RELOC_16_31 }, + { "mh", RELOC_32_47 }, + { "uhi", RELOC_U_48_63 }, + { "uml", RELOC_U_16_31 }, + { "umh", RELOC_U_32_47 }, + { 0, } + }; + + /* Handle macros: "%macroname(expr)" */ + if (*str == '%') + { + struct am *m; + char *p, *q; + + str++; + m = ¯o[0]; + while (q = m->name) + { + p = str; + while (*q && *p == *q) + p++, q++; + if (*q == 0) + break; + m++; + } + if (q) + { + str = p; /* keep the '(' */ + this_insn->reloc = m->reloc; + } + } +#endif + + save_in = input_line_pointer; + input_line_pointer = str; + + seg = expression (&this_insn->reloc[0].exp); + /* XXX validate seg and exp, make sure they're reasonable */ + expr_end = input_line_pointer; + input_line_pointer = save_in; + + return 0; +} + +/* Note that for now, this function is called recursively. Some of the + macros defined as part of the assembly language are currently + rewritten as sequences of strings to be assembled. See, for example, + the handling of "divq". + + For efficiency, this should be fixed someday. */ +static int +alpha_ip (str, insns) + char *str; + struct alpha_it insns[]; +{ + char *s; + const char *args; + char c; + unsigned long i; + struct alpha_opcode *pattern; + char *argsStart; + unsigned int opcode; + unsigned int mask; + int match = 0, num_gen = 1; + int comma = 0; + + for (s = str; + islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8'; + ++s) + ; + switch (*s) + { + + case '\0': + break; + + case ',': + comma = 1; + + /*FALLTHROUGH*/ + + case ' ': + *s++ = '\0'; + break; + + default: + as_warn ("Unknown opcode: `%s'", str); + exit (1); + } + if ((pattern = (struct alpha_opcode *) hash_find (op_hash, str)) == NULL) + { + as_warn ("Unknown opcode: `%s'", str); + return -1; + } + if (comma) + *--s = ','; + + argsStart = s; + for (;;) + { + opcode = pattern->match; + num_gen = 1; + memset (insns, 0, sizeof (*insns)); + for (i = 0; i < MAX_RELOCS; i++) + insns[0].reloc[i].code = BFD_RELOC_NONE; + for (i = 1; i < MAX_INSNS; i++) + insns[i] = insns[0]; + + /* Build the opcode, checking as we go to make sure that the + operands match. */ + for (args = pattern->args;; ++args) + { + switch (*args) + { + + case '\0': /* end of args */ + if (*s == '\0') + { + match = 1; + } + break; + + case '+': + if (*s == '+') + { + ++s; + continue; + } + if (*s == '-') + { + continue; + } + break; + + case '(': /* these must match exactly */ + case ')': + case ',': + case ' ': + case '0': + if (*s++ == *args) + continue; + break; + + case '1': /* next operand must be a register */ + case '2': + case '3': + case 'r': + case 'R': + if (*s++ == '$') + { + switch (c = *s++) + { + + case 'a': /* $at: as temporary */ + if (*s++ != 't') + goto error; + mask = AT; + break; + + case 'g': /* $gp: base register */ + if (*s++ != 'p') + goto error; + mask = base_register; + break; + + case 's': /* $sp: stack pointer */ + if (*s++ != 'p') + goto error; + mask = SP; + break; + + + case 'r': /* any register */ + if (!isdigit (c = *s++)) + { + goto error; + } + /* FALLTHROUGH */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (isdigit (*s)) + { + if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) + { + goto error; + } + } + else + { + c -= '0'; + } + if ((c == GP) && first_32bit_quadrant) + c = ZERO; + + mask = c; + break; + + default: + goto error; + } + note_gpreg (mask); + /* Got the register, now figure out where it goes in + the opcode. */ + doregister: + switch (*args) + { + + case '1': + case 'e': + opcode |= mask << SA; + continue; + + case '2': + case 'f': + opcode |= mask << SB; + continue; + + case '3': + case 'g': + opcode |= mask; + continue; + + case 'r': + opcode |= (mask << SA) | mask; + continue; + + case 'R': /* ra and rb are the same */ + opcode |= (mask << SA) | (mask << SB); + continue; + + case 'E': + opcode |= (mask << SA) | (mask << SB) | (mask); + continue; + } + } + break; + + case 'e': /* next operand is a floating point register */ + case 'f': + case 'g': + case 'E': + if (*s++ == '$' && *s++ == 'f' && isdigit (*s)) + { + mask = *s++; + if (isdigit (*s)) + { + mask = 10 * (mask - '0') + (*s++ - '0'); + if (mask >= 32) + { + break; + } + } + else + { + mask -= '0'; + } + note_fpreg (mask); + /* same encoding as gp registers */ + goto doregister; + } + break; + +#if 0 + case 'h': /* bits 16..31 */ + insns[0].reloc = RELOC_16_31; + goto immediate; +#endif + + case 'l': /* bits 0..15 */ + insns[0].reloc[0].code = BFD_RELOC_16; + goto immediate; + + case 'L': /* 21 bit PC relative immediate */ + insns[0].reloc[0].code = BFD_RELOC_23_PCREL_S2; + insns[0].reloc[0].pcrel = 1; + goto immediate; + + case 'i': /* 14 bit immediate */ + if (OPCODE (opcode) != 0x1a) + /* Not a jmp variant?? */ + abort (); + else if (opcode & 0x8000) + /* ret or jsr_coroutine */ + { + insns[0].reloc[0].code = BFD_RELOC_14; + insns[0].reloc[0].pcrel = 0; + } + else + /* jmp or jsr */ + { + insns[0].reloc[0].code = BFD_RELOC_ALPHA_HINT; + insns[0].reloc[0].pcrel = 1; + } + goto immediate; + + case 'b': /* 8 bit immediate */ + insns[0].reloc[0].code = BFD_RELOC_8; + goto immediate; + +#if 0 + case 't': /* 12 bit 0...11 */ + insns[0].reloc = RELOC_0_12; + goto immediate; + + case '8': /* 8 bit 0...7 */ + insns[0].reloc = RELOC_0_8; + goto immediate; + + case 'I': /* 26 bit immediate */ + insns[0].reloc = RELOC_0_25; +#else + case 't': + case '8': + case 'I': + abort (); +#endif + /*FALLTHROUGH*/ + + immediate: + if (*s == ' ') + s++; + (void) getExpression (s, &insns[0]); + s = expr_end; + /* Handle overflow in certain instructions by converting + to other instructions. */ + if (insns[0].reloc[0].code == BFD_RELOC_8 + && insns[0].reloc[0].exp.X_op == O_constant + && (insns[0].reloc[0].exp.X_add_number < 0 + || insns[0].reloc[0].exp.X_add_number > 0xff)) + { + if (OPCODE (opcode) == 0x10 + && (OP_FCN (opcode) == 0x00 /* addl */ + || OP_FCN (opcode) == 0x40 /* addl/v */ + || OP_FCN (opcode) == 0x20 /* addq */ + || OP_FCN (opcode) == 0x60 /* addq/v */ + || OP_FCN (opcode) == 0x09 /* subl */ + || OP_FCN (opcode) == 0x49 /* subl/v */ + || OP_FCN (opcode) == 0x29 /* subq */ + || OP_FCN (opcode) == 0x69 /* subq/v */ + || OP_FCN (opcode) == 0x02 /* s4addl */ + || OP_FCN (opcode) == 0x22 /* s4addq */ + || OP_FCN (opcode) == 0x0b /* s4subl */ + || OP_FCN (opcode) == 0x2b /* s4subq */ + || OP_FCN (opcode) == 0x12 /* s8addl */ + || OP_FCN (opcode) == 0x32 /* s8addq */ + || OP_FCN (opcode) == 0x1b /* s8subl */ + || OP_FCN (opcode) == 0x3b /* s8subq */ + ) + /* Can we make it fit by negating? */ + && -insns[0].reloc[0].exp.X_add_number < 0xff + && -insns[0].reloc[0].exp.X_add_number > 0) + { + opcode ^= 0x120; /* convert add<=>sub */ + insns[0].reloc[0].exp.X_add_number *= -1; + } + else if (at_ok && macro_ok) + { + /* Constant value supplied, but it's too large. */ + char expansion[64]; + sprintf (expansion, "lda $%d,%d($%d)", AT, + insns[0].reloc[0].exp.X_add_number, ZERO); + md_assemble (expansion); + opcode |= 0x1000 /* use reg */ | (AT << SB); + insns[0].reloc[0].code = BFD_RELOC_NONE; + } + else + as_bad ("overflow in 8-bit literal field in `operate' format insn"); + } + continue; + + /* The following two.. take advantage of the fact that + opcode already contains most of what we need to know. + We just prepend to the instr an "ldah + $r,%ml(expr)($base)" and turn this one (done later + after we return) into something like "stq + $r,%lo(expr)(at)" or "ldq $r,%lo(expr)($r)". + + NOTE: This can fail later on at link time if the + offset from $base actually turns out to be more than + 2**31 or 2**47 if use_large_offsets is set. */ + case 'P': /* Addressing macros: PUT */ + mask = AT; /* register 'at' */ + /* fall through */ + + case 'G': /* Addressing macros: GET */ + get_macro: + /* All it is missing is the expression, which is what we + will get now */ + + if (*s == ' ') + s++; + (void) getExpression (s, &insns[0]); + s = expr_end; + + /* Must check for "lda ..,number" too */ + if (insns[0].reloc[0].exp.X_op == O_big) + { + as_warn ("Sorry, not yet. Put bignums in .data section yourself."); + return -1; + } + if (insns[0].reloc[0].exp.X_op == O_constant) + { + /* This only handles 32bit numbers */ + register int val = insns[0].reloc[0].exp.X_add_number; + register short sval; + + insns[0].reloc[0].code = BFD_RELOC_NONE; + insns[1].reloc[0].code = BFD_RELOC_NONE; + + sval = val; + if (0) + fprintf (stderr, "val %lx sval %lx\n", val, sval); + if ((sval != val) && (val & 0x8000)) + { + val += 0x10000; + sval = val; + } + + if (optnum && (sval == val)) + { + /* optimize away the ldah */ + num_gen = 1; + opcode |= (ZERO << SB) | (val & 0xffff); + } + else + { + num_gen = 2; + insns[1].opcode = opcode | (mask << SB) | (val & 0xffff); + opcode = 0x24000000 /*ldah*/ | + mask << SA | (ZERO << SB) | + ((val >> 16) & 0xffff); + } + } + else if (insns[0].reloc[0].exp.X_op == O_symbol) + { + unsigned long old_opcode = opcode; + int tmp_reg; + + if (!macro_ok) + as_bad ("insn requires expansion but `nomacro' specified"); + else if (*args == 'G') + tmp_reg = mask; + else if (!at_ok) + as_bad ("insn expansion requires AT use, but `noat' specified"); + else + tmp_reg = AT; + num_gen = load_expression (tmp_reg, insns); + opcode = insns[0].opcode; + /* lda is opcode 8, 0x20000000 */ + if (OPCODE (old_opcode) != 0x08) + { + struct alpha_it *i; + i = &insns[num_gen++]; + i->reloc[0].code = BFD_RELOC_NONE; + i->opcode = old_opcode | (tmp_reg << SB); + } + } + else + { + /* Not a number */ + num_gen = 2; + insns[1].reloc[0].exp = insns[0].reloc[0].exp; + + /* Generate: ldah REG,x1(GP); OP ?,x0(REG) */ + + abort (); /* relocs need fixing */ +#if 0 + insns[1].reloc = RELOC_0_15; + insns[1].opcode = opcode | mask << SB; + + insns[0].reloc = RELOC_16_31; + opcode = 0x24000000 /*ldah*/ | mask << SA | (base_register << SB); +#endif + } + + continue; + + /* Same failure modes as above, actually most of the + same code shared. */ + case 'B': /* Builtins */ + args++; + switch (*args) + { + + case 'a': /* ldgp */ + + if (first_32bit_quadrant || no_mixed_code) + return -1; + switch (OUTPUT_FLAVOR) + { + case bfd_target_aout_flavour: + /* this is cmu's a.out version */ + insns[0].reloc[0].code = BFD_RELOC_NONE; + /* generate "zap %r,0xf,%r" to take high 32 bits */ + opcode |= 0x48001600 /* zap ?,#,?*/ | (0xf << SN); + break; + case bfd_target_ecoff_flavour: + /* Given "ldgp R1,N(R2)", turn it into something + like "ldah R1,###(R2) ; lda R1,###(R1)" with + appropriate constants and relocations. */ + { + unsigned long r1, r2; + unsigned long addend = 0; + + num_gen = 2; + r2 = mask; + r1 = opcode & 0x3f; + insns[0].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_HI16; + insns[0].reloc[0].pcrel = 1; + insns[0].reloc[0].exp.X_op = O_symbol; + insns[0].reloc[0].exp.X_add_symbol = gp; + insns[0].reloc[0].exp.X_add_number = 0; + insns[0].opcode = (0x24000000 /* ldah */ + | (r1 << SA) + | (r2 << SB)); + insns[1].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_LO16; + insns[1].reloc[0].exp.X_op = O_symbol; + insns[1].reloc[0].exp.X_add_symbol = gp; + insns[1].reloc[0].exp.X_add_number = 4; + insns[1].reloc[0].pcrel = 1; + insns[1].opcode = 0x20000000 | (r1 << SA) | (r1 << SB); + opcode = insns[0].opcode; + /* merge in addend */ + insns[1].opcode |= addend & 0xffff; + insns[0].opcode |= ((addend >> 16) + + (addend & 0x8000 ? 1 : 0)); + ecoff_set_gp_prolog_size (0); + } + break; + default: + abort (); + } + continue; + + + case 'b': /* setgp */ + switch (OUTPUT_FLAVOR) + { + case bfd_target_aout_flavour: + /* generate "zap %r,0xf,$gp" to take high 32 bits */ + opcode |= 0x48001600 /* zap ?,#,?*/ + | (0xf << SN) | (base_register); + break; + default: + abort (); + } + continue; + + case 'c': /* jsr $r,foo becomes + lda $27,foo + jsr $r,($27),foo + Register 27, t12, is used by convention + here. */ + { + struct alpha_it *jsr; + expressionS etmp; + struct reloc_data *r; + + /* We still have to parse the function name */ + if (*s == ' ') + s++; + (void) getExpression (s, &insns[0]); + etmp = insns[0].reloc[0].exp; + s = expr_end; + num_gen = load_expression (PV, &insns[0]); + note_gpreg (PV); + + jsr = &insns[num_gen++]; + jsr->opcode = (0x68004000 /* jsr */ + | (mask << SA) + | (PV << SB) + | 0); + if (num_gen == 2) + { + /* LITUSE wasn't emitted yet */ + jsr->reloc[0].code = BFD_RELOC_ALPHA_LITUSE; + jsr->reloc[0].exp = lituse_jsr; + r = &jsr->reloc[1]; + } + else + r = &jsr->reloc[0]; + r->exp = etmp; + r->code = BFD_RELOC_ALPHA_HINT; + r->pcrel = 1; + opcode = insns[0].opcode; + } + continue; + + /* DIVISION and MODULUS. Yech. + Convert OP x,y,result + to mov x,t10 + mov y,t11 + jsr t9, __OP + mov t12,result + + with appropriate optimizations if t10,t11,t12 + are the registers specified by the compiler. + We are missing an obvious optimization + opportunity here; if the ldq generated by the + jsr assembly requires a cycle or two to make + the value available, initiating it before one + or two of the mov instructions would result in + faster execution. */ + case '0': /* reml */ + case '1': /* divl */ + case '2': /* remq */ + case '3': /* divq */ + case '4': /* remlu */ + case '5': /* divlu */ + case '6': /* remqu */ + case '7': /* divqu */ + { + static char func[8][6] = { + "reml", "divl", "remq", "divq", + "remlu", "divlu", "remqu", "divqu" + }; + char expansion[64]; + int reg; + + /* All regs parsed, in opcode */ + + /* Do the expansions, one instr at a time */ + + reg = (opcode >> SA) & 31; + if (reg != T10) + { + /* x->t10 */ + sprintf (expansion, "mov $%d,$%d", reg, T10); + md_assemble (expansion); + } + reg = (opcode >> SB) & 31; + if (reg == T10) + /* we already overwrote it! */ + abort (); + else if (reg != T11) + { + /* y->t11 */ + sprintf (expansion, "mov $%d,$%d", reg, T11); + md_assemble (expansion); + } + sprintf (expansion, "lda $%d,__%s", PV, func[*args - '0']); + md_assemble (expansion); + sprintf (expansion, "jsr $%d,($%d),__%s", T9, PV, + func[*args - '0']); + md_assemble (expansion); +#if 0 /* huh? */ + if (!first_32bit_quadrant) + { + sprintf (expansion, + "zap $%d,0xf,$%d", + T9, base_register); + md_assemble (expansion); + } +#endif + sprintf (expansion, "ldgp $%d,0($%d)", + base_register, T9); + md_assemble (expansion); + + /* Use insns[0] to get at the result */ + if ((reg = (opcode & 31)) != PV) + opcode = (0x47e00400 /* or zero,zero,zero */ + | (PV << SB) + | reg /* Rc */ ); /* pv->z */ + else + num_gen = 0; + } + continue; + } + /* fall through */ + + default: + abort (); + } + break; + } + error: + if (match == 0) + { + /* Args don't match. */ + if (&pattern[1] - alpha_opcodes < NUMOPCODES + && !strcmp (pattern->name, pattern[1].name)) + { + ++pattern; + s = argsStart; + continue; + } + else + { + as_warn ("Illegal operands"); + return -1; + } + } + else + { + /* Args match, see if a float instructions and -nofloats */ + if (nofloats && pattern->isa_float) + return -1; + } + break; + } + + insns[0].opcode = opcode; + return num_gen; +} + +/* Turn a string in input_line_pointer into a floating point constant + of type type, and store the appropriate bytes in *litP. The number + of LITTLENUMS emitted is stored in *sizeP. An error message is + returned, or NULL on OK. */ + +/* Equal to MAX_PRECISION in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + char *atof_ieee (), *vax_md_atof (); + + switch (type) + { + /* VAX floats */ + case 'G': + type = 'g'; + case 'F': + case 'D': + return vax_md_atof (type, litP, sizeP); + + /* IEEE floats */ + case 'f': + prec = 2; + break; + + case 'd': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * sizeof (LITTLENUM_TYPE); + + for (wordP = words + prec - 1; prec--;) + { + md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + + return 0; +} + +void +md_bignum_to_chars (buf, bignum, nchars) + char *buf; + LITTLENUM_TYPE *bignum; + int nchars; +{ + while (nchars) + { + LITTLENUM_TYPE work = *bignum++; + int nb = CHARS_PER_LITTLENUM; + + do + { + *buf++ = work & ((1 << BITS_PER_CHAR) - 1); + if (--nchars == 0) + return; + work >>= BITS_PER_CHAR; + } + while (--nb); + } +} + +int +md_parse_option (argP, cntP, vecP) + char **argP; + int *cntP; + char ***vecP; +{ + if (**argP == 'F') + { + nofloats = 1; + return 1; + } +#if 0 /* I have no idea if this stuff would work any more. And it's + probably not right for ECOFF anyways. */ + /* Use base-register addressing, e.g. PIC code */ + if (**argP == 'B') + { + if (first_32bit_quadrant) + { + first_32bit_quadrant = 0; + base_register = GP; + } + else + { + first_32bit_quadrant = 1; + base_register = ZERO; + } + if (argP[0][1] == 'k') + no_mixed_code = 1; + argP[0][1] = 0; + return 1; + } +#endif + if (!strcmp (*argP, "nocpp")) + { + *argP += 5; + return 1; + } + return 0; +} + +static void +s_proc (is_static) +{ + /* XXXX Align to cache linesize XXXXX */ + char *name; + char c; + char *p; + symbolS *symbolP; + int temp; + + /* Takes ".proc name,nargs" */ + name = input_line_pointer; + c = get_symbol_end (); + p = input_line_pointer; + symbolP = symbol_find_or_make (name); + *p = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + *p = 0; + as_warn ("Expected comma after name \"%s\"", name); + *p = c; + temp = 0; + ignore_rest_of_line (); + } + else + { + input_line_pointer++; + temp = get_absolute_expression (); + } + /* symbolP->sy_other = (signed char) temp; */ + as_warn ("unhandled: .proc %s,%d", name, temp); + demand_empty_rest_of_line (); +} + +static void +s_alpha_set (x) + int x; +{ + char *name = input_line_pointer, ch, *s; + int yesno = 1; + + while (!is_end_of_line[(unsigned char) *input_line_pointer]) + input_line_pointer++; + ch = *input_line_pointer; + *input_line_pointer = '\0'; + + s = name; + if (s[0] == 'n' && s[1] == 'o') + { + yesno = 0; + s += 2; + } + if (!strcmp ("reorder", s)) + /* ignore */ ; + else if (!strcmp ("at", s)) + at_ok = yesno; + else if (!strcmp ("macro", s)) + macro_ok = yesno; + else + as_warn ("Tried to set unrecognized symbol: %s", name); + *input_line_pointer = ch; + demand_empty_rest_of_line (); +} + +/* @@ Is this right?? */ +long +md_pcrel_from (fixP) + fixS *fixP; +{ + valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; + switch (fixP->fx_r_type) + { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + return addr; + default: + return fixP->fx_size + addr; + } +} + +int +alpha_do_align (n, fill) + int n; + char *fill; +{ + if (!fill + && (now_seg == text_section + || !strcmp (now_seg->name, ".init") + || !strcmp (now_seg->name, ".fini"))) + { + static const char nop_pattern[] = { 0x1f, 0x04, 0xff, 0x47 }; + frag_align_pattern (n, nop_pattern, sizeof (nop_pattern)); + return 1; + } + return 0; +} + +int +md_apply_fix (fixP, valueP) + fixS *fixP; + valueT *valueP; +{ + valueT value; + int size; + valueT addend; + char *p = fixP->fx_frag->fr_literal + fixP->fx_where; + + value = *valueP; + + switch (fixP->fx_r_type) + { + /* The GPDISP relocations are processed internally with a symbol + referring to the current function; we need to drop in a value + which, when added to the address of the start of the function, + gives the desired GP. */ + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + addend = value; + if (fixP->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16) + { + assert (fixP->fx_next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16); +#ifdef DEBUG1 + printf ("hi16: "); + fprintf_vma (stdout, addend); + printf ("\n"); +#endif + if (addend & 0x8000) + addend += 0x10000; + addend >>= 16; + fixP->fx_offset = 4; /* @@ Compute this using fx_next. */ + } + else + { +#ifdef DEBUG1 + printf ("lo16: "); + fprintf_vma (stdout, addend); + printf ("\n"); +#endif + addend &= 0xffff; + fixP->fx_offset = 0; + } + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, + addend, 2); + fixP->fx_addsy = section_symbol (absolute_section); + fixP->fx_offset += fixP->fx_frag->fr_address + fixP->fx_where; + break; + + case BFD_RELOC_8: + /* Write 8 bits, shifted left 13 bit positions. */ + value &= 0xff; + p++; + *p &= 0x1f; + *p |= (value << 5) & 0xe0; + value >>= 3; + p++; + *p &= 0xe0; + *p |= value; + value >>= 5; + fixP->fx_done = 1; + check_zov: + if (value != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + "overflow in type-%d reloc", (int) fixP->fx_r_type); + return 3; + + case BFD_RELOC_32: + case BFD_RELOC_64: + return 42; + case BFD_RELOC_16: + /* Don't want overflow checking. */ + size = 2; + do_it: + if (fixP->fx_pcrel == 0 + && fixP->fx_addsy == 0) + { + md_number_to_chars (p, value, size); + /* @@ Overflow checks?? */ + goto done; + } + break; + + case BFD_RELOC_14: + if (fixP->fx_addsy != 0 + && fixP->fx_addsy->bsym->section != absolute_section) + as_bad_where (fixP->fx_file, fixP->fx_line, + "ret/jsr_coroutine requires constant in displacement field"); + else if (value >> 14 != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + "overflow in 14-bit operand field of ret or jsr_coroutine"); + *p++ = value & 0xff; + value >>= 8; + *p = (*p & 0xc0) | (value & 0x3f); + goto done; + + case BFD_RELOC_23_PCREL_S2: + /* Write 21 bits only. */ + value >>= 2; + *p++ = value & 0xff; + value >>= 8; + *p++ = value & 0xff; + value >>= 8; + *p &= 0xe0; + *p |= (value & 0x1f); + goto done; + + case BFD_RELOC_ALPHA_LITERAL: + case BFD_RELOC_ALPHA_LITUSE: + return 2; + + case BFD_RELOC_GPREL32: + assert (fixP->fx_subsy == gp); + value = - gp_value; /* huh? this works... */ + fixP->fx_subsy = 0; + md_number_to_chars (p, value, 4); + break; + + case BFD_RELOC_ALPHA_HINT: + if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) + { + size = 2; + goto do_it; + } + return 2; + + default: + as_fatal ("unknown relocation type %d?", fixP->fx_r_type); + return 9; + } + + if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) + { + printf ("type %d reloc done?\n", fixP->fx_r_type); + done: + fixP->fx_done = 1; + return 42; + } + + return 0x12345678; +} + +void +alpha_end () +{ + /* $zero and $f31 are read-only */ + alpha_gprmask &= ~(1L << 31); + alpha_fprmask &= ~(1L << 31); +} + +/* The Alpha has support for some VAX floating point types, as well as for + IEEE floating point. We consider IEEE to be the primary floating point + format, and sneak in the VAX floating point support here. */ +#define md_atof vax_md_atof +#include "config/atof-vax.c" diff --git a/gas/config/tc-alpha.h b/gas/config/tc-alpha.h new file mode 100644 index 0000000000..4994cf962b --- /dev/null +++ b/gas/config/tc-alpha.h @@ -0,0 +1,67 @@ +/* This file is tc-alpha.h + Copyright (C) 1994 Free Software Foundation, Inc. + Written by Ken Raeburn . + + 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