diff options
| author | cgd <cgd@NetBSD.org> | 1993-05-13 14:48:19 +0000 |
|---|---|---|
| committer | cgd <cgd@NetBSD.org> | 1993-05-13 14:48:19 +0000 |
| commit | f8d29a33fcbb1a0031582def19f5c3c6a71dcda5 (patch) | |
| tree | 7b79a3064edf400f067784a3b4ceda6f58d391d8 /gnu/usr.bin | |
| parent | 767fcb4410051ffcac827d87a3698c15d5b0ab33 (diff) | |
add gas config files from net/2
Diffstat (limited to 'gnu/usr.bin')
| -rw-r--r-- | gnu/usr.bin/gas/config/Makefile.hp300 | 4 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/Makefile.vax | 3 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/atof-vax.c | 513 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/i860-opcode.h | 491 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/i860.c | 1142 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/i860.h | 48 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/m-hpux.h | 24 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/m-sun3.h | 31 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/m68k-opcode.h | 1680 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/m68k.c | 3540 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/m68k.h | 20 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/ns32k-opcode.h | 434 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/ns32k.c | 1768 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/sparc-opcode.h | 636 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/sparc.c | 1285 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/sparc.h | 52 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/vax-inst.h | 77 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/vax-opcode.h | 382 | ||||
| -rw-r--r-- | gnu/usr.bin/gas/config/vax.c | 3364 |
19 files changed, 15494 insertions, 0 deletions
diff --git a/gnu/usr.bin/gas/config/Makefile.hp300 b/gnu/usr.bin/gas/config/Makefile.hp300 new file mode 100644 index 00000000000..16ca9bddcc4 --- /dev/null +++ b/gnu/usr.bin/gas/config/Makefile.hp300 @@ -0,0 +1,4 @@ +# @(#)Makefile.hp300 6.1 (Berkeley) 3/3/91 + +CFLAGS+= -Dm68851 +SRCS+= m68k.c atof-ieee.c diff --git a/gnu/usr.bin/gas/config/Makefile.vax b/gnu/usr.bin/gas/config/Makefile.vax new file mode 100644 index 00000000000..1230e4b578a --- /dev/null +++ b/gnu/usr.bin/gas/config/Makefile.vax @@ -0,0 +1,3 @@ +# @(#)Makefile.vax 6.1 (Berkeley) 3/3/91 + +SRCS+= vax.c atof-vax.c diff --git a/gnu/usr.bin/gas/config/atof-vax.c b/gnu/usr.bin/gas/config/atof-vax.c new file mode 100644 index 00000000000..cd343ba4ce0 --- /dev/null +++ b/gnu/usr.bin/gas/config/atof-vax.c @@ -0,0 +1,513 @@ +/* atof_vax.c - turn a Flonum into a VAX floating point number + Copyright (C) 1987 Free Software Foundation, Inc. + +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 1, 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. */ + + /* JF added these two for md_atof() */ +#include "as.h" +#include "read.h" + +#include "flonum.h" + + + /* Precision in LittleNums. */ +#define MAX_PRECISION (8) +#define H_PRECISION (8) +#define G_PRECISION (4) +#define D_PRECISION (4) +#define F_PRECISION (2) + + /* Length in LittleNums of guard bits. */ +#define GUARD (2) + +int /* Number of chars in flonum type 'letter'. */ +atof_vax_sizeof (letter) + char letter; +{ + int return_value; + + /* + * Permitting uppercase letters is probably a bad idea. + * Please use only lower-cased letters in case the upper-cased + * ones become unsupported! + */ + switch (letter) + { + case 'f': + case 'F': + return_value = 4; + break; + + case 'd': + case 'D': + case 'g': + case 'G': + return_value = 8; + break; + + case 'h': + case 'H': + return_value = 16; + break; + + default: + return_value = 0; + break; + } + return (return_value); +} /* atof_vax_sizeof */ + +static const long int mask [] = { + 0x00000000, + 0x00000001, + 0x00000003, + 0x00000007, + 0x0000000f, + 0x0000001f, + 0x0000003f, + 0x0000007f, + 0x000000ff, + 0x000001ff, + 0x000003ff, + 0x000007ff, + 0x00000fff, + 0x00001fff, + 0x00003fff, + 0x00007fff, + 0x0000ffff, + 0x0001ffff, + 0x0003ffff, + 0x0007ffff, + 0x000fffff, + 0x001fffff, + 0x003fffff, + 0x007fffff, + 0x00ffffff, + 0x01ffffff, + 0x03ffffff, + 0x07ffffff, + 0x0fffffff, + 0x1fffffff, + 0x3fffffff, + 0x7fffffff, + 0xffffffff + }; + + +/* Shared between flonum_gen2vax and next_bits */ +static int bits_left_in_littlenum; +static LITTLENUM_TYPE * littlenum_pointer; +static LITTLENUM_TYPE * littlenum_end; + +static int +next_bits (number_of_bits) + int number_of_bits; +{ + int return_value; + + if(littlenum_pointer<littlenum_end) + return 0; + if (number_of_bits >= bits_left_in_littlenum) + { + return_value = mask [bits_left_in_littlenum] & * littlenum_pointer; + number_of_bits -= bits_left_in_littlenum; + return_value <<= number_of_bits; + bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; + littlenum_pointer --; + if(littlenum_pointer>=littlenum_end) + return_value |= ( (* littlenum_pointer) >> (bits_left_in_littlenum) ) & mask [number_of_bits]; + } + else + { + bits_left_in_littlenum -= number_of_bits; + return_value = mask [number_of_bits] & ( (* littlenum_pointer) >> bits_left_in_littlenum); + } + return (return_value); +} + +static void +make_invalid_floating_point_number (words) + LITTLENUM_TYPE * words; +{ + * words = 0x8000; /* Floating Reserved Operand Code */ +} + +static int /* 0 means letter is OK. */ +what_kind_of_float (letter, precisionP, exponent_bitsP) + char letter; /* In: lowercase please. What kind of float? */ + int * precisionP; /* Number of 16-bit words in the float. */ + long int * exponent_bitsP; /* Number of exponent bits. */ +{ + int retval; /* 0: OK. */ + + retval = 0; + switch (letter) + { + case 'f': + * precisionP = F_PRECISION; + * exponent_bitsP = 8; + break; + + case 'd': + * precisionP = D_PRECISION; + * exponent_bitsP = 8; + break; + + case 'g': + * precisionP = G_PRECISION; + * exponent_bitsP = 11; + break; + + case 'h': + * precisionP = H_PRECISION; + * exponent_bitsP = 15; + break; + + default: + retval = 69; + break; + } + return (retval); +} + +/***********************************************************************\ +* * +* Warning: this returns 16-bit LITTLENUMs, because that is * +* what the VAX thinks in. It is up to the caller to figure * +* out any alignment problems and to conspire for the bytes/word * +* to be emitted in the right order. Bigendians beware! * +* * +\***********************************************************************/ + +char * /* Return pointer past text consumed. */ +atof_vax (str, what_kind, words) + char * str; /* Text to convert to binary. */ + char what_kind; /* 'd', 'f', 'g', 'h' */ + LITTLENUM_TYPE * words; /* Build the binary here. */ +{ + FLONUM_TYPE f; + LITTLENUM_TYPE bits [MAX_PRECISION + MAX_PRECISION + GUARD]; + /* Extra bits for zeroed low-order bits. */ + /* The 1st MAX_PRECISION are zeroed, */ + /* the last contain flonum bits. */ + char * return_value; + int precision; /* Number of 16-bit words in the format. */ + long int exponent_bits; + + return_value = str; + f . low = bits + MAX_PRECISION; + f . high = NULL; + f . leader = NULL; + f . exponent = NULL; + f . sign = '\0'; + + if (what_kind_of_float (what_kind, & precision, & exponent_bits)) + { + return_value = NULL; /* We lost. */ + make_invalid_floating_point_number (words); + } + if (return_value) + { + bzero (bits, sizeof(LITTLENUM_TYPE) * MAX_PRECISION); + + /* Use more LittleNums than seems */ + /* necessary: the highest flonum may have */ + /* 15 leading 0 bits, so could be useless. */ + f . high = f . low + precision - 1 + GUARD; + + if (atof_generic (& return_value, ".", "eE", & f)) + { + make_invalid_floating_point_number (words); + return_value = NULL; /* we lost */ + } + else + { + if (flonum_gen2vax (what_kind, & f, words)) + { + return_value = NULL; + } + } + } + return (return_value); +} + +/* + * In: a flonum, a vax floating point format. + * Out: a vax floating-point bit pattern. + */ + +int /* 0: OK. */ +flonum_gen2vax (format_letter, f, words) + char format_letter; /* One of 'd' 'f' 'g' 'h'. */ + FLONUM_TYPE * f; + LITTLENUM_TYPE * words; /* Deliver answer here. */ +{ + LITTLENUM_TYPE * lp; + int precision; + long int exponent_bits; + int return_value; /* 0 == OK. */ + + return_value = what_kind_of_float (format_letter, & precision, & exponent_bits); + if (return_value != 0) + { + make_invalid_floating_point_number (words); + } + else + { + if (f -> low > f -> leader) + { + /* 0.0e0 seen. */ + bzero (words, sizeof(LITTLENUM_TYPE) * precision); + } + else + { + long int exponent_1; + long int exponent_2; + long int exponent_3; + long int exponent_4; + int exponent_skippage; + LITTLENUM_TYPE word1; + + /* JF: Deal with new Nan, +Inf and -Inf codes */ + if(f->sign!='-' && f->sign!='+') { + make_invalid_floating_point_number(words); + return return_value; + } + /* + * All vaxen floating_point formats (so far) have: + * Bit 15 is sign bit. + * Bits 14:n are excess-whatever exponent. + * Bits n-1:0 (if any) are most significant bits of fraction. + * Bits 15:0 of the next word are the next most significant bits. + * And so on for each other word. + * + * All this to be compatible with a KF11?? (Which is still faster + * than lots of vaxen I can think of, but it also has higher + * maintenance costs ... sigh). + * + * So we need: number of bits of exponent, number of bits of + * mantissa. + */ + +#ifdef NEVER /******* This zeroing seems redundant - Dean 3may86 **********/ + /* + * No matter how few bits we got back from the atof() + * routine, add enough zero littlenums so the rest of the + * code won't run out of "significant" bits in the mantissa. + */ + { + LITTLENUM_TYPE * ltp; + for (ltp = f -> leader + 1; + ltp <= f -> low + precision; + ltp ++) + { + * ltp = 0; + } + } +#endif + + bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; + littlenum_pointer = f -> leader; + littlenum_end = f->low; + /* Seek (and forget) 1st significant bit */ + for (exponent_skippage = 0; + ! next_bits(1); + exponent_skippage ++) + { + } + exponent_1 = f -> exponent + f -> leader + 1 - f -> low; + /* Radix LITTLENUM_RADIX, point just higher than f -> leader. */ + exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; + /* Radix 2. */ + exponent_3 = exponent_2 - exponent_skippage; + /* Forget leading zeros, forget 1st bit. */ + exponent_4 = exponent_3 + (1 << (exponent_bits - 1)); + /* Offset exponent. */ + + if (exponent_4 & ~ mask [exponent_bits]) + { + /* + * Exponent overflow. Lose immediately. + */ + + make_invalid_floating_point_number (words); + + /* + * We leave return_value alone: admit we read the + * number, but return a floating exception + * because we can't encode the number. + */ + } + else + { + lp = words; + + /* Word 1. Sign, exponent and perhaps high bits. */ + /* Assume 2's complement integers. */ + word1 = ((exponent_4 & mask [exponent_bits]) << (15 - exponent_bits)) + | ((f -> sign == '+') ? 0 : 0x8000) + | next_bits (15 - exponent_bits); + * lp ++ = word1; + + /* The rest of the words are just mantissa bits. */ + for (; lp < words + precision; lp++) + { + * lp = next_bits (LITTLENUM_NUMBER_OF_BITS); + } + + if (next_bits (1)) + { + /* + * Since the NEXT bit is a 1, round UP the mantissa. + * The cunning design of these hidden-1 floats permits + * us to let the mantissa overflow into the exponent, and + * it 'does the right thing'. However, we lose if the + * highest-order bit of the lowest-order word flips. + * Is that clear? + */ + + unsigned long int carry; + + /* + #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) + Please allow at least 1 more bit in carry than is in a LITTLENUM. + We need that extra bit to hold a carry during a LITTLENUM carry + propagation. Another extra bit (kept 0) will assure us that we + don't get a sticky sign bit after shifting right, and that + permits us to propagate the carry without any masking of bits. + #endif + */ + for (carry = 1, lp --; + carry && (lp >= words); + lp --) + { + carry = * lp + carry; + * lp = carry; + carry >>= LITTLENUM_NUMBER_OF_BITS; + } + + if ( (word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)) ) + { + make_invalid_floating_point_number (words); + /* + * We leave return_value alone: admit we read the + * number, but return a floating exception + * because we can't encode the number. + */ + } + } /* if (we needed to round up) */ + } /* if (exponent overflow) */ + } /* if (0.0e0) */ + } /* if (float_type was OK) */ + return (return_value); +} + + +/* JF this used to be in vax.c but this looks like a better place for it */ + +/* + * md_atof() + * + * In: input_line_pointer -> the 1st character of a floating-point + * number. + * 1 letter denoting the type of statement that wants a + * binary floating point number returned. + * Address of where to build floating point literal. + * Assumed to be 'big enough'. + * Address of where to return size of literal (in chars). + * + * Out: Input_line_pointer -> of next char after floating number. + * Error message, or "". + * Floating point literal. + * Number of chars we used for the literal. + */ + +int atof_vax_sizeof(); + +#define MAXIMUM_NUMBER_OF_LITTLENUMS (8) /* For .hfloats. */ + +char * +md_atof (what_statement_type, literalP, sizeP) + char what_statement_type; + char * literalP; + int * sizeP; +{ + LITTLENUM_TYPE words [MAXIMUM_NUMBER_OF_LITTLENUMS]; + register char kind_of_float; + register int number_of_chars; + register LITTLENUM_TYPE * littlenum_pointer; + + switch (what_statement_type) + { + case 'F': /* .float */ + case 'f': /* .ffloat */ + kind_of_float = 'f'; + break; + + case 'D': /* .double */ + case 'd': /* .dfloat */ + kind_of_float = 'd'; + break; + + case 'g': /* .gfloat */ + kind_of_float = 'g'; + break; + + case 'h': /* .hfloat */ + kind_of_float = 'h'; + break; + + default: + kind_of_float = 0; + break; + }; + + if (kind_of_float) + { + register LITTLENUM_TYPE * limit; + char * atof_vax(); + + input_line_pointer = atof_vax (input_line_pointer, + kind_of_float, + words); + /* + * The atof_vax() builds up 16-bit numbers. + * Since the assembler may not be running on + * a little-endian machine, be very careful about + * converting words to chars. + */ + number_of_chars = atof_vax_sizeof (kind_of_float); + know( number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof(LITTLENUM_TYPE) ); + limit = words + (number_of_chars / sizeof(LITTLENUM_TYPE)); + for (littlenum_pointer = words; + littlenum_pointer < limit; + littlenum_pointer ++) + { + md_number_to_chars (literalP, * littlenum_pointer, sizeof(LITTLENUM_TYPE)); + literalP += sizeof(LITTLENUM_TYPE); + }; + } + else + { + number_of_chars = 0; + }; + + * sizeP = number_of_chars; + return (kind_of_float ? "" : "Bad call to md_atof()"); +} /* md_atof() */ + +/* atof_vax.c */ diff --git a/gnu/usr.bin/gas/config/i860-opcode.h b/gnu/usr.bin/gas/config/i860-opcode.h new file mode 100644 index 00000000000..18336da4d32 --- /dev/null +++ b/gnu/usr.bin/gas/config/i860-opcode.h @@ -0,0 +1,491 @@ +/* Table of opcodes for the i860. + 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 i860_opcode +{ + const char *name; + unsigned long int match; /* Bits that must be set. */ + unsigned long int lose; /* Bits that must not be set. */ + const char *args; + /* Nonzero if this is a possible expand-instruction. */ + char expand; +}; + +enum expand_type +{ + E_MOV = 1, E_ADDR, E_U32, E_AND, E_S32, E_DELAY +}; + +/* + All i860 opcodes are 32 bits, except for the pseudoinstructions + and the operations utilizing a 32-bit address expression, an + unsigned 32-bit constant, or a signed 32-bit constant. + These opcodes are expanded into a two-instruction sequence for + any situation where the immediate operand does not fit in 32 bits. + In the case of the add and subtract operations the expansion is + to a three-instruction sequence (ex: orh, or, adds). In cases + where the address is to be relocated, the instruction is + expanded to handle the worse case, this could be optimized at + the final link if the actual address were known. + + The pseudoinstructions are: mov, fmov, pmov, nop, and fnop. + These instructions are implemented as a one or two instruction + sequence of other operations. + + 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: + # Number used by optimizer. It is ignored. + 1 src1 integer register. + 2 src2 integer register. + d dest register. + c ctrlreg control register. + i 16 bit immediate. + I 16 bit immediate, aligned. + 5 5 bit immediate. + l lbroff 26 bit PC relative immediate. + r sbroff 16 bit PC relative immediate. + s split 16 bit immediate. + S split 16 bit immediate, aligned. + e src1 floating point register. + f src2 floating point register. + g dest floating point register. + +*/ + +/* 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 struct i860_opcode i860_opcodes[] = +{ + +/* REG-Format Instructions */ +{ "ld.c", 0x30000000, 0xcc000000, "c,d", 0 }, /* ld.c csrc2,idest */ +{ "ld.b", 0x00000000, 0xfc000000, "1(2),d", 0 }, /* ld.b isrc1(isrc2),idest */ +{ "ld.b", 0x04000000, 0xf8000000, "I(2),d", E_ADDR }, /* ld.b #const(isrc2),idest */ +{ "ld.s", 0x10000000, 0xec000001, "1(2),d", 0 }, /* ld.s isrc1(isrc2),idest */ +{ "ld.s", 0x14000001, 0xe8000000, "I(2),d", E_ADDR }, /* ld.s #const(isrc2),idest */ +{ "ld.l", 0x10000001, 0xec000000, "1(2),d", 0 }, /* ld.l isrc1(isrc2),idest */ +{ "ld.l", 0x14000001, 0xe8000000, "I(2),d", E_ADDR }, /* ld.l #const(isrc2),idest */ + +{ "st.c", 0x38000000, 0xc4000000, "1,c", 0 }, /* st.c isrc1ni,csrc2 */ +{ "st.b", 0x0c000000, 0xf0000000, "1,S(2)", E_ADDR }, /* st.b isrc1ni,#const(isrc2) */ +{ "st.s", 0x1c000000, 0xe0000000, "1,S(2)", E_ADDR }, /* st.s isrc1ni,#const(isrc2) */ +{ "st.l", 0x1c000001, 0xe0000000, "1,S(2)", E_ADDR }, /* st.l isrc1ni,#const(isrc2) */ + +{ "ixfr", 0x08000000, 0xf4000000, "1,g", 0 }, /* ixfr isrc1ni,fdest */ + +{ "fld.l", 0x20000002, 0xdc000001, "1(2),g", 0 }, /* fld.l isrc1(isrc2),fdest */ +{ "fld.l", 0x24000002, 0xd8000001, "i(2),g", E_ADDR }, /* fld.l #const(isrc2),fdest */ +{ "fld.l", 0x20000003, 0xdc000000, "1(2)++,g", 0 }, /* fld.l isrc1(isrc2)++,fdest */ +{ "fld.l", 0x24000003, 0xd8000000, "i(2)++,g", E_ADDR }, /* fld.l #const(isrc2)++,fdest */ +{ "fld.d", 0x20000000, 0xdc000007, "1(2),g", 0 }, /* fld.d isrc1(isrc2),fdest */ +{ "fld.d", 0x24000000, 0xd8000007, "i(2),g", E_ADDR }, /* fld.d #const(isrc2),fdest */ +{ "fld.d", 0x20000001, 0xdc000006, "1(2)++,g", 0 }, /* fld.d isrc1(isrc2)++,fdest */ +{ "fld.d", 0x24000001, 0xd8000006, "i(2)++,g", E_ADDR }, /* fld.d #const(isrc2)++,fdest */ +{ "fld.q", 0x20000004, 0xdc000003, "1(2),g", 0 }, /* fld.q isrc1(isrc2),fdest */ +{ "fld.q", 0x24000004, 0xd8000003, "i(2),g", E_ADDR }, /* fld.q #const(isrc2),fdest */ +{ "fld.q", 0x20000005, 0xdc000002, "1(2)++,g", 0 }, /* fld.q isrc1(isrc2)++,fdest */ +{ "fld.q", 0x24000005, 0xd8000002, "i(2)++,g", E_ADDR }, /* fld.q #const(isrc2)++,fdest */ + +{ "pfld.l", 0x60000000, 0x9c000003, "1(2),g", 0 }, /* pfld.l isrc1(isrc2),fdest */ +{ "pfld.l", 0x64000000, 0x98000003, "i(2),g", E_ADDR }, /* pfld.l #const(isrc2),fdest */ +{ "pfld.l", 0x60000001, 0x9c000002, "1(2)++,g", 0 }, /* pfld.l isrc1(isrc2)++,fdest */ +{ "pfld.l", 0x64000001, 0x98000002, "i(2)++,g", E_ADDR }, /* pfld.l #const(isrc2)++,fdest */ +{ "pfld.d", 0x60000000, 0x9c000007, "1(2),g", 0 }, /* pfld.d isrc1(isrc2),fdest */ +{ "pfld.d", 0x64000000, 0x98000007, "i(2),g", E_ADDR }, /* pfld.d #const(isrc2),fdest */ +{ "pfld.d", 0x60000001, 0x9c000006, "1(2)++,g", 0 }, /* pfld.d isrc1(isrc2)++,fdest */ +{ "pfld.d", 0x64000001, 0x98000006, "i(2)++,g", E_ADDR }, /* pfld.d #const(isrc2)++,fdest */ + +{ "fst.l", 0x28000002, 0xd4000001, "g,1(2)", 0 }, /* fst.l fdest,isrc1(isrc2) */ +{ "fst.l", 0x2c000002, 0xd0000001, "g,i(2)", E_ADDR }, /* fst.l fdest,#const(isrc2) */ +{ "fst.l", 0x28000003, 0xd4000000, "g,1(2)++", 0 }, /* fst.l fdest,isrc1(isrc2)++ */ +{ "fst.l", 0x2c000003, 0xd0000000, "g,i(2)++", E_ADDR }, /* fst.l fdest,#const(isrc2)++ */ +{ "fst.d", 0x28000000, 0xd4000007, "g,1(2)", 0 }, /* fst.d fdest,isrc1(isrc2) */ +{ "fst.d", 0x2c000000, 0xd0000007, "g,i(2)", E_ADDR }, /* fst.d fdest,#const(isrc2) */ +{ "fst.d", 0x28000001, 0xd4000006, "g,1(2)++", 0 }, /* fst.d fdest,isrc1(isrc2)++ */ +{ "fst.d", 0x2c000001, 0xd0000006, "g,i(2)++", E_ADDR }, /* fst.d fdest,#const(isrc2)++ */ + +{ "pst.d", 0x3c000000, 0xc0000007, "g,i(2)", E_ADDR }, /* pst.d fdest,#const(isrc2) */ +{ "pst.d", 0x3c000001, 0xc0000006, "g,i(2)++", E_ADDR }, /* pst.d fdest,#const(isrc2)++ */ + +{ "addu", 0x80000000, 0x7c000000, "1,2,d", 0 }, /* addu isrc1,isrc2,idest */ +{ "addu", 0x84000000, 0x78000000, "i,2,d", E_S32 }, /* addu #const,isrc2,idest */ +{ "adds", 0x90000000, 0x6c000000, "1,2,d", 0 }, /* adds isrc1,isrc2,idest */ +{ "adds", 0x94000000, 0x68000000, "i,2,d", E_S32 }, /* adds #const,isrc2,idest */ +{ "subu", 0x88000000, 0x74000000, "1,2,d", 0 }, /* subu isrc1,isrc2,idest */ +{ "subu", 0x8c000000, 0x70000000, "i,2,d", E_S32 }, /* subu #const,isrc2,idest */ +{ "subs", 0x98000000, 0x64000000, "1,2,d", 0 }, /* subs isrc1,isrc2,idest */ +{ "subs", 0x9c000000, 0x60000000, "i,2,d", E_S32 }, /* subs #const,isrc2,idest */ + +{ "shl", 0xa0000000, 0x5c000000, "1,2,d", 0 }, /* shl isrc1,isrc2,idest */ +{ "shl", 0xa4000000, 0x58000000, "i,2,d", 0 }, /* shl #const,isrc2,idest */ +{ "shr", 0xa8000000, 0x54000000, "1,2,d", 0 }, /* shr isrc1,isrc2,idest */ +{ "shr", 0xac000000, 0x50000000, "i,2,d", 0 }, /* shr #const,isrc2,idest */ +{ "shrd", 0xb0000000, 0x4c000000, "1,2,d", 0 }, /* shrd isrc1,isrc2,idest */ +{ "shra", 0xb8000000, 0x44000000, "1,2,d", 0 }, /* shra isrc1,isrc2,idest */ +{ "shra", 0xbc000000, 0x40000000, "i,2,d", 0 }, /* shra #const,isrc2,idest */ + +{ "mov", 0xa0000000, 0x5c00f800, "2,d", 0 }, /* shl r0,isrc2,idest */ +{ "mov", 0x94000000, 0x69e00000, "i,d", E_MOV }, /* adds #const,r0,idest */ +{ "nop", 0xa0000000, 0x5ffff800, "", 0 }, /* shl r0,r0,r0 */ +{ "fnop", 0xb0000000, 0x4ffff800, "", 0 }, /* shrd r0,r0,r0 */ + +{ "trap", 0x44000000, 0xb8000000, "1,2,d", 0 }, /* trap isrc1ni,isrc2,idest */ + +{ "flush", 0x34000000, 0xc81f0001, "i(2)", E_ADDR }, /* flush #const(isrc2) */ +{ "flush", 0x34000001, 0xc81f0000, "i(2)++", E_ADDR }, /* flush #const(isrc2)++ */ + +{ "and", 0xc0000000, 0x3c000000, "1,2,d", 0 }, /* and isrc1,isrc2,idest */ +{ "and", 0xc4000000, 0x38000000, "i,2,d", E_AND }, /* and #const,isrc2,idest */ +{ "andh", 0xc8000000, 0x34000000, "1,2,d", 0 }, /* andh isrc1,isrc2,idest */ +{ "andh", 0xcc000000, 0x30000000, "i,2,d", 0 }, /* andh #const,isrc2,idest */ +{ "andnot", 0xd0000000, 0x2c000000, "1,2,d", 0 }, /* andnot isrc1,isrc2,idest */ +{ "andnot", 0xd4000000, 0x28000000, "i,2,d", E_U32 }, /* andnot #const,isrc2,idest */ +{ "andnoth", 0xd8000000, 0x24000000, "1,2,d", 0 }, /* andnoth isrc1,isrc2,idest */ +{ "andnoth", 0xdc000000, 0x20000000, "i,2,d", 0 }, /* andnoth #const,isrc2,idest */ +{ "or", 0xe0000000, 0x1c000000, "1,2,d", 0 }, /* or isrc1,isrc2,idest */ +{ "or", 0xe4000000, 0x18000000, "i,2,d", E_U32 }, /* or #const,isrc2,idest */ +{ "orh", 0xe8000000, 0x14000000, "1,2,d", 0 }, /* orh isrc1,isrc2,idest */ +{ "orh", 0xec000000, 0x10000000, "i,2,d", 0 }, /* orh #const,isrc2,idest */ +{ "xor", 0xf0000000, 0x0c000000, "1,2,d", 0 }, /* xor isrc1,isrc2,idest */ +{ "xor", 0xf4000000, 0x08000000, "i,2,d", E_U32 }, /* xor #const,isrc2,idest */ +{ "xorh", 0xf8000000, 0x04000000, "1,2,d", 0 }, /* xorh isrc1,isrc2,idest */ +{ "xorh", 0xfc000000, 0x00000000, "i,2,d", 0 }, /* xorh #const,isrc2,idest */ + +{ "bte", 0x58000000, 0xa4000000, "1,2,s", 0 }, /* bte isrc1s,isrc2,sbroff */ +{ "bte", 0x5c000000, 0xa0000000, "5,2,s", 0 }, /* bte #const5,isrc2,sbroff */ +{ "btne", 0x50000000, 0xac000000, "1,2,s", 0 }, /* btne isrc1s,isrc2,sbroff */ +{ "btne", 0x54000000, 0xa8000000, "5,2,s", 0 }, /* btne #const5,isrc2,sbroff */ +{ "bla", 0xb4000000, 0x48000000, "1,2,s", E_DELAY }, /* bla isrc1s,isrc2,sbroff */ +{ "bri", 0x40000000, 0xbc000000, "1", E_DELAY }, /* bri isrc1ni */ + +/* Core Escape Instruction Format */ +{ "lock", 0x4c000001, 0xb000001e, "", 0 }, /* lock set BL in dirbase */ +{ "calli", 0x4c000002, 0xb000001d, "1", E_DELAY }, /* calli isrc1ni */ +{ "intovr", 0x4c000004, 0xb000001b, "", 0 }, /* intovr trap on integer overflow */ +{ "unlock", 0x4c000007, 0xb0000018, "", 0 }, /* unlock clear BL in dirbase */ + +/* CTRL-Format Instructions */ +{ "br", 0x68000000, 0x94000000, "l", E_DELAY }, /* br lbroff */ +{ "call", 0x6c000000, 0x90000000, "l", E_DELAY }, /* call lbroff */ +{ "bc", 0x70000000, 0x8c000000, "l", 0 }, /* bc lbroff */ +{ "bc.t", 0x74000000, 0x88000000, "l", E_DELAY }, /* bc.t lbroff */ +{ "bnc", 0x78000000, 0x84000000, "l", 0 }, /* bnc lbroff */ +{ "bnc.t", 0x7c000000, 0x80000000, "l", E_DELAY }, /* bnc.t lbroff */ + +/* Floating Point Escape Instruction Format - pfam.p fsrc1,fsrc2,fdest */ +{ "r2p1.ss", 0x48000400, 0xb40003ff, "e,f,g", 0 }, +{ "r2p1.sd", 0x48000480, 0xb400037f, "e,f,g", 0 }, +{ "r2p1.dd", 0x48000580, 0xb400027f, "e,f,g", 0 }, +{ "r2pt.ss", 0x48000401, 0xb40003fe, "e,f,g", 0 }, +{ "r2pt.sd", 0x48000481, 0xb400037e, "e,f,g", 0 }, +{ "r2pt.dd", 0x48000581, 0xb400027e, "e,f,g", 0 }, +{ "r2ap1.ss", 0x48000402, 0xb40003fd, "e,f,g", 0 }, +{ "r2ap1.sd", 0x48000482, 0xb400037d, "e,f,g", 0 }, +{ "r2ap1.dd", 0x48000582, 0xb400027d, "e,f,g", 0 }, +{ "r2apt.ss", 0x48000403, 0xb40003fc, "e,f,g", 0 }, +{ "r2apt.sd", 0x48000483, 0xb400037c, "e,f,g", 0 }, +{ "r2apt.dd", 0x48000583, 0xb400027c, "e,f,g", 0 }, +{ "i2p1.ss", 0x48000404, 0xb40003fb, "e,f,g", 0 }, +{ "i2p1.sd", 0x48000484, 0xb400037b, "e,f,g", 0 }, +{ "i2p1.dd", 0x48000584, 0xb400027b, "e,f,g", 0 }, +{ "i2pt.ss", 0x48000405, 0xb40003fa, "e,f,g", 0 }, +{ "i2pt.sd", 0x48000485, 0xb400037a, "e,f,g", 0 }, +{ "i2pt.dd", 0x48000585, 0xb400027a, "e,f,g", 0 }, +{ "i2ap1.ss", 0x48000406, 0xb40003f9, "e,f,g", 0 }, +{ "i2ap1.sd", 0x48000486, 0xb4000379, "e,f,g", 0 }, +{ "i2ap1.dd", 0x48000586, 0xb4000279, "e,f,g", 0 }, +{ "i2apt.ss", 0x48000407, 0xb40003f8, "e,f,g", 0 }, +{ "i2apt.sd", 0x48000487, 0xb4000378, "e,f,g", 0 }, +{ "i2apt.dd", 0x48000587, 0xb4000278, "e,f,g", 0 }, +{ "rat1p2.ss", 0x48000408, 0xb40003f7, "e,f,g", 0 }, +{ "rat1p2.sd", 0x48000488, 0xb4000377, "e,f,g", 0 }, +{ "rat1p2.dd", 0x48000588, 0xb4000277, "e,f,g", 0 }, +{ "m12apm.ss", 0x48000409, 0xb40003f6, "e,f,g", 0 }, +{ "m12apm.sd", 0x48000489, 0xb4000376, "e,f,g", 0 }, +{ "m12apm.dd", 0x48000589, 0xb4000276, "e,f,g", 0 }, +{ "ra1p2.ss", 0x4800040a, 0xb40003f5, "e,f,g", 0 }, +{ "ra1p2.sd", 0x4800048a, 0xb4000375, "e,f,g", 0 }, +{ "ra1p2.dd", 0x4800058a, 0xb4000275, "e,f,g", 0 }, +{ "m12ttpa.ss", 0x4800040b, 0xb40003f4, "e,f,g", 0 }, +{ "m12ttpa.sd", 0x4800048b, 0xb4000374, "e,f,g", 0 }, +{ "m12ttpa.dd", 0x4800058b, 0xb4000274, "e,f,g", 0 }, +{ "iat1p2.ss", 0x4800040c, 0xb40003f3, "e,f,g", 0 }, +{ "iat1p2.sd", 0x4800048c, 0xb4000373, "e,f,g", 0 }, +{ "iat1p2.dd", 0x4800058c, 0xb4000273, "e,f,g", 0 }, +{ "m12tpm.ss", 0x4800040d, 0xb40003f2, "e,f,g", 0 }, +{ "m12tpm.sd", 0x4800048d, 0xb4000372, "e,f,g", 0 }, +{ "m12tpm.dd", 0x4800058d, 0xb4000272, "e,f,g", 0 }, +{ "ia1p2.ss", 0x4800040e, 0xb40003f1, "e,f,g", 0 }, +{ "ia1p2.sd", 0x4800048e, 0xb4000371, "e,f,g", 0 }, +{ "ia1p2.dd", 0x4800058e, 0xb4000271, "e,f,g", 0 }, +{ "m12tpa.ss", 0x4800040f, 0xb40003f0, "e,f,g", 0 }, +{ "m12tpa.sd", 0x4800048f, 0xb4000370, "e,f,g", 0 }, +{ "m12tpa.dd", 0x4800058f, 0xb4000270, "e,f,g", 0 }, + +/* Floating Point Escape Instruction Format - pfsm.p fsrc1,fsrc2,fdest */ +{ "r2s1.ss", 0x48000410, 0xb40003ef, "e,f,g", 0 }, +{ "r2s1.sd", 0x48000490, 0xb400036f, "e,f,g", 0 }, +{ "r2s1.dd", 0x48000590, 0xb400026f, "e,f,g", 0 }, +{ "r2st.ss", 0x48000411, 0xb40003ee, "e,f,g", 0 }, +{ "r2st.sd", 0x48000491, 0xb400036e, "e,f,g", 0 }, +{ "r2st.dd", 0x48000591, 0xb400026e, "e,f,g", 0 }, +{ "r2as1.ss", 0x48000412, 0xb40003ed, "e,f,g", 0 }, +{ "r2as1.sd", 0x48000492, 0xb400036d, "e,f,g", 0 }, +{ "r2as1.dd", 0x48000592, 0xb400026d, "e,f,g", 0 }, +{ "r2ast.ss", 0x48000413, 0xb40003ec, "e,f,g", 0 }, +{ "r2ast.sd", 0x48000493, 0xb400036c, "e,f,g", 0 }, +{ "r2ast.dd", 0x48000593, 0xb400026c, "e,f,g", 0 }, +{ "i2s1.ss", 0x48000414, 0xb40003eb, "e,f,g", 0 }, +{ "i2s1.sd", 0x48000494, 0xb400036b, "e,f,g", 0 }, +{ "i2s1.dd", 0x48000594, 0xb400026b, "e,f,g", 0 }, +{ "i2st.ss", 0x48000415, 0xb40003ea, "e,f,g", 0 }, +{ "i2st.sd", 0x48000495, 0xb400036a, "e,f,g", 0 }, +{ "i2st.dd", 0x48000595, 0xb400026a, "e,f,g", 0 }, +{ "i2as1.ss", 0x48000416, 0xb40003e9, "e,f,g", 0 }, +{ "i2as1.sd", 0x48000496, 0xb4000369, "e,f,g", 0 }, +{ "i2as1.dd", 0x48000596, 0xb4000269, "e,f,g", 0 }, +{ "i2ast.ss", 0x48000417, 0xb40003e8, "e,f,g", 0 }, +{ "i2ast.sd", 0x48000497, 0xb4000368, "e,f,g", 0 }, +{ "i2ast.dd", 0x48000597, 0xb4000268, "e,f,g", 0 }, +{ "rat1s2.ss", 0x48000418, 0xb40003e7, "e,f,g", 0 }, +{ "rat1s2.sd", 0x48000498, 0xb4000367, "e,f,g", 0 }, +{ "rat1s2.dd", 0x48000598, 0xb4000267, "e,f,g", 0 }, +{ "m12asm.ss", 0x48000419, 0xb40003e6, "e,f,g", 0 }, +{ "m12asm.sd", 0x48000499, 0xb4000366, "e,f,g", 0 }, +{ "m12asm.dd", 0x48000599, 0xb4000266, "e,f,g", 0 }, +{ "ra1s2.ss", 0x4800041a, 0xb40003e5, "e,f,g", 0 }, +{ "ra1s2.sd", 0x4800049a, 0xb4000365, "e,f,g", 0 }, +{ "ra1s2.dd", 0x4800059a, 0xb4000265, "e,f,g", 0 }, +{ "m12ttsa.ss", 0x4800041b, 0xb40003e4, "e,f,g", 0 }, +{ "m12ttsa.sd", 0x4800049b, 0xb4000364, "e,f,g", 0 }, +{ "m12ttsa.dd", 0x4800059b, 0xb4000264, "e,f,g", 0 }, +{ "iat1s2.ss", 0x4800041c, 0xb40003e3, "e,f,g", 0 }, +{ "iat1s2.sd", 0x4800049c, 0xb4000363, "e,f,g", 0 }, +{ "iat1s2.dd", 0x4800059c, 0xb4000263, "e,f,g", 0 }, +{ "m12tsm.ss", 0x4800041d, 0xb40003e2, "e,f,g", 0 }, +{ "m12tsm.sd", 0x4800049d, 0xb4000362, "e,f,g", 0 }, +{ "m12tsm.dd", 0x4800059d, 0xb4000262, "e,f,g", 0 }, +{ "ia1s2.ss", 0x4800041e, 0xb40003e1, "e,f,g", 0 }, +{ "ia1s2.sd", 0x4800049e, 0xb4000361, "e,f,g", 0 }, +{ "ia1s2.dd", 0x4800059e, 0xb4000261, "e,f,g", 0 }, +{ "m12tsa.ss", 0x4800041f, 0xb40003e0, "e,f,g", 0 }, +{ "m12tsa.sd", 0x4800049f, 0xb4000360, "e,f,g", 0 }, +{ "m12tsa.dd", 0x4800059f, 0xb4000260, "e,f,g", 0 }, + +/* Floating Point Escape Instruction Format - pfmam.p fsrc1,fsrc2,fdest */ +{ "mr2p1.ss", 0x48000000, 0xb40007ff, "e,f,g", 0 }, +{ "mr2p1.sd", 0x48000080, 0xb400077f, "e,f,g", 0 }, +{ "mr2p1.dd", 0x48000180, 0xb400067f, "e,f,g", 0 }, +{ "mr2pt.ss", 0x48000001, 0xb40007fe, "e,f,g", 0 }, +{ "mr2pt.sd", 0x48000081, 0xb400077e, "e,f,g", 0 }, +{ "mr2pt.dd", 0x48000181, 0xb400067e, "e,f,g", 0 }, +{ "mr2mp1.ss", 0x48000002, 0xb40007fd, "e,f,g", 0 }, +{ "mr2mp1.sd", 0x48000082, 0xb400077d, "e,f,g", 0 }, +{ "mr2mp1.dd", 0x48000182, 0xb400067d, "e,f,g", 0 }, +{ "mr2mpt.ss", 0x48000003, 0xb40007fc, "e,f,g", 0 }, +{ "mr2mpt.sd", 0x48000083, 0xb400077c, "e,f,g", 0 }, +{ "mr2mpt.dd", 0x48000183, 0xb400067c, "e,f,g", 0 }, +{ "mi2p1.ss", 0x48000004, 0xb40007fb, "e,f,g", 0 }, +{ "mi2p1.sd", 0x48000084, 0xb400077b, "e,f,g", 0 }, +{ "mi2p1.dd", 0x48000184, 0xb400067b, "e,f,g", 0 }, +{ "mi2pt.ss", 0x48000005, 0xb40007fa, "e,f,g", 0 }, +{ "mi2pt.sd", 0x48000085, 0xb400077a, "e,f,g", 0 }, +{ "mi2pt.dd", 0x48000185, 0xb400067a, "e,f,g", 0 }, +{ "mi2mp1.ss", 0x48000006, 0xb40007f9, "e,f,g", 0 }, +{ "mi2mp1.sd", 0x48000086, 0xb4000779, "e,f,g", 0 }, +{ "mi2mp1.dd", 0x48000186, 0xb4000679, "e,f,g", 0 }, +{ "mi2mpt.ss", 0x48000007, 0xb40007f8, "e,f,g", 0 }, +{ "mi2mpt.sd", 0x48000087, 0xb4000778, "e,f,g", 0 }, +{ "mi2mpt.dd", 0x48000187, 0xb4000678, "e,f,g", 0 }, +{ "mrmt1p2.ss", 0x48000008, 0xb40007f7, "e,f,g", 0 }, +{ "mrmt1p2.sd", 0x48000088, 0xb4000777, "e,f,g", 0 }, +{ "mrmt1p2.dd", 0x48000188, 0xb4000677, "e,f,g", 0 }, +{ "mm12mpm.ss", 0x48000009, 0xb40007f6, "e,f,g", 0 }, +{ "mm12mpm.sd", 0x48000089, 0xb4000776, "e,f,g", 0 }, +{ "mm12mpm.dd", 0x48000189, 0xb4000676, "e,f,g", 0 }, +{ "mrm1p2.ss", 0x4800000a, 0xb40007f5, "e,f,g", 0 }, +{ "mrm1p2.sd", 0x4800008a, 0xb4000775, "e,f,g", 0 }, +{ "mrm1p2.dd", 0x4800018a, 0xb4000675, "e,f,g", 0 }, +{ "mm12ttpm.ss",0x4800000b, 0xb40007f4, "e,f,g", 0 }, +{ "mm12ttpm.sd",0x4800008b, 0xb4000774, "e,f,g", 0 }, +{ "mm12ttpm.dd",0x4800018b, 0xb4000674, "e,f,g", 0 }, +{ "mimt1p2.ss", 0x4800000c, 0xb40007f3, "e,f,g", 0 }, +{ "mimt1p2.sd", 0x4800008c, 0xb4000773, "e,f,g", 0 }, +{ "mimt1p2.dd", 0x4800018c, 0xb4000673, "e,f,g", 0 }, +{ "mm12tpm.ss", 0x4800000d, 0xb40007f2, "e,f,g", 0 }, +{ "mm12tpm.sd", 0x4800008d, 0xb4000772, "e,f,g", 0 }, +{ "mm12tpm.dd", 0x4800018d, 0xb4000672, "e,f,g", 0 }, +{ "mim1p2.ss", 0x4800000e, 0xb40007f1, "e,f,g", 0 }, +{ "mim1p2.sd", 0x4800008e, 0xb4000771, "e,f,g", 0 }, +{ "mim1p2.dd", 0x4800018e, 0xb4000671, "e,f,g", 0 }, + +/* Floating Point Escape Instruction Format - pfmsm.p fsrc1,fsrc2,fdest */ +{ "mr2s1.ss", 0x48000010, 0xb40007ef, "e,f,g", 0 }, +{ "mr2s1.sd", 0x48000090, 0xb400076f, "e,f,g", 0 }, +{ "mr2s1.dd", 0x48000190, 0xb400066f, "e,f,g", 0 }, +{ "mr2st.ss", 0x48000011, 0xb40007ee, "e,f,g", 0 }, +{ "mr2st.sd", 0x48000091, 0xb400076e, "e,f,g", 0 }, +{ "mr2st.dd", 0x48000191, 0xb400066e, "e,f,g", 0 }, +{ "mr2ms1.ss", 0x48000012, 0xb40007ed, "e,f,g", 0 }, +{ "mr2ms1.sd", 0x48000092, 0xb400076d, "e,f,g", 0 }, +{ "mr2ms1.dd", 0x48000192, 0xb400066d, "e,f,g", 0 }, +{ "mr2mst.ss", 0x48000013, 0xb40007ec, "e,f,g", 0 }, +{ "mr2mst.sd", 0x48000093, 0xb400076c, "e,f,g", 0 }, +{ "mr2mst.dd", 0x48000193, 0xb400066c, "e,f,g", 0 }, +{ "mi2s1.ss", 0x48000014, 0xb40007eb, "e,f,g", 0 }, +{ "mi2s1.sd", 0x48000094, 0xb400076b, "e,f,g", 0 }, +{ "mi2s1.dd", 0x48000194, 0xb400066b, "e,f,g", 0 }, +{ "mi2st.ss", 0x48000015, 0xb40007ea, "e,f,g", 0 }, +{ "mi2st.sd", 0x48000095, 0xb400076a, "e,f,g", 0 }, +{ "mi2st.dd", 0x48000195, 0xb400066a, "e,f,g", 0 }, +{ "mi2ms1.ss", 0x48000016, 0xb40007e9, "e,f,g", 0 }, +{ "mi2ms1.sd", 0x48000096, 0xb4000769, "e,f,g", 0 }, +{ "mi2ms1.dd", 0x48000196, 0xb4000669, "e,f,g", 0 }, +{ "mi2mst.ss", 0x48000017, 0xb40007e8, "e,f,g", 0 }, +{ "mi2mst.sd", 0x48000097, 0xb4000768, "e,f,g", 0 }, +{ "mi2mst.dd", 0x48000197, 0xb4000668, "e,f,g", 0 }, +{ "mrmt1s2.ss", 0x48000018, 0xb40007e7, "e,f,g", 0 }, +{ "mrmt1s2.sd", 0x48000098, 0xb4000767, "e,f,g", 0 }, +{ "mrmt1s2.dd", 0x48000198, 0xb4000667, "e,f,g", 0 }, +{ "mm12msm.ss", 0x48000019, 0xb40007e6, "e,f,g", 0 }, +{ "mm12msm.sd", 0x48000099, 0xb4000766, "e,f,g", 0 }, +{ "mm12msm.dd", 0x48000199, 0xb4000666, "e,f,g", 0 }, +{ "mrm1s2.ss", 0x4800001a, 0xb40007e5, "e,f,g", 0 }, +{ "mrm1s2.sd", 0x4800009a, 0xb4000765, "e,f,g", 0 }, +{ "mrm1s2.dd", 0x4800019a, 0xb4000665, "e,f,g", 0 }, +{ "mm12ttsm.ss",0x4800001b, 0xb40007e4, "e,f,g", 0 }, +{ "mm12ttsm.sd",0x4800009b, 0xb4000764, "e,f,g", 0 }, +{ "mm12ttsm.dd",0x4800019b, 0xb4000664, "e,f,g", 0 }, +{ "mimt1s2.ss", 0x4800001c, 0xb40007e3, "e,f,g", 0 }, +{ "mimt1s2.sd", 0x4800009c, 0xb4000763, "e,f,g", 0 }, +{ "mimt1s2.dd", 0x4800019c, 0xb4000663, "e,f,g", 0 }, +{ "mm12tsm.ss", 0x4800001d, 0xb40007e2, "e,f,g", 0 }, +{ "mm12tsm.sd", 0x4800009d, 0xb4000762, "e,f,g", 0 }, +{ "mm12tsm.dd", 0x4800019d, 0xb4000662, "e,f,g", 0 }, +{ "mim1s2.ss", 0x4800001e, 0xb40007e1, "e,f,g", 0 }, +{ "mim1s2.sd", 0x4800009e, 0xb4000761, "e,f,g", 0 }, +{ "mim1s2.dd", 0x4800019e, 0xb4000661, "e,f,g", 0 }, + + +{ "fmul.ss", 0x48000020, 0xb40007df, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */ +{ "fmul.sd", 0x480000a0, 0xb400075f, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */ +{ "fmul.dd", 0x480001a0, 0xb400065f, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */ +{ "pfmul.ss", 0x48000420, 0xb40003df, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */ +{ "pfmul.sd", 0x480004a0, 0xb400035f, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */ +{ "pfmul.dd", 0x480005a0, 0xb400025f, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */ +{ "pfmul3.dd", 0x480005a4, 0xb400025b, "e,f,g", 0 }, /* pfmul3.p fsrc1,fsrc2,fdest */ +{ "fmlow.dd", 0x480001a1, 0xb400065e, "e,f,g", 0 }, /* fmlow.dd fsrc1,fsrc2,fdest */ +{ "frcp.ss", 0x48000022, 0xb40007dd, "f,g", 0 }, /* frcp.p fsrc2,fdest */ +{ "frcp.sd", 0x480000a2, 0xb400075d, "f,g", 0 }, /* frcp.p fsrc2,fdest */ +{ "frcp.dd", 0x480001a2, 0xb400065d, "f,g", 0 }, /* frcp.p fsrc2,fdest */ +{ "frsqr.ss", 0x48000023, 0xb40007dc, "f,g", 0 }, /* frsqr.p fsrc2,fdest */ +{ "frsqr.sd", 0x480000a3, 0xb400075c, "f,g", 0 }, /* frsqr.p fsrc2,fdest */ +{ "frsqr.dd", 0x480001a3, 0xb400065c, "f,g", 0 }, /* frsqr.p fsrc2,fdest */ +{ "fadd.ss", 0x48000030, 0xb40007cf, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */ +{ "fadd.sd", 0x480000b0, 0xb400074f, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */ +{ "fadd.dd", 0x480001b0, 0xb400064f, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */ +{ "pfadd.ss", 0x48000430, 0xb40003cf, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */ +{ "pfadd.sd", 0x480004b0, 0xb400034f, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */ +{ "pfadd.dd", 0x480005b0, 0xb400024f, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */ +{ "fsub.ss", 0x48000031, 0xb40007ce, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */ +{ "fsub.sd", 0x480000b1, 0xb400074e, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */ +{ "fsub.dd", 0x480001b1, 0xb400064e, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */ +{ "pfsub.ss", 0x48000431, 0xb40003ce, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */ +{ "pfsub.sd", 0x480004b1, 0xb400034e, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */ +{ "pfsub.dd", 0x480005b1, 0xb400024e, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */ +{ "fix.ss", 0x48000032, 0xb40007cd, "e,g", 0 }, /* fix.p fsrc1,fdest */ +{ "fix.sd", 0x480000b2, 0xb400074d, "e,g", 0 }, /* fix.p fsrc1,fdest */ +{ "fix.dd", 0x480001b2, 0xb400064d, "e,g", 0 }, /* fix.p fsrc1,fdest */ +{ "pfix.ss", 0x48000432, 0xb40003cd, "e,g", 0 }, /* pfix.p fsrc1,fdest */ +{ "pfix.sd", 0x480004b2, 0xb400034d, "e,g", 0 }, /* pfix.p fsrc1,fdest */ +{ "pfix.dd", 0x480005b2, 0xb400024d, "e,g", 0 }, /* pfix.p fsrc1,fdest */ +{ "famov.ss", 0x48000033, 0xb40007cc, "e,g", 0 }, /* famov.p fsrc1,fdest */ +{ "famov.ds", 0x48000133, 0xb40006cc, "e,g", 0 }, /* famov.p fsrc1,fdest */ +{ "famov.sd", 0x480000b3, 0xb400074c, "e,g", 0 }, /* famov.p fsrc1,fdest */ +{ "famov.dd", 0x480001b3, 0xb400064c, "e,g", 0 }, /* famov.p fsrc1,fdest */ +{ "pfamov.ss", 0x48000433, 0xb40003cc, "e,g", 0 }, /* pfamov.p fsrc1,fdest */ +{ "pfamov.ds", 0x48000533, 0xb40002cc, "e,g", 0 }, /* pfamov.p fsrc1,fdest */ +{ "pfamov.sd", 0x480004b3, 0xb400034c, "e,g", 0 }, /* pfamov.p fsrc1,fdest */ +{ "pfamov.dd", 0x480005b3, 0xb400024c, "e,g", 0 }, /* pfamov.p fsrc1,fdest */ +/* pfgt has R bit cleared; pfle has R bit set */ +{ "pfgt.ss", 0x48000434, 0xb40003cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */ +{ "pfgt.sd", 0x48000434, 0xb40003cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */ +{ "pfgt.dd", 0x48000534, 0xb40002cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */ +/* pfgt has R bit cleared; pfle has R bit set */ +{ "pfle.ss", 0x480004b4, 0xb400034b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */ +{ "pfle.sd", 0x480004b4, 0xb400034b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */ +{ "pfle.dd", 0x480005b4, 0xb400024b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */ +{ "ftrunc.ss", 0x4800003a, 0xb40007c5, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */ +{ "ftrunc.sd", 0x480000ba, 0xb4000745, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */ +{ "ftrunc.dd", 0x480001ba, 0xb4000645, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */ +{ "pftrunc.ss", 0x4800043a, 0xb40003c5, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */ +{ "pftrunc.sd", 0x480004ba, 0xb4000345, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */ +{ "pftrunc.dd", 0x480005ba, 0xb4000245, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */ +{ "fxfr", 0x48000040, 0xb40007bf, "e,d", 0 }, /* fxfr fsrc1,idest */ +{ "fiadd.ss", 0x48000049, 0xb40007b6, "e,f,g", 0 }, /* fiadd.w fsrc1,fsrc2,fdest */ +{ "fiadd.dd", 0x480001c9, 0xb4000636, "e,f,g", 0 }, /* fiadd.w fsrc1,fsrc2,fdest */ +{ "pfiadd.ss", 0x48000449, 0xb40003b6, "e,f,g", 0 }, /* pfiadd.w fsrc1,fsrc2,fdest */ +{ "pfiadd.dd", 0x480005c9, 0xb4000236, "e,f,g", 0 }, /* pfiadd.w fsrc1,fsrc2,fdest */ +{ "fisub.ss", 0x4800004d, 0xb40007b2, "e,f,g", 0 }, /* fisub.w fsrc1,fsrc2,fdest */ +{ "fisub.dd", 0x480001cd, 0xb4000632, "e,f,g", 0 }, /* fisub.w fsrc1,fsrc2,fdest */ +{ "pfisub.ss", 0x4800044d, 0xb40003b2, "e,f,g", 0 }, /* pfisub.w fsrc1,fsrc2,fdest */ +{ "pfisub.dd", 0x480005cd, 0xb4000232, "e,f,g", 0 }, /* pfisub.w fsrc1,fsrc2,fdest */ +{ "fzchkl", 0x48000057, 0xb40007a8, "e,f,g", 0 }, /* fzchkl fsrc1,fsrc2,fdest */ +{ "pfzchkl", 0x48000457, 0xb40003a8, "e,f,g", 0 }, /* pfzchkl fsrc1,fsrc2,fdest */ +{ "fzchks", 0x4800005f, 0xb40007a0, "e,f,g", 0 }, /* fzchks fsrc1,fsrc2,fdest */ +{ "pfzchks", 0x4800045f, 0xb40003a0, "e,f,g", 0 }, /* pfzchks fsrc1,fsrc2,fdest */ +{ "faddp", 0x48000050, 0xb40007af, "e,f,g", 0 }, /* faddp fsrc1,fsrc2,fdest */ +{ "pfaddp", 0x48000450, 0xb40003af, "e,f,g", 0 }, /* pfaddp fsrc1,fsrc2,fdest */ +{ "faddz", 0x48000051, 0xb40007ae, "e,f,g", 0 }, /* faddz fsrc1,fsrc2,fdest */ +{ "pfaddz", 0x48000451, 0xb40003ae, "e,f,g", 0 }, /* pfaddz fsrc1,fsrc2,fdest */ +{ "form", 0x4800005a, 0xb40007a5, "e,g", 0 }, /* form fsrc1,fdest */ +{ "pform", 0x4800045a, 0xb40003a5, "e,g", 0 }, /* pform fsrc1,fdest */ + +/* Floating point pseudo-instructions */ +{ "fmov.ss", 0x48000049, 0xb7e007b6, "e,g", 0 }, /* fiadd.ss fsrc1,f0,fdest */ +{ "fmov.dd", 0x480001c9, 0xb7e00636, "e,g", 0 }, /* fiadd.dd fsrc1,f0,fdest */ +{ "fmov.sd", 0x480000b0, 0xb7e0074f, "e,g", 0 }, /* fadd.sd fsrc1,f0,fdest */ +{ "fmov.ds", 0x48000130, 0xb7e006cf, "e,g", 0 }, /* fadd.ds fsrc1,f0,fdest */ +{ "pfmov.ds", 0x48000530, 0xb73002cf, "e,g", 0 }, /* pfadd.ds fsrc1,f0,fdest */ +{ "pfmov.dd", 0x480005c9, 0xb7e00236, "e,g", 0 }, /* pfiadd.dd fsrc1,f0,fdest */ + + +}; + +#define NUMOPCODES ((sizeof i860_opcodes)/(sizeof i860_opcodes[0])) + + diff --git a/gnu/usr.bin/gas/config/i860.c b/gnu/usr.bin/gas/config/i860.c new file mode 100644 index 00000000000..96669435698 --- /dev/null +++ b/gnu/usr.bin/gas/config/i860.c @@ -0,0 +1,1142 @@ +/* i860.c -- Assemble for the I860 + Copyright (C) 1989 Free Software Foundation, Inc. + +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 1, 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. */ + + +#include <stdio.h> +#include <ctype.h> + +#include "i860-opcode.h" +#include "as.h" +#include "frags.h" +#include "struc-symbol.h" +#include "flonum.h" +#include "expr.h" +#include "hash.h" +#include "md.h" +#include "i860.h" /* position dependent redefine */ +#include "write.h" +#include "read.h" +#include "symbols.h" + +void md_begin(); +void md_end(); +void md_number_to_chars(); +void md_assemble(); +char *md_atof(); +void md_convert_frag(); +void md_create_short_jump(); +void md_create_long_jump(); +int md_estimate_size_before_relax(); +void md_number_to_imm(); +void md_number_to_disp(); +void md_number_to_field(); +void md_ri_to_chars(); +static void i860_ip(); +void emit_relocations(); + +const relax_typeS md_relax_table[] = { 0 }; + +/* handle of the OPCODE hash table */ +static struct hash_control *op_hash = NULL; + +static void s_dual(), s_enddual(); +static void s_atmp(); + +const pseudo_typeS +md_pseudo_table[] = { + { "dual", s_dual, 4 }, + { "enddual", s_enddual, 4 }, + { "atmp", s_atmp, 4 }, + { NULL, 0, 0 }, +}; + +int md_short_jump_size = 4; +int md_long_jump_size = 4; +int omagic = OMAGIC; /* Magic number for header */ + +/* This array holds the chars that always start a comment. If the + pre-processor is disabled, these aren't very useful */ +char comment_chars[] = "!/"; /* JF removed '|' from 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 */ +char line_comment_chars[] = "#/"; + +/* Chars that can be used to separate mant from exp in floating point nums */ +char EXP_CHARS[] = "eE"; + +/* 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. + */ +int size_reloc_info = sizeof(struct relocation_info); + +static unsigned char octal[256]; +#define isoctal(c) octal[c] +static unsigned char toHex[256]; + +struct i860_it { + char *error; + unsigned long opcode; + struct nlist *nlistp; + expressionS exp; + int pcrel; + enum expand_type expand; + enum highlow_type highlow; + enum reloc_type reloc; +} the_insn; + +#ifdef __STDC__ +static void print_insn(struct i860_it *insn); +static int getExpression(char *str); +#else +static void print_insn(); +static int getExpression(); +#endif +static char *expr_end; +static char last_expand; /* error if expansion after branch */ + +enum dual +{ + DUAL_OFF = 0, DUAL_ON, DUAL_DDOT, DUAL_ONDDOT, +}; +static enum dual dual_mode = DUAL_OFF; /* dual-instruction mode */ + +static void +s_dual() /* floating point instructions have dual set */ +{ + dual_mode = DUAL_ON; +} + +static void +s_enddual() /* floating point instructions have dual set */ +{ + dual_mode = DUAL_OFF; +} + +static int atmp = 31; /* temporary register for pseudo's */ + +static void +s_atmp() +{ + register int temp; + if (strncmp(input_line_pointer, "sp", 2) == 0) { + input_line_pointer += 2; + atmp = 2; + } + else if (strncmp(input_line_pointer, "fp", 2) == 0) { + input_line_pointer += 2; + atmp = 3; + } + else if (strncmp(input_line_pointer, "r", 1) == 0) { + input_line_pointer += 1; + temp = get_absolute_expression(); + if (temp >= 0 && temp <= 31) + atmp = temp; + else + as_warn("Unknown temporary pseudo register"); + } + else { + as_warn("Unknown temporary pseudo register"); + } + demand_empty_rest_of_line(); + return; +} + +/* 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() +{ + register char *retval = NULL; + int lose = 0; + register unsigned int i = 0; + + op_hash = hash_new(); + if (op_hash == NULL) + as_fatal("Virtual memory exhausted"); + + while (i < NUMOPCODES) + { + const char *name = i860_opcodes[i].name; + retval = hash_insert(op_hash, name, &i860_opcodes[i]); + if(retval != NULL && *retval != '\0') + { + fprintf (stderr, "internal error: can't hash `%s': %s\n", + i860_opcodes[i].name, retval); + lose = 1; + } + do + { + if (i860_opcodes[i].match & i860_opcodes[i].lose) + { + fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n", + i860_opcodes[i].name, i860_opcodes[i].args); + lose = 1; + } + ++i; + } while (i < NUMOPCODES + && !strcmp(i860_opcodes[i].name, name)); + } + + if (lose) + as_fatal ("Broken assembler. No assembly attempted."); + + for (i = '0'; i < '8'; ++i) + octal[i] = 1; + for (i = '0'; i <= '9'; ++i) + toHex[i] = i - '0'; + for (i = 'a'; i <= 'f'; ++i) + toHex[i] = i + 10 - 'a'; + for (i = 'A'; i <= 'F'; ++i) + toHex[i] = i + 10 - 'A'; +} + +void +md_end() +{ + return; +} + +void +md_assemble(str) + char *str; +{ + char *toP; + int rsd; + int no_opcodes = 1; + int i; + struct i860_it pseudo[3]; + + assert(str); + i860_ip(str); + + /* check for expandable flag to produce pseudo-instructions */ + if (the_insn.expand != 0 && the_insn.highlow == NO_SPEC) { + for (i = 0; i < 3; i++) + pseudo[i] = the_insn; + + switch (the_insn.expand) { + + case E_DELAY: + no_opcodes = 1; + break; + + case E_MOV: + if (the_insn.exp.X_add_symbol == NULL && + the_insn.exp.X_subtract_symbol == NULL && + (the_insn.exp.X_add_number < (1 << 15) && + the_insn.exp.X_add_number >= -(1 << 15))) + break; + /* or l%const,r0,ireg_dest */ + pseudo[0].opcode = (the_insn.opcode & 0x001f0000) | 0xe4000000; + pseudo[0].highlow = PAIR; + /* orh h%const,ireg_dest,ireg_dest */ + pseudo[1].opcode = (the_insn.opcode & 0x03ffffff) | 0xec000000 | + ((the_insn.opcode & 0x001f0000) << 5); + pseudo[1].highlow = HIGH; + no_opcodes = 2; + break; + + case E_ADDR: + if (the_insn.exp.X_add_symbol == NULL && + the_insn.exp.X_subtract_symbol == NULL) + break; + /* orh ha%addr_expr,r0,r31 */ + pseudo[0].opcode = 0xec000000 | (atmp<<16); + pseudo[0].highlow = HIGHADJ; + pseudo[0].reloc = LOW0; /* must overwrite */ + /* l%addr_expr(r31),ireg_dest */ + pseudo[1].opcode = (the_insn.opcode & ~0x003e0000) | (atmp << 21); + pseudo[1].highlow = PAIR; + no_opcodes = 2; + break; + + case E_U32: /* 2nd version emulates Intel as, not doc. */ + if (the_insn.exp.X_add_symbol == NULL && + the_insn.exp.X_subtract_symbol == NULL && + (the_insn.exp.X_add_number < (1 << 16) && + the_insn.exp.X_add_number >= 0)) + break; + /* $(opcode)h h%const,ireg_src2,ireg_dest + pseudo[0].opcode = (the_insn.opcode & 0xf3ffffff) | 0x0c000000; */ + /* $(opcode)h h%const,ireg_src2,r31 */ + pseudo[0].opcode = (the_insn.opcode & 0xf3e0ffff) | 0x0c000000 | + (atmp << 16); + pseudo[0].highlow = HIGH; + /* $(opcode) l%const,ireg_dest,ireg_dest + pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 | + ((the_insn.opcode & 0x001f0000) << 5); */ + /* $(opcode) l%const,r31,ireg_dest */ + pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 | + (atmp << 21); + pseudo[1].highlow = PAIR; + no_opcodes = 2; + break; + + case E_AND: /* 2nd version emulates Intel as, not doc. */ + if (the_insn.exp.X_add_symbol == NULL && + the_insn.exp.X_subtract_symbol == NULL && + (the_insn.exp.X_add_number < (1 << 16) && + the_insn.exp.X_add_number >= 0)) + break; + /* andnot h%const,ireg_src2,ireg_dest + pseudo[0].opcode = (the_insn.opcode & 0x03ffffff) | 0xd4000000; */ + /* andnot h%const,ireg_src2,r31 */ + pseudo[0].opcode = (the_insn.opcode & 0x03e0ffff) | 0xd4000000 | + (atmp << 16); + pseudo[0].highlow = HIGH; + pseudo[0].exp.X_add_number = -1 - the_insn.exp.X_add_number; + /* andnot l%const,ireg_dest,ireg_dest + pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 | + ((the_insn.opcode & 0x001f0000) << 5); */ + /* andnot l%const,r31,ireg_dest */ + pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 | + (atmp << 21); + pseudo[1].highlow = PAIR; + pseudo[1].exp.X_add_number = -1 - the_insn.exp.X_add_number; + no_opcodes = 2; + break; + + case E_S32: + if (the_insn.exp.X_add_symbol == NULL && + the_insn.exp.X_subtract_symbol == NULL && + (the_insn.exp.X_add_number < (1 << 15) && + the_insn.exp.X_add_number >= -(1 << 15))) + break; + /* orh h%const,r0,r31 */ + pseudo[0].opcode = 0xec000000 | (atmp << 16); + pseudo[0].highlow = HIGH; + /* or l%const,r31,r31 */ + pseudo[1].opcode = 0xe4000000 | (atmp << 21) | (atmp << 16); + pseudo[1].highlow = PAIR; + /* r31,ireg_src2,ireg_dest */ + pseudo[2].opcode = (the_insn.opcode & ~0x0400ffff) | (atmp << 11); + pseudo[2].reloc = NO_RELOC; + no_opcodes = 3; + break; + + default: + abort(); + } + + the_insn = pseudo[0]; + /* check for expanded opcode after branch or in dual */ + if (no_opcodes > 1 && last_expand == TRUE) + as_warn("Expanded opcode after delayed branch: `%s'", str); + if (no_opcodes > 1 && dual_mode != DUAL_OFF) + as_warn("Expanded opcode in dual mode: `%s'", str); + } + + i = 0; + do { /* always produce at least one opcode */ + toP = frag_more(4); + /* put out the opcode */ + md_number_to_chars(toP, the_insn.opcode, 4); + + /* check for expanded opcode after branch or in dual */ + last_expand = the_insn.pcrel; + + /* put out the symbol-dependent stuff */ + if (the_insn.reloc != NO_RELOC) { + fix_new( + frag_now, /* which frag */ + (toP - frag_now->fr_literal), /* where */ + 4, /* size */ + the_insn.exp.X_add_symbol, + the_insn.exp.X_subtract_symbol, + the_insn.exp.X_add_number, + the_insn.pcrel, + /* merge bit fields into one argument */ + (int)(((the_insn.highlow & 0x3) << 4) | (the_insn.reloc & 0xf)) + ); + } + the_insn = pseudo[++i]; + } while (--no_opcodes > 0); + +} + +static void +i860_ip(str) + char *str; +{ + char *s; + const char *args; + char c; + unsigned long i; + struct i860_opcode *insn; + char *argsStart; + unsigned long opcode; + unsigned int mask; + int match = FALSE; + int comma = 0; + + + for (s = str; islower(*s) || *s == '.' || *s == '3'; ++s) + ; + switch (*s) { + + case '\0': + break; + + case ',': + comma = 1; + + /*FALLTHROUGH*/ + + case ' ': + *s++ = '\0'; + break; + + default: + as_warn("Unknown opcode: `%s'", str); + exit(1); + } + + if (strncmp(str, "d.", 2) == 0) { /* check for d. opcode prefix */ + if (dual_mode == DUAL_ON) + dual_mode = DUAL_ONDDOT; + else + dual_mode = DUAL_DDOT; + str += 2; + } + + if ((insn = (struct i860_opcode *) hash_find(op_hash, str)) == NULL) { + if (dual_mode == DUAL_DDOT || dual_mode == DUAL_ONDDOT) + str -= 2; + as_warn("Unknown opcode: `%s'", str); + return; + } + if (comma) { + *--s = ','; + } + argsStart = s; + for (;;) { + opcode = insn->match; + bzero(&the_insn, sizeof(the_insn)); + the_insn.reloc = NO_RELOC; + + /* + * Build the opcode, checking as we go to make + * sure that the operands match + */ + for (args = insn->args; ; ++args) { + switch (*args) { + + case '\0': /* end of args */ + if (*s == '\0') { + match = TRUE; + } + break; + + case '+': + case '(': /* these must match exactly */ + case ')': + case ',': + case ' ': + if (*s++ == *args) + continue; + break; + + case '#': /* must be at least one digit */ + if (isdigit(*s++)) { + while (isdigit(*s)) { + ++s; + } + continue; + } + break; + + case '1': /* next operand must be a register */ + case '2': + case 'd': + switch (*s) { + + case 'f': /* frame pointer */ + s++; + if (*s++ == 'p') { + mask = 0x3; + break; + } + goto error; + + case 's': /* stack pointer */ + s++; + if (*s++ == 'p') { + mask= 0x2; + break; + } + goto error; + + case 'r': /* any register */ + s++; + if (!isdigit(c = *s++)) { + goto error; + } + if (isdigit(*s)) { + if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) { + goto error; + } + } else { + c -= '0'; + } + mask= c; + break; + + default: /* not this opcode */ + goto error; + } + /* + * Got the register, now figure out where + * it goes in the opcode. + */ + switch (*args) { + + case '1': + opcode |= mask << 11; + continue; + + case '2': + opcode |= mask << 21; + continue; + + case 'd': + opcode |= mask << 16; + continue; + + } + break; + + case 'e': /* next operand is a floating point register */ + case 'f': + case 'g': + if (*s++ == 'f' && isdigit(*s)) { + mask = *s++; + if (isdigit(*s)) { + mask = 10 * (mask - '0') + (*s++ - '0'); + if (mask >= 32) { + break; + } + } else { + mask -= '0'; + } + switch (*args) { + + case 'e': + opcode |= mask << 11; + continue; + + case 'f': + opcode |= mask << 21; + continue; + + case 'g': + opcode |= mask << 16; + if (dual_mode != DUAL_OFF) + opcode |= (1 << 9); /* dual mode instruction */ + if (dual_mode == DUAL_DDOT) + dual_mode = DUAL_OFF; + if (dual_mode == DUAL_ONDDOT) + dual_mode = DUAL_ON; + if ((opcode & (1 << 10)) && (mask == ((opcode >> 11) & 0x1f))) + as_warn("Fsr1 equals fdest with Pipelining"); + continue; + } + } + break; + + case 'c': /* next operand must be a control register */ + if (strncmp(s, "fir", 3) == 0) { + opcode |= 0x0 << 21; + s += 3; + continue; + } + if (strncmp(s, "psr", 3) == 0) { + opcode |= 0x1 << 21; + s += 3; + continue; + } + if (strncmp(s, "dirbase", 7) == 0) { + opcode |= 0x2 << 21; + s += 7; + continue; + } + if (strncmp(s, "db", 2) == 0) { + opcode |= 0x3 << 21; + s += 2; + continue; + } + if (strncmp(s, "fsr", 3) == 0) { + opcode |= 0x4 << 21; + s += 3; + continue; + } + if (strncmp(s, "epsr", 4) == 0) { + opcode |= 0x5 << 21; + s += 4; + continue; + } + break; + + case '5': /* 5 bit immediate in src1 */ + bzero(&the_insn, sizeof(the_insn)); + if ( !getExpression(s)) { + s = expr_end; + if (the_insn.exp.X_add_number & ~0x1f) + as_warn("5-bit immediate too large"); + opcode |= (the_insn.exp.X_add_number & 0x1f) << 11; + bzero(&the_insn, sizeof(the_insn)); + the_insn.reloc = NO_RELOC; + continue; + } + break; + + case 'l': /* 26 bit immediate, relative branch */ + the_insn.reloc = BRADDR; + the_insn.pcrel = TRUE; + goto immediate; + + case 's': /* 16 bit immediate, split relative branch */ + /* upper 5 bits of offset in dest field */ + the_insn.pcrel = TRUE; + the_insn.reloc = SPLIT0; + goto immediate; + + case 'S': /* 16 bit immediate, split (st), aligned */ + if (opcode & (1 << 28)) + if (opcode & 0x1) + the_insn.reloc = SPLIT2; + else + the_insn.reloc = SPLIT1; + else + the_insn.reloc = SPLIT0; + goto immediate; + + case 'I': /* 16 bit immediate, aligned */ + if (opcode & (1 << 28)) + if (opcode & 0x1) + the_insn.reloc = LOW2; + else + the_insn.reloc = LOW1; + else + the_insn.reloc = LOW0; + goto immediate; + + case 'i': /* 16 bit immediate */ + the_insn.reloc = LOW0; + + /*FALLTHROUGH*/ + + immediate: + if(*s==' ') + s++; + if (strncmp(s, "ha%", 3) == 0) { + the_insn.highlow = HIGHADJ; + s += 3; + } else if (strncmp(s, "h%", 2) == 0) { + the_insn.highlow = HIGH; + s += 2; + } else if (strncmp(s, "l%", 2) == 0) { + the_insn.highlow = PAIR; + s += 2; + } + the_insn.expand = insn->expand; + + /* Note that if the getExpression() fails, we will still have + created U entries in the symbol table for the 'symbols' + in the input string. Try not to create U symbols for + registers, etc. */ + + if ( !getExpression(s)) { + s = expr_end; + continue; + } + break; + + default: + abort(); + } + break; + } + error: + if (match == FALSE) + { + /* Args don't match. */ + if (&insn[1] - i860_opcodes < NUMOPCODES + && !strcmp(insn->name, insn[1].name)) + { + ++insn; + s = argsStart; + continue; + } + else + { + as_warn("Illegal operands"); + return; + } + } + break; + } + + the_insn.opcode = opcode; + return; +} + +static int +getExpression(str) + char *str; +{ + char *save_in; + segT seg; + + save_in = input_line_pointer; + input_line_pointer = str; + switch (seg = expression(&the_insn.exp)) { + + case SEG_ABSOLUTE: + case SEG_TEXT: + case SEG_DATA: + case SEG_BSS: + case SEG_UNKNOWN: + case SEG_DIFFERENCE: + case SEG_BIG: + case SEG_NONE: + break; + + default: + the_insn.error = "bad segment"; + expr_end = input_line_pointer; + input_line_pointer=save_in; + return 1; + } + expr_end = input_line_pointer; + input_line_pointer = save_in; + return 0; +} + + +/* + This is identical to the md_atof in m68k.c. I think this is right, + but I'm not sure. + + 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(); + + switch(type) { + + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + 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--;) { + md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE)); + litP+=sizeof(LITTLENUM_TYPE); + } + return ""; /* Someone should teach Dean about null pointers */ +} + +/* + * Write out big-endian. + */ +void +md_number_to_chars(buf,val,n) + char *buf; + long val; + int n; +{ + switch(n) { + + case 4: + *buf++ = val >> 24; + *buf++ = val >> 16; + case 2: + *buf++ = val >> 8; + case 1: + *buf = val; + break; + + default: + abort(); + } + return; +} + +void +md_number_to_imm(buf,val,n, fixP, seg_type) + char *buf; + long val; + int n; + fixS *fixP; + int seg_type; +{ + enum reloc_type reloc = fixP->fx_r_type & 0xf; + enum highlow_type highlow = (fixP->fx_r_type >> 4) & 0x3; + + assert(buf); + assert(n == 4); /* always on i860 */ + + switch(highlow) + { + + case HIGHADJ: /* adjusts the high-order 16-bits */ + if (val & (1 << 15)) + val += (1 << 16); + + /*FALLTHROUGH*/ + + case HIGH: /* selects the high-order 16-bits */ + val >>= 16; + break; + + case PAIR: /* selects the low-order 16-bits */ + val = val & 0xffff; + break; + + default: + break; + } + + switch(reloc) + { + + case BRADDR: /* br,call,bc,bc.t,bnc,bnc.t w/26-bit immediate */ + if (fixP->fx_pcrel != TRUE) + as_warn("26-bit branch w/o pc relative set: 0x%08x", val); + val >>= 2; /* align pcrel offset, see manual */ + + if (val >= (1 << 25) || val < -(1 << 25)) /* check for overflow */ + as_warn("26-bit branch offset overflow: 0x%08x", val); + buf[0] = (buf[0] & 0xfc) | ((val >> 24) & 0x3); + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val; + break; + + case SPLIT2: /* 16 bit immediate, 4-byte aligned */ + if (val & 0x3) + as_warn("16-bit immediate 4-byte alignment error: 0x%08x", val); + val &= ~0x3; /* 4-byte align value */ + /*FALLTHROUGH*/ + case SPLIT1: /* 16 bit immediate, 2-byte aligned */ + if (val & 0x1) + as_warn("16-bit immediate 2-byte alignment error: 0x%08x", val); + val &= ~0x1; /* 2-byte align value */ + /*FALLTHROUGH*/ + case SPLIT0: /* st,bla,bte,btne w/16-bit immediate */ + if (fixP->fx_pcrel == TRUE) + val >>= 2; /* align pcrel offset, see manual */ + /* check for bounds */ + if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15))) + as_warn("16-bit branch offset overflow: 0x%08x", val); + buf[1] = (buf[1] & ~0x1f) | ((val >> 11) & 0x1f); + buf[2] = (buf[2] & ~0x7) | ((val >> 8) & 0x7); + buf[3] |= val; /* perserve bottom opcode bits */ + break; + + case LOW4: /* fld,pfld,pst,flush 16-byte aligned */ + if (val & 0xf) + as_warn("16-bit immediate 16-byte alignment error: 0x%08x", val); + val &= ~0xf; /* 16-byte align value */ + /*FALLTHROUGH*/ + case LOW3: /* fld,pfld,pst,flush 8-byte aligned */ + if (val & 0x7) + as_warn("16-bit immediate 8-byte alignment error: 0x%08x", val); + val &= ~0x7; /* 8-byte align value */ + /*FALLTHROUGH*/ + case LOW2: /* 16 bit immediate, 4-byte aligned */ + if (val & 0x3) + as_warn("16-bit immediate 4-byte alignment error: 0x%08x", val); + val &= ~0x3; /* 4-byte align value */ + /*FALLTHROUGH*/ + case LOW1: /* 16 bit immediate, 2-byte aligned */ + if (val & 0x1) + as_warn("16-bit immediate 2-byte alignment error: 0x%08x", val); + val &= ~0x1; /* 2-byte align value */ + /*FALLTHROUGH*/ + case LOW0: /* 16 bit immediate, byte aligned */ + /* check for bounds */ + if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15))) + as_warn("16-bit immediate overflow: 0x%08x", val); + buf[2] = val >> 8; + buf[3] |= val; /* perserve bottom opcode bits */ + break; + + case NO_RELOC: + default: + as_warn("bad relocation type: 0x%02x", reloc); + break; + } + return; +} + +/* should never be called for i860 */ +void +md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + long from_addr, to_addr; +{ + fprintf(stderr, "i860_create_short_jmp\n"); + abort(); +} + +/* should never be called for i860 */ +void +md_number_to_disp(buf,val,n) + char *buf; + long val; +{ + fprintf(stderr, "md_number_to_disp\n"); + abort(); +} + +/* should never be called for i860 */ +void +md_number_to_field(buf,val,fix) + char *buf; + long val; + void *fix; +{ + fprintf(stderr, "i860_number_to_field\n"); + abort(); +} + +/* the bit-field entries in the relocation_info struct plays hell + with the byte-order problems of cross-assembly. So as a hack, + I added this mach. dependent ri twiddler. Ugly, but it gets + you there. -KWK */ +/* on i860: first 4 bytes are normal unsigned long address, next three + bytes are index, most sig. byte first. Byte 7 is broken up with + bit 7 as pcrel, bit 6 as extern, and the lower six bits as + relocation type (highlow 5-4). Next 4 bytes are long int addend. */ +/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ +void +md_ri_to_chars(ri_p, ri) + struct relocation_info *ri_p, ri; +{ +#if 0 + unsigned char the_bytes[sizeof(*ri_p)]; + + /* this is easy */ + md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address)); + /* now the fun stuff */ + the_bytes[4] = (ri.r_index >> 16) & 0x0ff; + the_bytes[5] = (ri.r_index >> 8) & 0x0ff; + the_bytes[6] = ri.r_index & 0x0ff; + the_bytes[7] = ((ri.r_extern << 7) & 0x80) | (0 & 0x60) | (ri.r_type & 0x1F); + /* Also easy */ + md_number_to_chars(&the_bytes[8], ri.r_addend, sizeof(ri.r_addend)); + /* now put it back where you found it, Junior... */ + bcopy (the_bytes, (char *)ri_p, sizeof(*ri_p)); +#endif +} + +/* should never be called for i860 */ +void +md_convert_frag(fragP) + register fragS *fragP; +{ + fprintf(stderr, "i860_convert_frag\n"); + abort(); +} + +/* should never be called for i860 */ +void +md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + long from_addr, + to_addr; + fragS *frag; + symbolS *to_symbol; +{ + fprintf(stderr, "i860_create_long_jump\n"); + abort(); +} + +/* should never be called for i860 */ +int +md_estimate_size_before_relax(fragP, segtype) + register fragS *fragP; +{ + fprintf(stderr, "i860_estimate_size_before_relax\n"); + abort(); + return 0; +} + +/* for debugging only, must match enum reloc_type */ +static char *Reloc[] = { + "NO_RELOC", + "BRADDR", + "LOW0", + "LOW1", + "LOW2", + "LOW3", + "LOW4", + "SPLIT0", + "SPLIT1", + "SPLIT2", + "RELOC_32", +}; +static char *Highlow[] = { + "NO_SPEC", + "PAIR", + "HIGH", + "HIGHADJ", +}; +static void +print_insn(insn) + struct i860_it *insn; +{ + if (insn->error) { + fprintf(stderr, "ERROR: %s\n"); + } + fprintf(stderr, "opcode=0x%08x\t", insn->opcode); + fprintf(stderr, "expand=0x%08x\t", insn->expand); + fprintf(stderr, "reloc = %s\t", Reloc[insn->reloc]); + fprintf(stderr, "highlow = %s\n", Highlow[insn->highlow]); + fprintf(stderr, "exp = {\n"); + fprintf(stderr, "\t\tX_add_symbol = %s\n", + insn->exp.X_add_symbol ? + (insn->exp.X_add_symbol->sy_name ? + insn->exp.X_add_symbol->sy_name : "???") : "0"); + fprintf(stderr, "\t\tX_sub_symbol = %s\n", + insn->exp.X_subtract_symbol ? + (insn->exp.X_subtract_symbol->sy_name ? + insn->exp.X_subtract_symbol->sy_name : "???") : "0"); + fprintf(stderr, "\t\tX_add_number = %d\n", + insn->exp.X_add_number); + fprintf(stderr, "}\n"); + return; +} + +int +md_parse_option(argP,cntP,vecP) + char **argP; + int *cntP; + char ***vecP; +{ + return 1; +} + +/* + * I860 relocations are completely different, so it needs + * this machine dependent routine to emit them. + */ +void +emit_relocations(fixP, segment_address_in_file) + register fixS *fixP; + relax_addressT segment_address_in_file; +{ + struct reloc_info_i860 ri; + register symbolS *symbolP; + extern char *next_object_file_charP; + long add_number; + + bzero((char *) &ri, sizeof(ri)); + for (; fixP; fixP = fixP->fx_next) { + + if (fixP->fx_r_type & ~0x3f) { + fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); + abort(); + } + ri.r_pcrel = fixP->fx_pcrel; + ri.r_type = fixP->fx_r_type; + + if ((symbolP = fixP->fx_addsy) != NULL) { + ri.r_address = fixP->fx_frag->fr_address + + fixP->fx_where - segment_address_in_file; + if ((symbolP->sy_type & N_TYPE) == N_UNDF) { + ri.r_extern = 1; + ri.r_symbolnum = symbolP->sy_number; + } else { + ri.r_extern = 0; + ri.r_symbolnum = symbolP->sy_type & N_TYPE; + } + if (symbolP && symbolP->sy_frag) { + ri.r_addend = symbolP->sy_frag->fr_address; + } + ri.r_type = fixP->fx_r_type; + if (fixP->fx_pcrel) { + /* preserve actual offset vs. pc + 4 */ + ri.r_addend -= (ri.r_address + 4); + } else { + ri.r_addend = fixP->fx_addnumber; + } + + md_ri_to_chars((char *) &ri, ri); + append(&next_object_file_charP, (char *)& ri, sizeof(ri)); + } + } + return; +} + diff --git a/gnu/usr.bin/gas/config/i860.h b/gnu/usr.bin/gas/config/i860.h new file mode 100644 index 00000000000..1abdedc8c42 --- /dev/null +++ b/gnu/usr.bin/gas/config/i860.h @@ -0,0 +1,48 @@ +/* i860.h -- Header file for the I860 + Copyright (C) 1989 Free Software Foundation, Inc. + +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 1, 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. */ + +enum reloc_type /* NOTE: three bits max, see struct reloc_info_i860.r_type */ +{ + NO_RELOC = 0, BRADDR, LOW0, LOW1, LOW2, LOW3, LOW4, SPLIT0, SPLIT1, SPLIT2, RELOC_32, +}; + +enum highlow_type /* NOTE: two bits max, see reloc_info_i860.r_type */ +{ + NO_SPEC = 0, PAIR, HIGH, HIGHADJ, +}; + +struct reloc_info_i860 +{ + unsigned long int r_address; +/* + * Using bit fields here is a bad idea because the order is not portable. :-( + */ + unsigned int r_symbolnum: 24; + unsigned int r_pcrel : 1; + unsigned int r_extern : 1; + /* combining the two field simplifies the argument passing in "new_fix()" */ + /* and is compatible with the existing Sparc #ifdef's */ + /* r_type: highlow_type - bits 5,4; reloc_type - bits 3-0 */ + unsigned int r_type : 6; + long int r_addend; +}; + +#define relocation_info reloc_info_i860 + + diff --git a/gnu/usr.bin/gas/config/m-hpux.h b/gnu/usr.bin/gas/config/m-hpux.h new file mode 100644 index 00000000000..d59ef84fcbd --- /dev/null +++ b/gnu/usr.bin/gas/config/m-hpux.h @@ -0,0 +1,24 @@ +/* m-hpux.h -- Header to compile the 68020 assembler under HP-UX + Copyright (C) 1988 Free Software Foundation, Inc. + +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 1, 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. */ + +/* This header file contains the #defines specific + to HPUX changes sent me by cph@zurich.ai.mit.edu */ +#ifndef hpux +#define hpux +#endif diff --git a/gnu/usr.bin/gas/config/m-sun3.h b/gnu/usr.bin/gas/config/m-sun3.h new file mode 100644 index 00000000000..85a9554eb13 --- /dev/null +++ b/gnu/usr.bin/gas/config/m-sun3.h @@ -0,0 +1,31 @@ +/* m-sun3.h -- 68020 version of the assembler for the Sun-3 + Copyright (C) 1987 Free Software Foundation, Inc. + +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 1, 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. */ + + + +/* This header file contains the #defines specific + to SUN computer SUN 3 series computers. (The only kind + we have around here, unfortunatly.) + + Rumor has it that this file will work on the Sun-2 if the assembler + is called with -m68010 This is not tested. */ + + +#define M_SUN 1 +#define SUN_ASM_SYNTAX diff --git a/gnu/usr.bin/gas/config/m68k-opcode.h b/gnu/usr.bin/gas/config/m68k-opcode.h new file mode 100644 index 00000000000..e670cb83b54 --- /dev/null +++ b/gnu/usr.bin/gas/config/m68k-opcode.h @@ -0,0 +1,1680 @@ +/* Opcode table for m68000/m68020 and m68881. + Copyright (C) 1989, Free Software Foundation. + +This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler. + +Both GDB and GAS are free software; you can redistribute 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. + +GDB and GAS are 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 GDB or GAS; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +struct m68k_opcode +{ + char *name; + unsigned long opcode; + unsigned long match; + char *args; +}; + +/* We store four bytes of opcode for all opcodes because that + is the most any of them need. The actual length of an instruction + is always at least 2 bytes, and is as much longer as necessary to + hold the operands it has. + + The match component is a mask saying which bits must match + particular opcode in order for an instruction to be an instance + of that opcode. + + The args component is a string containing two characters + for each operand of the instruction. The first specifies + the kind of operand; the second, the place it is stored. */ + +/* Kinds of operands: + D data register only. Stored as 3 bits. + A address register only. Stored as 3 bits. + R either kind of register. Stored as 4 bits. + F floating point coprocessor register only. Stored as 3 bits. + O an offset (or width): immediate data 0-31 or data register. + Stored as 6 bits in special format for BF... insns. + + autoincrement only. Stored as 3 bits (number of the address register). + - autodecrement only. Stored as 3 bits (number of the address register). + Q quick immediate data. Stored as 3 bits. + This matches an immediate operand only when value is in range 1 .. 8. + M moveq immediate data. Stored as 8 bits. + This matches an immediate operand only when value is in range -128..127 + T trap vector immediate data. Stored as 4 bits. + + k K-factor for fmove.p instruction. Stored as a 7-bit constant or + a three bit register offset, depending on the field type. + + # immediate data. Stored in special places (b, w or l) + which say how many bits to store. + ^ immediate data for floating point instructions. Special places + are offset by 2 bytes from '#'... + B pc-relative address, converted to an offset + that is treated as immediate data. + d displacement and register. Stores the register as 3 bits + and stores the displacement in the entire second word. + + C the CCR. No need to store it; this is just for filtering validity. + S the SR. No need to store, just as with CCR. + U the USP. No need to store, just as with CCR. + + I Coprocessor ID. Not printed if 1. The Coprocessor ID is always + extracted from the 'd' field of word one, which means that an extended + coprocessor opcode can be skipped using the 'i' place, if needed. + + s System Control register for the floating point coprocessor. + S List of system control registers for floating point coprocessor. + + J Misc register for movec instruction, stored in 'j' format. + Possible values: + 000 SFC Source Function Code reg + 001 DFC Data Function Code reg + 002 CACR Cache Control Register + 800 USP User Stack Pointer + 801 VBR Vector Base reg + 802 CAAR Cache Address Register + 803 MSP Master Stack Pointer + 804 ISP Interrupt Stack Pointer + + L Register list of the type d0-d7/a0-a7 etc. + (New! Improved! Can also hold fp0-fp7, as well!) + The assembler tries to see if the registers match the insn by + looking at where the insn wants them stored. + + l Register list like L, but with all the bits reversed. + Used for going the other way. . . + + They are all stored as 6 bits using an address mode and a register number; + they differ in which addressing modes they match. + + * all (modes 0-6,7.*) + ~ alterable memory (modes 2-6,7.0,7.1)(not 0,1,7.~) + % alterable (modes 0-6,7.0,7.1)(not 7.~) + ; data (modes 0,2-6,7.*)(not 1) + @ data, but not immediate (modes 0,2-6,7.? ? ?)(not 1,7.?) This may really be ;, the 68020 book says it is + ! control (modes 2,5,6,7.*-)(not 0,1,3,4,7.4) + & alterable control (modes 2,5,6,7.0,7.1)(not 0,1,7.? ? ?) + $ alterable data (modes 0,2-6,7.0,7.1)(not 1,7.~) + ? alterable control, or data register (modes 0,2,5,6,7.0,7.1)(not 1,3,4,7.~) + / control, or data register (modes 0,2,5,6,7.0,7.1,7.2,7.3)(not 1,3,4,7.4) +*/ + +/* JF: for the 68851 */ +/* + I didn't use much imagination in choosing the + following codes, so many of them aren't very + mnemonic. -rab + + P pmmu register + Possible values: + 000 TC Translation Control reg + 100 CAL Current Access Level + 101 VAL Validate Access Level + 110 SCC Stack Change Control + 111 AC Access Control + + W wide pmmu registers + Possible values: + 001 DRP Dma Root Pointer + 010 SRP Supervisor Root Pointer + 011 CRP Cpu Root Pointer + + f function code register + 0 SFC + 1 DFC + + V VAL register only + + X BADx, BACx + 100 BAD Breakpoint Acknowledge Data + 101 BAC Breakpoint Acknowledge Control + + Y PSR + Z PCSR + + | memory (modes 2-6, 7.*) + +*/ + +/* Places to put an operand, for non-general operands: + s source, low bits of first word. + d dest, shifted 9 in first word + 1 second word, shifted 12 + 2 second word, shifted 6 + 3 second word, shifted 0 + 4 third word, shifted 12 + 5 third word, shifted 6 + 6 third word, shifted 0 + 7 second word, shifted 7 + 8 second word, shifted 10 + D store in both place 1 and place 3; for divul and divsl. + b second word, low byte + w second word (entire) + l second and third word (entire) + g branch offset for bra and similar instructions. + The place to store depends on the magnitude of offset. + t store in both place 7 and place 8; for floating point operations + c branch offset for cpBcc operations. + The place to store is word two if bit six of word one is zero, + and words two and three if bit six of word one is one. + i Increment by two, to skip over coprocessor extended operands. Only + works with the 'I' format. + k Dynamic K-factor field. Bits 6-4 of word 2, used as a register number. + Also used for dynamic fmovem instruction. + C floating point coprocessor constant - 7 bits. Also used for static + K-factors... + j Movec register #, stored in 12 low bits of second word. + + Places to put operand, for general operands: + d destination, shifted 6 bits in first word + b source, at low bit of first word, and immediate uses one byte + w source, at low bit of first word, and immediate uses two bytes + l source, at low bit of first word, and immediate uses four bytes + s source, at low bit of first word. + Used sometimes in contexts where immediate is not allowed anyway. + f single precision float, low bit of 1st word, immediate uses 4 bytes + F double precision float, low bit of 1st word, immediate uses 8 bytes + x extended precision float, low bit of 1st word, immediate uses 12 bytes + p packed float, low bit of 1st word, immediate uses 12 bytes +*/ + +#define one(x) ((x) << 16) +#define two(x, y) (((x) << 16) + y) + +/* + *** DANGER WILL ROBINSON *** + + The assembler requires that all instances of the same mnemonic must be + consecutive. If they aren't, the assembler will bomb at runtime + */ +struct m68k_opcode m68k_opcodes[] = +{ +{"abcd", one(0140400), one(0170770), "DsDd"}, +{"abcd", one(0140410), one(0170770), "-s-d"}, + + /* Add instructions */ +{"addal", one(0150700), one(0170700), "*lAd"}, +{"addaw", one(0150300), one(0170700), "*wAd"}, +{"addib", one(0003000), one(0177700), "#b$b"}, +{"addil", one(0003200), one(0177700), "#l$l"}, +{"addiw", one(0003100), one(0177700), "#w$w"}, +{"addqb", one(0050000), one(0170700), "Qd$b"}, +{"addql", one(0050200), one(0170700), "Qd%l"}, +{"addqw", one(0050100), one(0170700), "Qd%w"}, + +{"addb", one(0050000), one(0170700), "Qd$b"}, /* addq written as add */ +{"addb", one(0003000), one(0177700), "#b$b"}, /* addi written as add */ +{"addb", one(0150000), one(0170700), ";bDd"}, /* addb <ea>, Dd */ +{"addb", one(0150400), one(0170700), "Dd~b"}, /* addb Dd, <ea> */ + +{"addw", one(0050100), one(0170700), "Qd%w"}, /* addq written as add */ +{"addw", one(0003100), one(0177700), "#w$w"}, /* addi written as add */ +{"addw", one(0150300), one(0170700), "*wAd"}, /* adda written as add */ +{"addw", one(0150100), one(0170700), "*wDd"}, /* addw <ea>, Dd */ +{"addw", one(0150500), one(0170700), "Dd~w"}, /* addw Dd, <ea> */ + +{"addl", one(0050200), one(0170700), "Qd%l"}, /* addq written as add */ +{"addl", one(0003200), one(0177700), "#l$l"}, /* addi written as add */ +{"addl", one(0150700), one(0170700), "*lAd"}, /* adda written as add */ +{"addl", one(0150200), one(0170700), "*lDd"}, /* addl <ea>, Dd */ +{"addl", one(0150600), one(0170700), "Dd~l"}, /* addl Dd, <ea> */ + +{"addxb", one(0150400), one(0170770), "DsDd"}, +{"addxb", one(0150410), one(0170770), "-s-d"}, +{"addxl", one(0150600), one(0170770), "DsDd"}, +{"addxl", one(0150610), one(0170770), "-s-d"}, +{"addxw", one(0150500), one(0170770), "DsDd"}, +{"addxw", one(0150510), one(0170770), "-s-d"}, + +{"andib", one(0001000), one(0177700), "#b$b"}, +{"andib", one(0001074), one(0177777), "#bCb"}, /* andi to ccr */ +{"andiw", one(0001100), one(0177700), "#w$w"}, +{"andiw", one(0001174), one(0177777), "#wSw"}, /* andi to sr */ +{"andil", one(0001200), one(0177700), "#l$l"}, + +{"andb", one(0001000), one(0177700), "#b$b"}, /* andi written as or */ +{"andb", one(0001074), one(0177777), "#bCb"}, /* andi to ccr */ +{"andb", one(0140000), one(0170700), ";bDd"}, /* memory to register */ +{"andb", one(0140400), one(0170700), "Dd~b"}, /* register to memory */ +{"andw", one(0001100), one(0177700), "#w$w"}, /* andi written as or */ +{"andw", one(0001174), one(0177777), "#wSw"}, /* andi to sr */ +{"andw", one(0140100), one(0170700), ";wDd"}, /* memory to register */ +{"andw", one(0140500), one(0170700), "Dd~w"}, /* register to memory */ +{"andl", one(0001200), one(0177700), "#l$l"}, /* andi written as or */ +{"andl", one(0140200), one(0170700), ";lDd"}, /* memory to register */ +{"andl", one(0140600), one(0170700), "Dd~l"}, /* register to memory */ + +{"aslb", one(0160400), one(0170770), "QdDs"}, +{"aslb", one(0160440), one(0170770), "DdDs"}, +{"asll", one(0160600), one(0170770), "QdDs"}, +{"asll", one(0160640), one(0170770), "DdDs"}, +{"aslw", one(0160500), one(0170770), "QdDs"}, +{"aslw", one(0160540), one(0170770), "DdDs"}, +{"aslw", one(0160700), one(0177700), "~s"}, /* Shift memory */ +{"asrb", one(0160000), one(0170770), "QdDs"}, +{"asrb", one(0160040), one(0170770), "DdDs"}, +{"asrl", one(0160200), one(0170770), "QdDs"}, +{"asrl", one(0160240), one(0170770), "DdDs"}, +{"asrw", one(0160100), one(0170770), "QdDs"}, +{"asrw", one(0160140), one(0170770), "DdDs"}, +{"asrw", one(0160300), one(0177700), "~s"}, /* Shift memory */ + +{"bhi", one(0061000), one(0177400), "Bg"}, +{"bls", one(0061400), one(0177400), "Bg"}, +{"bcc", one(0062000), one(0177400), "Bg"}, +{"bcs", one(0062400), one(0177400), "Bg"}, +{"bne", one(0063000), one(0177400), "Bg"}, +{"beq", one(0063400), one(0177400), "Bg"}, +{"bvc", one(0064000), one(0177400), "Bg"}, +{"bvs", one(0064400), one(0177400), "Bg"}, +{"bpl", one(0065000), one(0177400), "Bg"}, +{"bmi", one(0065400), one(0177400), "Bg"}, +{"bge", one(0066000), one(0177400), "Bg"}, +{"blt", one(0066400), one(0177400), "Bg"}, +{"bgt", one(0067000), one(0177400), "Bg"}, +{"ble", one(0067400), one(0177400), "Bg"}, + +{"bchg", one(0000500), one(0170700), "Dd$s"}, +{"bchg", one(0004100), one(0177700), "#b$s"}, +{"bclr", one(0000600), one(0170700), "Dd$s"}, +{"bclr", one(0004200), one(0177700), "#b$s"}, +{"bfchg", two(0165300, 0), two(0177700, 0170000), "?sO2O3"}, +{"bfclr", two(0166300, 0), two(0177700, 0170000), "?sO2O3"}, +{"bfexts", two(0165700, 0), two(0177700, 0100000), "/sO2O3D1"}, +{"bfextu", two(0164700, 0), two(0177700, 0100000), "/sO2O3D1"}, +{"bfffo", two(0166700, 0), two(0177700, 0100000), "/sO2O3D1"}, +{"bfins", two(0167700, 0), two(0177700, 0100000), "D1?sO2O3"}, +{"bfset", two(0167300, 0), two(0177700, 0170000), "?sO2O3"}, +{"bftst", two(0164300, 0), two(0177700, 0170000), "/sO2O3"}, +{"bset", one(0000700), one(0170700), "Dd$s"}, +{"bset", one(0004300), one(0177700), "#b$s"}, +{"btst", one(0000400), one(0170700), "Dd@s"}, +{"btst", one(0004000), one(0177700), "#b@s"}, + +{"bkpt", one(0044110), one(0177770), "Qs"}, +{"bra", one(0060000), one(0177400), "Bg"}, +{"bras", one(0060000), one(0177400), "Bw"}, +{"bsr", one(0060400), one(0177400), "Bg"}, +{"bsrs", one(0060400), one(0177400), "Bw"}, + +{"callm", one(0003300), one(0177700), "#b!s"}, +{"cas2l", two(0007374, 0), two(0177777, 0107070), "D3D6D2D5R1R4"}, /* JF FOO this is really a 3 word ins */ +{"cas2w", two(0006374, 0), two(0177777, 0107070), "D3D6D2D5R1R4"}, /* JF ditto */ +{"casb", two(0005300, 0), two(0177700, 0177070), "D3D2~s"}, +{"casl", two(0007300, 0), two(0177700, 0177070), "D3D2~s"}, +{"casw", two(0006300, 0), two(0177700, 0177070), "D3D2~s"}, + +/* {"chk", one(0040600), one(0170700), ";wDd"}, JF FOO this looks wrong */ +{"chk2b", two(0000300, 0004000), two(0177700, 07777), "!sR1"}, +{"chk2l", two(0002300, 0004000), two(0177700, 07777), "!sR1"}, +{"chk2w", two(0001300, 0004000), two(0177700, 07777), "!sR1"}, +{"chkl", one(0040400), one(0170700), ";lDd"}, +{"chkw", one(0040600), one(0170700), ";wDd"}, +{"clrb", one(0041000), one(0177700), "$s"}, +{"clrl", one(0041200), one(0177700), "$s"}, +{"clrw", one(0041100), one(0177700), "$s"}, + +{"cmp2b", two(0000300, 0), two(0177700, 07777), "!sR1"}, +{"cmp2l", two(0002300, 0), two(0177700, 07777), "!sR1"}, +{"cmp2w", two(0001300, 0), two(0177700, 07777), "!sR1"}, +{"cmpal", one(0130700), one(0170700), "*lAd"}, +{"cmpaw", one(0130300), one(0170700), "*wAd"}, +{"cmpib", one(0006000), one(0177700), "#b;b"}, +{"cmpil", one(0006200), one(0177700), "#l;l"}, +{"cmpiw", one(0006100), one(0177700), "#w;w"}, +{"cmpb", one(0006000), one(0177700), "#b;b"}, /* cmpi written as cmp */ +{"cmpb", one(0130000), one(0170700), ";bDd"}, +{"cmpw", one(0006100), one(0177700), "#w;w"}, +{"cmpw", one(0130100), one(0170700), "*wDd"}, +{"cmpw", one(0130300), one(0170700), "*wAd"}, /* cmpa written as cmp */ +{"cmpl", one(0006200), one(0177700), "#l;l"}, +{"cmpl", one(0130200), one(0170700), "*lDd"}, +{"cmpl", one(0130700), one(0170700), "*lAd"}, +{"cmpmb", one(0130410), one(0170770), "+s+d"}, +{"cmpml", one(0130610), one(0170770), "+s+d"}, +{"cmpmw", one(0130510), one(0170770), "+s+d"}, + +{"dbcc", one(0052310), one(0177770), "DsBw"}, +{"dbcs", one(0052710), one(0177770), "DsBw"}, +{"dbeq", one(0053710), one(0177770), "DsBw"}, +{"dbf", one(0050710), one(0177770), "DsBw"}, +{"dbge", one(0056310), one(0177770), "DsBw"}, +{"dbgt", one(0057310), one(0177770), "DsBw"}, +{"dbhi", one(0051310), one(0177770), "DsBw"}, +{"dble", one(0057710), one(0177770), "DsBw"}, +{"dbls", one(0051710), one(0177770), "DsBw"}, +{"dblt", one(0056710), one(0177770), "DsBw"}, +{"dbmi", one(0055710), one(0177770), "DsBw"}, +{"dbne", one(0053310), one(0177770), "DsBw"}, +{"dbpl", one(0055310), one(0177770), "DsBw"}, +{"dbra", one(0050710), one(0177770), "DsBw"}, +{"dbt", one(0050310), one(0177770), "DsBw"}, +{"dbvc", one(0054310), one(0177770), "DsBw"}, +{"dbvs", one(0054710), one(0177770), "DsBw"}, + +{"divsl", two(0046100, 0006000), two(0177700, 0107770), ";lD3D1"}, +{"divsl", two(0046100, 0004000), two(0177700, 0107770), ";lDD"}, +{"divsll", two(0046100, 0004000), two(0177700, 0107770), ";lD3D1"}, +{"divsw", one(0100700), one(0170700), ";wDd"}, +{"divs", one(0100700), one(0170700), ";wDd"}, +{"divul", two(0046100, 0002000), two(0177700, 0107770), ";lD3D1"}, +{"divul", two(0046100, 0000000), two(0177700, 0107770), ";lDD"}, +{"divull", two(0046100, 0000000), two(0177700, 0107770), ";lD3D1"}, +{"divuw", one(0100300), one(0170700), ";wDd"}, +{"divu", one(0100300), one(0170700), ";wDd"}, +{"eorb", one(0005000), one(0177700), "#b$s"}, /* eori written as or */ +{"eorb", one(0005074), one(0177777), "#bCs"}, /* eori to ccr */ +{"eorb", one(0130400), one(0170700), "Dd$s"}, /* register to memory */ +{"eorib", one(0005000), one(0177700), "#b$s"}, +{"eorib", one(0005074), one(0177777), "#bCs"}, /* eori to ccr */ +{"eoril", one(0005200), one(0177700), "#l$s"}, +{"eoriw", one(0005100), one(0177700), "#w$s"}, +{"eoriw", one(0005174), one(0177777), "#wSs"}, /* eori to sr */ +{"eorl", one(0005200), one(0177700), "#l$s"}, +{"eorl", one(0130600), one(0170700), "Dd$s"}, +{"eorw", one(0005100), one(0177700), "#w$s"}, +{"eorw", one(0005174), one(0177777), "#wSs"}, /* eori to sr */ +{"eorw", one(0130500), one(0170700), "Dd$s"}, + +{"exg", one(0140500), one(0170770), "DdDs"}, +{"exg", one(0140510), one(0170770), "AdAs"}, +{"exg", one(0140610), one(0170770), "DdAs"}, +{"exg", one(0140610), one(0170770), "AsDd"}, + +{"extw", one(0044200), one(0177770), "Ds"}, +{"extl", one(0044300), one(0177770), "Ds"}, +{"extbl", one(0044700), one(0177770), "Ds"}, +{"extb.l", one(0044700), one(0177770), "Ds"}, /* Not sure we should support this one*/ + +{"illegal", one(0045374), one(0177777), ""}, +{"jmp", one(0047300), one(0177700), "!s"}, +{"jsr", one(0047200), one(0177700), "!s"}, +{"lea", one(0040700), one(0170700), "!sAd"}, +{"linkw", one(0047120), one(0177770), "As#w"}, +{"linkl", one(0044010), one(0177770), "As#l"}, +{"link", one(0047120), one(0177770), "As#w"}, +{"link", one(0044010), one(0177770), "As#l"}, + +{"lslb", one(0160410), one(0170770), "QdDs"}, /* lsrb #Q, Ds */ +{"lslb", one(0160450), one(0170770), "DdDs"}, /* lsrb Dd, Ds */ +{"lslw", one(0160510), one(0170770), "QdDs"}, /* lsrb #Q, Ds */ +{"lslw", one(0160550), one(0170770), "DdDs"}, /* lsrb Dd, Ds */ +{"lslw", one(0161700), one(0177700), "~s"}, /* Shift memory */ +{"lsll", one(0160610), one(0170770), "QdDs"}, /* lsrb #Q, Ds */ +{"lsll", one(0160650), one(0170770), "DdDs"}, /* lsrb Dd, Ds */ + +{"lsrb", one(0160010), one(0170770), "QdDs"} /* lsrb #Q, Ds */, +{"lsrb", one(0160050), one(0170770), "DdDs"}, /* lsrb Dd, Ds */ +{"lsrl", one(0160210), one(0170770), "QdDs"}, /* lsrb #Q, Ds */ +{"lsrl", one(0160250), one(0170770), "DdDs"}, /* lsrb #Q, Ds */ +{"lsrw", one(0160110), one(0170770), "QdDs"}, /* lsrb #Q, Ds */ +{"lsrw", one(0160150), one(0170770), "DdDs"}, /* lsrb #Q, Ds */ +{"lsrw", one(0161300), one(0177700), "~s"}, /* Shift memory */ + +{"moveal", one(0020100), one(0170700), "*lAd"}, +{"moveaw", one(0030100), one(0170700), "*wAd"}, +{"moveb", one(0010000), one(0170000), ";b$d"}, /* move */ +{"movel", one(0070000), one(0170400), "MsDd"}, /* moveq written as move */ +{"movel", one(0020000), one(0170000), "*l$d"}, +{"movel", one(0020100), one(0170700), "*lAd"}, +{"movel", one(0047140), one(0177770), "AsUd"}, /* move to USP */ +{"movel", one(0047150), one(0177770), "UdAs"}, /* move from USP */ + +{"movec", one(0047173), one(0177777), "R1Jj"}, +{"movec", one(0047173), one(0177777), "R1#j"}, +{"movec", one(0047172), one(0177777), "JjR1"}, +{"movec", one(0047172), one(0177777), "#jR1"}, + +/* JF added these next four for the assembler */ +{"moveml", one(0044300), one(0177700), "Lw&s"}, /* movem reg to mem. */ +{"moveml", one(0044340), one(0177770), "lw-s"}, /* movem reg to autodecrement. */ +{"moveml", one(0046300), one(0177700), "!sLw"}, /* movem mem to reg. */ +{"moveml", one(0046330), one(0177770), "+sLw"}, /* movem autoinc to reg. */ + +{"moveml", one(0044300), one(0177700), "#w&s"}, /* movem reg to mem. */ +{"moveml", one(0044340), one(0177770), "#w-s"}, /* movem reg to autodecrement. */ +{"moveml", one(0046300), one(0177700), "!s#w"}, /* movem mem to reg. */ +{"moveml", one(0046330), one(0177770), "+s#w"}, /* movem autoinc to reg. */ + +/* JF added these next four for the assembler */ +{"movemw", one(0044200), one(0177700), "Lw&s"}, /* movem reg to mem. */ +{"movemw", one(0044240), one(0177770), "lw-s"}, /* movem reg to autodecrement. */ +{"movemw", one(0046200), one(0177700), "!sLw"}, /* movem mem to reg. */ +{"movemw", one(0046230), one(0177770), "+sLw"}, /* movem autoinc to reg. */ + +{"movemw", one(0044200), one(0177700), "#w&s"}, /* movem reg to mem. */ +{"movemw", one(0044240), one(0177770), "#w-s"}, /* movem reg to autodecrement. */ +{"movemw", one(0046200), one(0177700), "!s#w"}, /* movem mem to reg. */ +{"movemw", one(0046230), one(0177770), "+s#w"}, /* movem autoinc to reg. */ + +{"movepl", one(0000510), one(0170770), "dsDd"}, /* memory to register */ +{"movepl", one(0000710), one(0170770), "Ddds"}, /* register to memory */ +{"movepw", one(0000410), one(0170770), "dsDd"}, /* memory to register */ +{"movepw", one(0000610), one(0170770), "Ddds"}, /* register to memory */ +{"moveq", one(0070000), one(0170400), "MsDd"}, +{"movew", one(0030000), one(0170000), "*w$d"}, +{"movew", one(0030100), one(0170700), "*wAd"}, /* movea, written as move */ +{"movew", one(0040300), one(0177700), "Ss$s"}, /* Move from sr */ +{"movew", one(0041300), one(0177700), "Cs$s"}, /* Move from ccr */ +{"movew", one(0042300), one(0177700), ";wCd"}, /* move to ccr */ +{"movew", one(0043300), one(0177700), ";wSd"}, /* move to sr */ + +{"movesb", two(0007000, 0), two(0177700, 07777), "~sR1"}, /* moves from memory */ +{"movesb", two(0007000, 04000), two(0177700, 07777), "R1~s"}, /* moves to memory */ +{"movesl", two(0007200, 0), two(0177700, 07777), "~sR1"}, /* moves from memory */ +{"movesl", two(0007200, 04000), two(0177700, 07777), "R1~s"}, /* moves to memory */ +{"movesw", two(0007100, 0), two(0177700, 07777), "~sR1"}, /* moves from memory */ +{"movesw", two(0007100, 04000), two(0177700, 07777), "R1~s"}, /* moves to memory */ + +{"mulsl", two(0046000, 004000), two(0177700, 0107770), ";lD1"}, +{"mulsl", two(0046000, 006000), two(0177700, 0107770), ";lD3D1"}, +{"mulsw", one(0140700), one(0170700), ";wDd"}, +{"muls", one(0140700), one(0170700), ";wDd"}, +{"mulul", two(0046000, 000000), two(0177700, 0107770), ";lD1"}, +{"mulul", two(0046000, 002000), two(0177700, 0107770), ";lD3D1"}, +{"muluw", one(0140300), one(0170700), ";wDd"}, +{"mulu", one(0140300), one(0170700), ";wDd"}, +{"nbcd", one(0044000), one(0177700), "$s"}, +{"negb", one(0042000), one(0177700), "$s"}, +{"negl", one(0042200), one(0177700), "$s"}, +{"negw", one(0042100), one(0177700), "$s"}, +{"negxb", one(0040000), one(0177700), "$s"}, +{"negxl", one(0040200), one(0177700), "$s"}, +{"negxw", one(0040100), one(0177700), "$s"}, +{"nop", one(0047161), one(0177777), ""}, +{"notb", one(0043000), one(0177700), "$s"}, +{"notl", one(0043200), one(0177700), "$s"}, +{"notw", one(0043100), one(0177700), "$s"}, + +{"orb", one(0000000), one(0177700), "#b$s"}, /* ori written as or */ +{"orb", one(0000074), one(0177777), "#bCs"}, /* ori to ccr */ +{"orb", one(0100000), one(0170700), ";bDd"}, /* memory to register */ +{"orb", one(0100400), one(0170700), "Dd~s"}, /* register to memory */ +{"orib", one(0000000), one(0177700), "#b$s"}, +{"orib", one(0000074), one(0177777), "#bCs"}, /* ori to ccr */ +{"oril", one(0000200), one(0177700), "#l$s"}, +{"oriw", one(0000100), one(0177700), "#w$s"}, +{"oriw", one(0000174), one(0177777), "#wSs"}, /* ori to sr */ +{"orl", one(0000200), one(0177700), "#l$s"}, +{"orl", one(0100200), one(0170700), ";lDd"}, /* memory to register */ +{"orl", one(0100600), one(0170700), "Dd~s"}, /* register to memory */ +{"orw", one(0000100), one(0177700), "#w$s"}, +{"orw", one(0000174), one(0177777), "#wSs"}, /* ori to sr */ +{"orw", one(0100100), one(0170700), ";wDd"}, /* memory to register */ +{"orw", one(0100500), one(0170700), "Dd~s"}, /* register to memory */ + +{"pack", one(0100500), one(0170770), "DsDd#w"}, /* pack Ds, Dd, #w */ +{"pack", one(0100510), one(0170770), "-s-d#w"}, /* pack -(As), -(Ad), #w */ +{"pea", one(0044100), one(0177700), "!s"}, +{"reset", one(0047160), one(0177777), ""}, + +{"rolb", one(0160430), one(0170770), "QdDs"}, /* rorb #Q, Ds */ +{"rolb", one(0160470), one(0170770), "DdDs"}, /* rorb Dd, Ds */ +{"roll", one(0160630), one(0170770), "QdDs"}, /* rorb #Q, Ds */ +{"roll", one(0160670), one(0170770), "DdDs"}, /* rorb Dd, Ds */ +{"rolw", one(0160530), one(0170770), "QdDs"}, /* rorb #Q, Ds */ +{"rolw", one(0160570), one(0170770), "DdDs"}, /* rorb Dd, Ds */ +{"rolw", one(0163700), one(0177700), "~s"}, /* Rotate memory */ +{"rorb", one(0160030), one(0170770), "QdDs"}, /* rorb #Q, Ds */ +{"rorb", one(0160070), one(0170770), "DdDs"}, /* rorb Dd, Ds */ +{"rorl", one(0160230), one(0170770), "QdDs"}, /* rorb #Q, Ds */ +{"rorl", one(0160270), one(0170770), "DdDs"}, /* rorb Dd, Ds */ +{"rorw", one(0160130), one(0170770), "QdDs"}, /* rorb #Q, Ds */ +{"rorw", one(0160170), one(0170770), "DdDs"}, /* rorb Dd, Ds */ +{"rorw", one(0163300), one(0177700), "~s"}, /* Rotate memory */ + +{"roxlb", one(0160420), one(0170770), "QdDs"}, /* roxrb #Q, Ds */ +{"roxlb", one(0160460), one(0170770), "DdDs"}, /* roxrb Dd, Ds */ +{"roxll", one(0160620), one(0170770), "QdDs"}, /* roxrb #Q, Ds */ +{"roxll", one(0160660), one(0170770), "DdDs"}, /* roxrb Dd, Ds */ +{"roxlw", one(0160520), one(0170770), "QdDs"}, /* roxrb #Q, Ds */ +{"roxlw", one(0160560), one(0170770), "DdDs"}, /* roxrb Dd, Ds */ +{"roxlw", one(0162700), one(0177700), "~s"}, /* Rotate memory */ +{"roxrb", one(0160020), one(0170770), "QdDs"}, /* roxrb #Q, Ds */ +{"roxrb", one(0160060), one(0170770), "DdDs"}, /* roxrb Dd, Ds */ +{"roxrl", one(0160220), one(0170770), "QdDs"}, /* roxrb #Q, Ds */ +{"roxrl", one(0160260), one(0170770), "DdDs"}, /* roxrb Dd, Ds */ +{"roxrw", one(0160120), one(0170770), "QdDs"}, /* roxrb #Q, Ds */ +{"roxrw", one(0160160), one(0170770), "DdDs"}, /* roxrb Dd, Ds */ +{"roxrw", one(0162300), one(0177700), "~s"}, /* Rotate memory */ + +{"rtd", one(0047164), one(0177777), "#w"}, +{"rte", one(0047163), one(0177777), ""}, +{"rtm", one(0003300), one(0177760), "Rs"}, +{"rtr", one(0047167), one(0177777), ""}, +{"rts", one(0047165), one(0177777), ""}, + +{"scc", one(0052300), one(0177700), "$s"}, +{"scs", one(0052700), one(0177700), "$s"}, +{"seq", one(0053700), one(0177700), "$s"}, +{"sf", one(0050700), one(0177700), "$s"}, +{"sge", one(0056300), one(0177700), "$s"}, +{"sgt", one(0057300), one(0177700), "$s"}, +{"shi", one(0051300), one(0177700), "$s"}, +{"sle", one(0057700), one(0177700), "$s"}, +{"sls", one(0051700), one(0177700), "$s"}, +{"slt", one(0056700), one(0177700), "$s"}, +{"smi", one(0055700), one(0177700), "$s"}, +{"sne", one(0053300), one(0177700), "$s"}, +{"spl", one(0055300), one(0177700), "$s"}, +{"st", one(0050300), one(0177700), "$s"}, +{"svc", one(0054300), one(0177700), "$s"}, +{"svs", one(0054700), one(0177700), "$s"}, + +{"sbcd", one(0100400), one(0170770), "DsDd"}, +{"sbcd", one(0100410), one(0170770), "-s-d"}, +{"stop", one(0047162), one(0177777), "#w"}, + +{"subal", one(0110700), one(0170700), "*lAd"}, +{"subaw", one(0110300), one(0170700), "*wAd"}, +{"subb", one(0050400), one(0170700), "Qd%s"}, /* subq written as sub */ +{"subb", one(0002000), one(0177700), "#b$s"}, /* subi written as sub */ +{"subb", one(0110000), one(0170700), ";bDd"}, /* subb ? ?, Dd */ +{"subb", one(0110400), one(0170700), "Dd~s"}, /* subb Dd, ? ? */ +{"subib", one(0002000), one(0177700), "#b$s"}, +{"subil", one(0002200), one(0177700), "#l$s"}, +{"subiw", one(0002100), one(0177700), "#w$s"}, +{"subl", one(0050600), one(0170700), "Qd%s"}, +{"subl", one(0002200), one(0177700), "#l$s"}, +{"subl", one(0110700), one(0170700), "*lAd"}, +{"subl", one(0110200), one(0170700), "*lDd"}, +{"subl", one(0110600), one(0170700), "Dd~s"}, +{"subqb", one(0050400), one(0170700), "Qd%s"}, +{"subql", one(0050600), one(0170700), "Qd%s"}, +{"subqw", one(0050500), one(0170700), "Qd%s"}, +{"subw", one(0050500), one(0170700), "Qd%s"}, +{"subw", one(0002100), one(0177700), "#w$s"}, +{"subw", one(0110100), one(0170700), "*wDd"}, +{"subw", one(0110300), one(0170700), "*wAd"}, /* suba written as sub */ +{"subw", one(0110500), one(0170700), "Dd~s"}, +{"subxb", one(0110400), one(0170770), "DsDd"}, /* subxb Ds, Dd */ +{"subxb", one(0110410), one(0170770), "-s-d"}, /* subxb -(As), -(Ad) */ +{"subxl", one(0110600), one(0170770), "DsDd"}, +{"subxl", one(0110610), one(0170770), "-s-d"}, +{"subxw", one(0110500), one(0170770), "DsDd"}, +{"subxw", one(0110510), one(0170770), "-s-d"}, + +{"swap", one(0044100), one(0177770), "Ds"}, + +{"tas", one(0045300), one(0177700), "$s"}, +{"trap", one(0047100), one(0177760), "Ts"}, + +{"trapcc", one(0052374), one(0177777), ""}, +{"trapcs", one(0052774), one(0177777), ""}, +{"trapeq", one(0053774), one(0177777), ""}, +{"trapf", one(0050774), one(0177777), ""}, +{"trapge", one(0056374), one(0177777), ""}, +{"trapgt", one(0057374), one(0177777), ""}, +{"traphi", one(0051374), one(0177777), ""}, +{"traple", one(0057774), one(0177777), ""}, +{"trapls", one(0051774), one(0177777), ""}, +{"traplt", one(0056774), one(0177777), ""}, +{"trapmi", one(0055774), one(0177777), ""}, +{"trapne", one(0053374), one(0177777), ""}, +{"trappl", one(0055374), one(0177777), ""}, +{"trapt", one(0050374), one(0177777), ""}, +{"trapvc", one(0054374), one(0177777), ""}, +{"trapvs", one(0054774), one(0177777), ""}, + +{"trapcc.w", one(0052372), one(0177777), ""}, +{"trapcs.w", one(0052772), one(0177777), ""}, +{"trapeq.w", one(0053772), one(0177777), ""}, +{"trapf.w", one(0050772), one(0177777), ""}, +{"trapge.w", one(0056372), one(0177777), ""}, +{"trapgt.w", one(0057372), one(0177777), ""}, +{"traphi.w", one(0051372), one(0177777), ""}, +{"traple.w", one(0057772), one(0177777), ""}, +{"trapls.w", one(0051772), one(0177777), ""}, +{"traplt.w", one(0056772), one(0177777), ""}, +{"trapmi.w", one(0055772), one(0177777), ""}, +{"trapne.w", one(0053372), one(0177777), ""}, +{"trappl.w", one(0055372), one(0177777), ""}, +{"trapt.w", one(0050372), one(0177777), ""}, +{"trapvc.w", one(0054372), one(0177777), ""}, +{"trapvs.w", one(0054772), one(0177777), ""}, + +{"trapcc.l", one(0052373), one(0177777), ""}, +{"trapcs.l", one(0052773), one(0177777), ""}, +{"trapeq.l", one(0053773), one(0177777), ""}, +{"trapf.l", one(0050773), one(0177777), ""}, +{"trapge.l", one(0056373), one(0177777), ""}, +{"trapgt.l", one(0057373), one(0177777), ""}, +{"traphi.l", one(0051373), one(0177777), ""}, +{"traple.l", one(0057773), one(0177777), ""}, +{"trapls.l", one(0051773), one(0177777), ""}, +{"traplt.l", one(0056773), one(0177777), ""}, +{"trapmi.l", one(0055773), one(0177777), ""}, +{"trapne.l", one(0053373), one(0177777), ""}, +{"trappl.l", one(0055373), one(0177777), ""}, +{"trapt.l", one(0050373), one(0177777), ""}, +{"trapvc.l", one(0054373), one(0177777), ""}, +{"trapvs.l", one(0054773), one(0177777), ""}, + +{"trapv", one(0047166), one(0177777), ""}, + +{"tstb", one(0045000), one(0177700), ";b"}, +{"tstw", one(0045100), one(0177700), "*w"}, +{"tstl", one(0045200), one(0177700), "*l"}, + +{"unlk", one(0047130), one(0177770), "As"}, +{"unpk", one(0100600), one(0170770), "DsDd#w"}, +{"unpk", one(0100610), one(0170770), "-s-d#w"}, + /* JF floating pt stuff moved down here */ + +{"fabsb", two(0xF000, 0x5818), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fabsd", two(0xF000, 0x5418), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fabsl", two(0xF000, 0x4018), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fabsp", two(0xF000, 0x4C18), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fabss", two(0xF000, 0x4418), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fabsw", two(0xF000, 0x5018), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fabsx", two(0xF000, 0x0018), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fabsx", two(0xF000, 0x4818), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fabsx", two(0xF000, 0x0018), two(0xF1C0, 0xE07F), "IiFt"}, + +{"facosb", two(0xF000, 0x581C), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"facosd", two(0xF000, 0x541C), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"facosl", two(0xF000, 0x401C), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"facosp", two(0xF000, 0x4C1C), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"facoss", two(0xF000, 0x441C), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"facosw", two(0xF000, 0x501C), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"facosx", two(0xF000, 0x001C), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"facosx", two(0xF000, 0x481C), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"facosx", two(0xF000, 0x001C), two(0xF1C0, 0xE07F), "IiFt"}, + +{"faddb", two(0xF000, 0x5822), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"faddd", two(0xF000, 0x5422), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"faddl", two(0xF000, 0x4022), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"faddp", two(0xF000, 0x4C22), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fadds", two(0xF000, 0x4422), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"faddw", two(0xF000, 0x5022), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"faddx", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"faddx", two(0xF000, 0x4822), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"faddx", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiFt"}, JF removed */ + +{"fasinb", two(0xF000, 0x580C), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fasind", two(0xF000, 0x540C), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fasinl", two(0xF000, 0x400C), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fasinp", two(0xF000, 0x4C0C), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fasins", two(0xF000, 0x440C), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fasinw", two(0xF000, 0x500C), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fasinx", two(0xF000, 0x000C), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fasinx", two(0xF000, 0x480C), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fasinx", two(0xF000, 0x000C), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fatanb", two(0xF000, 0x580A), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fatand", two(0xF000, 0x540A), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fatanl", two(0xF000, 0x400A), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fatanp", two(0xF000, 0x4C0A), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fatans", two(0xF000, 0x440A), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fatanw", two(0xF000, 0x500A), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fatanx", two(0xF000, 0x000A), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fatanx", two(0xF000, 0x480A), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fatanx", two(0xF000, 0x000A), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fatanhb", two(0xF000, 0x580D), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fatanhd", two(0xF000, 0x540D), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fatanhl", two(0xF000, 0x400D), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fatanhp", two(0xF000, 0x4C0D), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fatanhs", two(0xF000, 0x440D), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fatanhw", two(0xF000, 0x500D), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fatanhx", two(0xF000, 0x000D), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fatanhx", two(0xF000, 0x480D), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fatanhx", two(0xF000, 0x000D), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fbeq", one(0xF081), one(0xF1BF), "IdBc"}, +{"fbf", one(0xF080), one(0xF1BF), "IdBc"}, +{"fbge", one(0xF093), one(0xF1BF), "IdBc"}, +{"fbgl", one(0xF096), one(0xF1BF), "IdBc"}, +{"fbgle", one(0xF097), one(0xF1BF), "IdBc"}, +{"fbgt", one(0xF092), one(0xF1BF), "IdBc"}, +{"fble", one(0xF095), one(0xF1BF), "IdBc"}, +{"fblt", one(0xF094), one(0xF1BF), "IdBc"}, +{"fbne", one(0xF08E), one(0xF1BF), "IdBc"}, +{"fbnge", one(0xF09C), one(0xF1BF), "IdBc"}, +{"fbngl", one(0xF099), one(0xF1BF), "IdBc"}, +{"fbngle", one(0xF098), one(0xF1BF), "IdBc"}, +{"fbngt", one(0xF09D), one(0xF1BF), "IdBc"}, +{"fbnle", one(0xF09A), one(0xF1BF), "IdBc"}, +{"fbnlt", one(0xF09B), one(0xF1BF), "IdBc"}, +{"fboge", one(0xF083), one(0xF1BF), "IdBc"}, +{"fbogl", one(0xF086), one(0xF1BF), "IdBc"}, +{"fbogt", one(0xF082), one(0xF1BF), "IdBc"}, +{"fbole", one(0xF085), one(0xF1BF), "IdBc"}, +{"fbolt", one(0xF084), one(0xF1BF), "IdBc"}, +{"fbor", one(0xF087), one(0xF1BF), "IdBc"}, +{"fbseq", one(0xF091), one(0xF1BF), "IdBc"}, +{"fbsf", one(0xF090), one(0xF1BF), "IdBc"}, +{"fbsne", one(0xF09E), one(0xF1BF), "IdBc"}, +{"fbst", one(0xF09F), one(0xF1BF), "IdBc"}, +{"fbt", one(0xF08F), one(0xF1BF), "IdBc"}, +{"fbueq", one(0xF089), one(0xF1BF), "IdBc"}, +{"fbuge", one(0xF08B), one(0xF1BF), "IdBc"}, +{"fbugt", one(0xF08A), one(0xF1BF), "IdBc"}, +{"fbule", one(0xF08D), one(0xF1BF), "IdBc"}, +{"fbult", one(0xF08C), one(0xF1BF), "IdBc"}, +{"fbun", one(0xF088), one(0xF1BF), "IdBc"}, + +{"fcmpb", two(0xF000, 0x5838), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fcmpd", two(0xF000, 0x5438), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fcmpl", two(0xF000, 0x4038), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fcmpp", two(0xF000, 0x4C38), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fcmps", two(0xF000, 0x4438), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fcmpw", two(0xF000, 0x5038), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fcmpx", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fcmpx", two(0xF000, 0x4838), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fcmpx", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiFt"}, JF removed */ + +{"fcosb", two(0xF000, 0x581D), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fcosd", two(0xF000, 0x541D), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fcosl", two(0xF000, 0x401D), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fcosp", two(0xF000, 0x4C1D), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fcoss", two(0xF000, 0x441D), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fcosw", two(0xF000, 0x501D), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fcosx", two(0xF000, 0x001D), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fcosx", two(0xF000, 0x481D), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fcosx", two(0xF000, 0x001D), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fcoshb", two(0xF000, 0x5819), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fcoshd", two(0xF000, 0x5419), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fcoshl", two(0xF000, 0x4019), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fcoshp", two(0xF000, 0x4C19), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fcoshs", two(0xF000, 0x4419), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fcoshw", two(0xF000, 0x5019), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fcoshx", two(0xF000, 0x0019), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fcoshx", two(0xF000, 0x4819), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fcoshx", two(0xF000, 0x0019), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fdbeq", two(0xF048, 0x0001), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbf", two(0xF048, 0x0000), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbge", two(0xF048, 0x0013), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbgl", two(0xF048, 0x0016), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbgle", two(0xF048, 0x0017), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbgt", two(0xF048, 0x0012), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdble", two(0xF048, 0x0015), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdblt", two(0xF048, 0x0014), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbne", two(0xF048, 0x000E), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbnge", two(0xF048, 0x001C), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbngl", two(0xF048, 0x0019), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbngle", two(0xF048, 0x0018), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbngt", two(0xF048, 0x001D), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbnle", two(0xF048, 0x001A), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbnlt", two(0xF048, 0x001B), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdboge", two(0xF048, 0x0003), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbogl", two(0xF048, 0x0006), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbogt", two(0xF048, 0x0002), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbole", two(0xF048, 0x0005), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbolt", two(0xF048, 0x0004), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbor", two(0xF048, 0x0007), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbseq", two(0xF048, 0x0011), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbsf", two(0xF048, 0x0010), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbsne", two(0xF048, 0x001E), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbst", two(0xF048, 0x001F), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbt", two(0xF048, 0x000F), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbueq", two(0xF048, 0x0009), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbuge", two(0xF048, 0x000B), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbugt", two(0xF048, 0x000A), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbule", two(0xF048, 0x000D), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbult", two(0xF048, 0x000C), two(0xF1F8, 0xFFFF), "IiDsBw"}, +{"fdbun", two(0xF048, 0x0008), two(0xF1F8, 0xFFFF), "IiDsBw"}, + +{"fdivb", two(0xF000, 0x5820), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fdivd", two(0xF000, 0x5420), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fdivl", two(0xF000, 0x4020), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fdivp", two(0xF000, 0x4C20), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fdivs", two(0xF000, 0x4420), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fdivw", two(0xF000, 0x5020), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fdivx", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fdivx", two(0xF000, 0x4820), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fdivx", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiFt"}, JF */ + +{"fetoxb", two(0xF000, 0x5810), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fetoxd", two(0xF000, 0x5410), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fetoxl", two(0xF000, 0x4010), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fetoxp", two(0xF000, 0x4C10), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fetoxs", two(0xF000, 0x4410), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fetoxw", two(0xF000, 0x5010), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fetoxx", two(0xF000, 0x0010), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fetoxx", two(0xF000, 0x4810), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fetoxx", two(0xF000, 0x0010), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fetoxm1b", two(0xF000, 0x5808), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fetoxm1d", two(0xF000, 0x5408), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fetoxm1l", two(0xF000, 0x4008), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fetoxm1p", two(0xF000, 0x4C08), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fetoxm1s", two(0xF000, 0x4408), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fetoxm1w", two(0xF000, 0x5008), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fetoxm1x", two(0xF000, 0x0008), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fetoxm1x", two(0xF000, 0x4808), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fetoxm1x", two(0xF000, 0x0008), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fgetexpb", two(0xF000, 0x581E), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fgetexpd", two(0xF000, 0x541E), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fgetexpl", two(0xF000, 0x401E), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fgetexpp", two(0xF000, 0x4C1E), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fgetexps", two(0xF000, 0x441E), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fgetexpw", two(0xF000, 0x501E), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fgetexpx", two(0xF000, 0x001E), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fgetexpx", two(0xF000, 0x481E), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fgetexpx", two(0xF000, 0x001E), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fgetmanb", two(0xF000, 0x581F), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fgetmand", two(0xF000, 0x541F), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fgetmanl", two(0xF000, 0x401F), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fgetmanp", two(0xF000, 0x4C1F), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fgetmans", two(0xF000, 0x441F), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fgetmanw", two(0xF000, 0x501F), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fgetmanx", two(0xF000, 0x001F), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fgetmanx", two(0xF000, 0x481F), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fgetmanx", two(0xF000, 0x001F), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fintb", two(0xF000, 0x5801), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fintd", two(0xF000, 0x5401), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fintl", two(0xF000, 0x4001), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fintp", two(0xF000, 0x4C01), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fints", two(0xF000, 0x4401), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fintw", two(0xF000, 0x5001), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fintx", two(0xF000, 0x0001), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fintx", two(0xF000, 0x4801), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fintx", two(0xF000, 0x0001), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fintrzb", two(0xF000, 0x5803), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fintrzd", two(0xF000, 0x5403), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fintrzl", two(0xF000, 0x4003), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fintrzp", two(0xF000, 0x4C03), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fintrzs", two(0xF000, 0x4403), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fintrzw", two(0xF000, 0x5003), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fintrzx", two(0xF000, 0x0003), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fintrzx", two(0xF000, 0x4803), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fintrzx", two(0xF000, 0x0003), two(0xF1C0, 0xE07F), "IiFt"}, + +{"flog10b", two(0xF000, 0x5815), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"flog10d", two(0xF000, 0x5415), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"flog10l", two(0xF000, 0x4015), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"flog10p", two(0xF000, 0x4C15), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"flog10s", two(0xF000, 0x4415), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"flog10w", two(0xF000, 0x5015), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"flog10x", two(0xF000, 0x0015), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"flog10x", two(0xF000, 0x4815), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"flog10x", two(0xF000, 0x0015), two(0xF1C0, 0xE07F), "IiFt"}, + +{"flog2b", two(0xF000, 0x5816), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"flog2d", two(0xF000, 0x5416), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"flog2l", two(0xF000, 0x4016), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"flog2p", two(0xF000, 0x4C16), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"flog2s", two(0xF000, 0x4416), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"flog2w", two(0xF000, 0x5016), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"flog2x", two(0xF000, 0x0016), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"flog2x", two(0xF000, 0x4816), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"flog2x", two(0xF000, 0x0016), two(0xF1C0, 0xE07F), "IiFt"}, + +{"flognb", two(0xF000, 0x5814), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"flognd", two(0xF000, 0x5414), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"flognl", two(0xF000, 0x4014), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"flognp", two(0xF000, 0x4C14), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"flogns", two(0xF000, 0x4414), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"flognw", two(0xF000, 0x5014), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"flognx", two(0xF000, 0x0014), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"flognx", two(0xF000, 0x4814), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"flognx", two(0xF000, 0x0014), two(0xF1C0, 0xE07F), "IiFt"}, + +{"flognp1b", two(0xF000, 0x5806), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"flognp1d", two(0xF000, 0x5406), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"flognp1l", two(0xF000, 0x4006), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"flognp1p", two(0xF000, 0x4C06), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"flognp1s", two(0xF000, 0x4406), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"flognp1w", two(0xF000, 0x5006), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"flognp1x", two(0xF000, 0x0006), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"flognp1x", two(0xF000, 0x4806), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"flognp1x", two(0xF000, 0x0006), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fmodb", two(0xF000, 0x5821), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fmodd", two(0xF000, 0x5421), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fmodl", two(0xF000, 0x4021), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fmodp", two(0xF000, 0x4C21), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fmods", two(0xF000, 0x4421), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fmodw", two(0xF000, 0x5021), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fmodx", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fmodx", two(0xF000, 0x4821), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fmodx", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiFt"}, JF */ + +{"fmoveb", two(0xF000, 0x5800), two(0xF1C0, 0xFC7F), "Ii;bF7"}, /* fmove from <ea> to fp<n> */ +{"fmoveb", two(0xF000, 0x7800), two(0xF1C0, 0xFC7F), "IiF7@b"}, /* fmove from fp<n> to <ea> */ +{"fmoved", two(0xF000, 0x5400), two(0xF1C0, 0xFC7F), "Ii;FF7"}, /* fmove from <ea> to fp<n> */ +{"fmoved", two(0xF000, 0x7400), two(0xF1C0, 0xFC7F), "IiF7@F"}, /* fmove from fp<n> to <ea> */ +{"fmovel", two(0xF000, 0x4000), two(0xF1C0, 0xFC7F), "Ii;lF7"}, /* fmove from <ea> to fp<n> */ +{"fmovel", two(0xF000, 0x6000), two(0xF1C0, 0xFC7F), "IiF7@l"}, /* fmove from fp<n> to <ea> */ +/* Warning: The addressing modes on these are probably not right: + esp, Areg direct is only allowed for FPI */ + /* fmove.l from/to system control registers: */ +{"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, +{"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ls8"}, + +/* {"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, +{"fmovel", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*ss8"}, */ + +{"fmovep", two(0xF000, 0x4C00), two(0xF1C0, 0xFC7F), "Ii;pF7"}, /* fmove from <ea> to fp<n> */ +{"fmovep", two(0xF000, 0x6C00), two(0xF1C0, 0xFC00), "IiF7@pkC"}, /* fmove.p with k-factors: */ +{"fmovep", two(0xF000, 0x7C00), two(0xF1C0, 0xFC0F), "IiF7@pDk"}, /* fmove.p with k-factors: */ + +{"fmoves", two(0xF000, 0x4400), two(0xF1C0, 0xFC7F), "Ii;fF7"}, /* fmove from <ea> to fp<n> */ +{"fmoves", two(0xF000, 0x6400), two(0xF1C0, 0xFC7F), "IiF7@f"}, /* fmove from fp<n> to <ea> */ +{"fmovew", two(0xF000, 0x5000), two(0xF1C0, 0xFC7F), "Ii;wF7"}, /* fmove from <ea> to fp<n> */ +{"fmovew", two(0xF000, 0x7000), two(0xF1C0, 0xFC7F), "IiF7@w"}, /* fmove from fp<n> to <ea> */ +{"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiF8F7"}, /* fmove from <ea> to fp<n> */ +{"fmovex", two(0xF000, 0x4800), two(0xF1C0, 0xFC7F), "Ii;xF7"}, /* fmove from <ea> to fp<n> */ +{"fmovex", two(0xF000, 0x6800), two(0xF1C0, 0xFC7F), "IiF7@x"}, /* fmove from fp<n> to <ea> */ +/* JF removed {"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiFt"}, / * fmove from <ea> to fp<n> */ + +{"fmovecrx", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7"}, /* fmovecr.x #ccc, FPn */ +{"fmovecr", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7"}, + +/* Other fmovemx. */ +{"fmovemx", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s"}, /* fmovem.x to autodecrement, static and dynamic */ +{"fmovemx", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s"}, /* fmovem.x to autodecrement, static and dynamic */ + +{"fmovemx", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s"}, /* fmovem.x to autodecrement, static and dynamic */ + +{"fmovemx", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3"}, /* fmovem.x from control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk"}, /* fmovem.x from control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3"}, /* fmovem.x from control, static and dynamic: */ + +{"fmovemx", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3"}, /* fmovem.x from autoincrement, static and dynamic: */ +{"fmovemx", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3"}, /* fmovem.x from autoincrement, static and dynamic: */ +{"fmovemx", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk"}, /* fmovem.x from autoincrement, static and dynamic: */ + +{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8@s"}, +{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Ii#8@s"}, +{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, + +{"fmoveml", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8"}, +{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*s#8"}, +{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8"}, + +/* fmovemx with register lists */ +{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s"}, /* fmovem.x to autodecrement, static and dynamic */ +{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3"}, /* fmovem.x from autoincrement, static and dynamic: */ +{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3"}, /* fmovem.x from control, static and dynamic: */ + + /* Alternate mnemonics for GNU as and GNU CC */ +{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s"}, /* fmovem.x to autodecrement, static and dynamic */ +{"fmovem", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s"}, /* fmovem.x to autodecrement, static and dynamic */ + +{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovem", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s"}, /* fmovem.x to control, static and dynamic: */ + +{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3"}, /* fmovem.x from autoincrement, static and dynamic: */ +{"fmovem", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk"}, /* fmovem.x from autoincrement, static and dynamic: */ + +{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3"}, /* fmovem.x from control, static and dynamic: */ +{"fmovem", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk"}, /* fmovem.x from control, static and dynamic: */ + +/* fmoveml a FP-control register */ +{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, +{"fmovem", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8"}, + +/* fmoveml a FP-control reglist */ +{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8@s"}, +{"fmovem", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8"}, + +{"fmulb", two(0xF000, 0x5823), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fmuld", two(0xF000, 0x5423), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fmull", two(0xF000, 0x4023), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fmulp", two(0xF000, 0x4C23), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fmuls", two(0xF000, 0x4423), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fmulw", two(0xF000, 0x5023), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fmulx", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fmulx", two(0xF000, 0x4823), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fmulx", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiFt"}, JF */ + +{"fnegb", two(0xF000, 0x581A), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fnegd", two(0xF000, 0x541A), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fnegl", two(0xF000, 0x401A), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fnegp", two(0xF000, 0x4C1A), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fnegs", two(0xF000, 0x441A), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fnegw", two(0xF000, 0x501A), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fnegx", two(0xF000, 0x001A), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fnegx", two(0xF000, 0x481A), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fnegx", two(0xF000, 0x001A), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fnop", two(0xF280, 0x0000), two(0xFFFF, 0xFFFF), "Ii"}, + +{"fremb", two(0xF000, 0x5825), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fremd", two(0xF000, 0x5425), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"freml", two(0xF000, 0x4025), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fremp", two(0xF000, 0x4C25), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"frems", two(0xF000, 0x4425), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fremw", two(0xF000, 0x5025), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fremx", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fremx", two(0xF000, 0x4825), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fremx", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiFt"}, JF */ + +{"frestore", one(0xF140), one(0xF1C0), "Id&s"}, +{"frestore", one(0xF158), one(0xF1F8), "Id+s"}, +{"fsave", one(0xF100), one(0xF1C0), "Id&s"}, +{"fsave", one(0xF120), one(0xF1F8), "Id-s"}, + +{"fsincosb", two(0xF000, 0x5830), two(0xF1C0, 0xFC78), "Ii;bF3F7"}, +{"fsincosd", two(0xF000, 0x5430), two(0xF1C0, 0xFC78), "Ii;FF3F7"}, +{"fsincosl", two(0xF000, 0x4030), two(0xF1C0, 0xFC78), "Ii;lF3F7"}, +{"fsincosp", two(0xF000, 0x4C30), two(0xF1C0, 0xFC78), "Ii;pF3F7"}, +{"fsincoss", two(0xF000, 0x4430), two(0xF1C0, 0xFC78), "Ii;fF3F7"}, +{"fsincosw", two(0xF000, 0x5030), two(0xF1C0, 0xFC78), "Ii;wF3F7"}, +{"fsincosx", two(0xF000, 0x0030), two(0xF1C0, 0xE078), "IiF8F3F7"}, +{"fsincosx", two(0xF000, 0x4830), two(0xF1C0, 0xFC78), "Ii;xF3F7"}, + +{"fscaleb", two(0xF000, 0x5826), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fscaled", two(0xF000, 0x5426), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fscalel", two(0xF000, 0x4026), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fscalep", two(0xF000, 0x4C26), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fscales", two(0xF000, 0x4426), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fscalew", two(0xF000, 0x5026), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fscalex", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fscalex", two(0xF000, 0x4826), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fscalex", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiFt"}, JF */ + +/* $ is necessary to prevent the assembler from using PC-relative. + If @ were used, "label: fseq label" could produce "ftrapeq", + because "label" became "pc@label". */ +{"fseq", two(0xF040, 0x0001), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsf", two(0xF040, 0x0000), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsge", two(0xF040, 0x0013), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsgl", two(0xF040, 0x0016), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsgle", two(0xF040, 0x0017), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsgt", two(0xF040, 0x0012), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsle", two(0xF040, 0x0015), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fslt", two(0xF040, 0x0014), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsne", two(0xF040, 0x000E), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsnge", two(0xF040, 0x001C), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsngl", two(0xF040, 0x0019), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsngle", two(0xF040, 0x0018), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsngt", two(0xF040, 0x001D), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsnle", two(0xF040, 0x001A), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsnlt", two(0xF040, 0x001B), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsoge", two(0xF040, 0x0003), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsogl", two(0xF040, 0x0006), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsogt", two(0xF040, 0x0002), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsole", two(0xF040, 0x0005), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsolt", two(0xF040, 0x0004), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsor", two(0xF040, 0x0007), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsseq", two(0xF040, 0x0011), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fssf", two(0xF040, 0x0010), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fssne", two(0xF040, 0x001E), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsst", two(0xF040, 0x001F), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fst", two(0xF040, 0x000F), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsueq", two(0xF040, 0x0009), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsuge", two(0xF040, 0x000B), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsugt", two(0xF040, 0x000A), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsule", two(0xF040, 0x000D), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsult", two(0xF040, 0x000C), two(0xF1C0, 0xFFFF), "Ii$s"}, +{"fsun", two(0xF040, 0x0008), two(0xF1C0, 0xFFFF), "Ii$s"}, + +{"fsgldivb", two(0xF000, 0x5824), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fsgldivd", two(0xF000, 0x5424), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fsgldivl", two(0xF000, 0x4024), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fsgldivp", two(0xF000, 0x4C24), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fsgldivs", two(0xF000, 0x4424), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fsgldivw", two(0xF000, 0x5024), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fsgldivx", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fsgldivx", two(0xF000, 0x4824), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsgldivx", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fsglmulb", two(0xF000, 0x5827), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fsglmuld", two(0xF000, 0x5427), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fsglmull", two(0xF000, 0x4027), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fsglmulp", two(0xF000, 0x4C27), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fsglmuls", two(0xF000, 0x4427), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fsglmulw", two(0xF000, 0x5027), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fsglmulx", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fsglmulx", two(0xF000, 0x4827), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsglmulx", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fsinb", two(0xF000, 0x580E), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fsind", two(0xF000, 0x540E), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fsinl", two(0xF000, 0x400E), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fsinp", two(0xF000, 0x4C0E), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fsins", two(0xF000, 0x440E), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fsinw", two(0xF000, 0x500E), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fsinx", two(0xF000, 0x000E), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fsinx", two(0xF000, 0x480E), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsinx", two(0xF000, 0x000E), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fsinhb", two(0xF000, 0x5802), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fsinhd", two(0xF000, 0x5402), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fsinhl", two(0xF000, 0x4002), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fsinhp", two(0xF000, 0x4C02), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fsinhs", two(0xF000, 0x4402), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fsinhw", two(0xF000, 0x5002), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fsinhx", two(0xF000, 0x0002), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fsinhx", two(0xF000, 0x4802), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsinhx", two(0xF000, 0x0002), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fsqrtb", two(0xF000, 0x5804), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fsqrtd", two(0xF000, 0x5404), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fsqrtl", two(0xF000, 0x4004), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fsqrtp", two(0xF000, 0x4C04), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fsqrts", two(0xF000, 0x4404), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fsqrtw", two(0xF000, 0x5004), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fsqrtx", two(0xF000, 0x0004), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fsqrtx", two(0xF000, 0x4804), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsqrtx", two(0xF000, 0x0004), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fsubb", two(0xF000, 0x5828), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"fsubd", two(0xF000, 0x5428), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"fsubl", two(0xF000, 0x4028), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"fsubp", two(0xF000, 0x4C28), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"fsubs", two(0xF000, 0x4428), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"fsubw", two(0xF000, 0x5028), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"fsubx", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"fsubx", two(0xF000, 0x4828), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsubx", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiFt"}, + +{"ftanb", two(0xF000, 0x580F), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"ftand", two(0xF000, 0x540F), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"ftanl", two(0xF000, 0x400F), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"ftanp", two(0xF000, 0x4C0F), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"ftans", two(0xF000, 0x440F), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"ftanw", two(0xF000, 0x500F), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"ftanx", two(0xF000, 0x000F), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"ftanx", two(0xF000, 0x480F), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"ftanx", two(0xF000, 0x000F), two(0xF1C0, 0xE07F), "IiFt"}, + +{"ftanhb", two(0xF000, 0x5809), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"ftanhd", two(0xF000, 0x5409), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"ftanhl", two(0xF000, 0x4009), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"ftanhp", two(0xF000, 0x4C09), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"ftanhs", two(0xF000, 0x4409), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"ftanhw", two(0xF000, 0x5009), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"ftanhx", two(0xF000, 0x0009), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"ftanhx", two(0xF000, 0x4809), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"ftanhx", two(0xF000, 0x0009), two(0xF1C0, 0xE07F), "IiFt"}, + +{"ftentoxb", two(0xF000, 0x5812), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"ftentoxd", two(0xF000, 0x5412), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"ftentoxl", two(0xF000, 0x4012), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"ftentoxp", two(0xF000, 0x4C12), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"ftentoxs", two(0xF000, 0x4412), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"ftentoxw", two(0xF000, 0x5012), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"ftentoxx", two(0xF000, 0x0012), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"ftentoxx", two(0xF000, 0x4812), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"ftentoxx", two(0xF000, 0x0012), two(0xF1C0, 0xE07F), "IiFt"}, + +{"ftrapeq", two(0xF07C, 0x0001), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapf", two(0xF07C, 0x0000), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapge", two(0xF07C, 0x0013), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapgl", two(0xF07C, 0x0016), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapgle", two(0xF07C, 0x0017), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapgt", two(0xF07C, 0x0012), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftraple", two(0xF07C, 0x0015), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftraplt", two(0xF07C, 0x0014), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapne", two(0xF07C, 0x000E), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapnge", two(0xF07C, 0x001C), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapngl", two(0xF07C, 0x0019), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapngle", two(0xF07C, 0x0018), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapngt", two(0xF07C, 0x001D), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapnle", two(0xF07C, 0x001A), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapnlt", two(0xF07C, 0x001B), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapoge", two(0xF07C, 0x0003), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapogl", two(0xF07C, 0x0006), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapogt", two(0xF07C, 0x0002), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapole", two(0xF07C, 0x0005), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapolt", two(0xF07C, 0x0004), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapor", two(0xF07C, 0x0007), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapseq", two(0xF07C, 0x0011), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapsf", two(0xF07C, 0x0010), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapsne", two(0xF07C, 0x001E), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapst", two(0xF07C, 0x001F), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapt", two(0xF07C, 0x000F), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapueq", two(0xF07C, 0x0009), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapuge", two(0xF07C, 0x000B), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapugt", two(0xF07C, 0x000A), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapule", two(0xF07C, 0x000D), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapult", two(0xF07C, 0x000C), two(0xF1FF, 0xFFFF), "Ii"}, +{"ftrapun", two(0xF07C, 0x0008), two(0xF1FF, 0xFFFF), "Ii"}, + +{"ftrapeqw", two(0xF07A, 0x0001), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapfw", two(0xF07A, 0x0000), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapgew", two(0xF07A, 0x0013), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapglw", two(0xF07A, 0x0016), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapglew", two(0xF07A, 0x0017), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapgtw", two(0xF07A, 0x0012), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftraplew", two(0xF07A, 0x0015), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapltw", two(0xF07A, 0x0014), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapnew", two(0xF07A, 0x000E), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapngew", two(0xF07A, 0x001C), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapnglw", two(0xF07A, 0x0019), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapnglew", two(0xF07A, 0x0018), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapngtw", two(0xF07A, 0x001D), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapnlew", two(0xF07A, 0x001A), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapnltw", two(0xF07A, 0x001B), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapogew", two(0xF07A, 0x0003), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapoglw", two(0xF07A, 0x0006), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapogtw", two(0xF07A, 0x0002), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapolew", two(0xF07A, 0x0005), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapoltw", two(0xF07A, 0x0004), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftraporw", two(0xF07A, 0x0007), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapseqw", two(0xF07A, 0x0011), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapsfw", two(0xF07A, 0x0010), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapsnew", two(0xF07A, 0x001E), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapstw", two(0xF07A, 0x001F), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftraptw", two(0xF07A, 0x000F), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapueqw", two(0xF07A, 0x0009), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapugew", two(0xF07A, 0x000B), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapugtw", two(0xF07A, 0x000A), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapulew", two(0xF07A, 0x000D), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapultw", two(0xF07A, 0x000C), two(0xF1FF, 0xFFFF), "Ii^w"}, +{"ftrapunw", two(0xF07A, 0x0008), two(0xF1FF, 0xFFFF), "Ii^w"}, + +{"ftrapeql", two(0xF07B, 0x0001), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapfl", two(0xF07B, 0x0000), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapgel", two(0xF07B, 0x0013), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapgll", two(0xF07B, 0x0016), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapglel", two(0xF07B, 0x0017), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapgtl", two(0xF07B, 0x0012), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftraplel", two(0xF07B, 0x0015), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapltl", two(0xF07B, 0x0014), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapnel", two(0xF07B, 0x000E), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapngel", two(0xF07B, 0x001C), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapngll", two(0xF07B, 0x0019), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapnglel", two(0xF07B, 0x0018), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapngtl", two(0xF07B, 0x001D), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapnlel", two(0xF07B, 0x001A), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapnltl", two(0xF07B, 0x001B), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapogel", two(0xF07B, 0x0003), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapogll", two(0xF07B, 0x0006), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapogtl", two(0xF07B, 0x0002), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapolel", two(0xF07B, 0x0005), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapoltl", two(0xF07B, 0x0004), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftraporl", two(0xF07B, 0x0007), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapseql", two(0xF07B, 0x0011), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapsfl", two(0xF07B, 0x0010), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapsnel", two(0xF07B, 0x001E), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapstl", two(0xF07B, 0x001F), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftraptl", two(0xF07B, 0x000F), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapueql", two(0xF07B, 0x0009), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapugel", two(0xF07B, 0x000B), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapugtl", two(0xF07B, 0x000A), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapulel", two(0xF07B, 0x000D), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapultl", two(0xF07B, 0x000C), two(0xF1FF, 0xFFFF), "Ii^l"}, +{"ftrapunl", two(0xF07B, 0x0008), two(0xF1FF, 0xFFFF), "Ii^l"}, + +{"ftstb", two(0xF000, 0x583A), two(0xF1C0, 0xFC7F), "Ii;b"}, +{"ftstd", two(0xF000, 0x543A), two(0xF1C0, 0xFC7F), "Ii;F"}, +{"ftstl", two(0xF000, 0x403A), two(0xF1C0, 0xFC7F), "Ii;l"}, +{"ftstp", two(0xF000, 0x4C3A), two(0xF1C0, 0xFC7F), "Ii;p"}, +{"ftsts", two(0xF000, 0x443A), two(0xF1C0, 0xFC7F), "Ii;f"}, +{"ftstw", two(0xF000, 0x503A), two(0xF1C0, 0xFC7F), "Ii;w"}, +{"ftstx", two(0xF000, 0x003A), two(0xF1C0, 0xE07F), "IiF8"}, +{"ftstx", two(0xF000, 0x483A), two(0xF1C0, 0xFC7F), "Ii;x"}, + +{"ftwotoxb", two(0xF000, 0x5811), two(0xF1C0, 0xFC7F), "Ii;bF7"}, +{"ftwotoxd", two(0xF000, 0x5411), two(0xF1C0, 0xFC7F), "Ii;FF7"}, +{"ftwotoxl", two(0xF000, 0x4011), two(0xF1C0, 0xFC7F), "Ii;lF7"}, +{"ftwotoxp", two(0xF000, 0x4C11), two(0xF1C0, 0xFC7F), "Ii;pF7"}, +{"ftwotoxs", two(0xF000, 0x4411), two(0xF1C0, 0xFC7F), "Ii;fF7"}, +{"ftwotoxw", two(0xF000, 0x5011), two(0xF1C0, 0xFC7F), "Ii;wF7"}, +{"ftwotoxx", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiF8F7"}, +{"ftwotoxx", two(0xF000, 0x4811), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"ftwotoxx", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiFt"}, + + +{"fjeq", one(0xF081), one(0xF1FF), "IdBc"}, +{"fjf", one(0xF080), one(0xF1FF), "IdBc"}, +{"fjge", one(0xF093), one(0xF1FF), "IdBc"}, +{"fjgl", one(0xF096), one(0xF1FF), "IdBc"}, +{"fjgle", one(0xF097), one(0xF1FF), "IdBc"}, +{"fjgt", one(0xF092), one(0xF1FF), "IdBc"}, +{"fjle", one(0xF095), one(0xF1FF), "IdBc"}, +{"fjlt", one(0xF094), one(0xF1FF), "IdBc"}, +{"fjne", one(0xF08E), one(0xF1FF), "IdBc"}, +{"fjnge", one(0xF09C), one(0xF1FF), "IdBc"}, +{"fjngl", one(0xF099), one(0xF1FF), "IdBc"}, +{"fjngle", one(0xF098), one(0xF1FF), "IdBc"}, +{"fjngt", one(0xF09D), one(0xF1FF), "IdBc"}, +{"fjnle", one(0xF09A), one(0xF1FF), "IdBc"}, +{"fjnlt", one(0xF09B), one(0xF1FF), "IdBc"}, +{"fjoge", one(0xF083), one(0xF1FF), "IdBc"}, +{"fjogl", one(0xF086), one(0xF1FF), "IdBc"}, +{"fjogt", one(0xF082), one(0xF1FF), "IdBc"}, +{"fjole", one(0xF085), one(0xF1FF), "IdBc"}, +{"fjolt", one(0xF084), one(0xF1FF), "IdBc"}, +{"fjor", one(0xF087), one(0xF1FF), "IdBc"}, +{"fjseq", one(0xF091), one(0xF1FF), "IdBc"}, +{"fjsf", one(0xF090), one(0xF1FF), "IdBc"}, +{"fjsne", one(0xF09E), one(0xF1FF), "IdBc"}, +{"fjst", one(0xF09F), one(0xF1FF), "IdBc"}, +{"fjt", one(0xF08F), one(0xF1FF), "IdBc"}, +{"fjueq", one(0xF089), one(0xF1FF), "IdBc"}, +{"fjuge", one(0xF08B), one(0xF1FF), "IdBc"}, +{"fjugt", one(0xF08A), one(0xF1FF), "IdBc"}, +{"fjule", one(0xF08D), one(0xF1FF), "IdBc"}, +{"fjult", one(0xF08C), one(0xF1FF), "IdBc"}, +{"fjun", one(0xF088), one(0xF1FF), "IdBc"}, + +/* The assembler will ignore attempts to force a short offset */ + +{"bhis", one(0061000), one(0177400), "Bg"}, +{"blss", one(0061400), one(0177400), "Bg"}, +{"bccs", one(0062000), one(0177400), "Bg"}, +{"bcss", one(0062400), one(0177400), "Bg"}, +{"bnes", one(0063000), one(0177400), "Bg"}, +{"beqs", one(0063400), one(0177400), "Bg"}, +{"bvcs", one(0064000), one(0177400), "Bg"}, +{"bvss", one(0064400), one(0177400), "Bg"}, +{"bpls", one(0065000), one(0177400), "Bg"}, +{"bmis", one(0065400), one(0177400), "Bg"}, +{"bges", one(0066000), one(0177400), "Bg"}, +{"blts", one(0066400), one(0177400), "Bg"}, +{"bgts", one(0067000), one(0177400), "Bg"}, +{"bles", one(0067400), one(0177400), "Bg"}, + +/* Alternate mnemonics for SUN */ + +{"jbsr", one(0060400), one(0177400), "Bg"}, +{"jbsr", one(0047200), one(0177700), "!s"}, +{"jra", one(0060000), one(0177400), "Bg"}, +{"jra", one(0047300), one(0177700), "!s"}, + +{"jhi", one(0061000), one(0177400), "Bg"}, +{"jls", one(0061400), one(0177400), "Bg"}, +{"jcc", one(0062000), one(0177400), "Bg"}, +{"jcs", one(0062400), one(0177400), "Bg"}, +{"jne", one(0063000), one(0177400), "Bg"}, +{"jeq", one(0063400), one(0177400), "Bg"}, +{"jvc", one(0064000), one(0177400), "Bg"}, +{"jvs", one(0064400), one(0177400), "Bg"}, +{"jpl", one(0065000), one(0177400), "Bg"}, +{"jmi", one(0065400), one(0177400), "Bg"}, +{"jge", one(0066000), one(0177400), "Bg"}, +{"jlt", one(0066400), one(0177400), "Bg"}, +{"jgt", one(0067000), one(0177400), "Bg"}, +{"jle", one(0067400), one(0177400), "Bg"}, + +/* Short offsets are ignored */ + +{"jbsrs", one(0060400), one(0177400), "Bg"}, +{"jras", one(0060000), one(0177400), "Bg"}, +{"jhis", one(0061000), one(0177400), "Bg"}, +{"jlss", one(0061400), one(0177400), "Bg"}, +{"jccs", one(0062000), one(0177400), "Bg"}, +{"jcss", one(0062400), one(0177400), "Bg"}, +{"jnes", one(0063000), one(0177400), "Bg"}, +{"jeqs", one(0063400), one(0177400), "Bg"}, +{"jvcs", one(0064000), one(0177400), "Bg"}, +{"jvss", one(0064400), one(0177400), "Bg"}, +{"jpls", one(0065000), one(0177400), "Bg"}, +{"jmis", one(0065400), one(0177400), "Bg"}, +{"jges", one(0066000), one(0177400), "Bg"}, +{"jlts", one(0066400), one(0177400), "Bg"}, +{"jgts", one(0067000), one(0177400), "Bg"}, +{"jles", one(0067400), one(0177400), "Bg"}, + +{"movql", one(0070000), one(0170400), "MsDd"}, +{"moveql", one(0070000), one(0170400), "MsDd"}, +{"moval", one(0020100), one(0170700), "*lAd"}, +{"movaw", one(0030100), one(0170700), "*wAd"}, +{"movb", one(0010000), one(0170000), ";b$d"}, /* mov */ +{"movl", one(0070000), one(0170400), "MsDd"}, /* movq written as mov */ +{"movl", one(0020000), one(0170000), "*l$d"}, +{"movl", one(0020100), one(0170700), "*lAd"}, +{"movl", one(0047140), one(0177770), "AsUd"}, /* mov to USP */ +{"movl", one(0047150), one(0177770), "UdAs"}, /* mov from USP */ +{"movc", one(0047173), one(0177777), "R1Jj"}, +{"movc", one(0047173), one(0177777), "R1#j"}, +{"movc", one(0047172), one(0177777), "JjR1"}, +{"movc", one(0047172), one(0177777), "#jR1"}, +{"movml", one(0044300), one(0177700), "#w&s"}, /* movm reg to mem. */ +{"movml", one(0044340), one(0177770), "#w-s"}, /* movm reg to autodecrement. */ +{"movml", one(0046300), one(0177700), "!s#w"}, /* movm mem to reg. */ +{"movml", one(0046330), one(0177770), "+s#w"}, /* movm autoinc to reg. */ +{"movml", one(0044300), one(0177700), "Lw&s"}, /* movm reg to mem. */ +{"movml", one(0044340), one(0177770), "lw-s"}, /* movm reg to autodecrement. */ +{"movml", one(0046300), one(0177700), "!sLw"}, /* movm mem to reg. */ +{"movml", one(0046330), one(0177770), "+sLw"}, /* movm autoinc to reg. */ +{"movmw", one(0044200), one(0177700), "#w&s"}, /* movm reg to mem. */ +{"movmw", one(0044240), one(0177770), "#w-s"}, /* movm reg to autodecrement. */ +{"movmw", one(0046200), one(0177700), "!s#w"}, /* movm mem to reg. */ +{"movmw", one(0046230), one(0177770), "+s#w"}, /* movm autoinc to reg. */ +{"movmw", one(0044200), one(0177700), "Lw&s"}, /* movm reg to mem. */ +{"movmw", one(0044240), one(0177770), "lw-s"}, /* movm reg to autodecrement. */ +{"movmw", one(0046200), one(0177700), "!sLw"}, /* movm mem to reg. */ +{"movmw", one(0046230), one(0177770), "+sLw"}, /* movm autoinc to reg. */ +{"movpl", one(0000510), one(0170770), "dsDd"}, /* memory to register */ +{"movpl", one(0000710), one(0170770), "Ddds"}, /* register to memory */ +{"movpw", one(0000410), one(0170770), "dsDd"}, /* memory to register */ +{"movpw", one(0000610), one(0170770), "Ddds"}, /* register to memory */ +{"movq", one(0070000), one(0170400), "MsDd"}, +{"movw", one(0030000), one(0170000), "*w$d"}, +{"movw", one(0030100), one(0170700), "*wAd"}, /* mova, written as mov */ +{"movw", one(0040300), one(0177700), "Ss$s"}, /* Move from sr */ +{"movw", one(0041300), one(0177700), "Cs$s"}, /* Move from ccr */ +{"movw", one(0042300), one(0177700), ";wCd"}, /* mov to ccr */ +{"movw", one(0043300), one(0177700), ";wSd"}, /* mov to sr */ + +{"movsb", two(0007000, 0), two(0177700, 07777), "~sR1"}, +{"movsb", two(0007000, 04000), two(0177700, 07777), "R1~s"}, +{"movsl", two(0007200, 0), two(0177700, 07777), "~sR1"}, +{"movsl", two(0007200, 04000), two(0177700, 07777), "R1~s"}, +{"movsw", two(0007100, 0), two(0177700, 07777), "~sR1"}, +{"movsw", two(0007100, 04000), two(0177700, 07777), "R1~s"}, + +#ifdef m68851 + /* name */ /* opcode */ /* match */ /* args */ + +{"pbac", one(0xf0c7), one(0xffbf), "Bc"}, +{"pbacw", one(0xf087), one(0xffbf), "Bc"}, +{"pbas", one(0xf0c6), one(0xffbf), "Bc"}, +{"pbasw", one(0xf086), one(0xffbf), "Bc"}, +{"pbbc", one(0xf0c1), one(0xffbf), "Bc"}, +{"pbbcw", one(0xf081), one(0xffbf), "Bc"}, +{"pbbs", one(0xf0c0), one(0xffbf), "Bc"}, +{"pbbsw", one(0xf080), one(0xffbf), "Bc"}, +{"pbcc", one(0xf0cf), one(0xffbf), "Bc"}, +{"pbccw", one(0xf08f), one(0xffbf), "Bc"}, +{"pbcs", one(0xf0ce), one(0xffbf), "Bc"}, +{"pbcsw", one(0xf08e), one(0xffbf), "Bc"}, +{"pbgc", one(0xf0cd), one(0xffbf), "Bc"}, +{"pbgcw", one(0xf08d), one(0xffbf), "Bc"}, +{"pbgs", one(0xf0cc), one(0xffbf), "Bc"}, +{"pbgsw", one(0xf08c), one(0xffbf), "Bc"}, +{"pbic", one(0xf0cb), one(0xffbf), "Bc"}, +{"pbicw", one(0xf08b), one(0xffbf), "Bc"}, +{"pbis", one(0xf0ca), one(0xffbf), "Bc"}, +{"pbisw", one(0xf08a), one(0xffbf), "Bc"}, +{"pblc", one(0xf0c3), one(0xffbf), "Bc"}, +{"pblcw", one(0xf083), one(0xffbf), "Bc"}, +{"pbls", one(0xf0c2), one(0xffbf), "Bc"}, +{"pblsw", one(0xf082), one(0xffbf), "Bc"}, +{"pbsc", one(0xf0c5), one(0xffbf), "Bc"}, +{"pbscw", one(0xf085), one(0xffbf), "Bc"}, +{"pbss", one(0xf0c4), one(0xffbf), "Bc"}, +{"pbssw", one(0xf084), one(0xffbf), "Bc"}, +{"pbwc", one(0xf0c9), one(0xffbf), "Bc"}, +{"pbwcw", one(0xf089), one(0xffbf), "Bc"}, +{"pbws", one(0xf0c8), one(0xffbf), "Bc"}, +{"pbwsw", one(0xf088), one(0xffbf), "Bc"}, + + +{"pdbac", two(0xf048, 0x0007), two(0xfff8, 0xffff), "DsBw"}, +{"pdbas", two(0xf048, 0x0006), two(0xfff8, 0xffff), "DsBw"}, +{"pdbbc", two(0xf048, 0x0001), two(0xfff8, 0xffff), "DsBw"}, +{"pdbbs", two(0xf048, 0x0000), two(0xfff8, 0xffff), "DsBw"}, +{"pdbcc", two(0xf048, 0x000f), two(0xfff8, 0xffff), "DsBw"}, +{"pdbcs", two(0xf048, 0x000e), two(0xfff8, 0xffff), "DsBw"}, +{"pdbgc", two(0xf048, 0x000d), two(0xfff8, 0xffff), "DsBw"}, +{"pdbgs", two(0xf048, 0x000c), two(0xfff8, 0xffff), "DsBw"}, +{"pdbic", two(0xf048, 0x000b), two(0xfff8, 0xffff), "DsBw"}, +{"pdbis", two(0xf048, 0x000a), two(0xfff8, 0xffff), "DsBw"}, +{"pdblc", two(0xf048, 0x0003), two(0xfff8, 0xffff), "DsBw"}, +{"pdbls", two(0xf048, 0x0002), two(0xfff8, 0xffff), "DsBw"}, +{"pdbsc", two(0xf048, 0x0005), two(0xfff8, 0xffff), "DsBw"}, +{"pdbss", two(0xf048, 0x0004), two(0xfff8, 0xffff), "DsBw"}, +{"pdbwc", two(0xf048, 0x0009), two(0xfff8, 0xffff), "DsBw"}, +{"pdbws", two(0xf048, 0x0008), two(0xfff8, 0xffff), "DsBw"}, + +{"pflusha", two(0xf000, 0x2400), two(0xffff, 0xffff), "" }, + +{"pflush", two(0xf000, 0x3010), two(0xffc0, 0xfe10), "T3T9" }, +{"pflush", two(0xf000, 0x3810), two(0xffc0, 0xfe10), "T3T9&s" }, +{"pflush", two(0xf000, 0x3008), two(0xffc0, 0xfe18), "D3T9" }, +{"pflush", two(0xf000, 0x3808), two(0xffc0, 0xfe18), "D3T9&s" }, +{"pflush", two(0xf000, 0x3000), two(0xffc0, 0xfe1e), "f3T9" }, +{"pflush", two(0xf000, 0x3800), two(0xffc0, 0xfe1e), "f3T9&s" }, + +{"pflushs", two(0xf000, 0x3410), two(0xfff8, 0xfe10), "T3T9" }, +{"pflushs", two(0xf000, 0x3c10), two(0xfff8, 0xfe00), "T3T9&s" }, +{"pflushs", two(0xf000, 0x3408), two(0xfff8, 0xfe18), "D3T9" }, +{"pflushs", two(0xf000, 0x3c08), two(0xfff8, 0xfe18), "D3T9&s" }, +{"pflushs", two(0xf000, 0x3400), two(0xfff8, 0xfe1e), "f3T9" }, +{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe1e), "f3T9&s"}, + +{"pflushr", two(0xf000, 0xa000), two(0xffc0, 0xffff), "|s" }, + +{"ploadr", two(0xf000, 0x2210), two(0xffc0, 0xfff0), "T3&s" }, +{"ploadr", two(0xf000, 0x2208), two(0xffc0, 0xfff8), "D3&s" }, +{"ploadr", two(0xf000, 0x2200), two(0xffc0, 0xfffe), "f3&s" }, +{"ploadw", two(0xf000, 0x2010), two(0xffc0, 0xfff0), "T3&s" }, +{"ploadw", two(0xf000, 0x2008), two(0xffc0, 0xfff8), "D3&s" }, +{"ploadw", two(0xf000, 0x2000), two(0xffc0, 0xfffe), "f3&s" }, + +/* TC, CRP, DRP, SRP, CAL, VAL, SCC, AC */ +{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "*sP8" }, +{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "P8%s" }, +{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "|sW8" }, +{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "W8~s" }, + +/* BADx, BACx */ +{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xe3e3), "*sX3" }, +{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xe3e3), "X3%s" }, + +/* PSR, PCSR */ +/* {"pmove", two(0xf000, 0x6100), two(oxffc0, oxffff), "*sZ8" }, */ +{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xffff), "*sY8" }, +{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xffff), "Y8%s" }, +{"pmove", two(0xf000, 0x6600), two(0xffc0, 0xffff), "Z8%s" }, + +{"prestore", one(0xf140), one(0xffc0), "&s"}, +{"prestore", one(0xf158), one(0xfff8), "+s"}, +{"psave", one(0xf100), one(0xffc0), "&s"}, +{"psave", one(0xf100), one(0xffc0), "+s"}, + +{"psac", two(0xf040, 0x0007), two(0xffc0, 0xffff), "@s"}, +{"psas", two(0xf040, 0x0006), two(0xffc0, 0xffff), "@s"}, +{"psbc", two(0xf040, 0x0001), two(0xffc0, 0xffff), "@s"}, +{"psbs", two(0xf040, 0x0000), two(0xffc0, 0xffff), "@s"}, +{"pscc", two(0xf040, 0x000f), two(0xffc0, 0xffff), "@s"}, +{"pscs", two(0xf040, 0x000e), two(0xffc0, 0xffff), "@s"}, +{"psgc", two(0xf040, 0x000d), two(0xffc0, 0xffff), "@s"}, +{"psgs", two(0xf040, 0x000c), two(0xffc0, 0xffff), "@s"}, +{"psic", two(0xf040, 0x000b), two(0xffc0, 0xffff), "@s"}, +{"psis", two(0xf040, 0x000a), two(0xffc0, 0xffff), "@s"}, +{"pslc", two(0xf040, 0x0003), two(0xffc0, 0xffff), "@s"}, +{"psls", two(0xf040, 0x0002), two(0xffc0, 0xffff), "@s"}, +{"pssc", two(0xf040, 0x0005), two(0xffc0, 0xffff), "@s"}, +{"psss", two(0xf040, 0x0004), two(0xffc0, 0xffff), "@s"}, +{"pswc", two(0xf040, 0x0009), two(0xffc0, 0xffff), "@s"}, +{"psws", two(0xf040, 0x0008), two(0xffc0, 0xffff), "@s"}, + +{"ptestr", two(0xf000, 0x8210), two(0xffc0, 0xe3f0), "T3&sQ8" }, +{"ptestr", two(0xf000, 0x8310), two(0xffc0, 0xe310), "T3&sQ8A9" }, +{"ptestr", two(0xf000, 0x8208), two(0xffc0, 0xe3f8), "D3&sQ8" }, +{"ptestr", two(0xf000, 0x8308), two(0xffc0, 0xe318), "D3&sQ8A9" }, +{"ptestr", two(0xf000, 0x8200), two(0xffc0, 0xe3fe), "f3&sQ8" }, +{"ptestr", two(0xf000, 0x8300), two(0xffc0, 0xe31e), "f3&sQ8A9" }, + +{"ptestw", two(0xf000, 0x8010), two(0xffc0, 0xe3f0), "T3&sQ8" }, +{"ptestw", two(0xf000, 0x8110), two(0xffc0, 0xe310), "T3&sQ8A9" }, +{"ptestw", two(0xf000, 0x8008), two(0xffc0, 0xe3f8), "D3&sQ8" }, +{"ptestw", two(0xf000, 0x8108), two(0xffc0, 0xe318), "D3&sQ8A9" }, +{"ptestw", two(0xf000, 0x8000), two(0xffc0, 0xe3fe), "f3&sQ8" }, +{"ptestw", two(0xf000, 0x8100), two(0xffc0, 0xe31e), "f3&sQ8A9" }, + +{"ptrapacw", two(0xf07a, 0x0007), two(0xffff, 0xffff), "#w"}, +{"ptrapacl", two(0xf07b, 0x0007), two(0xffff, 0xffff), "#l"}, +{"ptrapac", two(0xf07c, 0x0007), two(0xffff, 0xffff), ""}, + +{"ptrapasw", two(0xf07a, 0x0006), two(0xffff, 0xffff), "#w"}, +{"ptrapasl", two(0xf07b, 0x0006), two(0xffff, 0xffff), "#l"}, +{"ptrapas", two(0xf07c, 0x0006), two(0xffff, 0xffff), ""}, + +{"ptrapbcw", two(0xf07a, 0x0001), two(0xffff, 0xffff), "#w"}, +{"ptrapbcl", two(0xf07b, 0x0001), two(0xffff, 0xffff), "#l"}, +{"ptrapbc", two(0xf07c, 0x0001), two(0xffff, 0xffff), ""}, + +{"ptrapbsw", two(0xf07a, 0x0000), two(0xffff, 0xffff), "#w"}, +{"ptrapbsl", two(0xf07b, 0x0000), two(0xffff, 0xffff), "#l"}, +{"ptrapbs", two(0xf07c, 0x0000), two(0xffff, 0xffff), ""}, + +{"ptrapccw", two(0xf07a, 0x000f), two(0xffff, 0xffff), "#w"}, +{"ptrapccl", two(0xf07b, 0x000f), two(0xffff, 0xffff), "#l"}, +{"ptrapcc", two(0xf07c, 0x000f), two(0xffff, 0xffff), ""}, + +{"ptrapcsw", two(0xf07a, 0x000e), two(0xffff, 0xffff), "#w"}, +{"ptrapcsl", two(0xf07b, 0x000e), two(0xffff, 0xffff), "#l"}, +{"ptrapcs", two(0xf07c, 0x000e), two(0xffff, 0xffff), ""}, + +{"ptrapgcw", two(0xf07a, 0x000d), two(0xffff, 0xffff), "#w"}, +{"ptrapgcl", two(0xf07b, 0x000d), two(0xffff, 0xffff), "#l"}, +{"ptrapgc", two(0xf07c, 0x000d), two(0xffff, 0xffff), ""}, + +{"ptrapgsw", two(0xf07a, 0x000c), two(0xffff, 0xffff), "#w"}, +{"ptrapgsl", two(0xf07b, 0x000c), two(0xffff, 0xffff), "#l"}, +{"ptrapgs", two(0xf07c, 0x000c), two(0xffff, 0xffff), ""}, + +{"ptrapicw", two(0xf07a, 0x000b), two(0xffff, 0xffff), "#w"}, +{"ptrapicl", two(0xf07b, 0x000b), two(0xffff, 0xffff), "#l"}, +{"ptrapic", two(0xf07c, 0x000b), two(0xffff, 0xffff), ""}, + +{"ptrapisw", two(0xf07a, 0x000a), two(0xffff, 0xffff), "#w"}, +{"ptrapisl", two(0xf07b, 0x000a), two(0xffff, 0xffff), "#l"}, +{"ptrapis", two(0xf07c, 0x000a), two(0xffff, 0xffff), ""}, + +{"ptraplcw", two(0xf07a, 0x0003), two(0xffff, 0xffff), "#w"}, +{"ptraplcl", two(0xf07b, 0x0003), two(0xffff, 0xffff), "#l"}, +{"ptraplc", two(0xf07c, 0x0003), two(0xffff, 0xffff), ""}, + +{"ptraplsw", two(0xf07a, 0x0002), two(0xffff, 0xffff), "#w"}, +{"ptraplsl", two(0xf07b, 0x0002), two(0xffff, 0xffff), "#l"}, +{"ptrapls", two(0xf07c, 0x0002), two(0xffff, 0xffff), ""}, + +{"ptrapscw", two(0xf07a, 0x0005), two(0xffff, 0xffff), "#w"}, +{"ptrapscl", two(0xf07b, 0x0005), two(0xffff, 0xffff), "#l"}, +{"ptrapsc", two(0xf07c, 0x0005), two(0xffff, 0xffff), ""}, + +{"ptrapssw", two(0xf07a, 0x0004), two(0xffff, 0xffff), "#w"}, +{"ptrapssl", two(0xf07b, 0x0004), two(0xffff, 0xffff), "#l"}, +{"ptrapss", two(0xf07c, 0x0004), two(0xffff, 0xffff), ""}, + +{"ptrapwcw", two(0xf07a, 0x0009), two(0xffff, 0xffff), "#w"}, +{"ptrapwcl", two(0xf07b, 0x0009), two(0xffff, 0xffff), "#l"}, +{"ptrapwc", two(0xf07c, 0x0009), two(0xffff, 0xffff), ""}, + +{"ptrapwsw", two(0xf07a, 0x0008), two(0xffff, 0xffff), "#w"}, +{"ptrapwsl", two(0xf07b, 0x0008), two(0xffff, 0xffff), "#l"}, +{"ptrapws", two(0xf07c, 0x0008), two(0xffff, 0xffff), ""}, + +{"pvalid", two(0xf000, 0x2800), two(0xffc0, 0xffff), "Vs&s"}, +{"pvalid", two(0xf000, 0x2c00), two(0xffc0, 0xfff8), "A3&s" }, + +#endif /* m68851 */ + +}; + +int numopcodes=sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]); + +struct m68k_opcode *endop = m68k_opcodes+sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]); diff --git a/gnu/usr.bin/gas/config/m68k.c b/gnu/usr.bin/gas/config/m68k.c new file mode 100644 index 00000000000..7401a91ed28 --- /dev/null +++ b/gnu/usr.bin/gas/config/m68k.c @@ -0,0 +1,3540 @@ +/* m68k.c All the m68020 specific stuff in one convenient, huge, + slow to compile, easy to find file. + Copyright (C) 1987 Free Software Foundation, Inc. + +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 1, 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. */ + +#include <ctype.h> + +#include "m68k-opcode.h" +#include "as.h" +#include "obstack.h" +#include "frags.h" +#include "struc-symbol.h" +#include "flonum.h" +#include "expr.h" +#include "hash.h" +#include "md.h" +#include "m68k.h" + +#ifdef M_SUN +/* This variable contains the value to write out at the beginning of + the a.out file. The 2<<16 means that this is a 68020 file instead + of an old-style 68000 file */ + +long omagic = 2<<16|OMAGIC; /* Magic byte for header file */ +#else +long omagic = OMAGIC; +#endif + + +/* 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"; + +/* Chars that mean this number is a floating point constant */ +/* As in 0f12.456 */ +/* or 0d1.2345e12 */ + +const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; + +/* 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. + */ + +void fix_new(); +void install_operand(); +void install_gen_operand(); + +/* Its an arbitrary name: This means I don't approve of it */ +/* See flames below */ +struct obstack robyn; + +#define TAB(x,y) (((x)<<2)+(y)) +#define TABTYPE(xy) ((xy) >> 2) +#define BYTE 0 +#define SHORT 1 +#define LONG 2 +#define SZ_UNDEF 3 + +#define BRANCH 1 +#define FBRANCH 2 +#define PCREL 3 +#define BCC68000 4 +#define DBCC 5 +#define PCLEA 6 + +/* BCC68000 is for patching in an extra jmp instruction for long offsets + on the 68000. The 68000 doesn't support long branches with branchs */ + +/* This table desribes how you change sizes for the various types of variable + size expressions. This version only supports two kinds. */ + +/* Note that calls to frag_var need to specify the maximum expansion needed */ +/* This is currently 10 bytes for DBCC */ + +/* The fields are: + How far Forward this mode will reach: + How far Backward this mode will reach: + How many bytes this mode will add to the size of the frag + Which mode to go to if the offset won't fit in this one + */ +const relax_typeS +md_relax_table[] = { +{ 1, 1, 0, 0 }, /* First entries aren't used */ +{ 1, 1, 0, 0 }, /* For no good reason except */ +{ 1, 1, 0, 0 }, /* that the VAX doesn't either */ +{ 1, 1, 0, 0 }, + +{ (127), (-128), 0, TAB(BRANCH,SHORT)}, +{ (32767), (-32768), 2, TAB(BRANCH,LONG) }, +{ 0, 0, 4, 0 }, +{ 1, 1, 0, 0 }, + +{ 1, 1, 0, 0 }, /* FBRANCH doesn't come BYTE */ +{ (32767), (-32768), 2, TAB(FBRANCH,LONG)}, +{ 0, 0, 4, 0 }, +{ 1, 1, 0, 0 }, + +{ 1, 1, 0, 0 }, /* PCREL doesn't come BYTE */ +{ (32767), (-32768), 2, TAB(PCREL,LONG)}, +{ 0, 0, 4, 0 }, +{ 1, 1, 0, 0 }, + +{ (127), (-128), 0, TAB(BCC68000,SHORT)}, +{ (32767), (-32768), 2, TAB(BCC68000,LONG) }, +{ 0, 0, 6, 0 }, /* jmp long space */ +{ 1, 1, 0, 0 }, + +{ 1, 1, 0, 0 }, /* DBCC doesn't come BYTE */ +{ (32767), (-32768), 2, TAB(DBCC,LONG) }, +{ 0, 0, 10, 0 }, /* bra/jmp long space */ +{ 1, 1, 0, 0 }, + +{ 1, 1, 0, 0 }, /* PCLEA doesn't come BYTE */ +{ 32767, -32768, 2, TAB(PCLEA,LONG) }, +{ 0, 0, 6, 0 }, +{ 1, 1, 0, 0 }, + +}; + +void s_data1(), s_data2(), s_even(), s_space(); +void s_proc(), float_cons(); + +/* These are the machine dependent pseudo-ops. These are included so + the assembler can work on the output from the SUN C compiler, which + generates these. + */ + +/* This table describes all the machine specific pseudo-ops the assembler + has to support. The fields are: + pseudo-op name without dot + function to call to execute this pseudo-op + Integer arg to pass to the function + */ +const pseudo_typeS md_pseudo_table[] = { + { "data1", s_data1, 0 }, + { "data2", s_data2, 0 }, + { "even", s_even, 0 }, + { "skip", s_space, 0 }, + { "proc", s_proc, 0 }, + { 0, 0, 0 } +}; + + +/* #define isbyte(x) ((x)>=-128 && (x)<=127) */ +/* #define isword(x) ((x)>=-32768 && (x)<=32767) */ + +#define issbyte(x) ((x)>=-128 && (x)<=127) +#define isubyte(x) ((x)>=0 && (x)<=255) +#define issword(x) ((x)>=-32768 && (x)<=32767) +#define isuword(x) ((x)>=0 && (x)<=65535) + +#define isbyte(x) ((x)>=-128 && (x)<=255) +#define isword(x) ((x)>=-32768 && (x)<=65535) +#define islong(x) (1) + +extern char *input_line_pointer; + +/* Operands we can parse: (And associated modes) + +numb: 8 bit num +numw: 16 bit num +numl: 32 bit num +dreg: data reg 0-7 +reg: address or data register +areg: address register +apc: address register, PC, ZPC or empty string +num: 16 or 32 bit num +num2: like num +sz: w or l if omitted, l assumed +scale: 1 2 4 or 8 if omitted, 1 assumed + +7.4 IMMED #num --> NUM +0.? DREG dreg --> dreg +1.? AREG areg --> areg +2.? AINDR areg@ --> *(areg) +3.? AINC areg@+ --> *(areg++) +4.? ADEC areg@- --> *(--areg) +5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here +6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale) +6.? AINDX apc@(reg:sz:scale) --> same, with num=0 +6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale) +6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0 +6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg) +6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2) +6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0 +7.0 ABSL num:sz --> *(num) + num --> *(num) (sz L assumed) +*** MSCR otherreg --> Magic +With -l option +5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still + +examples: + #foo #0x35 #12 + d2 + a4 + a3@ + a5@+ + a6@- + a2@(12) pc@(14) + a1@(5,d2:w:1) @(45,d6:l:4) + pc@(a2) @(d4) + etc . . . + + +#name@(numw) -->turn into PC rel mode +apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale) + +*/ + +#define IMMED 1 +#define DREG 2 +#define AREG 3 +#define AINDR 4 +#define ADEC 5 +#define AINC 6 +#define AOFF 7 +#define AINDX 8 +#define APODX 9 +#define AMIND 10 +#define APRDX 11 +#define ABSL 12 +#define MSCR 13 +#define REGLST 14 + +#define FAIL 0 +#define OK 1 + +/* DATA and ADDR have to be contiguous, so that reg-DATA gives 0-7==data reg, + 8-15==addr reg for operands that take both types */ +#define DATA 1 /* 1- 8 == data registers 0-7 */ +#define ADDR (DATA+8) /* 9-16 == address regs 0-7 */ +#define FPREG (ADDR+8) /* 17-24 Eight FP registers */ +#define COPNUM (FPREG+8) /* 25-32 Co-processor #1-#8 */ + +#define PC (COPNUM+8) /* 33 Program counter */ +#define ZPC (PC+1) /* 34 Hack for Program space, but 0 addressing */ +#define SR (ZPC+1) /* 35 Status Reg */ +#define CCR (SR+1) /* 36 Condition code Reg */ + +/* These have to be in order for the movec instruction to work. */ +#define USP (CCR+1) /* 37 User Stack Pointer */ +#define ISP (USP+1) /* 38 Interrupt stack pointer */ +#define SFC (ISP+1) /* 39 */ +#define DFC (SFC+1) /* 40 */ +#define CACR (DFC+1) /* 41 */ +#define VBR (CACR+1) /* 42 */ +#define CAAR (VBR+1) /* 43 */ +#define MSP (CAAR+1) /* 44 */ + +#define FPI (MSP+1) /* 45 */ +#define FPS (FPI+1) /* 46 */ +#define FPC (FPS+1) /* 47 */ +/* + * these defines should be in m68k.c but + * i put them here to keep all the m68851 stuff + * together -rab + * JF--Make sure these #s don't clash with the ones in m68k.c + * That would be BAD. + */ +#define TC (FPC+1) /* 48 */ +#define DRP (TC+1) /* 49 */ +#define SRP (DRP+1) /* 50 */ +#define CRP (SRP+1) /* 51 */ +#define CAL (CRP+1) /* 52 */ +#define VAL (CAL+1) /* 53 */ +#define SCC (VAL+1) /* 54 */ +#define AC (SCC+1) /* 55 */ +#define BAD (AC+1) /* 56,57,58,59, 60,61,62,63 */ +#define BAC (BAD+8) /* 64,65,66,67, 68,69,70,71 */ +#define PSR (BAC+8) /* 72 */ +#define PCSR (PSR+1) /* 73 */ + + +/* Note that COPNUM==processor #1 -- COPNUM+7==#8, which stores as 000 */ +/* I think. . . */ + +#define SP ADDR+7 + +/* JF these tables here are for speed at the expense of size */ +/* You can replace them with the #if 0 versions if you really + need space and don't mind it running a bit slower */ + +static char mklower_table[256]; +#define mklower(c) (mklower_table[(unsigned char)(c)]) +static char notend_table[256]; +static char alt_notend_table[256]; +#define notend(s) ( !(notend_table[(unsigned char)(*s)] || (*s==':' &&\ + alt_notend_table[(unsigned char)(s[1])]))) + +#if 0 +#define mklower(c) (isupper(c) ? tolower(c) : c) +#endif + + +struct m68k_exp { + char *e_beg; + char *e_end; + expressionS e_exp; + short e_siz; /* 0== default 1==short/byte 2==word 3==long */ +}; + +/* Internal form of an operand. */ +struct m68k_op { + char *error; /* Couldn't parse it */ + int mode; /* What mode this instruction is in. */ + unsigned long int reg; /* Base register */ + struct m68k_exp *con1; + int ireg; /* Index register */ + int isiz; /* 0==unspec 1==byte(?) 2==short 3==long */ + int imul; /* Multipy ireg by this (1,2,4,or 8) */ + struct m68k_exp *con2; +}; + +/* internal form of a 68020 instruction */ +struct m68_it { + char *error; + char *args; /* list of opcode info */ + int numargs; + + int numo; /* Number of shorts in opcode */ + short opcode[11]; + + struct m68k_op operands[6]; + + int nexp; /* number of exprs in use */ + struct m68k_exp exprs[4]; + + int nfrag; /* Number of frags we have to produce */ + struct { + int fragoff; /* Where in the current opcode[] the frag ends */ + symbolS *fadd; + long int foff; + int fragty; + } fragb[4]; + + int nrel; /* Num of reloc strucs in use */ + struct { + int n; + symbolS *add, + *sub; + long int off; + char wid; + char pcrel; + } reloc[5]; /* Five is enough??? */ +}; + +struct m68_it the_ins; /* the instruction being assembled */ + + +/* Macros for adding things to the m68_it struct */ + +#define addword(w) the_ins.opcode[the_ins.numo++]=(w) + +/* Like addword, but goes BEFORE general operands */ +#define insop(w) {int z;\ + for(z=the_ins.numo;z>opcode->m_codenum;--z)\ + the_ins.opcode[z]=the_ins.opcode[z-1];\ + for(z=0;z<the_ins.nrel;z++)\ + the_ins.reloc[z].n+=2;\ + the_ins.opcode[opcode->m_codenum]=w;\ + the_ins.numo++;\ +} + + +#define add_exp(beg,end) (\ + the_ins.exprs[the_ins.nexp].e_beg=beg,\ + the_ins.exprs[the_ins.nexp].e_end=end,\ + &the_ins.exprs[the_ins.nexp++]\ +) + + +/* The numo+1 kludge is so we can hit the low order byte of the prev word. Blecch*/ +#define add_fix(width,exp,pc_rel) {\ + the_ins.reloc[the_ins.nrel].n= ((width)=='B') ? (the_ins.numo*2-1) : \ + (((width)=='b') ? ((the_ins.numo-1)*2) : (the_ins.numo*2));\ + the_ins.reloc[the_ins.nrel].add=adds((exp));\ + the_ins.reloc[the_ins.nrel].sub=subs((exp));\ + the_ins.reloc[the_ins.nrel].off=offs((exp));\ + the_ins.reloc[the_ins.nrel].wid=width;\ + the_ins.reloc[the_ins.nrel++].pcrel=pc_rel;\ +} + +#define add_frag(add,off,type) {\ + the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;\ + the_ins.fragb[the_ins.nfrag].fadd=add;\ + the_ins.fragb[the_ins.nfrag].foff=off;\ + the_ins.fragb[the_ins.nfrag++].fragty=type;\ +} + +#define isvar(exp) ((exp) && (adds(exp) || subs(exp))) + +#define seg(exp) ((exp)->e_exp.X_seg) +#define adds(exp) ((exp)->e_exp.X_add_symbol) +#define subs(exp) ((exp)->e_exp.X_subtract_symbol) +#define offs(exp) ((exp)->e_exp.X_add_number) + + +struct m68_incant { + char *m_operands; + unsigned long m_opcode; + short m_opnum; + short m_codenum; + struct m68_incant *m_next; +}; + +#define getone(x) ((((x)->m_opcode)>>16)&0xffff) +#define gettwo(x) (((x)->m_opcode)&0xffff) + + +/* JF modified this to handle cases where the first part of a symbol name + looks like a register */ + +int +m68k_reg_parse(ccp) +register char **ccp; +{ + register char c1, + c2, + c3, + c4; + register int n = 0, + ret = FAIL; + + c1=mklower(ccp[0][0]); +#ifdef REGISTER_PREFIX + if(c1!=REGISTER_PREFIX) + return FAIL; + c1=mklower(ccp[0][1]); + c2=mklower(ccp[0][2]); + c3=mklower(ccp[0][3]); + c4=mklower(ccp[0][4]); +#else + c2=mklower(ccp[0][1]); + c3=mklower(ccp[0][2]); + c4=mklower(ccp[0][3]); +#endif + switch(c1) { + case 'a': + if(c2>='0' && c2<='7') { + n=2; + ret=ADDR+c2-'0'; + } +#ifdef m68851 + else if (c2 == 'c') { + n = 2; + ret = AC; + } +#endif + break; +#ifdef m68851 + case 'b': + if (c2 == 'a') { + if (c3 == 'd') { + if (c4 >= '0' && c4 <= '7') { + n = 4; + ret = BAD + c4 - '0'; + } + } + if (c3 == 'c') { + if (c4 >= '0' && c4 <= '7') { + n = 4; + ret = BAC + c4 - '0'; + } + } + } + break; +#endif + case 'c': +#ifdef m68851 + if (c2 == 'a' && c3 == 'l') { + n = 3; + ret = CAL; + } else +#endif + /* This supports both CCR and CC as the ccr reg. */ + if(c2=='c' && c3=='r') { + n=3; + ret = CCR; + } else if(c2=='c') { + n=2; + ret = CCR; + } else if(c2=='a' && (c3=='a' || c3=='c') && c4=='r') { + n=4; + ret = c3=='a' ? CAAR : CACR; + } +#ifdef m68851 + else if (c2 == 'r' && c3 == 'p') { + n = 3; + ret = (CRP); + } +#endif + break; + case 'd': + if(c2>='0' && c2<='7') { + n=2; + ret = DATA+c2-'0'; + } else if(c2=='f' && c3=='c') { + n=3; + ret = DFC; + } +#ifdef m68851 + else if (c2 == 'r' && c3 == 'p') { + n = 3; + ret = (DRP); + } +#endif + break; + case 'f': + if(c2=='p') { + if(c3>='0' && c3<='7') { + n=3; + ret = FPREG+c3-'0'; + if(c4==':') + ccp[0][3]=','; + } else if(c3=='i') { + n=3; + ret = FPI; + } else if(c3=='s') { + n= (c4 == 'r' ? 4 : 3); + ret = FPS; + } else if(c3=='c') { + n= (c4 == 'r' ? 4 : 3); + ret = FPC; + } + } + break; + case 'i': + if(c2=='s' && c3=='p') { + n=3; + ret = ISP; + } + break; + case 'm': + if(c2=='s' && c3=='p') { + n=3; + ret = MSP; + } + break; + case 'p': + if(c2=='c') { +#ifdef m68851 + if(c3 == 's' && c4=='r') { + n=4; + ret = (PCSR); + } else +#endif + { + n=2; + ret = PC; + } + } +#ifdef m68851 + else if (c2 == 's' && c3 == 'r') { + n = 3; + ret = (PSR); + } +#endif + break; + case 's': +#ifdef m68851 + if (c2 == 'c' && c3 == 'c') { + n = 3; + ret = (SCC); + } else if (c2 == 'r' && c3 == 'p') { + n = 3; + ret = (SRP); + } else +#endif + if(c2=='r') { + n=2; + ret = SR; + } else if(c2=='p') { + n=2; + ret = ADDR+7; + } else if(c2=='f' && c3=='c') { + n=3; + ret = SFC; + } + break; +#ifdef m68851 + case 't': + if(c2 == 'c') { + n=2; + ret=TC; + } + break; +#endif + case 'u': + if(c2=='s' && c3=='p') { + n=3; + ret = USP; + } + break; + case 'v': +#ifdef m68851 + if (c2 == 'a' && c3 == 'l') { + n = 3; + ret = (VAL); + } else +#endif + if(c2=='b' && c3=='r') { + n=3; + ret = VBR; + } + break; + case 'z': + if(c2=='p' && c3=='c') { + n=3; + ret = ZPC; + } + break; + default: + break; + } + if(n) { +#ifdef REGISTER_PREFIX + n++; +#endif + if(isalnum(ccp[0][n]) || ccp[0][n]=='_') + ret=FAIL; + else + ccp[0]+=n; + } else + ret = FAIL; + return ret; +} + +#define SKIP_WHITE() { str++; if(*str==' ') str++;} + +int +m68k_ip_op(str,opP) +char *str; +register struct m68k_op *opP; +{ + char *strend; + long i; + char *parse_index(); + + if(*str==' ') + str++; + /* Find the end of the string */ + if(!*str) { + /* Out of gas */ + opP->error="Missing operand"; + return FAIL; + } + for(strend=str;*strend;strend++) + ; + --strend; + + /* Guess what: A constant. Shar and enjoy */ + if(*str=='#') { + str++; + opP->con1=add_exp(str,strend); + opP->mode=IMMED; + return OK; + } + i=m68k_reg_parse(&str); + if((i==FAIL || *str!='\0') && *str!='@') { + char *stmp; + char *index(); + + if(i!=FAIL && (*str=='/' || *str=='-')) { + opP->mode=REGLST; + return get_regs(i,str,opP); + } + if(stmp=index(str,'@')) { + opP->con1=add_exp(str,stmp-1); + if(stmp==strend) { + opP->mode=AINDX; + return OK; + } + stmp++; + if(*stmp++!='(' || *strend--!=')') { + opP->error="Malformed operand"; + return FAIL; + } + i=try_index(&stmp,opP); + opP->con2=add_exp(stmp,strend); + if(i==FAIL) opP->mode=AMIND; + else opP->mode=APODX; + return OK; + } + opP->mode=ABSL; + opP->con1=add_exp(str,strend); + return OK; + } + opP->reg=i; + if(*str=='\0') { + if(i>=DATA+0 && i<=DATA+7) + opP->mode=DREG; + else if(i>=ADDR+0 && i<=ADDR+7) + opP->mode=AREG; + else + opP->mode=MSCR; + return OK; + } + if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC && i!=FAIL) { /* Can't indirect off non address regs */ + opP->error="Invalid indirect register"; + return FAIL; + } + if(*str!='@') + abort(); + str++; + switch(*str) { + case '\0': + opP->mode=AINDR; + return OK; + case '-': + opP->mode=ADEC; + return OK; + case '+': + opP->mode=AINC; + return OK; + case '(': + str++; + break; + default: + opP->error="Junk after indirect"; + return FAIL; + } + /* Some kind of indexing involved. Lets find out how bad it is */ + i=try_index(&str,opP); + /* Didn't start with an index reg, maybe its offset or offset,reg */ + if(i==FAIL) { + char *beg_str; + + beg_str=str; + for(i=1;i;) { + switch(*str++) { + case '\0': + opP->error="Missing )"; + return FAIL; + case ',': i=0; break; + case '(': i++; break; + case ')': --i; break; + } + } + /* if(str[-3]==':') { + int siz; + + switch(str[-2]) { + case 'b': + case 'B': + siz=1; + break; + case 'w': + case 'W': + siz=2; + break; + case 'l': + case 'L': + siz=3; + break; + default: + opP->error="Specified size isn't :w or :l"; + return FAIL; + } + opP->con1=add_exp(beg_str,str-4); + opP->con1->e_siz=siz; + } else */ + opP->con1=add_exp(beg_str,str-2); + /* Should be offset,reg */ + if(str[-1]==',') { + i=try_index(&str,opP); + if(i==FAIL) { + opP->error="Malformed index reg"; + return FAIL; + } + } + } + /* We've now got offset) offset,reg) or reg) */ + + if(*str=='\0') { + /* Th-the-thats all folks */ + if(opP->reg==FAIL) opP->mode=AINDX; /* Other form of indirect */ + else if(opP->ireg==FAIL) opP->mode=AOFF; + else opP->mode=AINDX; + return OK; + } + /* Next thing had better be another @ */ + if(*str!='@' || str[1]!='(') { + opP->error="junk after indirect"; + return FAIL; + } + str+=2; + if(opP->ireg!=FAIL) { + opP->mode=APRDX; + i=try_index(&str,opP); + if(i!=FAIL) { + opP->error="Two index registers! not allowed!"; + return FAIL; + } + } else + i=try_index(&str,opP); + if(i==FAIL) { + char *beg_str; + + beg_str=str; + for(i=1;i;) { + switch(*str++) { + case '\0': + opP->error="Missing )"; + return FAIL; + case ',': i=0; break; + case '(': i++; break; + case ')': --i; break; + } + } + opP->con2=add_exp(beg_str,str-2); + if(str[-1]==',') { + if(opP->ireg!=FAIL) { + opP->error="Can't have two index regs"; + return FAIL; + } + i=try_index(&str,opP); + if(i==FAIL) { + opP->error="malformed index reg"; + return FAIL; + } + opP->mode=APODX; + } else if(opP->ireg!=FAIL) + opP->mode=APRDX; + else + opP->mode=AMIND; + } else + opP->mode=APODX; + if(*str!='\0') { + opP->error="Junk after indirect"; + return FAIL; + } + return OK; +} + +int +try_index(s,opP) +char **s; +struct m68k_op *opP; +{ + register int i; + char *ss; +#define SKIP_W() { ss++; if(*ss==' ') ss++;} + + ss= *s; + /* SKIP_W(); */ + i=m68k_reg_parse(&ss); + if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */ + *s=ss; + return FAIL; + } + opP->ireg=i; + /* SKIP_W(); */ + if(*ss==')') { + opP->isiz=0; + opP->imul=1; + SKIP_W(); + *s=ss; + return OK; + } + if(*ss!=':') { + opP->error="Missing : in index register"; + *s=ss; + return FAIL; + } + SKIP_W(); + switch(*ss) { + case 'w': + case 'W': + opP->isiz=2; + break; + case 'l': + case 'L': + opP->isiz=3; + break; + default: + opP->error="Index register size spec not :w or :l"; + *s=ss; + return FAIL; + } + SKIP_W(); + if(*ss==':') { + SKIP_W(); + switch(*ss) { + case '1': + case '2': + case '4': + case '8': + opP->imul= *ss-'0'; + break; + default: + opP->error="index multiplier not 1, 2, 4 or 8"; + *s=ss; + return FAIL; + } + SKIP_W(); + } else opP->imul=1; + if(*ss!=')') { + opP->error="Missing )"; + *s=ss; + return FAIL; + } + SKIP_W(); + *s=ss; + return OK; +} + +#ifdef TEST1 /* TEST1 tests m68k_ip_op(), which parses operands */ +main() +{ + char buf[128]; + struct m68k_op thark; + + for(;;) { + if(!gets(buf)) + break; + bzero(&thark,sizeof(thark)); + if(!m68k_ip_op(buf,&thark)) printf("FAIL:"); + if(thark.error) + printf("op1 error %s in %s\n",thark.error,buf); + printf("mode %d, reg %d, ",thark.mode,thark.reg); + if(thark.b_const) + printf("Constant: '%.*s',",1+thark.e_const-thark.b_const,thark.b_const); + printf("ireg %d, isiz %d, imul %d ",thark.ireg,thark.isiz,thark.imul); + if(thark.b_iadd) + printf("Iadd: '%.*s'",1+thark.e_iadd-thark.b_iadd,thark.b_iadd); + printf("\n"); + } + exit(0); +} + +#endif + + +static struct hash_control* op_hash = NULL; /* handle of the OPCODE hash table + NULL means any use before m68_ip_begin() + will crash */ + + +/* + * m 6 8 _ i p ( ) + * + * This converts a string into a 68k instruction. + * The string must be a bare single instruction in sun format + * with RMS-style 68020 indirects + * (example: ) + * + * It provides some error messages: at most one fatal error message (which + * stops the scan) and at most one warning message for each operand. + * The 68k instruction is returned in exploded form, since we have no + * knowledge of how you parse (or evaluate) your expressions. + * We do however strip off and decode addressing modes and operation + * mnemonic. + * + * This function's value is a string. If it is not "" then an internal + * logic error was found: read this code to assign meaning to the string. + * No argument string should generate such an error string: + * it means a bug in our code, not in the user's text. + * + * You MUST have called m86_ip_begin() once and m86_ip_end() never before using + * this function. + */ + +/* JF this function no longer returns a useful value. Sorry */ +void +m68_ip (instring) +char *instring; +{ + register char *p; + register struct m68k_op *opP; + register struct m68_incant *opcode; + register char *s; + register int tmpreg, + baseo, + outro, + nextword; + int siz1, + siz2; + char c; + int losing; + int opsfound; + char *crack_operand(); + LITTLENUM_TYPE words[6]; + LITTLENUM_TYPE *wordp; + + if (*instring == ' ') + instring++; /* skip leading whitespace */ + + /* Scan up to end of operation-code, which MUST end in end-of-string + or exactly 1 space. */ + for (p = instring; *p != '\0'; p++) + if (*p == ' ') + break; + + + if (p == instring) { + the_ins.error = "No operator"; + the_ins.opcode[0] = NULL; + /* the_ins.numo=1; */ + return; + } + + /* p now points to the end of the opcode name, probably whitespace. + make sure the name is null terminated by clobbering the whitespace, + look it up in the hash table, then fix it back. */ + c = *p; + *p = '\0'; + opcode = (struct m68_incant *)hash_find (op_hash, instring); + *p = c; + + if (opcode == NULL) { + the_ins.error = "Unknown operator"; + the_ins.opcode[0] = NULL; + /* the_ins.numo=1; */ + return; + } + + /* found a legitimate opcode, start matching operands */ + for(opP= &the_ins.operands[0];*p;opP++) { + p = crack_operand (p, opP); + if(opP->error) { + the_ins.error=opP->error; + return; + } + } + + opsfound=opP- &the_ins.operands[0]; + /* This ugly hack is to support the floating pt opcodes in their standard form */ + /* Essentially, we fake a first enty of type COP#1 */ + if(opcode->m_operands[0]=='I') { + int n; + + for(n=opsfound;n>0;--n) + the_ins.operands[n]=the_ins.operands[n-1]; + + /* bcopy((char *)(&the_ins.operands[0]),(char *)(&the_ins.operands[1]),opsfound*sizeof(the_ins.operands[0])); */ + bzero((char *)(&the_ins.operands[0]),sizeof(the_ins.operands[0])); + the_ins.operands[0].mode=MSCR; + the_ins.operands[0].reg=COPNUM; /* COP #1 */ + opsfound++; + } + /* We've got the operands. Find an opcode that'll + accept them */ + for(losing=0;;) { + if(opsfound!=opcode->m_opnum) + losing++; + else for(s=opcode->m_operands,opP= &the_ins.operands[0];*s && !losing;s+=2,opP++) { + /* Warning: this switch is huge! */ + /* I've tried to organize the cases into this order: + non-alpha first, then alpha by letter. lower-case goes directly + before uppercase counterpart. */ + /* Code with multiple case ...: gets sorted by the lowest case ... + it belongs to. I hope this makes sense. */ + switch(*s) { + case '!': + if(opP->mode==MSCR || opP->mode==IMMED || + opP->mode==DREG || opP->mode==AREG || opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST) + losing++; + break; + + case '#': + if(opP->mode!=IMMED) + losing++; + else { + long t; + + t=get_num(opP->con1,80); + if(s[1]=='b' && !isbyte(t)) + losing++; + else if(s[1]=='w' && !isword(t)) + losing++; + } + break; + + case '^': + case 'T': + if(opP->mode!=IMMED) + losing++; + break; + + case '$': + if(opP->mode==MSCR || opP->mode==AREG || + opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST) + losing++; + break; + + case '%': + if(opP->mode==MSCR || opP->reg==PC || + opP->reg==ZPC || opP->mode==REGLST) + losing++; + break; + + + case '&': + if(opP->mode==MSCR || opP->mode==DREG || + opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || + opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST) + losing++; + break; + + case '*': + if(opP->mode==MSCR || opP->mode==REGLST) + losing++; + break; + + case '+': + if(opP->mode!=AINC) + losing++; + break; + + case '-': + if(opP->mode!=ADEC) + losing++; + break; + + case '/': + if(opP->mode==MSCR || opP->mode==AREG || + opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->mode==REGLST) + losing++; + break; + + case ';': + if(opP->mode==MSCR || opP->mode==AREG || opP->mode==REGLST) + losing++; + break; + + case '?': + if(opP->mode==MSCR || opP->mode==AREG || + opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->reg==PC || + opP->reg==ZPC || opP->mode==REGLST) + losing++; + break; + + case '@': + if(opP->mode==MSCR || opP->mode==AREG || + opP->mode==IMMED || opP->mode==REGLST) + losing++; + break; + + case '~': /* For now! (JF FOO is this right?) */ + if(opP->mode==MSCR || opP->mode==DREG || + opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST) + losing++; + break; + + case 'A': + if(opP->mode!=AREG) + losing++; + break; + + case 'B': /* FOO */ + if(opP->mode!=ABSL) + losing++; + break; + + case 'C': + if(opP->mode!=MSCR || opP->reg!=CCR) + losing++; + break; + + case 'd': /* FOO This mode is a KLUDGE!! */ + if(opP->mode!=AOFF && (opP->mode!=ABSL || + opP->con1->e_beg[0]!='(' || opP->con1->e_end[0]!=')')) + losing++; + break; + + case 'D': + if(opP->mode!=DREG) + losing++; + break; + + case 'F': + if(opP->mode!=MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7)) + losing++; + break; + + case 'I': + if(opP->mode!=MSCR || opP->reg<COPNUM || + opP->reg>=COPNUM+7) + losing++; + break; + + case 'J': + if(opP->mode!=MSCR || opP->reg<USP || opP->reg>MSP) + losing++; + break; + + case 'k': + if(opP->mode!=IMMED) + losing++; + break; + + case 'l': + case 'L': + if(opP->mode==DREG || opP->mode==AREG || opP->mode==FPREG) { + if(s[1]=='8') + losing++; + else { + opP->mode=REGLST; + opP->reg=1<<(opP->reg-DATA); + } + } else if(opP->mode!=REGLST) { + losing++; + } else if(s[1]=='8' && opP->reg&0x0FFffFF) + losing++; + else if(s[1]=='3' && opP->reg&0x7000000) + losing++; + break; + + case 'M': + if(opP->mode!=IMMED) + losing++; + else { + long t; + + t=get_num(opP->con1,80); + if(!issbyte(t) || isvar(opP->con1)) + losing++; + } + break; + + case 'O': + if(opP->mode!=DREG && opP->mode!=IMMED) + losing++; + break; + + case 'Q': + if(opP->mode!=IMMED) + losing++; + else { + long t; + + t=get_num(opP->con1,80); + if(t<1 || t>8 || isvar(opP->con1)) + losing++; + } + break; + + case 'R': + if(opP->mode!=DREG && opP->mode!=AREG) + losing++; + break; + + case 's': + if(opP->mode!=MSCR || !(opP->reg==FPI || opP->reg==FPS || opP->reg==FPC)) + losing++; + break; + + case 'S': + if(opP->mode!=MSCR || opP->reg!=SR) + losing++; + break; + + case 'U': + if(opP->mode!=MSCR || opP->reg!=USP) + losing++; + break; + + /* JF these are out of order. We could put them + in order if we were willing to put up with + bunches of #ifdef m68851s in the code */ +#ifdef m68851 + /* Memory addressing mode used by pflushr */ + case '|': + if(opP->mode==MSCR || opP->mode==DREG || + opP->mode==AREG || opP->mode==REGLST) + losing++; + break; + + case 'f': + if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC)) + losing++; + break; + + case 'P': + if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL && + opP->reg != VAL && opP->reg != SCC && opP->reg != AC)) + losing++; + break; + + case 'V': + if (opP->reg != VAL) + losing++; + break; + + case 'W': + if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP && + opP->reg != CRP)) + losing++; + break; + + case 'X': + if (opP->mode != MSCR || + (!(opP->reg >= BAD && opP->reg <= BAD+7) && + !(opP->reg >= BAC && opP->reg <= BAC+7))) + losing++; + break; + + case 'Y': + if (opP->reg != PSR) + losing++; + break; + + case 'Z': + if (opP->reg != PCSR) + losing++; + break; +#endif + default: + as_fatal("Internal error: Operand mode %c unknown",*s); + } + } + if(!losing) + break; + opcode=opcode->m_next; + if(!opcode) { /* Fell off the end */ + the_ins.error="instruction/operands mismatch"; + return; + } + losing=0; + } + the_ins.args=opcode->m_operands; + the_ins.numargs=opcode->m_opnum; + the_ins.numo=opcode->m_codenum; + the_ins.opcode[0]=getone(opcode); + the_ins.opcode[1]=gettwo(opcode); + + for(s=the_ins.args,opP= &the_ins.operands[0];*s;s+=2,opP++) { + /* This switch is a doozy. + What the first step; its a big one! */ + switch(s[0]) { + + case '*': + case '~': + case '%': + case ';': + case '@': + case '!': + case '&': + case '$': + case '?': + case '/': +#ifdef m68851 + case '|': +#endif + switch(opP->mode) { + case IMMED: + tmpreg=0x3c; /* 7.4 */ + if(index("bwl",s[1])) nextword=get_num(opP->con1,80); + else nextword=nextword=get_num(opP->con1,0); + if(isvar(opP->con1)) + add_fix(s[1],opP->con1,0); + switch(s[1]) { + case 'b': + if(!isbyte(nextword)) + opP->error="operand out of range"; + addword(nextword); + baseo=0; + break; + case 'w': + if(!isword(nextword)) + opP->error="operand out of range"; + addword(nextword); + baseo=0; + break; + case 'l': + addword(nextword>>16); + addword(nextword); + baseo=0; + break; + + case 'f': + baseo=2; + outro=8; + break; + case 'F': + baseo=4; + outro=11; + break; + case 'x': + baseo=6; + outro=15; + break; + case 'p': + baseo=6; + outro= -1; + break; + default: + as_fatal("Internal error: Can't decode %c%c",*s,s[1]); + } + if(!baseo) + break; + + /* We gotta put out some float */ + if(seg(opP->con1)!=SEG_BIG) { + int_to_gen(nextword); + gen_to_words(words,baseo,(long int)outro); + for(wordp=words;baseo--;wordp++) + addword(*wordp); + break; + } /* Its BIG */ + if(offs(opP->con1)>0) { + as_warn("Bignum assumed to be binary bit-pattern"); + if(offs(opP->con1)>baseo) { + as_warn("Bignum too big for %c format; truncated",s[1]); + offs(opP->con1)=baseo; + } + baseo-=offs(opP->con1); + for(wordp=generic_bignum+offs(opP->con1)-1;offs(opP->con1)--;--wordp) + addword(*wordp); + while(baseo--) + addword(0); + break; + } + gen_to_words(words,baseo,(long int)outro); + for(wordp=words;baseo--;wordp++) + addword(*wordp); + break; + case DREG: + tmpreg=opP->reg-DATA; /* 0.dreg */ + break; + case AREG: + tmpreg=0x08+opP->reg-ADDR; /* 1.areg */ + break; + case AINDR: + tmpreg=0x10+opP->reg-ADDR; /* 2.areg */ + break; + case ADEC: + tmpreg=0x20+opP->reg-ADDR; /* 4.areg */ + break; + case AINC: + tmpreg=0x18+opP->reg-ADDR; /* 3.areg */ + break; + case AOFF: + + nextword=get_num(opP->con1,80); + /* Force into index mode. Hope this works */ + + /* We do the first bit for 32-bit displacements, + and the second bit for 16 bit ones. It is + possible that we should make the default be + WORD instead of LONG, but I think that'd + break GCC, so we put up with a little + inefficiency for the sake of working output. + */ + + if( !issword(nextword) + || ( isvar(opP->con1) + && ( ( opP->con1->e_siz==0 + && flagseen['l']==0) + || opP->con1->e_siz==3))) { + + if(opP->reg==PC) + tmpreg=0x3B; /* 7.3 */ + else + tmpreg=0x30+opP->reg-ADDR; /* 6.areg */ + if(isvar(opP->con1)) { + if(opP->reg==PC) { + add_frag(adds(opP->con1), + offs(opP->con1), + TAB(PCLEA,SZ_UNDEF)); + break; + } else { + addword(0x0170); + add_fix('l',opP->con1,1); + } + } else + addword(0x0170); + addword(nextword>>16); + } else { + if(opP->reg==PC) + tmpreg=0x3A; /* 7.2 */ + else + tmpreg=0x28+opP->reg-ADDR; /* 5.areg */ + + if(isvar(opP->con1)) { + if(opP->reg==PC) { + add_fix('w',opP->con1,1); + } else + add_fix('w',opP->con1,0); + } + } + addword(nextword); + break; + case AINDX: + case APODX: + case AMIND: + case APRDX: + nextword=0; + baseo=get_num(opP->con1,80); + outro=get_num(opP->con2,80); + /* Figure out the 'addressing mode' */ + /* Also turn on the BASE_DISABLE bit, if needed */ + if(opP->reg==PC || opP->reg==ZPC) { + tmpreg=0x3b; /* 7.3 */ + if(opP->reg==ZPC) + nextword|=0x80; + } else if(opP->reg==FAIL) { + nextword|=0x80; + tmpreg=0x30; /* 6.garbage */ + } else tmpreg=0x30+opP->reg-ADDR; /* 6.areg */ + + siz1= (opP->con1) ? opP->con1->e_siz : 0; + siz2= (opP->con2) ? opP->con2->e_siz : 0; + + /* Index register stuff */ + if(opP->ireg>=DATA+0 && opP->ireg<=ADDR+7) { + nextword|=(opP->ireg-DATA)<<12; + + if(opP->isiz==0 || opP->isiz==3) + nextword|=0x800; + switch(opP->imul) { + case 1: break; + case 2: nextword|=0x200; break; + case 4: nextword|=0x400; break; + case 8: nextword|=0x600; break; + default: abort(); + } + /* IF its simple, + GET US OUT OF HERE! */ + + /* Must be INDEX, with an index + register. Address register + cannot be ZERO-PC, and either + :b was forced, or we know + it will fit */ + if( opP->mode==AINDX + && opP->reg!=FAIL + && opP->reg!=ZPC + && ( siz1==1 + || ( issbyte(baseo) + && !isvar(opP->con1)))) { + nextword +=baseo&0xff; + addword(nextword); + if(isvar(opP->con1)) + add_fix('B',opP->con1,0); + break; + } + } else + nextword|=0x40; /* No index reg */ + + /* It aint simple */ + nextword|=0x100; + /* If the guy specified a width, we assume that + it is wide enough. Maybe it isn't. Ifso, we lose + */ + switch(siz1) { + case 0: + if(isvar(opP->con1) || !issword(baseo)) { + siz1=3; + nextword|=0x30; + } else if(baseo==0) + nextword|=0x10; + else { + nextword|=0x20; + siz1=2; + } + break; + case 1: + as_warn("Byte dispacement won't work. Defaulting to :w"); + case 2: + nextword|=0x20; + break; + case 3: + nextword|=0x30; + break; + } + + /* Figure out innner displacement stuff */ + if(opP->mode!=AINDX) { + switch(siz2) { + case 0: + if(isvar(opP->con2) || !issword(outro)) { + siz2=3; + nextword|=0x3; + } else if(outro==0) + nextword|=0x1; + else { + nextword|=0x2; + siz2=2; + } + break; + case 1: + as_warn("Byte dispacement won't work. Defaulting to :w"); + case 2: + nextword|=0x2; + break; + case 3: + nextword|=0x3; + break; + } + if(opP->mode==APODX) nextword|=0x04; + else if(opP->mode==AMIND) nextword|=0x40; + } + addword(nextword); + + if(isvar(opP->con1)) { + if(opP->reg==PC || opP->reg==ZPC) { + add_fix(siz1==3 ? 'l' : 'w',opP->con1,1); + opP->con1->e_exp.X_add_number+=6; + } else + add_fix(siz1==3 ? 'l' : 'w',opP->con1,0); + } + if(siz1==3) + addword(baseo>>16); + if(siz1) + addword(baseo); + + if(isvar(opP->con2)) { + if(opP->reg==PC || opP->reg==ZPC) { + add_fix(siz2==3 ? 'l' : 'w',opP->con2,1); + opP->con1->e_exp.X_add_number+=6; + } else + add_fix(siz2==3 ? 'l' : 'w',opP->con2,0); + } + if(siz2==3) + addword(outro>>16); + if(siz2) + addword(outro); + + break; + + case ABSL: + nextword=get_num(opP->con1,80); + switch(opP->con1->e_siz) { + default: + as_warn("Unknown size for absolute reference"); + case 0: + if(!isvar(opP->con1) && issword(offs(opP->con1))) { + tmpreg=0x38; /* 7.0 */ + addword(nextword); + break; + } + /* Don't generate pc relative code + on 68010 and 68000 */ + if(isvar(opP->con1) && + !subs(opP->con1) && + seg(opP->con1)==SEG_TEXT && + now_seg==SEG_TEXT && + flagseen['m']==0 && + !index("~%&$?", s[0])) { + tmpreg=0x3A; /* 7.2 */ + add_frag(adds(opP->con1), + offs(opP->con1), + TAB(PCREL,SZ_UNDEF)); + break; + } + case 3: /* Fall through into long */ + if(isvar(opP->con1)) + add_fix('l',opP->con1,0); + + tmpreg=0x39; /* 7.1 mode */ + addword(nextword>>16); + addword(nextword); + break; + + case 2: /* Word */ + if(isvar(opP->con1)) + add_fix('w',opP->con1,0); + + tmpreg=0x38; /* 7.0 mode */ + addword(nextword); + break; + } + break; + case MSCR: + default: + as_bad("unknown/incorrect operand"); + /* abort(); */ + } + install_gen_operand(s[1],tmpreg); + break; + + case '#': + case '^': + switch(s[1]) { /* JF: I hate floating point! */ + case 'j': + tmpreg=70; + break; + case '8': + tmpreg=20; + break; + case 'C': + tmpreg=50; + break; + case '3': + default: + tmpreg=80; + break; + } + tmpreg=get_num(opP->con1,tmpreg); + if(isvar(opP->con1)) + add_fix(s[1],opP->con1,0); + switch(s[1]) { + case 'b': /* Danger: These do no check for + certain types of overflow. + user beware! */ + if(!isbyte(tmpreg)) + opP->error="out of range"; + insop(tmpreg); + if(isvar(opP->con1)) + the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; + break; + case 'w': + if(!isword(tmpreg)) + opP->error="out of range"; + insop(tmpreg); + if(isvar(opP->con1)) + the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; + break; + case 'l': + insop(tmpreg); /* Because of the way insop works, we put these two out backwards */ + insop(tmpreg>>16); + if(isvar(opP->con1)) + the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; + break; + case '3': + tmpreg&=0xFF; + case '8': + case 'C': + install_operand(s[1],tmpreg); + break; + default: + as_fatal("Internal error: Unknown mode #%c",s[1]); + } + break; + + case '+': + case '-': + case 'A': + install_operand(s[1],opP->reg-ADDR); + break; + + case 'B': + tmpreg=get_num(opP->con1,80); + switch(s[1]) { + case 'g': + if(opP->con1->e_siz) { /* Deal with fixed size stuff by hand */ + switch(opP->con1->e_siz) { + case 1: + add_fix('b',opP->con1,1); + break; + case 2: + add_fix('w',opP->con1,1); + addword(0); + break; + case 3: + add_fix('l',opP->con1,1); + addword(0); + addword(0); + break; + default: + as_fatal("Bad size for expression %d",opP->con1->e_siz); + } + } else if(subs(opP->con1)) { + /* We can't relax it */ + the_ins.opcode[the_ins.numo-1]|=0xff; + add_fix('l',opP->con1,1); + addword(0); + addword(0); + } else if(adds(opP->con1)) { + if (flagseen['m'] && + (the_ins.opcode[0] >= 0x6200) && + (the_ins.opcode[0] <= 0x6f00)) { + add_frag(adds(opP->con1),offs(opP->con1),TAB(BCC68000,SZ_UNDEF)); + } else { + add_frag(adds(opP->con1),offs(opP->con1),TAB(BRANCH,SZ_UNDEF)); + } + } else { + /* JF: This is the WRONG thing to do + add_frag((symbolS *)0,offs(opP->con1),TAB(BRANCH,BYTE)); */ + the_ins.opcode[the_ins.numo-1]|=0xff; + offs(opP->con1)+=4; + add_fix('l',opP->con1,1); + addword(0); + addword(0); + } + break; + case 'w': + if(isvar(opP->con1)) { + /* check for DBcc instruction */ + if ((the_ins.opcode[0] & 0xf0f8) ==0x50c8) { + /* size varies if patch */ + /* needed for long form */ + add_frag(adds(opP->con1),offs(opP->con1),TAB(DBCC,SZ_UNDEF)); + break; + } + + /* Don't ask! */ + opP->con1->e_exp.X_add_number+=2; + add_fix('w',opP->con1,1); + } + addword(0); + break; + case 'c': + if(opP->con1->e_siz) { + switch(opP->con1->e_siz) { + case 2: + add_fix('w',opP->con1,1) + addword(0); + break; + case 3: + the_ins.opcode[the_ins.numo-1]|=0x40; + add_fix('l',opP->con1,1); + addword(0); + addword(0); + break; + default: + as_bad("Bad size for offset, must be word or long"); + break; + } + } else if(subs(opP->con1)) { + add_fix('l',opP->con1,1); + add_frag((symbolS *)0,(long)0,TAB(FBRANCH,LONG)); + } else if(adds(opP->con1)) { + add_frag(adds(opP->con1),offs(opP->con1),TAB(FBRANCH,SZ_UNDEF)); + } else { + /* add_frag((symbolS *)0,offs(opP->con1),TAB(FBRANCH,SHORT)); */ + the_ins.opcode[the_ins.numo-1]|=0x40; + add_fix('l',opP->con1,1); + addword(0); + addword(4); + } + break; + default: + as_fatal("Internal error: operand type B%c unknown",s[1]); + } + break; + + case 'C': /* Ignore it */ + break; + + case 'd': /* JF this is a kludge */ + if(opP->mode==AOFF) { + install_operand('s',opP->reg-ADDR); + } else { + char *tmpP; + + tmpP=opP->con1->e_end-2; + opP->con1->e_beg++; + opP->con1->e_end-=4; /* point to the , */ + baseo=m68k_reg_parse(&tmpP); + if(baseo<ADDR+0 || baseo>ADDR+7) { + as_bad("Unknown address reg, using A0"); + baseo=0; + } else baseo-=ADDR; + install_operand('s',baseo); + } + tmpreg=get_num(opP->con1,80); + if(!issword(tmpreg)) { + as_warn("Expression out of range, using 0"); + tmpreg=0; + } + addword(tmpreg); + break; + + case 'D': + install_operand(s[1],opP->reg-DATA); + break; + + case 'F': + install_operand(s[1],opP->reg-FPREG); + break; + + case 'I': + tmpreg=1+opP->reg-COPNUM; + if(tmpreg==8) + tmpreg=0; + install_operand(s[1],tmpreg); + break; + + case 'J': /* JF foo */ + switch(opP->reg) { + case SFC: + tmpreg=0; + break; + case DFC: + tmpreg=0x001; + break; + case CACR: + tmpreg=0x002; + break; + case USP: + tmpreg=0x800; + break; + case VBR: + tmpreg=0x801; + break; + case CAAR: + tmpreg=0x802; + break; + case MSP: + tmpreg=0x803; + break; + case ISP: + tmpreg=0x804; + break; + default: + abort(); + } + install_operand(s[1],tmpreg); + break; + + case 'k': + tmpreg=get_num(opP->con1,55); + install_operand(s[1],tmpreg&0x7f); + break; + + case 'l': + tmpreg=opP->reg; + if(s[1]=='w') { + if(tmpreg&0x7FF0000) + as_bad("Floating point register in register list"); + insop(reverse_16_bits(tmpreg)); + } else { + if(tmpreg&0x700FFFF) + as_bad("Wrong register in floating-point reglist"); + install_operand(s[1],reverse_8_bits(tmpreg>>16)); + } + break; + + case 'L': + tmpreg=opP->reg; + if(s[1]=='w') { + if(tmpreg&0x7FF0000) + as_bad("Floating point register in register list"); + insop(tmpreg); + } else if(s[1]=='8') { + if(tmpreg&0x0FFFFFF) + as_bad("incorrect register in reglist"); + install_operand(s[1],tmpreg>>24); + } else { + if(tmpreg&0x700FFFF) + as_bad("wrong register in floating-point reglist"); + else + install_operand(s[1],tmpreg>>16); + } + break; + + case 'M': + install_operand(s[1],get_num(opP->con1,60)); + break; + + case 'O': + tmpreg= (opP->mode==DREG) + ? 0x20+opP->reg-DATA + : (get_num(opP->con1,40)&0x1F); + install_operand(s[1],tmpreg); + break; + + case 'Q': + tmpreg=get_num(opP->con1,10); + if(tmpreg==8) + tmpreg=0; + install_operand(s[1],tmpreg); + break; + + case 'R': + /* This depends on the fact that ADDR registers are + eight more than their corresponding DATA regs, so + the result will have the ADDR_REG bit set */ + install_operand(s[1],opP->reg-DATA); + break; + + case 's': + if(opP->reg==FPI) tmpreg=0x1; + else if(opP->reg==FPS) tmpreg=0x2; + else if(opP->reg==FPC) tmpreg=0x4; + else abort(); + install_operand(s[1],tmpreg); + break; + + case 'S': /* Ignore it */ + break; + + case 'T': + install_operand(s[1],get_num(opP->con1,30)); + break; + + case 'U': /* Ignore it */ + break; + +#ifdef m68851 + /* JF: These are out of order, I fear. */ + case 'f': + switch (opP->reg) { + case SFC: + tmpreg=0; + break; + case DFC: + tmpreg=1; + break; + default: + abort(); + } + install_operand(s[1],tmpreg); + break; + + case 'P': + switch(opP->reg) { + case TC: + tmpreg=0; + break; + case CAL: + tmpreg=4; + break; + case VAL: + tmpreg=5; + break; + case SCC: + tmpreg=6; + break; + case AC: + tmpreg=7; + break; + default: + abort(); + } + install_operand(s[1],tmpreg); + break; + + case 'V': + if (opP->reg == VAL) + break; + abort(); + + case 'W': + switch(opP->reg) { + + case DRP: + tmpreg=1; + break; + case SRP: + tmpreg=2; + break; + case CRP: + tmpreg=3; + break; + default: + abort(); + } + install_operand(s[1],tmpreg); + break; + + case 'X': + switch (opP->reg) { + case BAD: case BAD+1: case BAD+2: case BAD+3: + case BAD+4: case BAD+5: case BAD+6: case BAD+7: + tmpreg = (4 << 10) | ((opP->reg - BAD) << 2); + break; + + case BAC: case BAC+1: case BAC+2: case BAC+3: + case BAC+4: case BAC+5: case BAC+6: case BAC+7: + tmpreg = (5 << 10) | ((opP->reg - BAC) << 2); + break; + + default: + abort(); + } + install_operand(s[1], tmpreg); + break; + case 'Y': + if (opP->reg == PSR) + break; + abort(); + + case 'Z': + if (opP->reg == PCSR) + break; + abort(); +#endif /* m68851 */ + default: + as_fatal("Internal error: Operand type %c unknown",s[0]); + } + } + /* By the time whe get here (FINALLY) the_ins contains the complete + instruction, ready to be emitted. . . */ +} + +int +get_regs(i,str,opP) +struct m68k_op *opP; +char *str; +{ + /* 26, 25, 24, 23-16, 15-8, 0-7 */ + /* Low order 24 bits encoded fpc,fps,fpi,fp7-fp0,a7-a0,d7-d0 */ + unsigned long int cur_regs = 0; + int reg1, + reg2; + +#define ADD_REG(x) { if(x==FPI) cur_regs|=(1<<24);\ + else if(x==FPS) cur_regs|=(1<<25);\ + else if(x==FPC) cur_regs|=(1<<26);\ + else cur_regs|=(1<<(x-1)); } + + reg1=i; + for(;;) { + if(*str=='/') { + ADD_REG(reg1); + str++; + } else if(*str=='-') { + str++; + reg2=m68k_reg_parse(&str); + if(reg2<DATA || reg2>=FPREG+8 || reg1==FPI || reg1==FPS || reg1==FPC) { + opP->error="unknown register in register list"; + return FAIL; + } + while(reg1<=reg2) { + ADD_REG(reg1); + reg1++; + } + if(*str=='\0') + break; + } else if(*str=='\0') { + ADD_REG(reg1); + break; + } else { + opP->error="unknow character in register list"; + return FAIL; + } +/* DJA -- Bug Fix. Did't handle d1-d2/a1 until the following instruction was added */ + if (*str=='/') + str ++; + reg1=m68k_reg_parse(&str); + if((reg1<DATA || reg1>=FPREG+8) && !(reg1==FPI || reg1==FPS || reg1==FPC)) { + opP->error="unknown register in register list"; + return FAIL; + } + } + opP->reg=cur_regs; + return OK; +} + +int +reverse_16_bits(in) +int in; +{ + int out=0; + int n; + + static int mask[16] = { +0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, +0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000 + }; + for(n=0;n<16;n++) { + if(in&mask[n]) + out|=mask[15-n]; + } + return out; +} + +int +reverse_8_bits(in) +int in; +{ + int out=0; + int n; + + static int mask[8] = { +0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, + }; + + for(n=0;n<8;n++) { + if(in&mask[n]) + out|=mask[7-n]; + } + return out; +} + +void +install_operand(mode,val) +int mode; +int val; +{ + switch(mode) { + case 's': + the_ins.opcode[0]|=val & 0xFF; /* JF FF is for M kludge */ + break; + case 'd': + the_ins.opcode[0]|=val<<9; + break; + case '1': + the_ins.opcode[1]|=val<<12; + break; + case '2': + the_ins.opcode[1]|=val<<6; + break; + case '3': + the_ins.opcode[1]|=val; + break; + case '4': + the_ins.opcode[2]|=val<<12; + break; + case '5': + the_ins.opcode[2]|=val<<6; + break; + case '6': + /* DANGER! This is a hack to force cas2l and cas2w cmds + to be three words long! */ + the_ins.numo++; + the_ins.opcode[2]|=val; + break; + case '7': + the_ins.opcode[1]|=val<<7; + break; + case '8': + the_ins.opcode[1]|=val<<10; + break; +#ifdef m68851 + case '9': + the_ins.opcode[1]|=val<<5; + break; +#endif + + case 't': + the_ins.opcode[1]|=(val<<10)|(val<<7); + break; + case 'D': + the_ins.opcode[1]|=(val<<12)|val; + break; + case 'g': + the_ins.opcode[0]|=val=0xff; + break; + case 'i': + the_ins.opcode[0]|=val<<9; + break; + case 'C': + the_ins.opcode[1]|=val; + break; + case 'j': + the_ins.opcode[1]|=val; + the_ins.numo++; /* What a hack */ + break; + case 'k': + the_ins.opcode[1]|=val<<4; + break; + case 'b': + case 'w': + case 'l': + break; + case 'c': + default: + abort(); + } +} + +void +install_gen_operand(mode,val) +int mode; +int val; +{ + switch(mode) { + case 's': + the_ins.opcode[0]|=val; + break; + case 'd': + /* This is a kludge!!! */ + the_ins.opcode[0]|=(val&0x07)<<9|(val&0x38)<<3; + break; + case 'b': + case 'w': + case 'l': + case 'f': + case 'F': + case 'x': + case 'p': + the_ins.opcode[0]|=val; + break; + /* more stuff goes here */ + default: + abort(); + } +} + +char * +crack_operand(str,opP) +register char *str; +register struct m68k_op *opP; +{ + register int parens; + register int c; + register char *beg_str; + + if(!str) { + return str; + } + beg_str=str; + for(parens=0;*str && (parens>0 || notend(str));str++) { + if(*str=='(') parens++; + else if(*str==')') { + if(!parens) { /* ERROR */ + opP->error="Extra )"; + return str; + } + --parens; + } + } + if(!*str && parens) { /* ERROR */ + opP->error="Missing )"; + return str; + } + c= *str; + *str='\0'; + if(m68k_ip_op(beg_str,opP)==FAIL) { + *str=c; + return str; + } + *str=c; + if(c=='}') + c= *++str; /* JF bitfield hack */ + if(c) { + c= *++str; + if(!c) + as_bad("Missing operand"); + } + return str; +} + +/* See the comment up above where the #define notend(... is */ +#if 0 +notend(s) +char *s; +{ + if(*s==',') return 0; + if(*s=='{' || *s=='}') + return 0; + if(*s!=':') return 1; + /* This kludge here is for the division cmd, which is a kludge */ + if(index("aAdD#",s[1])) return 0; + return 1; +} +#endif + +/* This is the guts of the machine-dependent assembler. STR points to a + machine dependent instruction. This funciton is supposed to emit + the frags/bytes it assembles to. + */ +void +md_assemble(str) +char *str; +{ + char *er; + short *fromP; + char *toP; + int m,n; + char *to_beg_P; + int shorts_this_frag; + + bzero((char *)(&the_ins),sizeof(the_ins)); /* JF for paranoia sake */ + m68_ip(str); + er=the_ins.error; + if(!er) { + for(n=the_ins.numargs;n;--n) + if(the_ins.operands[n].error) { + er=the_ins.operands[n].error; + break; + } + } + if(er) { + as_bad("\"%s\" -- Statement '%s' ignored",er,str); + return; + } + + if(the_ins.nfrag==0) { /* No frag hacking involved; just put it out */ + toP=frag_more(2*the_ins.numo); + fromP= &the_ins.opcode[0]; + for(m=the_ins.numo;m;--m) { + md_number_to_chars(toP,(long)(*fromP),2); + toP+=2; + fromP++; + } + /* put out symbol-dependent info */ + for(m=0;m<the_ins.nrel;m++) { + switch(the_ins.reloc[m].wid) { + case 'B': + n=1; + break; + case 'b': + n=1; + break; + case '3': + n=2; + break; + case 'w': + n=2; + break; + case 'l': + n=4; + break; + default: + as_fatal("Don't know how to figure width of %c in md_assemble()",the_ins.reloc[m].wid); + } + + fix_new(frag_now, + (toP-frag_now->fr_literal)-the_ins.numo*2+the_ins.reloc[m].n, + n, + the_ins.reloc[m].add, + the_ins.reloc[m].sub, + the_ins.reloc[m].off, + the_ins.reloc[m].pcrel); + } + return; + } + + /* There's some frag hacking */ + for(n=0,fromP= &the_ins.opcode[0];n<the_ins.nfrag;n++) { + int wid; + + if(n==0) wid=2*the_ins.fragb[n].fragoff; + else wid=2*(the_ins.numo-the_ins.fragb[n-1].fragoff); + toP=frag_more(wid); + to_beg_P=toP; + shorts_this_frag=0; + for(m=wid/2;m;--m) { + md_number_to_chars(toP,(long)(*fromP),2); + toP+=2; + fromP++; + shorts_this_frag++; + } + for(m=0;m<the_ins.nrel;m++) { + if((the_ins.reloc[m].n)>= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */) { + the_ins.reloc[m].n-= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */; + break; + } + wid=the_ins.reloc[m].wid; + if(wid==0) + continue; + the_ins.reloc[m].wid=0; + wid = (wid=='b') ? 1 : (wid=='w') ? 2 : (wid=='l') ? 4 : 4000; + + fix_new(frag_now, + (toP-frag_now->fr_literal)-the_ins.numo*2+the_ins.reloc[m].n, + wid, + the_ins.reloc[m].add, + the_ins.reloc[m].sub, + the_ins.reloc[m].off, + the_ins.reloc[m].pcrel); + } + know(the_ins.fragb[n].fadd); + (void)frag_var(rs_machine_dependent,10,0,(relax_substateT)(the_ins.fragb[n].fragty), + the_ins.fragb[n].fadd,the_ins.fragb[n].foff,to_beg_P); + } + n=(the_ins.numo-the_ins.fragb[n-1].fragoff); + shorts_this_frag=0; + if(n) { + toP=frag_more(n*sizeof(short)); + while(n--) { + md_number_to_chars(toP,(long)(*fromP),2); + toP+=2; + fromP++; + shorts_this_frag++; + } + } + for(m=0;m<the_ins.nrel;m++) { + int wid; + + wid=the_ins.reloc[m].wid; + if(wid==0) + continue; + the_ins.reloc[m].wid=0; + wid = (wid=='b') ? 1 : (wid=='w') ? 2 : (wid=='l') ? 4 : 4000; + + fix_new(frag_now, + (the_ins.reloc[m].n + toP-frag_now->fr_literal)-/* the_ins.numo */ shorts_this_frag*2, + wid, + the_ins.reloc[m].add, + the_ins.reloc[m].sub, + the_ins.reloc[m].off, + the_ins.reloc[m].pcrel); + } +} + +/* This function is called once, at assembler startup time. This should + set up all the tables, etc that the MD part of the assembler needs + */ +void +md_begin() +{ +/* + * md_begin -- set up hash tables with 68000 instructions. + * similar to what the vax assembler does. ---phr + */ + /* RMS claims the thing to do is take the m68k-opcode.h table, and make + a copy of it at runtime, adding in the information we want but isn't + there. I think it'd be better to have an awk script hack the table + at compile time. Or even just xstr the table and use it as-is. But + my lord ghod hath spoken, so we do it this way. Excuse the ugly var + names. */ + + register struct m68k_opcode *ins; + register struct m68_incant *hack, + *slak; + register char *retval = 0; /* empty string, or error msg text */ + register int i; + register char c; + + if ((op_hash = hash_new()) == NULL) + as_fatal("Virtual memory exhausted"); + + obstack_begin(&robyn,4000); + for (ins = m68k_opcodes; ins < endop; ins++) { + hack=slak=(struct m68_incant *)obstack_alloc(&robyn,sizeof(struct m68_incant)); + do { + slak->m_operands=ins->args; + slak->m_opnum=strlen(slak->m_operands)/2; + slak->m_opcode=ins->opcode; + /* This is kludgey */ + slak->m_codenum=((ins->match)&0xffffL) ? 2 : 1; + if((ins+1)!=endop && !strcmp(ins->name,(ins+1)->name)) { + slak->m_next=(struct m68_incant *) +obstack_alloc(&robyn,sizeof(struct m68_incant)); + ins++; + } else + slak->m_next=0; + slak=slak->m_next; + } while(slak); + + retval = hash_insert (op_hash, ins->name,(char *)hack); + /* Didn't his mommy tell him about null pointers? */ + if(retval && *retval) + as_fatal("Internal Error: Can't hash %s: %s",ins->name,retval); + } + + for (i = 0; i < sizeof(mklower_table) ; i++) + mklower_table[i] = (isupper(c = (char) i)) ? tolower(c) : c; + + for (i = 0 ; i < sizeof(notend_table) ; i++) { + notend_table[i] = 0; + alt_notend_table[i] = 0; + } + notend_table[','] = 1; + notend_table['{'] = 1; + notend_table['}'] = 1; + alt_notend_table['a'] = 1; + alt_notend_table['A'] = 1; + alt_notend_table['d'] = 1; + alt_notend_table['D'] = 1; + alt_notend_table['#'] = 1; + alt_notend_table['f'] = 1; + alt_notend_table['F'] = 1; +#ifdef REGISTER_PREFIX + alt_notend_table[REGISTER_PREFIX] = 1; +#endif +} + +#if 0 +#define notend(s) ((*s == ',' || *s == '}' || *s == '{' \ + || (*s == ':' && index("aAdD#", s[1]))) \ + ? 0 : 1) +#endif + +/* This funciton is called once, before the assembler exits. It is + supposed to do any final cleanup for this part of the assembler. + */ +void +md_end() +{ +} + +/* Equal to MAX_PRECISION in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +/* 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. + */ +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(); + + switch(type) { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + 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--;) { + md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE)); + litP+=sizeof(LITTLENUM_TYPE); + } + return ""; /* Someone should teach Dean about null pointers */ +} + +/* Turn an integer of n bytes (in val) into a stream of bytes appropriate + for use in the a.out file, and stores them in the array pointed to by buf. + This knows about the endian-ness of the target machine and does + THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) + 2 (short) and 4 (long) Floating numbers are put out as a series of + LITTLENUMS (shorts, here at least) + */ +void +md_number_to_chars(buf,val,n) +char *buf; +long val; +int n; +{ + switch(n) { + case 1: + *buf++=val; + break; + case 2: + *buf++=(val>>8); + *buf++=val; + break; + case 4: + *buf++=(val>>24); + *buf++=(val>>16); + *buf++=(val>>8); + *buf++=val; + break; + default: + abort(); + } +} + +void +md_number_to_imm(buf,val,n) +char *buf; +long val; +int n; +{ + switch(n) { + case 1: + *buf++=val; + break; + case 2: + *buf++=(val>>8); + *buf++=val; + break; + case 4: + *buf++=(val>>24); + *buf++=(val>>16); + *buf++=(val>>8); + *buf++=val; + break; + default: + abort(); + } +} + +void +md_number_to_disp(buf,val,n) +char *buf; +long val; +int n; +{ + abort(); +} + +void +md_number_to_field(buf,val,fix) +char *buf; +long val; +void *fix; +{ + abort(); +} + + +/* *fragP has been relaxed to its final size, and now needs to have + the bytes inside it modified to conform to the new size There is UGLY + MAGIC here. .. + */ +void +md_convert_frag(fragP) +register fragS *fragP; +{ + long disp; + long ext; + + /* Address in gas core of the place to store the displacement. */ + register char *buffer_address = fragP -> fr_fix + fragP -> fr_literal; + /* Address in object code of the displacement. */ + register int object_address = fragP -> fr_fix + fragP -> fr_address; + + know(fragP->fr_symbol); + + /* The displacement of the address, from current location. */ + disp = (fragP->fr_symbol->sy_value + fragP->fr_offset) - object_address; + + switch(fragP->fr_subtype) { + case TAB(BCC68000,BYTE): + case TAB(BRANCH,BYTE): + know(issbyte(disp)); + if(disp==0) + as_bad("short branch with zero offset: use :w"); + fragP->fr_opcode[1]=disp; + ext=0; + break; + case TAB(DBCC,SHORT): + know(issword(disp)); + ext=2; + break; + case TAB(BCC68000,SHORT): + case TAB(BRANCH,SHORT): + know(issword(disp)); + fragP->fr_opcode[1]=0x00; + ext=2; + break; + case TAB(BRANCH,LONG): + if(flagseen['m']) { + if(fragP->fr_opcode[0]==0x61) { + fragP->fr_opcode[0]= 0x4E; + fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */ + subseg_change(SEG_TEXT, 0); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0); + fragP->fr_fix+=4; + ext=0; + } else if(fragP->fr_opcode[0]==0x60) { + fragP->fr_opcode[0]= 0x4E; + fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */ + subseg_change(SEG_TEXT, 0); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset,0); + fragP->fr_fix+=4; + ext=0; + }else { + as_bad("Long branch offset not supported."); + } + } else { + fragP->fr_opcode[1]=0xff; + ext=4; + } + break; + case TAB(BCC68000,LONG): + /* only Bcc 68000 instructions can come here */ + /* change bcc into b!cc/jmp absl long */ + fragP->fr_opcode[0] ^= 0x01; /* invert bcc */ + fragP->fr_opcode[1] = 0x6; /* branch offset = 6 */ + + /* JF: these used to be fr_opcode[2,3], but they may be in a + different frag, in which case refering to them is a no-no. + Only fr_opcode[0,1] are guaranteed to work. */ + *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */ + *buffer_address++ = 0xf9; + fragP->fr_fix += 2; /* account for jmp instruction */ + subseg_change(SEG_TEXT,0); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, + fragP->fr_offset,0); + fragP->fr_fix += 4; + ext=0; + break; + case TAB(DBCC,LONG): + /* only DBcc 68000 instructions can come here */ + /* change dbcc into dbcc/jmp absl long */ + /* JF: these used to be fr_opcode[2-7], but that's wrong */ + *buffer_address++ = 0x00; /* branch offset = 4 */ + *buffer_address++ = 0x04; + *buffer_address++ = 0x60; /* put in bra pc+6 */ + *buffer_address++ = 0x06; + *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */ + *buffer_address++ = 0xf9; + + fragP->fr_fix += 6; /* account for bra/jmp instructions */ + subseg_change(SEG_TEXT,0); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, + fragP->fr_offset,0); + fragP->fr_fix += 4; + ext=0; + break; + case TAB(FBRANCH,SHORT): + know((fragP->fr_opcode[1]&0x40)==0); + ext=2; + break; + case TAB(FBRANCH,LONG): + fragP->fr_opcode[1]|=0x40; /* Turn on LONG bit */ + ext=4; + break; + case TAB(PCREL,SHORT): + ext=2; + break; + case TAB(PCREL,LONG): + /* The thing to do here is force it to ABSOLUTE LONG, since + PCREL is really trying to shorten an ABSOLUTE address anyway */ + /* JF FOO This code has not been tested */ + subseg_change(SEG_TEXT,0); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0); + if((fragP->fr_opcode[1] & 0x3F) != 0x3A) + as_bad("Internal error (long PC-relative operand) for insn 0x%04lx at 0x%lx", + fragP->fr_opcode[0],fragP->fr_address); + fragP->fr_opcode[1]&= ~0x3F; + fragP->fr_opcode[1]|=0x39; /* Mode 7.1 */ + fragP->fr_fix+=4; + /* md_number_to_chars(buffer_address, + (long)(fragP->fr_symbol->sy_value + fragP->fr_offset), + 4); */ + ext=0; + break; + case TAB(PCLEA,SHORT): + subseg_change(SEG_TEXT,0); + fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol,(symbolS *)0,fragP->fr_offset,1); + fragP->fr_opcode[1] &= ~0x3F; + fragP->fr_opcode[1] |= 0x3A; + ext=2; + break; + case TAB(PCLEA,LONG): + subseg_change(SEG_TEXT,0); + fix_new(fragP,(int)(fragP->fr_fix)+2,4,fragP->fr_symbol,(symbolS *)0,fragP->fr_offset+2,1); + *buffer_address++ = 0x01; + *buffer_address++ = 0x70; + fragP->fr_fix+=2; + /* buffer_address+=2; */ + ext=4; + break; + + } + if(ext) { + md_number_to_chars(buffer_address,(long)disp,(int)ext); + fragP->fr_fix+=ext; + } +} + +/* Force truly undefined symbols to their maximum size, and generally set up + the frag list to be relaxed + */ +int +md_estimate_size_before_relax(fragP,segtype) +register fragS *fragP; +int segtype; +{ + int old_fix; + register char *buffer_address = fragP -> fr_fix + fragP -> fr_literal; + + old_fix=fragP->fr_fix; + + /* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */ + switch(fragP->fr_subtype) { + case TAB(BRANCH,SZ_UNDEF): + if((fragP->fr_symbol->sy_type&N_TYPE)==segtype) { + fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),BYTE); + break; + } else if(flagseen['m']) { + if(fragP->fr_opcode[0]==0x61) { + if(flagseen['l']) { + fragP->fr_opcode[0]= 0x4E; + fragP->fr_opcode[1]= 0xB8; /* JBSR with ABSL WORD offset */ + subseg_change(SEG_TEXT, 0); + fix_new(fragP, fragP->fr_fix, 2, + fragP->fr_symbol, 0, fragP->fr_offset, 0); + fragP->fr_fix+=2; + } else { + fragP->fr_opcode[0]= 0x4E; + fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */ + subseg_change(SEG_TEXT, 0); + fix_new(fragP, fragP->fr_fix, 4, + fragP->fr_symbol, 0, fragP->fr_offset, 0); + fragP->fr_fix+=4; + } + frag_wane(fragP); + } else if(fragP->fr_opcode[0]==0x60) { + if(flagseen['l']) { + fragP->fr_opcode[0]= 0x4E; + fragP->fr_opcode[1]= 0xF8; /* JMP with ABSL WORD offset */ + subseg_change(SEG_TEXT, 0); + fix_new(fragP, fragP->fr_fix, 2, + fragP->fr_symbol, 0, fragP->fr_offset, 0); + fragP->fr_fix+=2; + } else { + fragP->fr_opcode[0]= 0x4E; + fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */ + subseg_change(SEG_TEXT, 0); + fix_new(fragP, fragP->fr_fix, 4, + fragP->fr_symbol, 0, fragP->fr_offset, 0); + fragP->fr_fix+=4; + } + frag_wane(fragP); + } else { + as_warn("Long branch offset to extern symbol not supported."); + } + } else if(flagseen['l']) { /* Symbol is still undefined. Make it simple */ + fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol, + (symbolS *)0,fragP->fr_offset + 2,1); + fragP->fr_fix+=2; + fragP->fr_opcode[1]=0x00; + frag_wane(fragP); + } else { + fix_new(fragP,(int)(fragP->fr_fix),4,fragP->fr_symbol, + (symbolS *)0,fragP->fr_offset + 4,1); + fragP->fr_fix+=4; + fragP->fr_opcode[1]=0xff; + frag_wane(fragP); + break; + } + break; + + case TAB(FBRANCH,SZ_UNDEF): + if((fragP->fr_symbol->sy_type&N_TYPE)==segtype || flagseen['l']) { + fragP->fr_subtype=TAB(FBRANCH,SHORT); + fragP->fr_var+=2; + } else { + fragP->fr_subtype=TAB(FBRANCH,LONG); + fragP->fr_var+=4; + } + break; + + case TAB(PCREL,SZ_UNDEF): + if((fragP->fr_symbol->sy_type&N_TYPE)==segtype || flagseen['l']) { + fragP->fr_subtype=TAB(PCREL,SHORT); + fragP->fr_var+=2; + } else { + fragP->fr_subtype=TAB(PCREL,LONG); + fragP->fr_var+=4; + } + break; + + case TAB(BCC68000,SZ_UNDEF): + if((fragP->fr_symbol->sy_type&N_TYPE)==segtype) { + fragP->fr_subtype=TAB(BCC68000,BYTE); + break; + } + /* only Bcc 68000 instructions can come here */ + /* change bcc into b!cc/jmp absl long */ + fragP->fr_opcode[0] ^= 0x01; /* invert bcc */ + if(flagseen['l']) { + fragP->fr_opcode[1] = 0x04; /* branch offset = 6 */ + /* JF: these were fr_opcode[2,3] */ + buffer_address[0] = 0x4e; /* put in jmp long (0x4ef9) */ + buffer_address[1] = 0xf8; + fragP->fr_fix += 2; /* account for jmp instruction */ + subseg_change(SEG_TEXT,0); + fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0, + fragP->fr_offset,0); + fragP->fr_fix += 2; + } else { + fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */ + /* JF: these were fr_opcode[2,3] */ + buffer_address[2] = 0x4e; /* put in jmp long (0x4ef9) */ + buffer_address[3] = 0xf9; + fragP->fr_fix += 2; /* account for jmp instruction */ + subseg_change(SEG_TEXT,0); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, + fragP->fr_offset,0); + fragP->fr_fix += 4; + } + frag_wane(fragP); + break; + + case TAB(DBCC,SZ_UNDEF): + if((fragP->fr_symbol->sy_type&N_TYPE)==segtype) { + fragP->fr_subtype=TAB(DBCC,SHORT); + fragP->fr_var+=2; + break; + } + /* only DBcc 68000 instructions can come here */ + /* change dbcc into dbcc/jmp absl long */ + /* JF: these used to be fr_opcode[2-4], which is wrong. */ + buffer_address[0] = 0x00; /* branch offset = 4 */ + buffer_address[1] = 0x04; + buffer_address[2] = 0x60; /* put in bra pc + ... */ + if(flagseen['l']) { + /* JF: these were fr_opcode[5-7] */ + buffer_address[3] = 0x04; /* plus 4 */ + buffer_address[4] = 0x4e;/* Put in Jump Word */ + buffer_address[5] = 0xf8; + fragP->fr_fix += 6; /* account for bra/jmp instruction */ + subseg_change(SEG_TEXT,0); + fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0, + fragP->fr_offset,0); + fragP->fr_fix+=2; + } else { + /* JF: these were fr_opcode[5-7] */ + buffer_address[3] = 0x06; /* Plus 6 */ + buffer_address[4] = 0x4e; /* put in jmp long (0x4ef9) */ + buffer_address[5] = 0xf9; + fragP->fr_fix += 6; /* account for bra/jmp instruction */ + subseg_change(SEG_TEXT,0); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, + fragP->fr_offset,0); + fragP->fr_fix += 4; + } + frag_wane(fragP); + break; + + case TAB(PCLEA,SZ_UNDEF): + if((fragP->fr_symbol->sy_type&N_TYPE)==segtype || flagseen['l']) { + fragP->fr_subtype=TAB(PCLEA,SHORT); + fragP->fr_var+=2; + } else { + fragP->fr_subtype=TAB(PCLEA,LONG); + fragP->fr_var+=6; + } + break; + + default: + break; + } + + /* now that SZ_UNDEF are taken care of, check others */ + switch(fragP->fr_subtype) { + case TAB(BCC68000,BYTE): + case TAB(BRANCH,BYTE): + /* We can't do a short jump to the next instruction, + so we force word mode. */ + if(fragP->fr_symbol && fragP->fr_symbol->sy_value==0 && + fragP->fr_symbol->sy_frag==fragP->fr_next) { + fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),SHORT); + fragP->fr_var+=2; + } + break; + default: + break; + } + return fragP->fr_var + fragP->fr_fix - old_fix; +} + +/* the bit-field entries in the relocation_info struct plays hell + with the byte-order problems of cross-assembly. So as a hack, + I added this mach. dependent ri twiddler. Ugly, but it gets + you there. -KWK */ +/* on m68k: first 4 bytes are normal unsigned long, next three bytes +are symbolnum, most sig. byte first. Last byte is broken up with +bit 7 as pcrel, bits 6 & 5 as length, bit 4 as pcrel, and the lower +nibble as nuthin. (on Sun 3 at least) */ +void +md_ri_to_chars(ri_p, ri) + struct relocation_info *ri_p, ri; +{ + unsigned char the_bytes[8]; + + /* this is easy */ + md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address)); + /* now the fun stuff */ + the_bytes[4] = (ri.r_symbolnum >> 16) & 0x0ff; + the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff; + the_bytes[6] = ri.r_symbolnum & 0x0ff; + the_bytes[7] = (((ri.r_pcrel << 7) & 0x80) | ((ri.r_length << 5) & 0x60) | + ((ri.r_extern << 4) & 0x10)); + /* now put it back where you found it */ + bcopy (the_bytes, (char *)ri_p, sizeof(struct relocation_info)); +} + +#ifndef WORKING_DOT_WORD +const int md_short_jump_size = 4; +const int md_long_jump_size = 6; + +void +md_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol) +char *ptr; +long from_addr, + to_addr; +fragS *frag; +symbolS *to_symbol; +{ + long offset; + + offset = to_addr - (from_addr+2); + + md_number_to_chars(ptr ,(long)0x6000,2); + md_number_to_chars(ptr+2,(long)offset,2); +} + +void +md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol) +char *ptr; +long from_addr, + to_addr; +fragS *frag; +symbolS *to_symbol; +{ + long offset; + + if(flagseen['m']) { + offset=to_addr-to_symbol->sy_value; + md_number_to_chars(ptr ,(long)0x4EF9,2); + md_number_to_chars(ptr+2,(long)offset,4); + fix_new(frag,(ptr+2)-frag->fr_literal,4,to_symbol,(symbolS *)0,(long int)0,0); + } else { + offset=to_addr - (from_addr+2); + md_number_to_chars(ptr ,(long)0x60ff,2); + md_number_to_chars(ptr+2,(long)offset,4); + } +} + +#endif +/* Different values of OK tell what its OK to return. Things that aren't OK are an error (what a shock, no?) + + 0: Everything is OK + 10: Absolute 1:8 only + 20: Absolute 0:7 only + 30: absolute 0:15 only + 40: Absolute 0:31 only + 50: absolute 0:127 only + 55: absolute -64:63 only + 60: absolute -128:127 only + 70: absolute 0:4095 only + 80: No bignums + +*/ +int +get_num(exp,ok) +struct m68k_exp *exp; +int ok; +{ +#ifdef TEST2 + long l = 0; + + if(!exp->e_beg) + return 0; + if(*exp->e_beg=='0') { + if(exp->e_beg[1]=='x') + sscanf(exp->e_beg+2,"%x",&l); + else + sscanf(exp->e_beg+1,"%O",&l); + return l; + } + return atol(exp->e_beg); +#else + char *save_in; + char c_save; + + if(!exp) { + /* Can't do anything */ + return 0; + } + if(!exp->e_beg || !exp->e_end) { + seg(exp)=SEG_ABSOLUTE; + adds(exp)=0; + subs(exp)=0; + offs(exp)= (ok==10) ? 1 : 0; + as_warn("Null expression defaults to %ld",offs(exp)); + return 0; + } + + exp->e_siz=0; + if(/* ok!=80 && */exp->e_end[-1]==':' && (exp->e_end-exp->e_beg)>=2) { + switch(exp->e_end[0]) { + case 's': + case 'S': + case 'b': + case 'B': + exp->e_siz=1; + break; + case 'w': + case 'W': + exp->e_siz=2; + break; + case 'l': + case 'L': + exp->e_siz=3; + break; + default: + as_bad("Unknown size for expression \"%c\"",exp->e_end[0]); + } + exp->e_end-=2; + } + c_save=exp->e_end[1]; + exp->e_end[1]='\0'; + save_in=input_line_pointer; + input_line_pointer=exp->e_beg; + switch(expression(&(exp->e_exp))) { + case SEG_PASS1: + seg(exp)=SEG_ABSOLUTE; + adds(exp)=0; + subs(exp)=0; + offs(exp)= (ok==10) ? 1 : 0; + as_warn("Unknown expression: '%s' defaulting to %d",exp->e_beg,offs(exp)); + break; + + case SEG_NONE: + /* Do the same thing the VAX asm does */ + seg(exp)=SEG_ABSOLUTE; + adds(exp)=0; + subs(exp)=0; + offs(exp)=0; + if(ok==10) { + as_warn("expression out of range: defaulting to 1"); + offs(exp)=1; + } + break; + case SEG_ABSOLUTE: + switch(ok) { + case 10: + if(offs(exp)<1 || offs(exp)>8) { + as_warn("expression out of range: defaulting to 1"); + offs(exp)=1; + } + break; + case 20: + if(offs(exp)<0 || offs(exp)>7) + goto outrange; + break; + case 30: + if(offs(exp)<0 || offs(exp)>15) + goto outrange; + break; + case 40: + if(offs(exp)<0 || offs(exp)>32) + goto outrange; + break; + case 50: + if(offs(exp)<0 || offs(exp)>127) + goto outrange; + break; + case 55: + if(offs(exp)<-64 || offs(exp)>63) + goto outrange; + break; + case 60: + if(offs(exp)<-128 || offs(exp)>127) + goto outrange; + break; + case 70: + if(offs(exp)<0 || offs(exp)>4095) { + outrange: + as_warn("expression out of range: defaulting to 0"); + offs(exp)=0; + } + break; + default: + break; + } + break; + case SEG_TEXT: + case SEG_DATA: + case SEG_BSS: + case SEG_UNKNOWN: + case SEG_DIFFERENCE: + if(ok>=10 && ok<=70) { + seg(exp)=SEG_ABSOLUTE; + adds(exp)=0; + subs(exp)=0; + offs(exp)= (ok==10) ? 1 : 0; + as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp)); + } + break; + case SEG_BIG: + if(ok==80 && offs(exp)<0) { /* HACK! Turn it into a long */ + LITTLENUM_TYPE words[6]; + + gen_to_words(words,2,8L);/* These numbers are magic! */ + seg(exp)=SEG_ABSOLUTE; + adds(exp)=0; + subs(exp)=0; + offs(exp)=words[1]|(words[0]<<16); + } else if(ok!=0) { + seg(exp)=SEG_ABSOLUTE; + adds(exp)=0; + subs(exp)=0; + offs(exp)= (ok==10) ? 1 : 0; + as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp)); + } + break; + default: + abort(); + } + if(input_line_pointer!=exp->e_end+1) + as_bad("Ignoring junk after expression"); + exp->e_end[1]=c_save; + input_line_pointer=save_in; + if(exp->e_siz) { + switch(exp->e_siz) { + case 1: + if(!isbyte(offs(exp))) + as_warn("expression doesn't fit in BYTE"); + break; + case 2: + if(!isword(offs(exp))) + as_warn("expression doesn't fit in WORD"); + break; + } + } + return offs(exp); +#endif +} + +/* These are the back-ends for the various machine dependent pseudo-ops. */ +void demand_empty_rest_of_line(); /* Hate those extra verbose names */ + +void +s_data1() +{ + subseg_new(SEG_DATA,1); + demand_empty_rest_of_line(); +} + +void +s_data2() +{ + subseg_new(SEG_DATA,2); + demand_empty_rest_of_line(); +} + +void +s_even() +{ + register int temp; + register long int temp_fill; + + temp = 1; /* JF should be 2? */ + temp_fill = get_absolute_expression (); + if ( ! need_pass_2 ) /* Never make frag if expect extra pass. */ + frag_align (temp, (int)temp_fill); + demand_empty_rest_of_line(); +} + +void +s_proc() +{ + demand_empty_rest_of_line(); +} + +/* s_space is defined in read.c .skip is simply an alias to it. */ + +int +md_parse_option(argP,cntP,vecP) +char **argP; +int *cntP; +char ***vecP; +{ + switch(**argP) { + case 'l': /* -l means keep external to 2 bit offset + rather than 16 bit one */ + break; + + case 'm': + /* Gas almost ignores this option! */ + (*argP)++; + if(**argP=='c') + (*argP)++; + if(!strcmp(*argP,"68000")) + flagseen['m']=2; + else if(!strcmp(*argP,"68010")) { +#ifdef M_SUN + omagic= 1<<16|OMAGIC; +#endif + flagseen['m']=1; + } else if(!strcmp(*argP,"68020")) + flagseen['m']=0; + else + as_warn("Unknown -m option ignored"); + while(**argP) + (*argP)++; + break; + + default: + return 0; + } + return 1; +} + + +#ifdef TEST2 + +/* TEST2: Test md_assemble() */ +/* Warning, this routine probably doesn't work anymore */ + +main() +{ + struct m68_it the_ins; + char buf[120]; + char *cp; + int n; + + m68_ip_begin(); + for(;;) { + if(!gets(buf) || !*buf) + break; + if(buf[0]=='|' || buf[1]=='.') + continue; + for(cp=buf;*cp;cp++) + if(*cp=='\t') + *cp=' '; + if(is_label(buf)) + continue; + bzero(&the_ins,sizeof(the_ins)); + m68_ip(&the_ins,buf); + if(the_ins.error) { + printf("Error %s in %s\n",the_ins.error,buf); + } else { + printf("Opcode(%d.%s): ",the_ins.numo,the_ins.args); + for(n=0;n<the_ins.numo;n++) + printf(" 0x%x",the_ins.opcode[n]&0xffff); + printf(" "); + print_the_insn(&the_ins.opcode[0],stdout); + (void)putchar('\n'); + } + for(n=0;n<strlen(the_ins.args)/2;n++) { + if(the_ins.operands[n].error) { + printf("op%d Error %s in %s\n",n,the_ins.operands[n].error,buf); + continue; + } + printf("mode %d, reg %d, ",the_ins.operands[n].mode,the_ins.operands[n].reg); + if(the_ins.operands[n].b_const) + printf("Constant: '%.*s', ",1+the_ins.operands[n].e_const-the_ins.operands[n].b_const,the_ins.operands[n].b_const); + printf("ireg %d, isiz %d, imul %d, ",the_ins.operands[n].ireg,the_ins.operands[n].isiz,the_ins.operands[n].imul); + if(the_ins.operands[n].b_iadd) + printf("Iadd: '%.*s',",1+the_ins.operands[n].e_iadd-the_ins.operands[n].b_iadd,the_ins.operands[n].b_iadd); + (void)putchar('\n'); + } + } + m68_ip_end(); + return 0; +} + +is_label(str) +char *str; +{ + while(*str==' ') + str++; + while(*str && *str!=' ') + str++; + if(str[-1]==':' || str[1]=='=') + return 1; + return 0; +} + +#endif + +/* Possible states for relaxation: + +0 0 branch offset byte (bra, etc) +0 1 word +0 2 long + +1 0 indexed offsets byte a0@(32,d4:w:1) etc +1 1 word +1 2 long + +2 0 two-offset index word-word a0@(32,d4)@(45) etc +2 1 word-long +2 2 long-word +2 3 long-long + +*/ + + + +#ifdef DONTDEF +abort() +{ + printf("ABORT!\n"); + exit(12); +} + +char *index(s,c) +char *s; +{ + while(*s!=c) { + if(!*s) return 0; + s++; + } + return s; +} + +bzero(s,n) +char *s; +{ + while(n--) + *s++=0; +} + +print_frags() +{ + fragS *fragP; + extern fragS *text_frag_root; + + for(fragP=text_frag_root;fragP;fragP=fragP->fr_next) { + printf("addr %lu next 0x%x fix %ld var %ld symbol 0x%x offset %ld\n", + fragP->fr_address,fragP->fr_next,fragP->fr_fix,fragP->fr_var,fragP->fr_symbol,fragP->fr_offset); + printf("opcode 0x%x type %d subtype %d\n\n",fragP->fr_opcode,fragP->fr_type,fragP->fr_subtype); + } + fflush(stdout); + return 0; +} +#endif + +#ifdef DONTDEF +/*VARARGS1*/ +panic(format,args) +char *format; +{ + fputs("Internal error:",stderr); + _doprnt(format,&args,stderr); + (void)putc('\n',stderr); + as_where(); + abort(); +} +#endif diff --git a/gnu/usr.bin/gas/config/m68k.h b/gnu/usr.bin/gas/config/m68k.h new file mode 100644 index 00000000000..2e4709e5ff6 --- /dev/null +++ b/gnu/usr.bin/gas/config/m68k.h @@ -0,0 +1,20 @@ +/* m-generic.h Generic machine-specific header file. + Copyright (C) 1987 Free Software Foundation, Inc. + +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 1, 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 M_GENERIC 1 diff --git a/gnu/usr.bin/gas/config/ns32k-opcode.h b/gnu/usr.bin/gas/config/ns32k-opcode.h new file mode 100644 index 00000000000..c851c34f0e6 --- /dev/null +++ b/gnu/usr.bin/gas/config/ns32k-opcode.h @@ -0,0 +1,434 @@ +/* ns32k-opcode.h -- Opcode table for National Semi 32k processor + Copyright (C) 1987 Free Software Foundation, Inc. + +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 1, 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. */ + + +#ifdef SEQUENT_COMPATABILITY +#define DEF_MODEC 20 +#define DEF_MODEL 21 +#endif + +#ifndef DEF_MODEC +#define DEF_MODEC 20 +#endif + +#ifndef DEF_MODEL +#define DEF_MODEL 20 +#endif +/* + After deciding the instruction entry (via hash.c) the instruction parser + will try to match the operands after the instruction to the required set + given in the entry operandfield. Every operand will result in a change in + the opcode or the addition of data to the opcode. + The operands in the source instruction are checked for inconsistent + semantics. + + F : 32 bit float general form + L : 64 bit float " + B : byte " + W : word " + D : double-word " + Q : quad-word " + A : double-word gen-address-form ie no regs allowed + d : displacement + b : displacement - pc relative addressing acb + p : displacement - pc relative addressing br bcond bsr cxp + q : quick + i : immediate (8 bits) + This is not a standard ns32k operandtype, it is used to build + instructions like svc arg1,arg2 + Svc is the instruction SuperVisorCall and is sometimes used to + call OS-routines from usermode. Some args might be handy! + r : register number (3 bits) + O : setcfg instruction optionslist + C : cinv instruction optionslist + S : stringinstruction optionslist + U : registerlist save,enter + u : registerlist restore,exit + M : mmu register + P : cpu register + g : 3:rd operand of inss or exts instruction + G : 4:th operand of inss or exts instruction + Those operands are encoded in the same byte. + This byte is placed last in the instruction. + f : operand of sfsr + H : sequent-hack for bsr (Warning) + +column 1 instructions + 2 number of bits in opcode. + 3 number of bits in opcode explicitly + determined by the instruction type. + 4 opcodeseed, the number we build our opcode + from. + 5 operandtypes, used by operandparser. + 6 size in bytes of immediate +*/ +struct ns32k_opcode { + char *name; + unsigned char opcode_id_size; /* not used by the assembler */ + unsigned char opcode_size; + unsigned long opcode_seed; + char *operands; + unsigned char im_size; /* not used by dissassembler */ + char *default_args; /* default to those args when none given */ + char default_modec; /* default to this addr-mode when ambigous + ie when the argument of a general addr-mode + is a plain constant */ + char default_model; /* is a plain label */ +}; + +struct ns32k_opcode ns32k_opcodes[]= +{ + { "absf", 14,24, 0x35be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "absl", 14,24, 0x34be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "absb", 14,24, 0x304e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "absw", 14,24, 0x314e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "absd", 14,24, 0x334e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "acbb", 7,16, 0x4c, "2B1q3p", 1, "", DEF_MODEC,DEF_MODEL }, + { "acbw", 7,16, 0x4d, "2W1q3p", 2, "", DEF_MODEC,DEF_MODEL }, + { "acbd", 7,16, 0x4f, "2D1q3p", 4, "", DEF_MODEC,DEF_MODEL }, + { "addf", 14,24, 0x01be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "addl", 14,24, 0x00be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "addb", 6,16, 0x00, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "addw", 6,16, 0x01, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "addd", 6,16, 0x03, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "addcb", 6,16, 0x10, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "addcw", 6,16, 0x11, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "addcd", 6,16, 0x13, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "addpb", 14,24, 0x3c4e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "addpw", 14,24, 0x3d4e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "addpd", 14,24, 0x3f4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "addqb", 7,16, 0x0c, "2B1q", 1, "", DEF_MODEC,DEF_MODEL }, + { "addqw", 7,16, 0x0d, "2W1q", 2, "", DEF_MODEC,DEF_MODEL }, + { "addqd", 7,16, 0x0f, "2D1q", 4, "", DEF_MODEC,DEF_MODEL }, + { "addr", 6,16, 0x27, "1A2D", 4, "", 21,21 }, + { "adjspb", 11,16, 0x057c, "1B", 1, "", DEF_MODEC,DEF_MODEL }, + { "adjspw", 11,16, 0x057d, "1W", 2, "", DEF_MODEC,DEF_MODEL }, + { "adjspd", 11,16, 0x057f, "1D", 4, "", DEF_MODEC,DEF_MODEL }, + { "andb", 6,16, 0x28, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "andw", 6,16, 0x29, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "andd", 6,16, 0x2b, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "ashb", 14,24, 0x044e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "ashw", 14,24, 0x054e, "1B2W", 1, "", DEF_MODEC,DEF_MODEL }, + { "ashd", 14,24, 0x074e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL }, + { "beq", 8,8, 0x0a, "1p", 0, "", 21,21 }, + { "bne", 8,8, 0x1a, "1p", 0, "", 21,21 }, + { "bcs", 8,8, 0x2a, "1p", 0, "", 21,21 }, + { "bcc", 8,8, 0x3a, "1p", 0, "", 21,21 }, + { "bhi", 8,8, 0x4a, "1p", 0, "", 21,21 }, + { "bls", 8,8, 0x5a, "1p", 0, "", 21,21 }, + { "bgt", 8,8, 0x6a, "1p", 0, "", 21,21 }, + { "ble", 8,8, 0x7a, "1p", 0, "", 21,21 }, + { "bfs", 8,8, 0x8a, "1p", 0, "", 21,21 }, + { "bfc", 8,8, 0x9a, "1p", 0, "", 21,21 }, + { "blo", 8,8, 0xaa, "1p", 0, "", 21,21 }, + { "bhs", 8,8, 0xba, "1p", 0, "", 21,21 }, + { "blt", 8,8, 0xca, "1p", 0, "", 21,21 }, + { "bge", 8,8, 0xda, "1p", 0, "", 21,21 }, + { "but", 8,8, 0xea, "1p", 0, "", 21,21 }, + { "buf", 8,8, 0xfa, "1p", 0, "", 21,21 }, + { "bicb", 6,16, 0x08, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "bicw", 6,16, 0x09, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "bicd", 6,16, 0x0b, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "bicpsrb", 11,16, 0x17c, "1B", 1, "", DEF_MODEC,DEF_MODEL }, + { "bicpsrw", 11,16, 0x17d, "1W", 2, "", DEF_MODEC,DEF_MODEL }, + { "bispsrb", 11,16, 0x37c, "1B", 1, "", DEF_MODEC,DEF_MODEL }, + { "bispsrw", 11,16, 0x37d, "1W", 2, "", DEF_MODEC,DEF_MODEL }, + { "bpt", 8,8, 0xf2, "", 0, "", DEF_MODEC,DEF_MODEL }, + { "br", 8,8, 0xea, "1p", 0, "", 21,21 }, +#ifdef SEQUENT_COMPATABILITY + { "bsr", 8,8, 0x02, "1H", 0, "", 21,21 }, +#else + { "bsr", 8,8, 0x02, "1p", 0, "", 21,21 }, +#endif + { "caseb", 11,16, 0x77c, "1B", 1, "", DEF_MODEC,DEF_MODEL }, + { "casew", 11,16, 0x77d, "1W", 2, "", DEF_MODEC,DEF_MODEL }, + { "cased", 11,16, 0x77f, "1D", 4, "", DEF_MODEC,DEF_MODEL }, + { "cbitb", 14,24, 0x084e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL }, + { "cbitw", 14,24, 0x094e, "1W2D", 2, "", DEF_MODEC,DEF_MODEL }, + { "cbitd", 14,24, 0x0b4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "cbitib", 14,24, 0x0c4e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL }, + { "cbitiw", 14,24, 0x0d4e, "1W2D", 2, "", DEF_MODEC,DEF_MODEL }, + { "cbitid", 14,24, 0x0f4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "checkb", 11,24, 0x0ee, "2A3B1r", 1, "", DEF_MODEC,DEF_MODEL }, + { "checkw", 11,24, 0x1ee, "2A3W1r", 2, "", DEF_MODEC,DEF_MODEL }, + { "checkd", 11,24, 0x3ee, "2A3D1r", 4, "", DEF_MODEC,DEF_MODEL }, + { "cinv", 14,24, 0x271e, "2D1C", 4, "", DEF_MODEC,DEF_MODEL }, + { "cmpf", 14,24, 0x09be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "cmpl", 14,24, 0x08be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "cmpb", 6,16, 0x04, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "cmpw", 6,16, 0x05, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "cmpd", 6,16, 0x07, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "cmpmb", 14,24, 0x04ce, "1A2A3b", 1, "", DEF_MODEC,DEF_MODEL }, + { "cmpmw", 14,24, 0x05ce, "1A2A3b", 2, "", DEF_MODEC,DEF_MODEL }, + { "cmpmd", 14,24, 0x07ce, "1A2A3b", 4, "", DEF_MODEC,DEF_MODEL }, + { "cmpqb", 7,16, 0x1c, "2B1q", 1, "", DEF_MODEC,DEF_MODEL }, + { "cmpqw", 7,16, 0x1d, "2W1q", 2, "", DEF_MODEC,DEF_MODEL }, + { "cmpqd", 7,16, 0x1f, "2D1q", 4, "", DEF_MODEC,DEF_MODEL }, + { "cmpsb", 16,24, 0x040e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "cmpsw", 16,24, 0x050e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "cmpsd", 16,24, 0x070e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "cmpst", 16,24, 0x840e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "comb", 14,24, 0x344e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "comw", 14,24, 0x354e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "comd", 14,24, 0x374e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "cvtp", 11,24, 0x036e, "2A3D1r", 4, "", DEF_MODEC,DEF_MODEL }, + { "cxp", 8,8, 0x22, "1p", 0, "", 21,21 }, + { "cxpd", 11,16, 0x07f, "1A", 4, "", DEF_MODEC,DEF_MODEL }, + { "deib", 14,24, 0x2cce, "1B2W", 1, "", DEF_MODEC,DEF_MODEL }, + { "deiw", 14,24, 0x2dce, "1W2D", 2, "", DEF_MODEC,DEF_MODEL }, + { "deid", 14,24, 0x2fce, "1D2Q", 4, "", DEF_MODEC,DEF_MODEL }, + { "dia", 8,8, 0xc2, "", 1, "", DEF_MODEC,DEF_MODEL }, + { "divf", 14,24, 0x21be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "divl", 14,24, 0x20be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "divb", 14,24, 0x3cce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "divw", 14,24, 0x3dce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "divd", 14,24, 0x3fce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "enter", 8,8, 0x82, "1U2d", 0, "", DEF_MODEC,DEF_MODEL }, + { "exit", 8,8, 0x92, "1u", 0, "", DEF_MODEC,DEF_MODEL }, + { "extb", 11,24, 0x02e, "2D3B1r4d", 1, "", DEF_MODEC,DEF_MODEL }, + { "extw", 11,24, 0x12e, "2D3W1r4d", 2, "", DEF_MODEC,DEF_MODEL }, + { "extd", 11,24, 0x32e, "2D3D1r4d", 4, "", DEF_MODEC,DEF_MODEL }, + { "extsb", 14,24, 0x0cce, "1D2B3g4G", 1, "", DEF_MODEC,DEF_MODEL }, + { "extsw", 14,24, 0x0dce, "1D2W3g4G", 2, "", DEF_MODEC,DEF_MODEL }, + { "extsd", 14,24, 0x0fce, "1D2D3g4G", 4, "", DEF_MODEC,DEF_MODEL }, + { "ffsb", 14,24, 0x046e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "ffsw", 14,24, 0x056e, "1W2B", 2, "", DEF_MODEC,DEF_MODEL }, + { "ffsd", 14,24, 0x076e, "1D2B", 4, "", DEF_MODEC,DEF_MODEL }, + { "flag", 8,8, 0xd2, "", 0, "", DEF_MODEC,DEF_MODEL }, + { "floorfb", 14,24, 0x3c3e, "1F2B", 4, "", DEF_MODEC,DEF_MODEL }, + { "floorfw", 14,24, 0x3d3e, "1F2W", 4, "", DEF_MODEC,DEF_MODEL }, + { "floorfd", 14,24, 0x3f3e, "1F2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "floorlb", 14,24, 0x383e, "1L2B", 8, "", DEF_MODEC,DEF_MODEL }, + { "floorlw", 14,24, 0x393e, "1L2W", 8, "", DEF_MODEC,DEF_MODEL }, + { "floorld", 14,24, 0x3b3e, "1L2D", 8, "", DEF_MODEC,DEF_MODEL }, + { "ibitb", 14,24, 0x384e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL }, + { "ibitw", 14,24, 0x394e, "1W2D", 2, "", DEF_MODEC,DEF_MODEL }, + { "ibitd", 14,24, 0x3b4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "indexb", 11,24, 0x42e, "2B3B1r", 1, "", DEF_MODEC,DEF_MODEL }, + { "indexw", 11,24, 0x52e, "2W3W1r", 2, "", DEF_MODEC,DEF_MODEL }, + { "indexd", 11,24, 0x72e, "2D3D1r", 4, "", DEF_MODEC,DEF_MODEL }, + { "insb", 11,24, 0x0ae, "2B3B1r4d", 1, "", DEF_MODEC,DEF_MODEL }, + { "insw", 11,24, 0x1ae, "2W3W1r4d", 2, "", DEF_MODEC,DEF_MODEL }, + { "insd", 11,24, 0x3ae, "2D3D1r4d", 4, "", DEF_MODEC,DEF_MODEL }, + { "inssb", 14,24, 0x08ce, "1B2D3g4G", 1, "", DEF_MODEC,DEF_MODEL }, + { "inssw", 14,24, 0x09ce, "1W2D3g4G", 2, "", DEF_MODEC,DEF_MODEL }, + { "inssd", 14,24, 0x0bce, "1D2D3g4G", 4, "", DEF_MODEC,DEF_MODEL }, + { "jsr", 11,16, 0x67f, "1A", 4, "", 21,21 }, + { "jump", 11,16, 0x27f, "1A", 4, "", 21,21 }, + { "lfsr", 19,24, 0x00f3e,"1D", 4, "", DEF_MODEC,DEF_MODEL }, + { "lmr", 15,24, 0x0b1e, "2D1M", 4, "", DEF_MODEC,DEF_MODEL }, + { "lprb", 7,16, 0x6c, "2B1P", 1, "", DEF_MODEC,DEF_MODEL }, + { "lprw", 7,16, 0x6d, "2W1P", 2, "", DEF_MODEC,DEF_MODEL }, + { "lprd", 7,16, 0x6f, "2D1P", 4, "", DEF_MODEC,DEF_MODEL }, + { "lshb", 14,24, 0x144e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "lshw", 14,24, 0x154e, "1B2W", 1, "", DEF_MODEC,DEF_MODEL }, + { "lshd", 14,24, 0x174e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL }, + { "meib", 14,24, 0x24ce, "1B2W", 1, "", DEF_MODEC,DEF_MODEL }, + { "meiw", 14,24, 0x25ce, "1W2D", 2, "", DEF_MODEC,DEF_MODEL }, + { "meid", 14,24, 0x27ce, "1D2Q", 4, "", DEF_MODEC,DEF_MODEL }, + { "modb", 14,24, 0x38ce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "modw", 14,24, 0x39ce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "modd", 14,24, 0x3bce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "movf", 14,24, 0x05be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "movl", 14,24, 0x04be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "movb", 6,16, 0x14, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "movw", 6,16, 0x15, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "movd", 6,16, 0x17, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "movbf", 14,24, 0x043e, "1B2F", 1, "", DEF_MODEC,DEF_MODEL }, + { "movwf", 14,24, 0x053e, "1W2F", 2, "", DEF_MODEC,DEF_MODEL }, + { "movdf", 14,24, 0x073e, "1D2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "movbl", 14,24, 0x003e, "1B2L", 1, "", DEF_MODEC,DEF_MODEL }, + { "movwl", 14,24, 0x013e, "1W2L", 2, "", DEF_MODEC,DEF_MODEL }, + { "movdl", 14,24, 0x033e, "1D2L", 4, "", DEF_MODEC,DEF_MODEL }, + { "movfl", 14,24, 0x1b3e, "1F2L", 4, "", DEF_MODEC,DEF_MODEL }, + { "movlf", 14,24, 0x163e, "1L2F", 8, "", DEF_MODEC,DEF_MODEL }, + { "movmb", 14,24, 0x00ce, "1A2A3b", 1, "", DEF_MODEC,DEF_MODEL }, + { "movmw", 14,24, 0x01ce, "1A2A3b", 2, "", DEF_MODEC,DEF_MODEL }, + { "movmd", 14,24, 0x03ce, "1A2A3b", 4, "", DEF_MODEC,DEF_MODEL }, + { "movqb", 7,16, 0x5c, "2B1q", 1, "", DEF_MODEC,DEF_MODEL }, + { "movqw", 7,16, 0x5d, "2B1q", 2, "", DEF_MODEC,DEF_MODEL }, + { "movqd", 7,16, 0x5f, "2B1q", 4, "", DEF_MODEC,DEF_MODEL }, + { "movsb", 16,24, 0x000e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "movsw", 16,24, 0x010e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "movsd", 16,24, 0x030e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "movst", 16,24, 0x800e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "movsub", 14,24, 0x0cae, "1A2A", 1, "", DEF_MODEC,DEF_MODEL }, + { "movsuw", 14,24, 0x0dae, "1A2A", 2, "", DEF_MODEC,DEF_MODEL }, + { "movsud", 14,24, 0x0fae, "1A2A", 4, "", DEF_MODEC,DEF_MODEL }, + { "movusb", 14,24, 0x1cae, "1A2A", 1, "", DEF_MODEC,DEF_MODEL }, + { "movusw", 14,24, 0x1dae, "1A2A", 2, "", DEF_MODEC,DEF_MODEL }, + { "movusd", 14,24, 0x1fae, "1A2A", 4, "", DEF_MODEC,DEF_MODEL }, + { "movxbd", 14,24, 0x1cce, "1B2D", 1, "", DEF_MODEC,DEF_MODEL }, + { "movxwd", 14,24, 0x1dce, "1W2D", 2, "", DEF_MODEC,DEF_MODEL }, + { "movxbw", 14,24, 0x10ce, "1B2W", 1, "", DEF_MODEC,DEF_MODEL }, + { "movzbd", 14,24, 0x18ce, "1B2D", 1, "", DEF_MODEC,DEF_MODEL }, + { "movzwd", 14,24, 0x19ce, "1W2D", 2, "", DEF_MODEC,DEF_MODEL }, + { "movzbw", 14,24, 0x14ce, "1B2W", 1, "", DEF_MODEC,DEF_MODEL }, + { "mulf", 14,24, 0x31be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "mull", 14,24, 0x30be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "mulb", 14,24, 0x20ce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "mulw", 14,24, 0x21ce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "muld", 14,24, 0x23ce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "negf", 14,24, 0x15be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "negl", 14,24, 0x14be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "negb", 14,24, 0x204e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "negw", 14,24, 0x214e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "negd", 14,24, 0x234e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "nop", 8,8, 0xa2, "", 0, "", DEF_MODEC,DEF_MODEL }, + { "notb", 14,24, 0x244e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "notw", 14,24, 0x254e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "notd", 14,24, 0x274e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "orb", 6,16, 0x18, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "orw", 6,16, 0x19, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "ord", 6,16, 0x1b, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "quob", 14,24, 0x30ce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "quow", 14,24, 0x31ce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "quod", 14,24, 0x33ce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "rdval", 19,24, 0x0031e,"1A", 4, "", DEF_MODEC,DEF_MODEL }, + { "remb", 14,24, 0x34ce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "remw", 14,24, 0x35ce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "remd", 14,24, 0x37ce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "restore", 8,8, 0x72, "1u", 0, "", DEF_MODEC,DEF_MODEL }, + { "ret", 8,8, 0x12, "1d", 0, "", DEF_MODEC,DEF_MODEL }, + { "reti", 8,8, 0x52, "", 0, "", DEF_MODEC,DEF_MODEL }, + { "rett", 8,8, 0x42, "1d", 0, "", DEF_MODEC,DEF_MODEL }, + { "rotb", 14,24, 0x004e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "rotw", 14,24, 0x014e, "1B2W", 1, "", DEF_MODEC,DEF_MODEL }, + { "rotd", 14,24, 0x034e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL }, + { "roundfb", 14,24, 0x243e, "1F2B", 4, "", DEF_MODEC,DEF_MODEL }, + { "roundfw", 14,24, 0x253e, "1F2W", 4, "", DEF_MODEC,DEF_MODEL }, + { "roundfd", 14,24, 0x273e, "1F2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "roundlb", 14,24, 0x203e, "1L2B", 8, "", DEF_MODEC,DEF_MODEL }, + { "roundlw", 14,24, 0x213e, "1L2W", 8, "", DEF_MODEC,DEF_MODEL }, + { "roundld", 14,24, 0x233e, "1L2D", 8, "", DEF_MODEC,DEF_MODEL }, + { "rxp", 8,8, 0x32, "1d", 0, "", DEF_MODEC,DEF_MODEL }, + { "seqb", 11,16, 0x3c, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "seqw", 11,16, 0x3d, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "seqd", 11,16, 0x3f, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sneb", 11,16, 0xbc, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "snew", 11,16, 0xbd, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sned", 11,16, 0xbf, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "scsb", 11,16, 0x13c, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "scsw", 11,16, 0x13d, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "scsd", 11,16, 0x13f, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sccb", 11,16, 0x1bc, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "sccw", 11,16, 0x1bd, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sccd", 11,16, 0x1bf, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "shib", 11,16, 0x23c, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "shiw", 11,16, 0x23d, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "shid", 11,16, 0x23f, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "slsb", 11,16, 0x2bc, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "slsw", 11,16, 0x2bd, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "slsd", 11,16, 0x2bf, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sgtb", 11,16, 0x33c, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "sgtw", 11,16, 0x33d, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sgtd", 11,16, 0x33f, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sleb", 11,16, 0x3bc, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "slew", 11,16, 0x3bd, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sled", 11,16, 0x3bf, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sfsb", 11,16, 0x43c, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "sfsw", 11,16, 0x43d, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sfsd", 11,16, 0x43f, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sfcb", 11,16, 0x4bc, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "sfcw", 11,16, 0x4bd, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sfcd", 11,16, 0x4bf, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "slob", 11,16, 0x53c, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "slow", 11,16, 0x53d, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "slod", 11,16, 0x53f, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "shsb", 11,16, 0x5bc, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "shsw", 11,16, 0x5bd, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "shsd", 11,16, 0x5bf, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sltb", 11,16, 0x63c, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "sltw", 11,16, 0x63d, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sltd", 11,16, 0x63f, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sgeb", 11,16, 0x6bc, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "sgew", 11,16, 0x6bd, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sged", 11,16, 0x6bf, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sutb", 11,16, 0x73c, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "sutw", 11,16, 0x73d, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sutd", 11,16, 0x73f, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "sufb", 11,16, 0x7bc, "1B", 0, "", DEF_MODEC,DEF_MODEL }, + { "sufw", 11,16, 0x7bd, "1W", 0, "", DEF_MODEC,DEF_MODEL }, + { "sufd", 11,16, 0x7bf, "1D", 0, "", DEF_MODEC,DEF_MODEL }, + { "save", 8,8, 0x62, "1U", 0, "", DEF_MODEC,DEF_MODEL }, + { "sbitb", 14,24, 0x184e, "1B2A", 1, "", DEF_MODEC,DEF_MODEL }, + { "sbitw", 14,24, 0x194e, "1W2A", 2, "", DEF_MODEC,DEF_MODEL }, + { "sbitd", 14,24, 0x1b4e, "1D2A", 4, "", DEF_MODEC,DEF_MODEL }, + { "sbitib", 14,24, 0x1c4e, "1B2A", 1, "", DEF_MODEC,DEF_MODEL }, + { "sbitiw", 14,24, 0x1d4e, "1W2A", 2, "", DEF_MODEC,DEF_MODEL }, + { "sbitid", 14,24, 0x1f4e, "1D2A", 4, "", DEF_MODEC,DEF_MODEL }, + { "setcfg", 15,24, 0x0b0e, "1O", 0, "", DEF_MODEC,DEF_MODEL }, + { "sfsr", 14,24, 0x373e, "1f", 0, "", DEF_MODEC,DEF_MODEL }, + { "skpsb", 16,24, 0x0c0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "skpsw", 16,24, 0x0d0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "skpsd", 16,24, 0x0f0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "skpst", 16,24, 0x8c0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL }, + { "smr", 15,24, 0x0f1e, "2D1M", 4, "", DEF_MODEC,DEF_MODEL }, + { "sprb", 7,16, 0x2c, "2B1P", 1, "", DEF_MODEC,DEF_MODEL }, + { "sprw", 7,16, 0x2d, "2W1P", 2, "", DEF_MODEC,DEF_MODEL }, + { "sprd", 7,16, 0x2f, "2D1P", 4, "", DEF_MODEC,DEF_MODEL }, + { "subf", 14,24, 0x11be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "subl", 14,24, 0x10be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "subb", 6,16, 0x20, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "subw", 6,16, 0x21, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "subd", 6,16, 0x23, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "subcb", 6,16, 0x30, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "subcw", 6,16, 0x31, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "subcd", 6,16, 0x33, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "subpb", 14,24, 0x2c4e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "subpw", 14,24, 0x2d4e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "subpd", 14,24, 0x2f4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, +#ifdef NS32K_SVC_IMMED_OPERANDS + { "svc", 8,8, 0xe2, "2i1i", 1, "", DEF_MODEC,DEF_MODEL }, /* not really, but unix uses it */ +#else + { "svc", 8,8, 0xe2, "", 0, "", DEF_MODEC,DEF_MODEL }, +#endif + { "tbitb", 6,16, 0x34, "1B2A", 1, "", DEF_MODEC,DEF_MODEL }, + { "tbitw", 6,16, 0x35, "1W2A", 2, "", DEF_MODEC,DEF_MODEL }, + { "tbitd", 6,16, 0x37, "1D2A", 4, "", DEF_MODEC,DEF_MODEL }, + { "truncfb", 14,24, 0x2c3e, "1F2B", 4, "", DEF_MODEC,DEF_MODEL }, + { "truncfw", 14,24, 0x2d3e, "1F2W", 4, "", DEF_MODEC,DEF_MODEL }, + { "truncfd", 14,24, 0x2f3e, "1F2D", 4, "", DEF_MODEC,DEF_MODEL }, + { "trunclb", 14,24, 0x283e, "1L2B", 8, "", DEF_MODEC,DEF_MODEL }, + { "trunclw", 14,24, 0x293e, "1L2W", 8, "", DEF_MODEC,DEF_MODEL }, + { "truncld", 14,24, 0x2b3e, "1L2D", 8, "", DEF_MODEC,DEF_MODEL }, + { "wait", 8,8, 0xb2, "", 0, "", DEF_MODEC,DEF_MODEL }, + { "wrval", 19,24, 0x0071e,"1A", 0, "", DEF_MODEC,DEF_MODEL }, + { "xorb", 6,16, 0x38, "1B2B", 1, "", DEF_MODEC,DEF_MODEL }, + { "xorw", 6,16, 0x39, "1W2W", 2, "", DEF_MODEC,DEF_MODEL }, + { "xord", 6,16, 0x3b, "1D2D", 4, "", DEF_MODEC,DEF_MODEL }, +#if defined(NS32381) /* I'm not too sure of these */ + { "dotf", 14,24, 0x0dfe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "dotl", 14,24, 0x0cfe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "logbf", 14,24, 0x15fe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "logbl", 14,24, 0x14fe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "polyf", 14,24, 0x09fe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "polyl", 14,24, 0x08fe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, + { "scalbf", 14,24, 0x11fe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL }, + { "scalbl", 14,24, 0x10fe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL }, +#endif +}; + +int numopcodes=sizeof(ns32k_opcodes)/sizeof(ns32k_opcodes[0]); + +struct ns32k_opcode *endop = ns32k_opcodes+sizeof(ns32k_opcodes)/sizeof(ns32k_opcodes[0]); + +#define MAX_ARGS 4 +#define ARG_LEN 50 + diff --git a/gnu/usr.bin/gas/config/ns32k.c b/gnu/usr.bin/gas/config/ns32k.c new file mode 100644 index 00000000000..8db917b243f --- /dev/null +++ b/gnu/usr.bin/gas/config/ns32k.c @@ -0,0 +1,1768 @@ +/* ns32k.c -- Assemble on the National Semiconductor 32k series + Copyright (C) 1987 Free Software Foundation, Inc. + +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 1, 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 NS32K +/*#define SHOW_NUM 1*/ /* uncomment for debugging */ + +#include <stdio.h> +#include <ctype.h> +#ifdef USG +#include <string.h> +#else +#include <strings.h> +#endif +#include "ns32k-opcode.h" +#include "as.h" +#include "obstack.h" +#include "frags.h" +#include "struc-symbol.h" +#include "flonum.h" +#include "expr.h" +#include "md.h" +#include "hash.h" +#include "write.h" +#include "symbols.h" + +/* Macros */ +#define IIF_ENTRIES 13 /* number of entries in iif */ +#define PRIVATE_SIZE 256 /* size of my garbage memory */ +#define MAX_ARGS 4 +#define DEFAULT -1 /* addr_mode returns this value when plain constant or label is encountered */ + +#define IIF(ptr,a1,c1,e1,g1,i1,k1,m1,o1,q1,s1,u1) \ + iif.iifP[ptr].type= a1; \ + iif.iifP[ptr].size= c1; \ + iif.iifP[ptr].object= e1; \ + iif.iifP[ptr].object_adjust= g1; \ + iif.iifP[ptr].pcrel= i1; \ + iif.iifP[ptr].pcrel_adjust= k1; \ + iif.iifP[ptr].im_disp= m1; \ + iif.iifP[ptr].relax_substate= o1; \ + iif.iifP[ptr].bit_fixP= q1; \ + iif.iifP[ptr].addr_mode= s1; \ + iif.iifP[ptr].bsr= u1; + +#ifdef SEQUENT_COMPATABILITY +#define LINE_COMMENT_CHARS "|" +#define ABSOLUTE_PREFIX '@' +#define IMMEDIATE_PREFIX '#' +#endif + +#ifndef LINE_COMMENT_CHARS +#define LINE_COMMENT_CHARS "#" +#endif + +char comment_chars[] = "#"; +char line_comment_chars[] = LINE_COMMENT_CHARS; +#if !defined(ABSOLUTE_PREFIX) && !defined(IMMEDIATE_PREFIX) +#define ABSOLUTE_PREFIX '@' /* One or the other MUST be defined */ +#endif + +struct addr_mode { + char mode; /* addressing mode of operand (0-31) */ + char scaled_mode; /* mode combined with scaled mode */ + char scaled_reg; /* register used in scaled+1 (1-8) */ + char float_flag; /* set if R0..R7 was F0..F7 ie a floating-point-register */ + char am_size; /* estimated max size of general addr-mode parts*/ + char im_disp; /* if im_disp==1 we have a displacement */ + char pcrel; /* 1 if pcrel, this is really redundant info */ + char disp_suffix[2]; /* length of displacement(s), 0=undefined */ + char *disp[2]; /* pointer(s) at displacement(s) + or immediates(s) (ascii) */ + char index_byte; /* index byte */ +}; +typedef struct addr_mode addr_modeS; + + +char *freeptr,*freeptr_static; /* points at some number of free bytes */ +struct hash_control *inst_hash_handle; + +struct ns32k_opcode *desc; /* pointer at description of instruction */ +addr_modeS addr_modeP; +char EXP_CHARS[] = "eE"; +char FLT_CHARS[] = "fd"; /* we don't want to support lowercase, do we */ +long omagic = OMAGIC; +void md_number_to_disp(); +void md_number_to_imm(); +segT evaluate_expr(); +void fix_new_ns32k(); + +/* UPPERCASE denotes live names + * when an instruction is built, IIF is used as an intermidiate form to store + * the actual parts of the instruction. A ns32k machine instruction can + * be divided into a couple of sub PARTs. When an instruction is assembled + * the appropriate PART get an assignment. When an IIF has been completed it's + * converted to a FRAGment as specified in AS.H */ + +/* internal structs */ +struct option { + char *pattern; + unsigned long or; + unsigned long and; +}; + +typedef struct { + int type; /* how to interpret object */ + int size; /* Estimated max size of object */ + unsigned long object; /* binary data */ + int object_adjust; /* number added to object */ + int pcrel; /* True if object is pcrel */ + int pcrel_adjust; /* It's value reflects the length in bytes from the instruction start to the displacement */ + int im_disp; /* True if the object is a displacement */ + relax_substateT relax_substate; /* Initial relaxsubstate */ + bit_fixS *bit_fixP; /* Pointer at bit_fix struct */ + int addr_mode; /* What addrmode do we associate with this iif-entry */ + char bsr; /* Sequent hack */ +}iif_entryT; /* Internal Instruction Format */ +struct int_ins_form { + int instr_size; /* Max size of instruction in bytes. */ + iif_entryT iifP[IIF_ENTRIES+1]; +}; +struct int_ins_form iif; +expressionS exprP; +char *input_line_pointer; +/* description of the PARTs in IIF + *object[n]: + * 0 total length in bytes of entries in iif + * 1 opcode + * 2 index_byte_a + * 3 index_byte_b + * 4 disp_a_1 + * 5 disp_a_2 + * 6 disp_b_1 + * 7 disp_b_2 + * 8 imm_a + * 9 imm_b + * 10 implied1 + * 11 implied2 + * + * For every entry there is a datalength in bytes. This is stored in size[n]. + * 0, the objectlength is not explicitly given by the instruction + * and the operand is undefined. This is a case for relaxation. + * Reserve 4 bytes for the final object. + * + * 1, the entry contains one byte + * 2, the entry contains two bytes + * 3, the entry contains three bytes + * 4, the entry contains four bytes + * etc + * + * Furthermore, every entry has a data type identifier in type[n]. + * + * 0, the entry is void, ignore it. + * 1, the entry is a binary number. + * 2, the entry is a pointer at an expression. + * Where expression may be as simple as a single '1', + * and as complicated as foo-bar+12, + * foo and bar may be undefined but suffixed by :{b|w|d} to + * control the length of the object. + * + * 3, the entry is a pointer at a bignum struct + * + * + * The low-order-byte coresponds to low physical memory. + * Obviously a FRAGment must be created for each valid disp in PART whose + * datalength is undefined (to bad) . + * The case where just the expression is undefined is less severe and is + * handled by fix. Here the number of bytes in the objectfile is known. + * With this representation we simplify the assembly and separates the + * machine dependent/independent parts in a more clean way (said OE) + */ + +struct option opt1[]= /* restore, exit */ +{ + { "r0", 0x80, 0xff }, + { "r1", 0x40, 0xff }, + { "r2", 0x20, 0xff }, + { "r3", 0x10, 0xff }, + { "r4", 0x08, 0xff }, + { "r5", 0x04, 0xff }, + { "r6", 0x02, 0xff }, + { "r7", 0x01, 0xff }, + { 0 , 0x00, 0xff } +}; +struct option opt2[]= /* save, enter */ +{ + { "r0", 0x01, 0xff }, + { "r1", 0x02, 0xff }, + { "r2", 0x04, 0xff }, + { "r3", 0x08, 0xff }, + { "r4", 0x10, 0xff }, + { "r5", 0x20, 0xff }, + { "r6", 0x40, 0xff }, + { "r7", 0x80, 0xff }, + { 0 , 0x00, 0xff } +}; +struct option opt3[]= /* setcfg */ +{ + { "c", 0x8, 0xff }, + { "m", 0x4, 0xff }, + { "f", 0x2, 0xff }, + { "i", 0x1, 0xff }, + { 0 , 0x0, 0xff } +}; +struct option opt4[]= /* cinv */ +{ + { "a", 0x4, 0xff }, + { "i", 0x2, 0xff }, + { "d", 0x1, 0xff }, + { 0 , 0x0, 0xff } +}; +struct option opt5[]= /* string inst */ +{ + { "b", 0x2, 0xff }, + { "u", 0xc, 0xff }, + { "w", 0x4, 0xff }, + { 0 , 0x0, 0xff } +}; +struct option opt6[]= /* plain reg ext,cvtp etc */ +{ + { "r0", 0x00, 0xff }, + { "r1", 0x01, 0xff }, + { "r2", 0x02, 0xff }, + { "r3", 0x03, 0xff }, + { "r4", 0x04, 0xff }, + { "r5", 0x05, 0xff }, + { "r6", 0x06, 0xff }, + { "r7", 0x07, 0xff }, + { 0 , 0x00, 0xff } +}; + +#if !defined(NS32032) && !defined(NS32532) +#define NS32032 +#endif + +struct option cpureg_532[]= /* lpr spr */ +{ + { "us", 0x0, 0xff }, + { "dcr", 0x1, 0xff }, + { "bpc", 0x2, 0xff }, + { "dsr", 0x3, 0xff }, + { "car", 0x4, 0xff }, + { "fp", 0x8, 0xff }, + { "sp", 0x9, 0xff }, + { "sb", 0xa, 0xff }, + { "usp", 0xb, 0xff }, + { "cfg", 0xc, 0xff }, + { "psr", 0xd, 0xff }, + { "intbase", 0xe, 0xff }, + { "mod", 0xf, 0xff }, + { 0 , 0x00, 0xff } +}; +struct option mmureg_532[]= /* lmr smr */ +{ + { "mcr", 0x9, 0xff }, + { "msr", 0xa, 0xff }, + { "tear", 0xb, 0xff }, + { "ptb0", 0xc, 0xff }, + { "ptb1", 0xd, 0xff }, + { "ivar0", 0xe, 0xff }, + { "ivar1", 0xf, 0xff }, + { 0 , 0x0, 0xff } +}; + +struct option cpureg_032[]= /* lpr spr */ +{ + { "upsr", 0x0, 0xff }, + { "fp", 0x8, 0xff }, + { "sp", 0x9, 0xff }, + { "sb", 0xa, 0xff }, + { "psr", 0xd, 0xff }, + { "intbase", 0xe, 0xff }, + { "mod", 0xf, 0xff }, + { 0 , 0x0, 0xff } +}; +struct option mmureg_032[]= /* lmr smr */ +{ + { "bpr0", 0x0, 0xff }, + { "bpr1", 0x1, 0xff }, + { "pf0", 0x4, 0xff }, + { "pf1", 0x5, 0xff }, + { "sc", 0x8, 0xff }, + { "msr", 0xa, 0xff }, + { "bcnt", 0xb, 0xff }, + { "ptb0", 0xc, 0xff }, + { "ptb1", 0xd, 0xff }, + { "eia", 0xf, 0xff }, + { 0 , 0x0, 0xff } +}; + +#if defined(NS32532) +struct option *cpureg = cpureg_532; +struct option *mmureg = mmureg_532; +#else +struct option *cpureg = cpureg_032; +struct option *mmureg = mmureg_032; +#endif + + +const pseudo_typeS md_pseudo_table[]={ /* so far empty */ + { 0, 0, 0 } +}; + +#define IND(x,y) (((x)<<2)+(y)) + +/* those are index's to relax groups in md_relax_table + ie it must be multiplied by 4 to point at a group start. Viz IND(x,y) + Se function relax_segment in write.c for more info */ + +#define BRANCH 1 +#define PCREL 2 + +/* those are index's to entries in a relax group */ + +#define BYTE 0 +#define WORD 1 +#define DOUBLE 2 +#define UNDEF 3 +/* Those limits are calculated from the displacement start in memory. + The ns32k uses the begining of the instruction as displacement base. + This type of displacements could be handled here by moving the limit window + up or down. I choose to use an internal displacement base-adjust as there + are other routines that must consider this. Also, as we have two various + offset-adjusts in the ns32k (acb versus br/brs/jsr/bcond), two set of limits + would have had to be used. + Now we dont have to think about that. */ + + +const relax_typeS md_relax_table[]={ + { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, + + { (63), (-64), 1, IND(BRANCH,WORD) }, + { (8192), (-8192), 2, IND(BRANCH,DOUBLE) }, + { 0, 0, 4, 0 }, + { 1, 1, 0, 0 } +}; + +/* Array used to test if mode contains displacements. + Value is true if mode contains displacement. */ + +char disp_test[]={ 0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1, + 1,1,1,0,0,1,1,0, + 1,1,1,1,1,1,1,1 }; + +/* Array used to calculate max size of displacements */ + +char disp_size[]={ 4,1,2,0,4 }; + +/* Parses a general operand into an addressingmode struct + + in: pointer at operand in ascii form + pointer at addr_mode struct for result + the level of recursion. (always 0 or 1) + + out: data in addr_mode struct + */ +int addr_mode(operand,addr_modeP,recursive_level) + char *operand; + register addr_modeS *addr_modeP; +int recursive_level; +{ + register char *str; + register int i; + register int strl; + register int mode; + int j; + mode = DEFAULT; /* default */ + addr_modeP->scaled_mode=0; /* why not */ + addr_modeP->scaled_reg=0; /* if 0, not scaled index */ + addr_modeP->float_flag=0; + addr_modeP->am_size=0; + addr_modeP->im_disp=0; + addr_modeP->pcrel=0; /* not set in this function */ + addr_modeP->disp_suffix[0]=0; + addr_modeP->disp_suffix[1]=0; + addr_modeP->disp[0]=NULL; + addr_modeP->disp[1]=NULL; + str=operand; + if (str[0]==0) {return (0);} /* we don't want this */ + strl=strlen(str); + switch (str[0]) { + /* the following three case statements controls the mode-chars + this is the place to ed if you want to change them */ +#ifdef ABSOLUTE_PREFIX + case ABSOLUTE_PREFIX: + if (str[strl-1]==']') break; + addr_modeP->mode=21; /* absolute */ + addr_modeP->disp[0]=str+1; + return (-1); +#endif +#ifdef IMMEDIATE_PREFIX + case IMMEDIATE_PREFIX: + if (str[strl-1]==']') break; + addr_modeP->mode=20; /* immediate */ + addr_modeP->disp[0]=str+1; + return (-1); +#endif + case '.': + if (str[strl-1]!=']') { + switch (str[1]) { + case'-':case'+': + if (str[2]!='\000') { + addr_modeP->mode=27; /* pc-relativ */ + addr_modeP->disp[0]=str+2; + return (-1); + } + default: + as_warn("Invalid syntax in PC-relative addressing mode"); + return(0); + } + } + break; + case'e': + if (str[strl-1]!=']') { + if((!strncmp(str,"ext(",4)) && strl>7) { /* external */ + addr_modeP->disp[0]=str+4; + i=0; + j=2; + do { /* disp[0]'s termination point */ + j+=1; + if (str[j]=='(') i++; + if (str[j]==')') i--; + } while (j<strl && i!=0); + if (i!=0 || !(str[j+1]=='-' || str[j+1]=='+') ) { + as_warn("Invalid syntax in External addressing mode"); + return(0); + } + str[j]='\000'; /* null terminate disp[0] */ + addr_modeP->disp[1]=str+j+2; + addr_modeP->mode=22; + return (-1); + } + } + break; + default:; + } + strl=strlen(str); + switch(strl) { + case 2: + switch (str[0]) { + case'f':addr_modeP->float_flag=1; + case'r': + if (str[1]>='0' && str[1]<'8') { + addr_modeP->mode=str[1]-'0'; + return (-1); + } + } + case 3: + if (!strncmp(str,"tos",3)) { + addr_modeP->mode=23; /* TopOfStack */ + return (-1); + } + default:; + } + if (strl>4) { + if (str[strl-1]==')') { + if (str[strl-2]==')') { + if (!strncmp(&str[strl-5],"(fp",3)) { + mode=16; /* Memory Relative */ + } + if (!strncmp(&str[strl-5],"(sp",3)) { + mode=17; + } + if (!strncmp(&str[strl-5],"(sb",3)) { + mode=18; + } + if (mode!=DEFAULT) { /* memory relative */ + addr_modeP->mode=mode; + j=strl-5; /* temp for end of disp[0] */ + i=0; + do { + strl-=1; + if (str[strl]==')') i++; + if (str[strl]=='(') i--; + } while (strl>-1 && i!=0); + if (i!=0) { + as_warn("Invalid syntax in Memory Relative addressing mode"); + return(0); + } + addr_modeP->disp[1]=str; + addr_modeP->disp[0]=str+strl+1; + str[j]='\000'; /* null terminate disp[0] */ + str[strl]='\000'; /* null terminate disp[1] */ + return (-1); + } + } + switch (str[strl-3]) { + case'r':case'R': + if (str[strl-2]>='0' && str[strl-2]<'8' && str[strl-4]=='(') { + addr_modeP->mode=str[strl-2]-'0'+8; + addr_modeP->disp[0]=str; + str[strl-4]=0; + return (-1); /* reg rel */ + } + default: + if (!strncmp(&str[strl-4],"(fp",3)) { + mode=24; + } + if (!strncmp(&str[strl-4],"(sp",3)) { + mode=25; + } + if (!strncmp(&str[strl-4],"(sb",3)) { + mode=26; + } + if (!strncmp(&str[strl-4],"(pc",3)) { + mode=27; + } + if (mode!=DEFAULT) { + addr_modeP->mode=mode; + addr_modeP->disp[0]=str; + str[strl-4]='\0'; + return (-1); /* memory space */ + } + } + } + /* no trailing ')' do we have a ']' ? */ + if (str[strl-1]==']') { + switch (str[strl-2]) { + case'b':mode=28;break; + case'w':mode=29;break; + case'd':mode=30;break; + case'q':mode=31;break; + default:; + as_warn("Invalid scaled-indexed mode, use (b,w,d,q)"); + if (str[strl-3]!=':' || str[strl-6]!='[' || + str[strl-5]=='r' || str[strl-4]<'0' || str[strl-4]>'7') { + as_warn("Syntax in scaled-indexed mode, use [Rn:m] where n=[0..7] m={b,w,d,q}"); + } + } /* scaled index */ + { + if (recursive_level>0) { + as_warn("Scaled-indexed addressing mode combined with scaled-index"); + return(0); + } + addr_modeP->am_size+=1; /* scaled index byte */ + j=str[strl-4]-'0'; /* store temporary */ + str[strl-6]='\000'; /* nullterminate for recursive call */ + i=addr_mode(str,addr_modeP,1); + if (!i || addr_modeP->mode==20) { + as_warn("Invalid or illegal addressing mode combined with scaled-index"); + return(0); + } + addr_modeP->scaled_mode=addr_modeP->mode; /* store the inferior mode */ + addr_modeP->mode=mode; + addr_modeP->scaled_reg=j+1; + return (-1); + } + } + } + addr_modeP->mode = DEFAULT; /* default to whatever */ + addr_modeP->disp[0]=str; + return (-1); +} + +/* ptr points at string + addr_modeP points at struct with result + This routine calls addr_mode to determine the general addr.mode of + the operand. When this is ready it parses the displacements for size + specifying suffixes and determines size of immediate mode via ns32k-opcode. + Also builds index bytes if needed. + */ +int get_addr_mode(ptr,addr_modeP) + char *ptr; + addr_modeS *addr_modeP; +{ + int tmp; + addr_mode(ptr,addr_modeP,0); + if (addr_modeP->mode == DEFAULT || addr_modeP->scaled_mode == -1) { + /* resolve ambigious operands, this shouldn't + be necessary if one uses standard NSC operand + syntax. But the sequent compiler doesn't!!! + This finds a proper addressinging mode if it + is implicitly stated. See ns32k-opcode.h */ + (void)evaluate_expr(&exprP,ptr); /* this call takes time Sigh! */ + if (addr_modeP->mode == DEFAULT) { + if (exprP.X_add_symbol || exprP.X_subtract_symbol) { + addr_modeP->mode=desc->default_model; /* we have a label */ + } else { + addr_modeP->mode=desc->default_modec; /* we have a constant */ + } + } else { + if (exprP.X_add_symbol || exprP.X_subtract_symbol) { + addr_modeP->scaled_mode=desc->default_model; + } else { + addr_modeP->scaled_mode=desc->default_modec; + } + } + /* must put this mess down in addr_mode to handle the scaled case better */ + } + /* It appears as the sequent compiler wants an absolute when we have a + label without @. Constants becomes immediates besides the addr case. + Think it does so with local labels too, not optimum, pcrel is better. + When I have time I will make gas check this and select pcrel when possible + Actually that is trivial. + */ + if (tmp=addr_modeP->scaled_reg) { /* build indexbyte */ + tmp--; /* remember regnumber comes incremented for flagpurpose */ + tmp|=addr_modeP->scaled_mode<<3; + addr_modeP->index_byte=(char)tmp; + addr_modeP->am_size+=1; + } + if (disp_test[addr_modeP->mode]) { /* there was a displacement, probe for length specifying suffix*/ + { + register char c; + register char suffix; + register char suffix_sub; + register int i; + register char *toP; + register char *fromP; + + addr_modeP->pcrel=0; + if (disp_test[addr_modeP->mode]) { /* there is a displacement */ + if (addr_modeP->mode==27 || addr_modeP->scaled_mode==27) { /* do we have pcrel. mode */ + addr_modeP->pcrel=1; + } + addr_modeP->im_disp=1; + for(i=0;i<2;i++) { + suffix_sub=suffix=0; + if (toP=addr_modeP->disp[i]) { /* suffix of expression, the largest size rules */ + fromP=toP; + while (c = *fromP++) { + *toP++=c; + if (c==':') { + switch (*fromP) { + case '\0': + as_warn("Premature end of suffix--Defaulting to d"); + suffix=4; + continue; + case 'b':suffix_sub=1;break; + case 'w':suffix_sub=2;break; + case 'd':suffix_sub=4;break; + default: + as_warn("Bad suffix after ':' use {b|w|d} Defaulting to d"); + suffix=4; + } + fromP++; + toP--; /* So we write over the ':' */ + if (suffix<suffix_sub) suffix=suffix_sub; + } + } + *toP='\0'; /* terminate properly */ + addr_modeP->disp_suffix[i]=suffix; + addr_modeP->am_size+=suffix ? suffix : 4; + } + } + } + } + } else { + if (addr_modeP->mode==20) { /* look in ns32k_opcode for size */ + addr_modeP->disp_suffix[0]=addr_modeP->am_size=desc->im_size; + addr_modeP->im_disp=0; + } + } + return addr_modeP->mode; +} + + +/* read an optionlist */ +void optlist(str,optionP,default_map) + char *str; /* the string to extract options from */ + struct option *optionP; /* how to search the string */ + unsigned long *default_map; /* default pattern and output */ +{ + register int i,j,k,strlen1,strlen2; + register char *patternP,*strP; + strlen1=strlen(str); + if (strlen1<1) { + as_fatal("Very short instr to option, ie you can't do it on a NULLstr"); + } + for (i=0;optionP[i].pattern!=0;i++) { + strlen2=strlen(optionP[i].pattern); + for (j=0;j<strlen1;j++) { + patternP=optionP[i].pattern; + strP = &str[j]; + for (k=0;k<strlen2;k++) { + if (*(strP++)!=*(patternP++)) break; + } + if (k==strlen2) { /* match */ + *default_map|=optionP[i].or; + *default_map&=optionP[i].and; + } + } + } +} +/* search struct for symbols + This function is used to get the short integer form of reg names + in the instructions lmr, smr, lpr, spr + return true if str is found in list */ + +int list_search(str,optionP,default_map) + char *str; /* the string to match */ + struct option *optionP; /* list to search */ + unsigned long *default_map; /* default pattern and output */ +{ + register int i; + for (i=0;optionP[i].pattern!=0;i++) { + if (!strncmp(optionP[i].pattern,str,20)) { /* use strncmp to be safe */ + *default_map|=optionP[i].or; + *default_map&=optionP[i].and; + return -1; + } + } + as_warn("No such entry in list. (cpu/mmu register)"); + return 0; +} +segT evaluate_expr(resultP,ptr) +expressionS *resultP; +char *ptr; +{ + register char *tmp_line; + register segT segment; + tmp_line=input_line_pointer; + input_line_pointer=ptr; + segment=expression(&exprP); + input_line_pointer=tmp_line; + return (segment); +} + +/* Convert operands to iif-format and adds bitfields to the opcode. + Operands are parsed in such an order that the opcode is updated from + its most significant bit, that is when the operand need to alter the + opcode. + Be carefull not to put to objects in the same iif-slot. + */ + +encode_operand(argc,argv,operandsP,suffixP,im_size,opcode_bit_ptr) + int argc; + char **argv; + char *operandsP; + char *suffixP; + char im_size; + char opcode_bit_ptr; +{ + register int i,j; + int pcrel,tmp,b,loop,pcrel_adjust; + for(loop=0;loop<argc;loop++) { + i=operandsP[loop<<1]-'1'; /* what operand are we supposed to work on */ + if (i>3) as_fatal("Internal error check ns32k-opcode.h"); + pcrel=0; + pcrel_adjust=0; + tmp=0; + switch (operandsP[(loop<<1)+1]) { + case 'f': /* operand of sfsr turns out to be a nasty specialcase */ + opcode_bit_ptr-=5; + case 'F': /* 32 bit float general form */ + case 'L': /* 64 bit float */ + case 'Q': /* quad-word */ + case 'B': /* byte */ + case 'W': /* word */ + case 'D': /* double-word */ + case 'A': /* double-word gen-address-form ie no regs allowed */ + get_addr_mode(argv[i],&addr_modeP); + iif.instr_size+=addr_modeP.am_size; + if (opcode_bit_ptr==desc->opcode_size) b=4; else b=6; + for (j=b;j<(b+2);j++) { + if (addr_modeP.disp[j-b]) { + IIF(j, + 2, + addr_modeP.disp_suffix[j-b], + (unsigned long)addr_modeP.disp[j-b], + 0, + addr_modeP.pcrel, + iif.instr_size-addr_modeP.am_size, /* this aint used (now) */ + addr_modeP.im_disp, + IND(BRANCH,BYTE), + NULL, + addr_modeP.scaled_reg ? addr_modeP.scaled_mode:addr_modeP.mode, + 0); + } + } + opcode_bit_ptr-=5; + iif.iifP[1].object|=((long)addr_modeP.mode)<<opcode_bit_ptr; + if (addr_modeP.scaled_reg) { + j=b/2; + IIF(j,1,1, (unsigned long)addr_modeP.index_byte,0,0,0,0,0, NULL,-1,0); + } + break; + case 'b': /* multiple instruction disp */ + freeptr++; /* OVE:this is an useful hack */ + tmp=(int)sprintf(freeptr,"((%s-1)*%d)\000",argv[i],desc->im_size); + argv[i]=freeptr; + freeptr=(char*)tmp; + pcrel-=1; /* make pcrel 0 inspite of what case 'p': wants */ + /* fall thru */ + case 'p': /* displacement - pc relative addressing */ + pcrel+=1; + /* fall thru */ + case 'd': /* displacement */ + iif.instr_size+=suffixP[i] ? suffixP[i] : 4; + IIF(12, 2, suffixP[i], (unsigned long)argv[i], 0, + pcrel, pcrel_adjust, 1, IND(BRANCH,BYTE), NULL,-1,0); + break; + case 'H': /* sequent-hack: the linker wants a bit set when bsr */ + pcrel=1; + iif.instr_size+=suffixP[i] ? suffixP[i] : 4; + IIF(12, 2, suffixP[i], (unsigned long)argv[i], 0, + pcrel, pcrel_adjust, 1, IND(BRANCH,BYTE), NULL,-1,1);break; + case 'q': /* quick */ + opcode_bit_ptr-=4; + IIF(11,2,42,(unsigned long)argv[i],0,0,0,0,0, + bit_fix_new(4,opcode_bit_ptr,-8,7,0,1,0),-1,0); + break; + case 'r': /* register number (3 bits) */ + list_search(argv[i],opt6,&tmp); + opcode_bit_ptr-=3; + iif.iifP[1].object|=tmp<<opcode_bit_ptr; + break; + case 'O': /* setcfg instruction optionslist */ + optlist(argv[i],opt3,&tmp); + opcode_bit_ptr-=4; + iif.iifP[1].object|=tmp<<15; + break; + case 'C': /* cinv instruction optionslist */ + optlist(argv[i],opt4,&tmp); + opcode_bit_ptr-=4; + iif.iifP[1].object|=tmp<<15;/*insert the regtype in opcode */ + break; + case 'S': /* stringinstruction optionslist */ + optlist(argv[i],opt5,&tmp); + opcode_bit_ptr-=4; + iif.iifP[1].object|=tmp<<15; + break; + case 'u':case 'U': /* registerlist */ + IIF(10,1,1,0,0,0,0,0,0,NULL,-1,0); + switch (operandsP[(i<<1)+1]) { + case 'u': /* restore, exit */ + optlist(argv[i],opt1,&iif.iifP[10].object); + break; + case 'U': /* save,enter */ + optlist(argv[i],opt2,&iif.iifP[10].object); + break; + } + iif.instr_size+=1; + break; + case 'M': /* mmu register */ + list_search(argv[i],mmureg,&tmp); + opcode_bit_ptr-=4; + iif.iifP[1].object|=tmp<<opcode_bit_ptr; + break; + case 'P': /* cpu register */ + list_search(argv[i],cpureg,&tmp); + opcode_bit_ptr-=4; + iif.iifP[1].object|=tmp<<opcode_bit_ptr; + break; + case 'g': /* inss exts */ + iif.instr_size+=1; /* 1 byte is allocated after the opcode */ + IIF(10,2,1, + (unsigned long)argv[i], /* i always 2 here */ + 0,0,0,0,0, + bit_fix_new(3,5,0,7,0,0,0), /* a bit_fix is targeted to the byte */ + -1,0); + case 'G': + IIF(11,2,42, + (unsigned long)argv[i], /* i always 3 here */ + 0,0,0,0,0, + bit_fix_new(5,0,1,32,-1,0,-1),-1,0); + break; + case 'i': + iif.instr_size+=1; + b=2+i; /* put the extension byte after opcode */ + IIF(b,2,1,0,0,0,0,0,0,0,-1,0); + default: + as_fatal("Bad opcode-table-option, check in file ns32k-opcode.h"); + } + } +} + +/* in: instruction line + out: internal structure of instruction + that has been prepared for direct conversion to fragment(s) and + fixes in a systematical fashion + Return-value = recursive_level +*/ +/* build iif of one assembly text line */ +int parse(line,recursive_level) + char *line; + int recursive_level; +{ + register char *lineptr,c,suffix_separator; + register int i; + int argc,arg_type; + char sqr,sep; + char suffix[MAX_ARGS],*argv[MAX_ARGS];/* no more than 4 operands */ + if (recursive_level<=0) { /* called from md_assemble */ + for (lineptr=line;(*lineptr)!='\0' && (*lineptr)!=' ';lineptr++); + c = *lineptr; + *lineptr='\0'; + if (!(desc=(struct ns32k_opcode*)hash_find(inst_hash_handle,line))) { + as_fatal("No such opcode"); + } + *lineptr=c; + } else { + lineptr=line; + } + argc=0; + if (*desc->operands) { + if (*lineptr++!='\0') { + sqr='['; + sep=','; + while (*lineptr!='\0') { + if (desc->operands[argc<<1]) { + suffix[argc]=0; + arg_type=desc->operands[(argc<<1)+1]; + switch (arg_type) { + case 'd': case 'b': case 'p': case 'H': /* the operand is supposed to be a displacement */ + /* Hackwarning: do not forget to update the 4 cases above when editing ns32k-opcode.h */ + suffix_separator=':'; + break; + default: + suffix_separator='\255'; /* if this char occurs we loose */ + } + suffix[argc]=0; /* 0 when no ':' is encountered */ + argv[argc]=freeptr; + *freeptr='\0'; + while ((c = *lineptr)!='\0' && c!=sep) { + if (c==sqr) { + if (sqr=='[') { + sqr=']';sep='\0'; + } else { + sqr='[';sep=','; + } + } + if (c==suffix_separator) { /* ':' - label/suffix separator */ + switch (lineptr[1]) { + case 'b':suffix[argc]=1;break; + case 'w':suffix[argc]=2;break; + case 'd':suffix[argc]=4;break; + default: as_warn("Bad suffix, defaulting to d"); + suffix[argc]=4; + if (lineptr[1]=='\0' || lineptr[1]==sep) { + lineptr+=1; + continue; + } + } + lineptr+=2; + continue; + } + *freeptr++=c; + lineptr++; + } + *freeptr++='\0'; + argc+=1; + if (*lineptr=='\0') continue; + lineptr+=1; + } else { + as_fatal("Too many operands passed to instruction"); + } + } + } + } + if (argc!=strlen(desc->operands)/2) { + if (strlen(desc->default_args)) { /* we can apply default, dont goof */ + if (parse(desc->default_args,1)!=1) { /* check error in default */ + as_fatal("Wrong numbers of operands in default, check ns32k-opcodes.h"); + } + } else { + as_fatal("Wrong number of operands"); + } + + } + for (i=0;i<IIF_ENTRIES;i++) { + iif.iifP[i].type=0; /* mark all entries as void*/ + } + + /* build opcode iif-entry */ + iif.instr_size=desc->opcode_size/8; + IIF(1,1,iif.instr_size,desc->opcode_seed,0,0,0,0,0,0,-1,0); + + /* this call encodes operands to iif format */ + if (argc) { + encode_operand(argc, + argv, + &desc->operands[0], + &suffix[0], + desc->im_size, + desc->opcode_size); + } + return recursive_level; +} + + + /* Convert iif to fragments. + From this point we start to dribble with functions in other files than + this one.(Except hash.c) So, if it's possible to make an iif for an other + CPU, you don't need to know what frags, relax, obstacks, etc is in order + to port this assembler. You only need to know if it's possible to reduce + your cpu-instruction to iif-format (takes some work) and adopt the other + md_? parts according to given instructions + Note that iif was invented for the clean ns32k`s architecure. + */ +convert_iif() +{ + register int i,j; + fragS *inst_frag; + char *inst_offset,*inst_opcode; + char *memP; + segT segment; + int l,k; + register int rem_size; /* count the remaining bytes of instruction */ + register char type; + register char size = 0; + int size_so_far=0; /* used to calculate pcrel_adjust */ + + rem_size=iif.instr_size; + memP=frag_more(iif.instr_size); /* make sure we have enough bytes for instruction */ + inst_opcode=memP; + inst_offset=(char*)(memP-frag_now->fr_literal); + inst_frag=frag_now; + for (i=0;i<IIF_ENTRIES;i++) { + if (type=iif.iifP[i].type) { /* the object exist, so handle it */ + switch (size=iif.iifP[i].size) { + case 42: size=0; /* it's a bitfix that operates on an existing object*/ + if (iif.iifP[i].bit_fixP->fx_bit_base) { /* expand fx_bit_base to point at opcode */ + iif.iifP[i].bit_fixP->fx_bit_base=(long)inst_opcode; + } + case 8: /* bignum or doublefloat */ + bzero (memP,8); + case 1:case 2:case 3:case 4:/* the final size in objectmemory is known */ + j=(unsigned long)iif.iifP[i].bit_fixP; + switch (type) { + case 1: /* the object is pure binary */ + if (j || iif.iifP[i].pcrel) { + fix_new_ns32k(frag_now, + (long)(memP-frag_now->fr_literal), + size, + 0, + 0, + iif.iifP[i].object, + iif.iifP[i].pcrel, + (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/ + iif.iifP[i].im_disp, + j, + iif.iifP[i].bsr); /* sequent hack */ + } else { /* good, just put them bytes out */ + switch (iif.iifP[i].im_disp) { + case 0: + md_number_to_chars(memP,iif.iifP[i].object,size);break; + case 1: + md_number_to_disp(memP,iif.iifP[i].object,size);break; + default: as_fatal("iif convert internal pcrel/binary"); + } + } + memP+=size; + rem_size-=size; + break; + case 2: /* the object is a pointer at an expression, so unpack + it, note that bignums may result from the expression + */ + if ((segment=evaluate_expr(&exprP,(char*)iif.iifP[i].object))==SEG_BIG || size==8) { + if ((k=exprP.X_add_number)>0) { /* we have a bignum ie a quad */ + /* this can only happens in a long suffixed instruction */ + bzero(memP,size); /* size normally is 8 */ + if (k*2>size) as_warn("Bignum too big for long"); + if (k==3) memP+=2; + for (l=0;k>0;k--,l+=2) { + md_number_to_chars(memP+l,generic_bignum[l>>1],sizeof(LITTLENUM_TYPE)); + } + } else { /* flonum */ + LITTLENUM_TYPE words[4]; + + switch(size) { + case 4: + gen_to_words(words,2,8); + md_number_to_imm(memP ,(long)words[0],sizeof(LITTLENUM_TYPE)); + md_number_to_imm(memP+sizeof(LITTLENUM_TYPE),(long)words[1],sizeof(LITTLENUM_TYPE)); + break; + case 8: + gen_to_words(words,4,11); + md_number_to_imm(memP ,(long)words[0],sizeof(LITTLENUM_TYPE)); + md_number_to_imm(memP+sizeof(LITTLENUM_TYPE) ,(long)words[1],sizeof(LITTLENUM_TYPE)); + md_number_to_imm(memP+2*sizeof(LITTLENUM_TYPE),(long)words[2],sizeof(LITTLENUM_TYPE)); + md_number_to_imm(memP+3*sizeof(LITTLENUM_TYPE),(long)words[3],sizeof(LITTLENUM_TYPE)); + break; + } + } + memP+=size; + rem_size-=size; + break; + } + if (j || + exprP.X_add_symbol || + exprP.X_subtract_symbol || + iif.iifP[i].pcrel) { /* fixit */ + /* the expression was undefined due to an undefined label */ + /* create a fix so we can fix the object later */ + exprP.X_add_number+=iif.iifP[i].object_adjust; + fix_new_ns32k(frag_now, + (long)(memP-frag_now->fr_literal), + size, + exprP.X_add_symbol, + exprP.X_subtract_symbol, + exprP.X_add_number, + iif.iifP[i].pcrel, + (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/ + iif.iifP[i].im_disp, + j, + iif.iifP[i].bsr); /* sequent hack */ + + } else { /* good, just put them bytes out */ + switch (iif.iifP[i].im_disp) { + case 0: + md_number_to_imm(memP,exprP.X_add_number,size);break; + case 1: + md_number_to_disp(memP,exprP.X_add_number,size);break; + default: as_fatal("iif convert internal pcrel/pointer"); + } + } + memP+=size; + rem_size-=size; + break; + default: as_fatal("Internal logic error in iif.iifP[n].type"); + } + break; + case 0: /* To bad, the object may be undefined as far as its final + nsize in object memory is concerned. The size of the object + in objectmemory is not explicitly given. + If the object is defined its length can be determined and + a fix can replace the frag. + */ + { + int temp; + segment=evaluate_expr(&exprP,(char*)iif.iifP[i].object); + if ((exprP.X_add_symbol || exprP.X_subtract_symbol) && + !iif.iifP[i].pcrel) { /* OVE: hack, clamp to 4 bytes */ + size=4; /* we dont wan't to frag this, use 4 so it reaches */ + fix_new_ns32k(frag_now, + (long)(memP-frag_now->fr_literal), + size, + exprP.X_add_symbol, + exprP.X_subtract_symbol, + exprP.X_add_number, + 0, /* never iif.iifP[i].pcrel, */ + (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/ + 1, /* always iif.iifP[i].im_disp, */ + 0,0); + memP+=size; + rem_size-=4; + break; /* exit this absolute hack */ + } + + if (exprP.X_add_symbol || exprP.X_subtract_symbol) { /* frag it */ + if (exprP.X_subtract_symbol) { /* We cant relax this case */ + as_fatal("Can't relax difference"); + } + else { + /* at this stage we must undo some of the effect caused + by frag_more, ie we must make sure that frag_var causes + frag_new to creat a valid fix-size in the frag it`s closing + */ + temp = -(rem_size-4); + obstack_blank_fast(&frags,temp); + /* we rewind none, some or all of the requested size we + requested by the first frag_more for this iif chunk. + Note: that we allocate 4 bytes to an object we NOT YET + know the size of, thus rem_size-4. + */ + (void)frag_variant(rs_machine_dependent, + 4, + 0, + IND(BRANCH,UNDEF), /* expecting the worst */ + exprP.X_add_symbol, + exprP.X_add_number, + (char*)inst_opcode, + (char)size_so_far, /*iif.iifP[i].pcrel_adjust);*/ + iif.iifP[i].bsr); /* sequent linker hack */ + rem_size-=4; + if (rem_size>0) { + memP=frag_more(rem_size); + } + } + } + else {/* Double work, this is done in md_number_to_disp */ + exprP.X_add_number; + if (-64<=exprP.X_add_number && exprP.X_add_number<=63) { + size=1; + } else { + if (-8192<=exprP.X_add_number && exprP.X_add_number<=8191) { + size=2; + } else { + if (-0x1f000000<=exprP.X_add_number && + exprP.X_add_number<=0x1fffffff) + /* if (-0x40000000<=exprP.X_add_number && + exprP.X_add_number<=0x3fffffff) */ + { + size=4; + } else { + as_warn("Displacement to large for :d"); + size=4; + } + } + } + /* rewind the bytes not used */ + temp = -(4-size); + md_number_to_disp(memP,exprP.X_add_number,size); + obstack_blank_fast(&frags,temp); + memP+=size; + rem_size-=4; /* we allocated this amount */ + } + } + break; + default: + as_fatal("Internal logic error in iif.iifP[].type"); + } + size_so_far+=size; + size=0; + } + } +} + +void md_assemble(line) +char *line; +{ + freeptr=freeptr_static; + parse(line,0); /* explode line to more fix form in iif */ + convert_iif(); /* convert iif to frags, fix's etc */ +#ifdef SHOW_NUM + printf(" \t\t\t%s\n",line); +#endif +} + + +void md_begin() +{ + /* build a hashtable of the instructions */ + register struct ns32k_opcode *ptr; + register char *stat; + inst_hash_handle=hash_new(); + for (ptr=ns32k_opcodes;ptr<endop;ptr++) { + if (*(stat=hash_insert(inst_hash_handle,ptr->name,(char*)ptr))) { + as_fatal("Can't hash %s: %s",ptr->name,stat); /*fatal*/ + exit(0); + } + } + freeptr_static=(char*)malloc(PRIVATE_SIZE); /* some private space please! */ +} + + +void +md_end() +{ + free(freeptr_static); +} + +/* Must be equal to MAX_PRECISON in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +/* Turn the string pointed to by litP into a floating point constant of type + type, and emit the appropriate bytes. The number of LITTLENUMS emitted + is stored in *sizeP . An error message is returned, or NULL on OK. + */ +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(); + + switch(type) { + case 'f': + prec = 2; + break; + + case 'd': + prec = 4; + 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;prec--;) { + md_number_to_chars(litP,(long)(*--wordP),sizeof(LITTLENUM_TYPE)); + litP+=sizeof(LITTLENUM_TYPE); + } + return ""; /* Someone should teach Dean about null pointers */ +} + +/* Convert number to chars in correct order */ + +void +md_number_to_chars (buf, value, nbytes) + char *buf; + long int value; + int nbytes; +{ + while (nbytes--) + { +#ifdef SHOW_NUM + printf("%x ",value & 0xff); +#endif + *buf++ = value; /* Lint wants & MASK_CHAR. */ + value >>= BITS_PER_CHAR; + } +} +/* Convert number to chars in correct order */ + + + +/* This is a variant of md_numbers_to_chars. The reason for its' existence + is the fact that ns32k uses Huffman coded displacements. This implies + that the bit order is reversed in displacements and that they are prefixed + with a size-tag. + + binary: msb -> lsb 0xxxxxxx byte + 10xxxxxx xxxxxxxx word + 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word + + This must be taken care of and we do it here! + */ +void md_number_to_disp(buf,val,n) + char *buf; + long val; + char n; +{ + switch(n) { + case 1: + if (val < -64 || val > 63) + as_warn("Byte displacement out of range. line number not valid"); + val&=0x7f; +#ifdef SHOW_NUM + printf("%x ",val & 0xff); +#endif + *buf++=val; + break; + case 2: + if (val < -8192 || val > 8191) + as_warn("Word displacement out of range. line number not valid"); + val&=0x3fff; + val|=0x8000; +#ifdef SHOW_NUM + printf("%x ",val>>8 & 0xff); +#endif + *buf++=(val>>8); +#ifdef SHOW_NUM + printf("%x ",val & 0xff); +#endif + *buf++=val; + break; + case 4: + if (val < -0x1f000000 || val >= 0x20000000) + /* if (val < -0x20000000 || val >= 0x20000000) */ + as_warn("Double word displacement out of range"); + val|=0xc0000000; +#ifdef SHOW_NUM + printf("%x ",val>>24 & 0xff); +#endif + *buf++=(val>>24); +#ifdef SHOW_NUM + printf("%x ",val>>16 & 0xff); +#endif + *buf++=(val>>16); +#ifdef SHOW_NUM + printf("%x ",val>>8 & 0xff); +#endif + *buf++=(val>>8); +#ifdef SHOW_NUM + printf("%x ",val & 0xff); +#endif + *buf++=val; + break; + default: + as_fatal("Internal logic error"); + } +} +void md_number_to_imm(buf,val,n) + char *buf; + long val; + char n; +{ + switch(n) { + case 1: +#ifdef SHOW_NUM + printf("%x ",val & 0xff); +#endif + *buf++=val; + break; + case 2: +#ifdef SHOW_NUM + printf("%x ",val>>8 & 0xff); +#endif + *buf++=(val>>8); +#ifdef SHOW_NUM + printf("%x ",val & 0xff); +#endif + *buf++=val; + break; + case 4: +#ifdef SHOW_NUM + printf("%x ",val>>24 & 0xff); +#endif + *buf++=(val>>24); +#ifdef SHOW_NUM + printf("%x ",val>>16 & 0xff); +#endif + *buf++=(val>>16); +#ifdef SHOW_NUM + printf("%x ",val>>8 & 0xff); +#endif + *buf++=(val>>8); +#ifdef SHOW_NUM + printf("%x ",val & 0xff); +#endif + *buf++=val; + break; + default: + as_fatal("Internal logic error"); + } +} +/* the bit-field entries in the relocation_info struct plays hell + with the byte-order problems of cross-assembly. So as a hack, + I added this mach. dependent ri twiddler. Ugly, but it gets + you there. -KWK */ +/* OVE: on a ns32k the twiddling continues at an even deeper level + here we have to distinguish between displacements and immediates. + + The sequent has a bit for this. It also has a bit for relocobjects that + points at the target for a bsr (BranchSubRoutine) !?!?!?! + + Using [] is importable but fast!! still, its rather funny :-) + This md_ri.... is tailored for sequent. + */ + +void md_ri_to_chars(ri_p, ri) + struct relocation_info *ri_p, ri; +{ + if (ri.r_bsr) {ri.r_pcrel=0;} /* sequent seems to want this */ + md_number_to_chars((char*)ri_p, ri.r_address, sizeof(ri.r_address)); + md_number_to_chars((char*)ri_p+4, + (long)(ri.r_symbolnum ) | + (long)(ri.r_pcrel << 24 ) | + (long)(ri.r_length << 25 ) | + (long)(ri.r_extern << 27 ) | + (long)(ri.r_bsr << 28 ) | + (long)(ri.r_disp << 29 ), + 4); + /* the first and second md_number_to_chars never overlaps (32bit cpu case) */ +} + +/* fast bitfiddling support */ +/* mask used to zero bitfield before oring in the true field */ + +static unsigned long l_mask[]={ 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, + 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, + 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, + 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, + 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, + 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, + 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, + 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000, + }; +static unsigned long r_mask[]={ 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, + 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, + 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, + }; +#define MASK_BITS 31 +/* Insert bitfield described by field_ptr and val at buf + This routine is written for modification of the first 4 bytes pointed + to by buf, to yield speed. + The ifdef stuff is for selection between a ns32k-dependent routine + and a general version. (My advice: use the general version!) + */ + +void md_number_to_field(buf,val,field_ptr) + register char *buf; + register long val; + register bit_fixS *field_ptr; +{ + register unsigned long object; + register unsigned long mask; +/* define ENDIAN on a ns32k machine */ +#ifdef ENDIAN + register unsigned long *mem_ptr; +#else + register char *mem_ptr; +#endif + if (field_ptr->fx_bit_min<=val && val<=field_ptr->fx_bit_max) { +#ifdef ENDIAN + if (field_ptr->fx_bit_base) { /* override buf */ + mem_ptr=(unsigned long*)field_ptr->fx_bit_base; + } else { + mem_ptr=(unsigned long*)buf; + } +#else + if (field_ptr->fx_bit_base) { /* override buf */ + mem_ptr=(char*)field_ptr->fx_bit_base; + } else { + mem_ptr=buf; + } +#endif + mem_ptr+=field_ptr->fx_bit_base_adj; +#ifdef ENDIAN /* we have a nice ns32k machine with lowbyte at low-physical mem */ + object = *mem_ptr; /* get some bytes */ +#else /* OVE Goof! the machine is a m68k or dito */ + /* That takes more byte fiddling */ + object=0; + object|=mem_ptr[3] & 0xff; + object<<=8; + object|=mem_ptr[2] & 0xff; + object<<=8; + object|=mem_ptr[1] & 0xff; + object<<=8; + object|=mem_ptr[0] & 0xff; +#endif + mask=0; + mask|=(r_mask[field_ptr->fx_bit_offset]); + mask|=(l_mask[field_ptr->fx_bit_offset+field_ptr->fx_bit_size]); + object&=mask; + val+=field_ptr->fx_bit_add; + object|=((val<<field_ptr->fx_bit_offset) & (mask ^ 0xffffffff)); +#ifdef ENDIAN + *mem_ptr=object; +#else + mem_ptr[0]=(char)object; + object>>=8; + mem_ptr[1]=(char)object; + object>>=8; + mem_ptr[2]=(char)object; + object>>=8; + mem_ptr[3]=(char)object; +#endif + } else { + as_warn("Bit field out of range"); + } +} + +/* Convert a relaxed displacement to dito in final output */ + +void + md_convert_frag(fragP) +register fragS *fragP; +{ + long disp; + long ext; + + /* Address in gas core of the place to store the displacement. */ + register char *buffer_address = fragP -> fr_fix + fragP -> fr_literal; + /* Address in object code of the displacement. */ + register int object_address = fragP -> fr_fix + fragP -> fr_address; + + know(fragP->fr_symbol); + + /* The displacement of the address, from current location. */ + disp = (fragP->fr_symbol->sy_value + fragP->fr_offset) - object_address; + disp+= fragP->fr_pcrel_adjust; + + switch(fragP->fr_subtype) { + case IND(BRANCH,BYTE): + ext=1; + break; + case IND(BRANCH,WORD): + ext=2; + break; + case IND(BRANCH,DOUBLE): + ext=4; + break; + } + if(ext) { + md_number_to_disp(buffer_address,(long)disp,(int)ext); + fragP->fr_fix+=ext; + } +} + + + +/* This function returns the estimated size a variable object will occupy, + one can say that we tries to guess the size of the objects before we + actually know it */ + +md_estimate_size_before_relax(fragP,segtype) + register fragS *fragP; +{ + int old_fix; + old_fix=fragP->fr_fix; + switch(fragP->fr_subtype) { + case IND(BRANCH,UNDEF): + if((fragP->fr_symbol->sy_type&N_TYPE)==segtype) { + /* the symbol has been assigned a value */ + fragP->fr_subtype=IND(BRANCH,BYTE); + } else { + /* we don't relax symbols defined in an other segment + the thing to do is to assume the object will occupy 4 bytes */ + fix_new_ns32k(fragP, + (int)(fragP->fr_fix), + 4, + fragP->fr_symbol, + (symbolS *)0, + fragP->fr_offset, + 1, + fragP->fr_pcrel_adjust, + 1, + 0, + fragP->fr_bsr); /*sequent hack */ + fragP->fr_fix+=4; + /* fragP->fr_opcode[1]=0xff; */ + frag_wane(fragP); + break; + } + case IND(BRANCH,BYTE): + fragP->fr_var+=1; + break; + default: + break; + } + return fragP->fr_var + fragP->fr_fix - old_fix; +} + +int md_short_jump_size = 3; +int md_long_jump_size = 5; + +void +md_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol) +char *ptr; +long from_addr, + to_addr; +fragS *frag; +symbolS *to_symbol; +{ + long offset; + + offset = to_addr - from_addr; + md_number_to_chars(ptr, (long)0xEA ,1); + md_number_to_disp(ptr+1,(long)offset,2); +} + +void +md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol) +char *ptr; +long from_addr, + to_addr; +fragS *frag; +symbolS *to_symbol; +{ + long offset; + + offset= to_addr - from_addr; + md_number_to_chars(ptr, (long)0xEA, 2); + md_number_to_disp(ptr+2,(long)offset,4); +} + +/* JF this is a new function to parse machine-dep options */ +int +md_parse_option(argP,cntP,vecP) +char **argP; +int *cntP; +char ***vecP; +{ + switch(**argP) { + case 'm': + (*argP)++; + + if(!strcmp(*argP,"32032")) { + cpureg = cpureg_032; + mmureg = mmureg_032; + } else if(!strcmp(*argP, "32532")) { + cpureg = cpureg_532; + mmureg = mmureg_532; + } else + as_warn("Unknown -m option ignored"); + + while(**argP) + (*argP)++; + break; + + default: + return 0; + } + return 1; +} + +/* + * bit_fix_new() + * + * Create a bit_fixS in obstack 'notes'. + * This struct is used to profile the normal fix. If the bit_fixP is a + * valid pointer (not NULL) the bit_fix data will be used to format the fix. + */ +bit_fixS * +bit_fix_new (size,offset,min,max,add,base_type,base_adj) + char size; /* Length of bitfield */ + char offset; /* Bit offset to bitfield */ + long base_type; /* 0 or 1, if 1 it's exploded to opcode ptr */ + long base_adj; + long min; /* Signextended min for bitfield */ + long max; /* Signextended max for bitfield */ + long add; /* Add mask, used for huffman prefix */ +{ + register bit_fixS * bit_fixP; + + bit_fixP = (bit_fixS *)obstack_alloc(¬es,sizeof(bit_fixS)); + + bit_fixP -> fx_bit_size = size; + bit_fixP -> fx_bit_offset = offset; + bit_fixP -> fx_bit_base = base_type; + bit_fixP -> fx_bit_base_adj = base_adj; + bit_fixP -> fx_bit_max = max; + bit_fixP -> fx_bit_min = min; + bit_fixP -> fx_bit_add = add; + + return bit_fixP; +} + +void +fix_new_ns32k (frag, where, size, add_symbol, sub_symbol, offset, pcrel, + pcrel_adjust, im_disp, bit_fixP, bsr) + fragS * frag; /* Which frag? */ + int where; /* Where in that frag? */ + short int size; /* 1, 2 or 4 usually. */ + symbolS * add_symbol; /* X_add_symbol. */ + symbolS * sub_symbol; /* X_subtract_symbol. */ + long int offset; /* X_add_number. */ + int pcrel; /* TRUE if PC-relative relocation. */ + char pcrel_adjust; /* not zero if adjustment of pcrel offset is needed */ + char im_disp; /* true if the value to write is a displacement */ + bit_fixS *bit_fixP; /* pointer at struct of bit_fix's, ignored if NULL */ + char bsr; /* sequent-linker-hack: 1 when relocobject is a bsr */ + +{ + register fixS * fixP; + + fixP = (fixS *)obstack_alloc(¬es,sizeof(fixS)); + fixP -> fx_frag = frag; + fixP -> fx_where = where; + fixP -> fx_size = size; + fixP -> fx_addsy = add_symbol; + fixP -> fx_subsy = sub_symbol; + fixP -> fx_offset = offset; + fixP -> fx_pcrel = pcrel; + fixP -> fx_pcrel_adjust = pcrel_adjust; + fixP -> fx_im_disp = im_disp; + fixP -> fx_bit_fixP = bit_fixP; + fixP -> fx_bsr = bsr; + fixP -> fx_next = * seg_fix_rootP; + + * seg_fix_rootP = fixP; +} diff --git a/gnu/usr.bin/gas/config/sparc-opcode.h b/gnu/usr.bin/gas/config/sparc-opcode.h new file mode 100644 index 00000000000..fa39354f5ad --- /dev/null +++ b/gnu/usr.bin/gas/config/sparc-opcode.h @@ -0,0 +1,636 @@ +/* Table of opcodes for the sparc. + 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 sparc_opcode +{ + const char *name; + unsigned long int match; /* Bits that must be set. */ + unsigned long int lose; /* Bits that must not be set. */ + const char *args; + /* Nonzero if this is a delayed branch instruction. */ + char delayed; +}; + +/* + All sparc 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: + # Number used by optimizer. It is ignored. + 1 rs1 register. + 2 rs2 register. + d rd register. + e frs1 floating point register. + f frs2 floating point register. + g frsd floating point register. + b crs1 coprocessor register + c crs2 coprocessor register + D crsd coprocessor register + h 22 high bits. + i 13 bit Immediate. + l 22 bit PC relative immediate. + L 30 bit PC relative immediate. + a Annul. The annul bit is set. + A Alternate address space. Stored as 8 bits. + C Coprocessor state register. + F floating point state register. + p Processor state register. + q Floating point queue. + r Single register that is both rs1 and rsd. + Q Coprocessor queue. + S Special case. + t Trap base register. + w Window invalid mask register. + y Y register. + +*/ + +/* 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 struct sparc_opcode sparc_opcodes[] = +{ + +{ "ldd", 0xc1980000, 0x0060201f, "[1],D", 0 }, /* ldd [rs1+%g0],d */ +{ "ldd", 0xc1982000, 0x00601fff, "[1],D", 0 }, /* ldd [rs1+0],d */ +{ "ldd", 0xc1982000, 0x00600000, "[1+i],D", 0 }, +{ "ldd", 0xc1982000, 0x00600000, "[i+1],D", 0 }, +{ "ldd", 0xc1980000, 0x00602000, "[1+2],D", 0 }, +{ "ldd", 0xc1180000, 0x00e0201f, "[1],g", 0 }, /* ldd [rs1+%g0],d */ +{ "ldd", 0xc1182000, 0x00e01fff, "[1],g", 0 }, /* ldd [rs1+0],d */ +{ "ldd", 0xc1182000, 0x00e00000, "[1+i],g", 0 }, +{ "ldd", 0xc1182000, 0x00e00000, "[i+1],g", 0 }, +{ "ldd", 0xc1180000, 0x00e02000, "[1+2],g", 0 }, +{ "ldd", 0xc0180000, 0x01e0201f, "[1],d", 0 }, /* ldd [rs1+%g0],d */ +{ "ldd", 0xc0182000, 0x01e01fff, "[1],d", 0 }, /* ldd [rs1+0],d */ +{ "ldd", 0xc0182000, 0x01e00000, "[1+i],d", 0 }, +{ "ldd", 0xc0182000, 0x01e00000, "[i+1],d", 0 }, +{ "ldd", 0xc0180000, 0x01e02000, "[1+2],d", 0 }, +{ "ld", 0xc1880000, 0x0070201f, "[1],C", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc1882000, 0x00701fff, "[1],C", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc1882000, 0x00700000, "[1+i],C", 0 }, +{ "ld", 0xc1882000, 0x00700000, "[i+1],C", 0 }, +{ "ld", 0xc1880000, 0x00702000, "[1+2],C", 0 }, +{ "ld", 0xc1800000, 0x0078201f, "[1],D", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc1802000, 0x00781fff, "[1],D", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc1802000, 0x00780000, "[1+i],D", 0 }, +{ "ld", 0xc1802000, 0x00780000, "[i+1],D", 0 }, +{ "ld", 0xc1800000, 0x00782000, "[1+2],D", 0 }, +{ "ld", 0xc1080000, 0x00f0201f, "[1],F", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc1082000, 0x00f01fff, "[1],F", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc1082000, 0x00f00000, "[1+i],F", 0 }, +{ "ld", 0xc1082000, 0x00f00000, "[i+1],F", 0 }, +{ "ld", 0xc1080000, 0x00f02000, "[1+2],F", 0 }, +{ "ld", 0xc1000000, 0x00f8201f, "[1],g", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc1002000, 0x00f81fff, "[1],g", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc1002000, 0x00f80000, "[1+i],g", 0 }, +{ "ld", 0xc1002000, 0x00f80000, "[i+1],g", 0 }, +{ "ld", 0xc1000000, 0x00f82000, "[1+2],g", 0 }, +{ "ld", 0xc0000000, 0x01f8201f, "[1],d", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc0002000, 0x01f81fff, "[1],d", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc0002000, 0x01f80000, "[1+i],d", 0 }, +{ "ld", 0xc0002000, 0x01f80000, "[i+1],d", 0 }, +{ "ld", 0xc0000000, 0x01f82000, "[1+2],d", 0 }, +{ "ldstuba", 0xc0d80000, 0x0100201f, "[1]A,d", 0 }, /* ldstuba [rs1+%g0],d */ +{ "ldstuba", 0xc0d80000, 0x01002000, "[1+2]A,d", 0 }, +{ "ldsha", 0xc0d00000, 0x0128201f, "[1]A,d", 0 }, /* ldsha [rs1+%g0],d */ +{ "ldsha", 0xc0d00000, 0x01282000, "[1+2]A,d", 0 }, +{ "ldsba", 0xc0c80000, 0x0130201f, "[1]A,d", 0 }, /* ldsba [rs1+%g0],d */ +{ "ldsba", 0xc0c80000, 0x01302000, "[1+2]A,d", 0 }, +{ "ldda", 0xc0980000, 0x0160201f, "[1]A,d", 0 }, /* ldda [rs1+%g0],d */ +{ "ldda", 0xc0980000, 0x01602000, "[1+2]A,d", 0 }, +{ "lduha", 0xc0900000, 0x0168201f, "[1]A,d", 0 }, /* lduha [rs1+%g0],d */ +{ "lduha", 0xc0900000, 0x01682000, "[1+2]A,d", 0 }, +{ "ldstub", 0xc0680000, 0x0190201f, "[1],d", 0 }, /* ldstub [rs1+%g0],d */ +{ "ldstub", 0xc0682000, 0x01900000, "[1+i],d", 0 }, +{ "ldstub", 0xc0682000, 0x01900000, "[i+1],d", 0 }, +{ "ldstub", 0xc0680000, 0x01902000, "[1+2],d", 0 }, +{ "lda", 0xc0800000, 0x0178201f, "[1]A,d", 0 }, /* lda [rs1+%g0],d */ +{ "lda", 0xc0800000, 0x01782000, "[1+2]A,d", 0 }, +{ "ldsh", 0xc0500000, 0x0000000d, "[1],d", 0 }, /* ldsh [rs1+%g0],d */ +{ "ldsh", 0xc0502000, 0x01a81fff, "[1],d", 0 }, /* ldsh [rs1+0],d */ +{ "ldsh", 0xc0502000, 0x01a80000, "[1+i],d", 0 }, +{ "ldsh", 0xc0502000, 0x01a80000, "[i+1],d", 0 }, +{ "ldsh", 0xc0500000, 0x01a82000, "[1+2],d", 0 }, +{ "ldsb", 0xc0480000, 0x01b0201f, "[1],d", 0 }, /* ldsb [rs1+%g0],d */ +{ "ldsb", 0xc0482000, 0x01b01fff, "[1],d", 0 }, /* ldsb [rs1+0],d */ +{ "ldsb", 0xc0482000, 0x01b00000, "[1+i],d", 0 }, +{ "ldsb", 0xc0482000, 0x01b00000, "[i+1],d", 0 }, +{ "ldsb", 0xc0480000, 0x01b02000, "[1+2],d", 0 }, +{ "ldub", 0xc0080000, 0x01f0201f, "[1],d", 0 }, /* ldub [rs1+%g0],d */ +{ "ldub", 0xc0082000, 0x01f01fff, "[1],d", 0 }, /* ldub [rs1+0],d */ +{ "ldub", 0xc0082000, 0x01f00000, "[1+i],d", 0 }, +{ "ldub", 0xc0082000, 0x01f00000, "[i+1],d", 0 }, +{ "ldub", 0xc0080000, 0x01f02000, "[1+2],d", 0 }, +{ "lduba", 0xc0880000, 0x0170201f, "[1]A,d", 0 }, /* lduba [rs1+%g0],d */ +{ "lduba", 0xc0880000, 0x01702000, "[1+2]A,d", 0 }, +{ "lduh", 0xc0102000, 0x01e80000, "[1+i],d", 0 }, +{ "lduh", 0xc0102000, 0x01e80000, "[i+1],d", 0 }, +{ "lduh", 0xc0100000, 0x01e8201f, "[1],d", 0 }, /* lduh [rs1+%g0],d */ +{ "lduh", 0xc0102000, 0x01e81fff, "[1],d", 0 }, /* lduh [rs1+0],d */ +{ "lduh", 0xc0100000, 0x01e82000, "[1+2],d", 0 }, + +{ "st", 0xc0200000, 0x01d8201f, "d,[1]", 0 }, /* st d,[rs1+%g0] */ +{ "st", 0xc0202000, 0x01d81fff, "d,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc0202000, 0x01d80000, "d,[1+i]", 0 }, +{ "st", 0xc0202000, 0x01d80000, "d,[i+1]", 0 }, +{ "st", 0xc0200000, 0x01d82000, "d,[1+2]", 0 }, +{ "st", 0xc1200000, 0x00d8201f, "g,[1]", 0 }, /* st d[rs1+%g0] */ +{ "st", 0xc1202000, 0x00d81fff, "g,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc1202000, 0x00d80000, "g,[1+i]", 0 }, +{ "st", 0xc1202000, 0x00d80000, "g,[i+1]", 0 }, +{ "st", 0xc1200000, 0x00d82000, "g,[1+2]", 0 }, +{ "st", 0xc1280000, 0x00c0d01f, "F,[1]", 0 }, /* st d,[rs1+%g0] */ +{ "st", 0xc1282000, 0x00c0dfff, "F,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc1282000, 0x00c0d000, "F,[1+i]", 0 }, +{ "st", 0xc1282000, 0x00c0d000, "F,[i+1]", 0 }, +{ "st", 0xc1280000, 0x00c0d000, "F,[1+2]", 0 }, +{ "st", 0xc1a00000, 0x0058201f, "D,[1]", 0 }, /* st d,[rs1+%g0] */ +{ "st", 0xc1a02000, 0x00581fff, "D,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc1a02000, 0x00580000, "D,[1+i]", 0 }, +{ "st", 0xc1a02000, 0x00580000, "D,[i+1]", 0 }, +{ "st", 0xc1a00000, 0x00582000, "D,[1+2]", 0 }, +{ "st", 0xc1a80000, 0x0050201f, "C,[1]", 0 }, /* st d,[rs1+%g0] */ +{ "st", 0xc1a82000, 0x00501fff, "C,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc1a82000, 0x00500000, "C,[1+i]", 0 }, +{ "st", 0xc1a82000, 0x00500000, "C,[i+1]", 0 }, +{ "st", 0xc1a80000, 0x00502000, "C,[1+2]", 0 }, +{ "sta", 0xc0a00000, 0x0108201f, "d,[1]A", 0 }, /* sta d,[rs1+%g0] */ +{ "sta", 0xc0a00000, 0x01082000, "d,[1+2]A", 0 }, + +{ "stb", 0xc0280000, 0x01d0201f, "d,[1]", 0 }, /* stb d,[rs1+%g0] */ +{ "stb", 0xc0282000, 0x01d01fff, "d,[1]", 0 }, /* stb d,[rs1+0] */ +{ "stb", 0xc0282000, 0x01d00000, "d,[1+i]", 0 }, +{ "stb", 0xc0282000, 0x01d00000, "d,[i+1]", 0 }, +{ "stb", 0xc0280000, 0x01d02000, "d,[1+2]", 0 }, +{ "stba", 0xc0a80000, 0x01002000, "d,[1+2]A", 0 }, +{ "stba", 0xc0a80000, 0x0100201f, "d,[1]A", 0 }, /* stba d,[rs1+%g0] */ + +{ "std", 0xc0380000, 0x01c0201f, "d,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc0382000, 0x01c01fff, "d,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc0382000, 0x01c00000, "d,[1+i]", 0 }, +{ "std", 0xc0382000, 0x01c00000, "d,[i+1]", 0 }, +{ "std", 0xc0380000, 0x01c02000, "d,[1+2]", 0 }, +{ "std", 0xc1380000, 0x00c0201f, "g,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc1382000, 0x00c01fff, "g,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc1382000, 0x00c00000, "g,[1+i]", 0 }, +{ "std", 0xc1382000, 0x00c00000, "g,[i+1]", 0 }, +{ "std", 0xc1380000, 0x00c02000, "g,[1+2]", 0 }, +{ "std", 0xc1300000, 0x00c8201f, "q,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc1302000, 0x00c81fff, "q,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc1302000, 0x00c80000, "q,[1+i]", 0 }, +{ "std", 0xc1302000, 0x00c80000, "q,[i+1]", 0 }, +{ "std", 0xc1300000, 0x00c82000, "q,[1+2]", 0 }, +{ "std", 0xc1b80000, 0x0040201f, "D,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc1b82000, 0x00401fff, "D,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc1b82000, 0x00400000, "D,[1+i]", 0 }, +{ "std", 0xc1b82000, 0x00400000, "D,[i+1]", 0 }, +{ "std", 0xc1b80000, 0x00402000, "D,[1+2]", 0 }, +{ "std", 0xc1b00000, 0x0048201f, "Q,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc1b02000, 0x00481fff, "Q,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc1b02000, 0x00480000, "Q,[1+i]", 0 }, +{ "std", 0xc1b02000, 0x00480000, "Q,[i+1]", 0 }, +{ "std", 0xc1b00000, 0x00482000, "Q,[1+2]", 0 }, +{ "stda", 0xc0b80000, 0x01402000, "d,[1+2]A", 0 }, +{ "stda", 0xc0b80000, 0x0140201f, "d,[1]A", 0 }, /* stda d,[rs1+%g0] */ + +{ "sth", 0xc0300000, 0x01c8201f, "d,[1]", 0 }, /* sth d,[rs1+%g0] */ +{ "sth", 0xc0302000, 0x01c81fff, "d,[1]", 0 }, /* sth d,[rs1+0] */ +{ "sth", 0xc0300000, 0x01c82000, "d,[1+2]", 0 }, +{ "sth", 0xc0302000, 0x01c80000, "d,[1+i]", 0 }, +{ "sth", 0xc0302000, 0x01c80000, "d,[i+1]", 0 }, +{ "stha", 0xc0b00000, 0x0148201f, "d,[1]A", 0 }, /* stha d,[rs1+%g0] */ +{ "stha", 0xc0b00000, 0x01482000, "d,[1+2]A", 0 }, + +{ "swap", 0xc0780000, 0x0180201f, "[1],d", 0 }, /* swap [rs1+%g0],d */ +{ "swap", 0xc0782000, 0x01801fff, "[1],d", 0 }, /* swap [rs1+0],d */ +{ "swap", 0xc0782000, 0x01800000, "[1+i],d", 0 }, +{ "swap", 0xc0782000, 0x01800000, "[i+1],d", 0 }, +{ "swap", 0xc0780000, 0x01802000, "[1+2],d", 0 }, +{ "swapa", 0xc0f80000, 0x01002000, "[1+2]A,d", 0 }, +{ "swapa", 0xc0f80000, 0x0100201f, "[1]A,d", 0 }, /* swapa [rs1+%g0],d */ + +{ "restore", 0x81e80000, 0x7e17e01f, "", 0 }, /* restore %g0,%g0,%g0 */ +{ "restore", 0x81e82000, 0x7e14dfff, "", 0 }, /* restore %g0,0,%g0 */ +{ "restore", 0x81e82000, 0x00000000, "1,i,d", 0 }, +{ "restore", 0x81e80000, 0x00000000, "1,2,d", 0 }, +{ "rett", 0x81c82000, 0x40300000, "1+i", 1 }, +{ "rett", 0x81c82000, 0x40300000, "i+1", 1 }, +{ "rett", 0x81c80000, 0x40302000, "1+2", 1 }, +{ "rett", 0x81c82000, 0x40300000, "1", 1}, +{ "save", 0x81e02000, 0x40180000, "1,i,d", 0 }, +{ "save", 0x81e00000, 0x40180000, "1,2,d", 0 }, + +{ "ret", 0x81c7e008, 0x00001ff7, "", 1 }, /* jmpl %i7+8,%g0 */ +{ "retl", 0x81c3e008, 0x00001ff7, "", 1 }, /* jmpl %o7+8,%g0 */ + +{ "jmpl", 0x81c00000, 0x4038201f, "1,d", 1 }, /* jmpl rs1+%g0,d */ +{ "jmpl", 0x81c02000, 0x4037c000, "i,d", 1 }, /* jmpl %g0+i,d */ +{ "jmpl", 0x81c02000, 0x40380000, "1+i,d", 1 }, +{ "jmpl", 0x81c02000, 0x40380000, "i+1,d", 1 }, +{ "jmpl", 0x81c00000, 0x40382000, "1+2,d", 1 }, +{ "wr", 0x81982000, 0x40600000, "1,i,t", 0 }, +{ "wr", 0x81980000, 0x40600000, "1,2,t", 0 }, +{ "wr", 0x81902000, 0x40680000, "1,i,w", 0 }, +{ "wr", 0x81900000, 0x40680000, "1,2,w", 0 }, +{ "wr", 0x81882000, 0x40700000, "1,i,p", 0 }, +{ "wr", 0x81880000, 0x40700000, "1,2,p", 0 }, +{ "wr", 0x81802000, 0x40780000, "1,i,y", 0 }, +{ "wr", 0x81800000, 0x40780000, "1,2,y", 0 }, + +{ "rd", 0x81580000, 0x40a00000, "t,d", 0 }, +{ "rd", 0x81500000, 0x40a80000, "w,d", 0 }, +{ "rd", 0x81480000, 0x40b00000, "p,d", 0 }, +{ "rd", 0x81400000, 0x40b80000, "y,d", 0 }, + +{ "sra", 0x81382000, 0x00000000, "1,i,d", 0 }, +{ "sra", 0x81380000, 0x00000000, "1,2,d", 0 }, +{ "srl", 0x81302000, 0x40c80000, "1,i,d", 0 }, +{ "srl", 0x81300000, 0x40c80000, "1,2,d", 0 }, +{ "sll", 0x81282000, 0x40d00000, "1,i,d", 0 }, +{ "sll", 0x81280000, 0x40d00000, "1,2,d", 0 }, + +{ "mulscc", 0x81202000, 0x40d80000, "1,i,d", 0 }, +{ "mulscc", 0x81200000, 0x40d80000, "1,2,d", 0 }, + +{ "clr", 0x80100000, 0x4e87e01f, "d", 0 }, /* or %g0,%g0,d */ +{ "clr", 0x80102000, 0x41efdfff, "d", 0 }, /* or %g0,0,d */ + +{ "orncc", 0x80b02000, 0x04048000, "1,i,d", 0 }, +{ "orncc", 0x80b02000, 0x04048000, "i,1,d", 0 }, +{ "orncc", 0x80b00000, 0x04048000, "1,2,d", 0 }, + +{ "tst", 0x80900000, 0x7f6fe000, "2", 0 }, /* orcc %g0, rs2, %g0 */ +{ "tst", 0x80900000, 0x7f68201f, "1", 0 }, /* orcc rs1, %g0, %g0 */ +{ "tst", 0x80902000, 0x7f681fff, "1", 0 }, /* orcc rs1, 0, %g0 */ + +{ "orcc", 0x80902000, 0x41680000, "1,i,d", 0 }, +{ "orcc", 0x80902000, 0x41680000, "i,1,d", 0 }, +{ "orcc", 0x80900000, 0x41680000, "1,2,d", 0 }, +{ "orn", 0x80302000, 0x41c80000, "1,i,d", 0 }, +{ "orn", 0x80302000, 0x41c80000, "i,1,d", 0 }, +{ "orn", 0x80300000, 0x41c80000, "1,2,d", 0 }, + +{ "mov", 0x81800000, 0x4078201f, "1,y", 0 }, /* wr rs1,%g0,%y */ +{ "mov", 0x81802000, 0x40781fff, "1,y", 0 }, /* wr rs1,0,%y */ +{ "mov", 0x81400000, 0x40b80000, "y,d", 0 }, /* rd %y,d */ +{ "mov", 0x81980000, 0x4060201f, "1,t", 0 }, /* wr rs1,%g0,%tbr */ +{ "mov", 0x81982000, 0x40601fff, "1,t", 0 }, /* wr rs1,0,%tbr */ +{ "mov", 0x81580000, 0x40a00000, "t,d", 0 }, /* rd %tbr,d */ +{ "mov", 0x81900000, 0x4068201f, "1,w", 0 }, /* wr rs1,%g0,%wim */ +{ "mov", 0x81902000, 0x40681fff, "1,w", 0 }, /* wr rs1,0,%wim */ +{ "mov", 0x81500000, 0x40a80000, "w,d", 0 }, /* rd %wim,d */ +{ "mov", 0x81880000, 0x4070201f, "1,p", 0 }, /* wr rs1,%g0,%psr */ +{ "mov", 0x81882000, 0x40701fff, "1,p", 0 }, /* wr rs1,0,%psr */ +{ "mov", 0x81480000, 0x40b00000, "p,d", 0 }, /* rd %psr,d */ + +{ "mov", 0x80102000, 0x41efc000, "i,d", 0 }, /* or %g0,i,d */ +{ "mov", 0x80100000, 0x41efe000, "2,d", 0 }, /* or %g0,rs2,d */ + +{ "or", 0x80102000, 0x40800000, "1,i,d", 0 }, +{ "or", 0x80102000, 0x40800000, "i,1,d", 0 }, +{ "or", 0x80100000, 0x40800000, "1,2,d", 0 }, + +{ "andncc", 0x80a82000, 0x41500000, "1,i,d", 0 }, +{ "andncc", 0x80a82000, 0x41500000, "i,1,d", 0 }, +{ "andncc", 0x80a80000, 0x41500000, "1,2,d", 0 }, +{ "andn", 0x80282000, 0x41d00000, "1,i,d", 0 }, +{ "andn", 0x80282000, 0x41d00000, "i,1,d", 0 }, +{ "andn", 0x80280000, 0x41d00000, "1,2,d", 0 }, + +{ "cmp", 0x80a02000, 0x7d580000, "1,i", 0 }, /* subcc rs1,i,%g0 */ +{ "cmp", 0x80a00000, 0x7d580000, "1,2", 0 }, /* subcc rs1,rs2,%g0 */ + +{ "subcc", 0x80a02000, 0x41580000, "1,i,d", 0 }, +{ "subcc", 0x80a00000, 0x41580000, "1,2,d", 0 }, +{ "sub", 0x80202000, 0x41d80000, "1,i,d", 0 }, +{ "sub", 0x80200000, 0x41d80000, "1,2,d", 0 }, +{ "subx", 0x80602000, 0x41980000, "1,i,d", 0 }, +{ "subx", 0x80600000, 0x41980000, "1,2,d", 0 }, +{ "subxcc", 0x80e02000, 0x41180000, "1,i,d", 0 }, +{ "subxcc", 0x80e00000, 0x41180000, "1,2,d", 0 }, + +{ "andcc", 0x80882000, 0x41700000, "1,i,d", 0 }, +{ "andcc", 0x80882000, 0x41700000, "i,1,d", 0 }, +{ "andcc", 0x80880000, 0x41700000, "1,2,d", 0 }, +{ "and", 0x80082000, 0x41f00000, "1,i,d", 0 }, +{ "and", 0x80082000, 0x41f00000, "i,1,d", 0 }, +{ "and", 0x80080000, 0x41f00000, "1,2,d", 0 }, + +{ "inc", 0x80002001, 0x41f81ffe, "r", 0 }, /* add rs1,1,rsd */ + +{ "addxcc", 0x80c02000, 0x41380000, "1,i,d", 0 }, +{ "addxcc", 0x80c02000, 0x41380000, "i,1,d", 0 }, +{ "addxcc", 0x80c00000, 0x41380000, "1,2,d", 0 }, +{ "addcc", 0x80802000, 0x41780000, "1,i,d", 0 }, +{ "addcc", 0x80802000, 0x41780000, "i,1,d", 0 }, +{ "addcc", 0x80800000, 0x41780000, "1,2,d", 0 }, +{ "addx", 0x80402000, 0x41b80000, "1,i,d", 0 }, +{ "addx", 0x80402000, 0x41b80000, "i,1,d", 0 }, +{ "addx", 0x80400000, 0x41b80000, "1,2,d", 0 }, +{ "add", 0x80002000, 0x41f80000, "1,i,d", 0 }, +{ "add", 0x80002000, 0x41f80000, "i,1,d", 0 }, +{ "add", 0x80000000, 0x41f80000, "1,2,d", 0 }, + +{ "call", 0x9fc00000, 0x4038201f, "1", 1 }, /* jmpl rs1+%g0, %o7 */ +{ "call", 0x9fc00000, 0x4038201f, "1,#", 1 }, +{ "call", 0x40000000, 0x80000000, "L", 1 }, +{ "call", 0x40000000, 0x80000000, "L,#", 1 }, + +{ "bvc", 0x3e800000, 0xc1400000, ",al", 1 }, +{ "bvc", 0x1e800000, 0xc1400000, "l", 1 }, +{ "bvs", 0x2e800000, 0xc1400000, ",al", 1 }, +{ "bvs", 0x0e800000, 0xc1400000, "l", 1 }, +{ "bpos", 0x3c800000, 0xc1400000, ",al", 1 }, +{ "bpos", 0x1c800000, 0xc1400000, "l", 1 }, +{ "bneg", 0x2c800000, 0xc1400000, ",al", 1 }, +{ "bneg", 0x0c800000, 0xc1400000, "l", 1 }, +{ "bcc", 0x3a800000, 0xc1400000, ",al", 1 }, +{ "bcc", 0x1a800000, 0xc1400000, "l", 1 }, +{ "bcs", 0x2a800000, 0xc1400000, ",al", 1 }, +{ "bcs", 0x0a800000, 0xc1400000, "l", 1 }, +{ "blu", 0x2a800000, 0xc1400000, ",al", 1 }, +{ "blu", 0x0a800000, 0xc1400000, "l", 1 }, /* same as bcs */ +{ "bgeu", 0x3a800000, 0xc1400000, ",al", 1 }, +{ "bgeu", 0x1a800000, 0xc1400000, "l", 1 }, /* same as bcc */ +{ "bgu", 0x38800000, 0xc1400000, ",al", 1 }, +{ "bgu", 0x18800000, 0xc1400000, "l", 1 }, +{ "bleu", 0x28800000, 0xc1400000, ",al", 1 }, +{ "bleu", 0x08800000, 0xc1400000, "l", 1 }, +{ "bge", 0x36800000, 0xc1400000, ",al", 1 }, +{ "bge", 0x16800000, 0xc1400000, "l", 1 }, +{ "bl", 0x26800000, 0xc1400000, ",al", 1 }, +{ "bl", 0x06800000, 0xc1400000, "l", 1 }, +{ "bg", 0x34800000, 0xc1400000, ",al", 1 }, +{ "bg", 0x14800000, 0xc1400000, "l", 1 }, +{ "ble", 0x24800000, 0xc1400000, ",al", 1 }, +{ "ble", 0x04800000, 0xc1400000, "l", 1 }, +{ "be", 0x22800000, 0xc1400000, ",al", 1 }, +{ "be", 0x02800000, 0xc1400000, "l", 1 }, +{ "bne", 0x32800000, 0xc1400000, ",al", 1 }, +{ "bne", 0x12800000, 0xc1400000, "l", 1 }, +{ "b", 0x30800000, 0xc1400000, ",al", 1 }, +{ "b", 0x10800000, 0xc1400000, "l", 1 }, +{ "ba", 0x30800000, 0xc1400000, ",al", 1 }, +{ "ba", 0x10800000, 0xc1400000, "l", 1 }, +{ "bn", 0x20800000, 0xc1400000, ",al", 1 }, +{ "bn", 0x00800000, 0xc1400000, "l", 1 }, + +{ "jmp", 0x81c00000, 0x7e38201f, "1", 1 }, /* jmpl rs1+%g0,%g0 */ +{ "jmp", 0x81c02000, 0x7e3fc000, "i", 1 }, /* jmpl %g0+i,%g0 */ +{ "jmp", 0x81c00000, 0x7e382000, "1+2", 1 }, /* jmpl rs1+rs2,%g0 */ +{ "jmp", 0x81c02000, 0x7e380000, "1+i", 1 }, /* jmpl rs1+i,%g0 */ +{ "jmp", 0x81c02000, 0x7e380000, "i+1", 1 }, /* jmpl i+rs1,%g0 */ + +{ "nop", 0x01000000, 0xfe3fffff, "", 0 }, /* sethi 0, %g0 */ + +{ "set", 0x01000000, 0xc0c00000, "Sh,d", 0 }, + +{ "sethi", 0x01000000, 0xc0c00000, "h,d", 0 }, + +{ "taddcctv", 0x81102000, 0x40e00000, "1,i,d", 0 }, +{ "taddcctv", 0x81100000, 0x40e00000, "1,2,d", 0 }, +{ "taddcc", 0x81002000, 0x40f80000, "1,i,d", 0 }, +{ "taddcc", 0x81000000, 0x40f80000, "1,2,d", 0 }, + +{ "tvc", 0x9fd02000, 0x402fc000, "i", 0 }, /* tvc %g0+i */ +{ "tvc", 0x9fd02000, 0x40280000, "1+i", 0 }, +{ "tvc", 0x9fd00000, 0x40282000, "1+2", 0 }, +{ "tvc", 0x9fd00000, 0x4028201f, "1", 0 }, /* tvc rs1+%g0 */ +{ "tpos", 0x9dd02000, 0x402fc000, "i", 0 }, /* tpos %g0+i */ +{ "tpos", 0x9dd02000, 0x40280000, "1+i", 0 }, +{ "tpos", 0x9dd00000, 0x40282000, "1+2", 0 }, +{ "tpos", 0x9dd00000, 0x4028201f, "1", 0 }, /* tpos rs1+%g0 */ +{ "tcc", 0x9bd02000, 0x402fc000, "i", 0 }, /* tcc %g0+i */ +{ "tcc", 0x9bd02000, 0x40280000, "1+i", 0 }, +{ "tcc", 0x9bd00000, 0x40282000, "1+2", 0 }, +{ "tcc", 0x9bd00000, 0x4028201f, "1", 0 }, /* tcc rs1+%g0 */ +{ "tgu", 0x99d02000, 0x402fc000, "i", 0 }, /* tgu %g0+i */ +{ "tgu", 0x99d02000, 0x40280000, "1+i", 0 }, +{ "tgu", 0x99d00000, 0x40282000, "1+2", 0 }, +{ "tgu", 0x99d00000, 0x4028201f, "1", 0 }, /* tgu rs1+%g0 */ +{ "tge", 0x97d02000, 0x402fc000, "i", 0 }, /* tge %g0+i */ +{ "tge", 0x97d02000, 0x40280000, "1+i", 0 }, +{ "tge", 0x97d00000, 0x40282000, "1+2", 0 }, +{ "tge", 0x97d00000, 0x4028201f, "1", 0 }, /* tge rs1+%g0 */ +{ "tg", 0x95d02000, 0x402fc000, "i", 0 }, /* tg %g0+i */ +{ "tg", 0x95d02000, 0x40280000, "1+i", 0 }, +{ "tg", 0x95d00000, 0x40282000, "1+2", 0 }, +{ "tg", 0x95d00000, 0x4028201f, "1", 0 }, /* tg rs1+%g0 */ +{ "tne", 0x93d02000, 0x402fc000, "i", 0 }, /* tne %g0+i */ +{ "tne", 0x93d02000, 0x40280000, "1+i", 0 }, +{ "tne", 0x93d00000, 0x40282000, "1+2", 0 }, +{ "tne", 0x93d00000, 0x4028201f, "1", 0 }, /* tne rs1+%g0 */ +{ "tleu", 0x8bd02000, 0x502fc000, "i", 0 }, /* tleu %g0+i */ +{ "tleu", 0x8bd02000, 0x50280000, "1+i", 0 }, +{ "tleu", 0x8bd00000, 0x50282000, "1+2", 0 }, +{ "tleu", 0x8bd00000, 0x5028201f, "1", 0 }, /* tleu rs1+%g0 */ +{ "ta", 0x91d02000, 0x402fc000, "i", 0 }, /* ta %g0+i */ +{ "ta", 0x91d02000, 0x402d0000, "1+i", 0 }, +{ "ta", 0x91d00000, 0x40282000, "1+2", 0 }, +{ "ta", 0x91d00000, 0x4028201f, "1", 0 }, /* ta rs1+%g0 */ +{ "tvs", 0x8fd02000, 0x502fc000, "i", 0 }, /* tvs %g0+i */ +{ "tvs", 0x8fd02000, 0x50280000, "1+i", 0 }, +{ "tvs", 0x8fd00000, 0x50282000, "1+2", 0 }, +{ "tvs", 0x8fd00000, 0x5028201f, "1", 0 }, /* tvs rs1+%g0 */ +{ "tneg", 0x8dd02000, 0x502fc000, "i", 0 }, /* tneg %g0+i */ +{ "tneg", 0x8dd02000, 0x50280000, "1+i", 0 }, +{ "tneg", 0x8dd00000, 0x50282000, "1+2", 0 }, +{ "tneg", 0x8dd00000, 0x5028201f, "1", 0 }, /* tneg rs1+%g0 */ +{ "tcs", 0x8bd02000, 0x502fc000, "i", 0 }, /* tcs %g0+i */ +{ "tcs", 0x8bd02000, 0x50280000, "1+i", 0 }, +{ "tcs", 0x8bd00000, 0x50282000, "1+2", 0 }, +{ "tcs", 0x8bd00000, 0x5028201f, "1", 0 }, /* tcs rs1+%g0 */ +{ "tl", 0x87d02000, 0x502fc000, "i", 0 }, /* tl %g0+i */ +{ "tl", 0x87d02000, 0x50280000, "1+i", 0 }, +{ "tl", 0x87d00000, 0x50282000, "1+2", 0 }, +{ "tl", 0x87d00000, 0x5028201f, "1", 0 }, /* tl rs1+%g0 */ +{ "tle", 0x85d02000, 0x502fc000, "i", 0 }, /* tle %g0+i */ +{ "tle", 0x85d02000, 0x50280000, "1+i", 0 }, +{ "tle", 0x85d00000, 0x50282000, "1+2", 0 }, +{ "tle", 0x85d00000, 0x5028201f, "1", 0 }, /* tle rs1+%g0 */ +{ "te", 0x83d02000, 0x502fc000, "i", 0 }, /* te %g0+i */ +{ "te", 0x83d02000, 0x50280000, "1+i", 0 }, +{ "te", 0x83d00000, 0x50282000, "1+2", 0 }, +{ "te", 0x83d00000, 0x5028201f, "1", 0 }, /* te rs1+%g0 */ +{ "tn", 0x81d02000, 0x502fc000, "i", 0 }, /* tn %g0+i */ +{ "tn", 0x81d02000, 0x50280000, "1+i", 0 }, +{ "tn", 0x81d00000, 0x50282000, "1+2", 0 }, +{ "tn", 0x81d00000, 0x5028201f, "1", 0 }, /* tn rs1+%g0 */ + +{ "tsubcc", 0x81080000, 0x40f00000, "1,2,d", 0 }, +{ "tsubcc", 0x81082000, 0x40f00000, "1,i,d", 0 }, +{ "tsubcctv", 0x80580000, 0x40a00000, "1,2,d", 0 }, +{ "tsubcctv", 0x80582000, 0x40a00000, "1,i,d", 0 }, + +{ "unimp", 0x00000000, 0x00000000, "l", 0 }, + +{ "iflush", 0x81d80000, 0x40202000, "1+2", 0 }, +{ "iflush", 0x81d82000, 0x40200000, "1+i", 0 }, + +{ "xnorcc", 0x80b80000, 0x41400000, "1,2,d", 0 }, +{ "xnorcc", 0x80b82000, 0x41400000, "1,i,d", 0 }, +{ "xnorcc", 0x80b82000, 0x41400000, "i,1,d", 0 }, +{ "xorcc", 0x80980000, 0x41600000, "1,2,d", 0 }, +{ "xorcc", 0x80982000, 0x41600000, "1,i,d", 0 }, +{ "xorcc", 0x80982000, 0x41600000, "i,1,d", 0 }, +{ "xnor", 0x80380000, 0x41c00000, "1,2,d", 0 }, +{ "xnor", 0x80382000, 0x41c00000, "1,i,d", 0 }, +{ "xnor", 0x80382000, 0x41c00000, "i,1,d", 0 }, +{ "xor", 0x80180000, 0x41e00000, "1,2,d", 0 }, +{ "xor", 0x80182000, 0x41e00000, "1,i,d", 0 }, +{ "xor", 0x80182000, 0x41e00000, "i,1,d", 0 }, + +{ "fpop1", 0x81a00000, 0x40580000, "[1+2],d", 0 }, +{ "fpop2", 0x81a80000, 0x40500000, "[1+2],d", 0 }, + +{ "fb", 0x31800000, 0xc0400000, ",al", 1 }, +{ "fb", 0x11800000, 0xc0400000, "l", 1 }, +{ "fba", 0x31800000, 0xc0400000, ",al", 1 }, +{ "fba", 0x11800000, 0xc0400000, "l", 1 }, +{ "fbn", 0x21800000, 0xc0400000, ",al", 1 }, +{ "fbn", 0x01800000, 0xc0400000, "l", 1 }, +{ "fbu", 0x2f800000, 0xc0400000, ",al", 1 }, +{ "fbu", 0x0f800000, 0xc0400000, "l", 1 }, +{ "fbg", 0x2d800000, 0xc0400000, ",al", 1 }, +{ "fbg", 0x0d800000, 0xc0400000, "l", 1 }, +{ "fbug", 0x2b800000, 0xc0400000, ",al", 1 }, +{ "fbug", 0x0b800000, 0xc0400000, "l", 1 }, +{ "fbl", 0x29800000, 0xc0400000, ",al", 1 }, +{ "fbl", 0x09800000, 0xc0400000, "l", 1 }, +{ "fbul", 0x27800000, 0xc0400000, ",al", 1 }, +{ "fbul", 0x07800000, 0xc0400000, "l", 1 }, +{ "fblg", 0x25800000, 0xc0400000, ",al", 1 }, +{ "fblg", 0x05800000, 0xc0400000, "l", 1 }, +{ "fbne", 0x23800000, 0xc0400000, ",al", 1 }, +{ "fbne", 0x03800000, 0xc0400000, "l", 1 }, +{ "fbe", 0x33800000, 0xc0400000, ",al", 1 }, +{ "fbe", 0x13800000, 0xc0400000, "l", 1 }, +{ "fbue", 0x35800000, 0xc0400000, ",al", 1 }, +{ "fbue", 0x15800000, 0xc0400000, "l", 1 }, +{ "fbge", 0x37800000, 0xc0400000, ",al", 1 }, +{ "fbge", 0x17800000, 0xc0400000, "l", 1 }, +{ "fbuge", 0x39800000, 0xc0400000, ",al", 1 }, +{ "fbuge", 0x19800000, 0xc0400000, "l", 1 }, +{ "fble", 0x3b800000, 0xc0400000, ",al", 1 }, +{ "fble", 0x1b800000, 0xc0400000, "l", 1 }, +{ "fbule", 0x3d800000, 0xc0400000, ",al", 1 }, +{ "fbule", 0x1d800000, 0xc0400000, "l", 1 }, +{ "fbo", 0x3f800000, 0xc0400000, ",al", 1 }, +{ "fbo", 0x1f800000, 0xc0400000, "l", 1 }, + +{ "cba", 0x31c00000, 0xce000000, ",al", 1 }, +{ "cba", 0x11c00000, 0xce000000, "l", 1 }, +{ "cbn", 0x21c00000, 0xde000000, ",al", 1 }, +{ "cbn", 0x01c00000, 0xde000000, "l", 1 }, +{ "cb3", 0x2fc00000, 0xc0000000, ",al", 1 }, +{ "cb3", 0x0fc00000, 0xc0000000, "l", 1 }, +{ "cb2", 0x2dc00000, 0xc0000000, ",al", 1 }, +{ "cb2", 0x0dc00000, 0xc0000000, "l", 1 }, +{ "cb23", 0x2bc00000, 0xc0000000, ",al", 1 }, +{ "cb23", 0x0bc00000, 0xc0000000, "l", 1 }, +{ "cb1", 0x29c00000, 0xc0000000, ",al", 1 }, +{ "cb1", 0x09c00000, 0xc0000000, "l", 1 }, +{ "cb13", 0x27c00000, 0xc0000000, ",al", 1 }, +{ "cb13", 0x07c00000, 0xc0000000, "l", 1 }, +{ "cb12", 0x25c00000, 0xc0000000, ",al", 1 }, +{ "cb12", 0x05c00000, 0xc0000000, "l", 1 }, +{ "cb123", 0x23c00000, 0xc0000000, ",al", 1 }, +{ "cb123", 0x03c00000, 0xc0000000, "l", 1 }, +{ "cb0", 0x33c00000, 0xc0000000, ",al", 1 }, +{ "cb0", 0x13c00000, 0xc0000000, "l", 1 }, +{ "cb03", 0x35c00000, 0xc0000000, ",al", 1 }, +{ "cb03", 0x15c00000, 0xc0000000, "l", 1 }, +{ "cb02", 0x37c00000, 0xc0000000, ",al", 1 }, +{ "cb02", 0x17c00000, 0xc0000000, "l", 1 }, +{ "cb023", 0x39c00000, 0xc0000000, ",al", 1 }, +{ "cb023", 0x19c00000, 0xc0000000, "l", 1 }, +{ "cb013", 0x3dc00000, 0xc0000000, ",al", 1 }, +{ "cb013", 0x1dc00000, 0xc0000000, "l", 1 }, +{ "cb012", 0x3fc00000, 0xc0000000, ",al", 1 }, +{ "cb012", 0x1fc00000, 0xc0000000, "l", 1 }, + +{ "fstoi", 0x81a01a20, 0x400025c0, "f,g", 0 }, +{ "fdtoi", 0x81a01a40, 0x400025a0, "f,g", 0 }, +{ "fxtoi", 0x81a01a60, 0x40002580, "f,g", 0 }, + +{ "fitox", 0x81a01980, 0x40002660, "f,g", 0 }, +{ "fitod", 0x81a01900, 0x400026e0, "f,g", 0 }, +{ "fitos", 0x81a01880, 0x40002660, "f,g", 0 }, + +{ "fstod", 0x81a01920, 0x400026c0, "f,g", 0 }, +{ "fstox", 0x81a019a0, 0x40002640, "f,g", 0 }, +{ "fdtos", 0x81a018c0, 0x40002720, "f,g", 0 }, +{ "fdtox", 0x81a019c0, 0x40002620, "f,g", 0 }, +{ "fxtos", 0x81a018e0, 0x40002700, "f,g", 0 }, +{ "fxtod", 0x81a01960, 0x40002680, "f,g", 0 }, + +{ "fdivx", 0x81a009e0, 0x40083600, "e,f,g", 0 }, +{ "fdivd", 0x81a009c0, 0x40003620, "e,f,g", 0 }, +{ "fdivs", 0x81a009a0, 0x40003640, "e,f,g", 0 }, +{ "fmuls", 0x81a00920, 0x400036c0, "e,f,g", 0 }, +{ "fmuld", 0x81a00940, 0x400036a0, "e,f,g", 0 }, +{ "fmulx", 0x81a00960, 0x40003680, "e,f,g", 0 }, + +{ "fsqrts", 0x81a00520, 0x40003ac0, "f,g", 0 }, +{ "fsqrtd", 0x81a00540, 0x40003aa8, "f,g", 0 }, +{ "fsqrtx", 0x81a00560, 0x40003a80, "f,g", 0 }, + +{ "fabss", 0x81a00120, 0x40003ec0, "f,g", 0 }, +{ "fnegs", 0x81a000a0, 0x40003f40, "f,g", 0 }, +{ "fmovs", 0x81a00020, 0x40003fc0, "f,g", 0 }, + +{ "fsubx", 0x81a008e0, 0x40003700, "e,f,g", 0 }, +{ "fsubd", 0x81a008c0, 0x40003720, "e,f,g", 0 }, +{ "fsubs", 0x81a008a0, 0x40003740, "e,f,g", 0 }, +{ "faddx", 0x81a00860, 0x40003780, "e,f,g", 0 }, +{ "faddd", 0x81a00840, 0x400037a0, "e,f,g", 0 }, +{ "fadds", 0x81a00820, 0x400037c0, "e,f,g", 0 }, + +{ "fcmpex", 0x81a80ae0, 0x40003500, "e,f", 0 }, +{ "fcmped", 0x81a80ac0, 0x40003520, "e,f", 0 }, +{ "fcmpes", 0x81a80aa0, 0x40003540, "e,f", 0 }, +{ "fcmpx", 0x81a80a60, 0x40003580, "e,f", 0 }, +{ "fcmpd", 0x81a80a40, 0x400035a0, "e,f", 0 }, +{ "fcmps", 0x81a80a20, 0x400035c0, "e,f", 0 }, + +{ "cpop1", 0x81b00000, 0x40480000, "[1+2],d", 0 }, +{ "cpop2", 0x81b80000, 0x40400000, "[1+2],d", 0 }, +}; + +#define NUMOPCODES ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0])) + diff --git a/gnu/usr.bin/gas/config/sparc.c b/gnu/usr.bin/gas/config/sparc.c new file mode 100644 index 00000000000..2fbddc5e08e --- /dev/null +++ b/gnu/usr.bin/gas/config/sparc.c @@ -0,0 +1,1285 @@ +/* sparc.c -- Assemble for the SPARC + Copyright (C) 1989 Free Software Foundation, Inc. + +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 1, 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. */ + + +#include <stdio.h> +#include <ctype.h> + +#include "sparc-opcode.h" +#include "as.h" +#include "frags.h" +#include "struc-symbol.h" +#include "flonum.h" +#include "expr.h" +#include "hash.h" +#include "md.h" +#include "sparc.h" +#include "write.h" +#include "read.h" +#include "symbols.h" + +void md_begin(); +void md_end(); +void md_number_to_chars(); +void md_assemble(); +char *md_atof(); +void md_convert_frag(); +void md_create_short_jump(); +void md_create_long_jump(); +int md_estimate_size_before_relax(); +void md_number_to_imm(); +void md_number_to_disp(); +void md_number_to_field(); +void md_ri_to_chars(); +void emit_relocations(); +static void sparc_ip(); + +const relax_typeS md_relax_table[] = { 0 }; + +/* handle of the OPCODE hash table */ +static struct hash_control *op_hash = NULL; + +static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common(); +extern void s_globl(), s_long(), s_short(), s_space(), cons(); + +const pseudo_typeS +md_pseudo_table[] = { + { "common", s_common, 0 }, + { "global", s_globl, 0 }, + { "half", cons, 2 }, + { "proc", s_proc, 0 }, + { "reserve", s_reserve, 0 }, + { "seg", s_seg, 0 }, + { "skip", s_space, 0 }, + { "word", cons, 4 }, + { NULL, 0, 0 }, +}; + +int md_short_jump_size = 4; +int md_long_jump_size = 4; +int omagic = (0x103 << 16) | OMAGIC; /* Magic number for header */ + +/* This array holds the chars that always start a comment. If the + pre-processor is disabled, these aren't very useful */ +char comment_chars[] = "!"; /* JF removed '|' from 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 */ +char line_comment_chars[] = "#"; + +/* Chars that can be used to separate mant from exp in floating point nums */ +char EXP_CHARS[] = "eE"; + +/* 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. + */ +int size_reloc_info = sizeof(struct reloc_info_sparc); + +static unsigned char octal[256]; +#define isoctal(c) octal[c] +static unsigned char toHex[256]; + +/* + * anull bit - causes the branch delay slot instructions to not be executed + */ +#define ANNUL (1 << 29) + +struct sparc_it { + char *error; + unsigned long opcode; + struct nlist *nlistp; + expressionS exp; + int pcrel; + enum reloc_type reloc; +} the_insn, set_insn; + +#ifdef __STDC__ +#if 0 +static void print_insn(struct sparc_it *insn); +#endif +static int getExpression(char *str); +#else +#if 0 +static void print_insn(); +#endif +static int getExpression(); +#endif +static char *expr_end; +static int special_case; + +#define SPECIAL_CASE_SET 1 + +/* + * sort of like s_lcomm + * + */ +static void +s_reserve() +{ + char *name; + char c; + char *p; + int temp; + symbolS *symbolP; + + name = input_line_pointer; + c = get_symbol_end(); + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE(); + if ( * input_line_pointer != ',' ) { + as_warn("Expected comma after name"); + ignore_rest_of_line(); + return; + } + input_line_pointer ++; + if ((temp = get_absolute_expression()) < 0) { + as_warn("BSS length (%d.) <0! Ignored.", temp); + ignore_rest_of_line(); + return; + } + *p = 0; + symbolP = symbol_find_or_make(name); + *p = c; + if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) { + as_warn("bad .reserve segment: `%s'", input_line_pointer); + return; + } + input_line_pointer += 6; + if (symbolP->sy_other == 0 + && symbolP->sy_desc == 0 + && ((symbolP->sy_type == N_BSS + && symbolP->sy_value == local_bss_counter) + || ((symbolP->sy_type & N_TYPE) == N_UNDF + && symbolP->sy_value == 0))) { + symbolP->sy_value = local_bss_counter; + symbolP->sy_type = N_BSS; + symbolP->sy_frag = & bss_address_frag; + local_bss_counter += temp; + } else { + as_warn( "Ignoring attempt to re-define symbol from %d. to %d.", + symbolP->sy_value, local_bss_counter ); + } + demand_empty_rest_of_line(); + return; +} + +static void +s_common() +{ + register char *name; + register char c; + register char *p; + register int 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(); + if ( * input_line_pointer != ',' ) { + as_warn("Expected comma after symbol-name"); + ignore_rest_of_line(); + return; + } + input_line_pointer ++; /* skip ',' */ + if ( (temp = get_absolute_expression ()) < 0 ) { + as_warn(".COMMon length (%d.) <0! Ignored.", temp); + ignore_rest_of_line(); + return; + } + *p = 0; + symbolP = symbol_find_or_make (name); + *p = c; + if ( (symbolP->sy_type & N_TYPE) != N_UNDF || + symbolP->sy_other != 0 || symbolP->sy_desc != 0) { + as_warn( "Ignoring attempt to re-define symbol"); + ignore_rest_of_line(); + return; + } + if (symbolP->sy_value) { + if (symbolP->sy_value != temp) { + as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.", + symbolP->sy_name, symbolP->sy_value, temp); + } + } else { + symbolP->sy_value = temp; + symbolP->sy_type |= N_EXT; + } + know(symbolP->sy_frag == &zero_address_frag); + if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) { + p=input_line_pointer; + while(*p && *p!='\n') + p++; + c= *p; + *p='\0'; + as_warn("bad .common segment: `%s'", input_line_pointer); + *p=c; + return; + } + input_line_pointer += 6; + demand_empty_rest_of_line(); + return; +} + +static void +s_seg() +{ + + if (strncmp(input_line_pointer, "\"text\"", 6) == 0) { + input_line_pointer += 6; + s_text(); + return; + } + if (strncmp(input_line_pointer, "\"data\"", 6) == 0) { + input_line_pointer += 6; + s_data(); + return; + } + if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) { + input_line_pointer += 7; + s_data1(); + return; + } + as_warn("Unknown segment type"); + demand_empty_rest_of_line(); + return; +} + +static void +s_data1() +{ + subseg_new(SEG_DATA, 1); + demand_empty_rest_of_line(); + return; +} + +static void +s_proc() +{ + extern char is_end_of_line[]; + + while (!is_end_of_line[*input_line_pointer]) { + ++input_line_pointer; + } + ++input_line_pointer; + return; +} + +/* 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() +{ + register char *retval = NULL; + int lose = 0; + register unsigned int i = 0; + + op_hash = hash_new(); + if (op_hash == NULL) + as_fatal("Virtual memory exhausted"); + + while (i < NUMOPCODES) + { + const char *name = sparc_opcodes[i].name; + retval = hash_insert(op_hash, name, &sparc_opcodes[i]); + if(retval != NULL && *retval != '\0') + { + fprintf (stderr, "internal error: can't hash `%s': %s\n", + sparc_opcodes[i].name, retval); + lose = 1; + } + do + { + if (sparc_opcodes[i].match & sparc_opcodes[i].lose) + { + fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n", + sparc_opcodes[i].name, sparc_opcodes[i].args); + lose = 1; + } + ++i; + } while (i < NUMOPCODES + && !strcmp(sparc_opcodes[i].name, name)); + } + + if (lose) + as_fatal ("Broken assembler. No assembly attempted."); + + for (i = '0'; i < '8'; ++i) + octal[i] = 1; + for (i = '0'; i <= '9'; ++i) + toHex[i] = i - '0'; + for (i = 'a'; i <= 'f'; ++i) + toHex[i] = i + 10 - 'a'; + for (i = 'A'; i <= 'F'; ++i) + toHex[i] = i + 10 - 'A'; +} + +void +md_end() +{ + return; +} + +void +md_assemble(str) + char *str; +{ + char *toP; + int rsd; + + assert(str); + sparc_ip(str); + toP = frag_more(4); + /* put out the opcode */ + md_number_to_chars(toP, the_insn.opcode, 4); + + /* put out the symbol-dependent stuff */ + if (the_insn.reloc != NO_RELOC) { + fix_new( + frag_now, /* which frag */ + (toP - frag_now->fr_literal), /* where */ + 4, /* size */ + the_insn.exp.X_add_symbol, + the_insn.exp.X_subtract_symbol, + the_insn.exp.X_add_number, + the_insn.pcrel, + the_insn.reloc + ); + } + switch (special_case) { + + case SPECIAL_CASE_SET: + special_case = 0; + assert(the_insn.reloc == RELOC_HI22); + toP = frag_more(4); + rsd = (the_insn.opcode >> 25) & 0x1f; + the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14); + md_number_to_chars(toP, the_insn.opcode, 4); + fix_new( + frag_now, /* which frag */ + (toP - frag_now->fr_literal), /* where */ + 4, /* size */ + the_insn.exp.X_add_symbol, + the_insn.exp.X_subtract_symbol, + the_insn.exp.X_add_number, + the_insn.pcrel, + RELOC_LO10 + ); + return; + + case 0: + return; + + default: + abort(); + } +} + +static void +sparc_ip(str) + char *str; +{ + char *s; + const char *args; + char c; + unsigned long i; + struct sparc_opcode *insn; + char *argsStart; + unsigned long opcode; + unsigned int mask; + int match = FALSE; + int comma = 0; + + for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s) + ; + switch (*s) { + + case '\0': + break; + + case ',': + comma = 1; + + /*FALLTHROUGH*/ + + case ' ': + *s++ = '\0'; + break; + + default: + as_warn("Unknown opcode: `%s'", str); + exit(1); + } + if ((insn = (struct sparc_opcode *) hash_find(op_hash, str)) == NULL) { + as_warn("Unknown opcode: `%s'", str); + return; + } + if (comma) { + *--s = ','; + } + argsStart = s; + for (;;) { + opcode = insn->match; + bzero(&the_insn, sizeof(the_insn)); + the_insn.reloc = NO_RELOC; + + /* + * Build the opcode, checking as we go to make + * sure that the operands match + */ + for (args = insn->args; ; ++args) { + switch (*args) { + + case '\0': /* end of args */ + if (*s == '\0') { + match = TRUE; + } + break; + + case '+': + if (*s == '+') { + ++s; + continue; + } + if (*s == '-') { + continue; + } + break; + + case '[': /* these must match exactly */ + case ']': + case ',': + case ' ': + if (*s++ == *args) + continue; + break; + + case '#': /* must be at least one digit */ + if (isdigit(*s++)) { + while (isdigit(*s)) { + ++s; + } + continue; + } + break; + + case 'C': /* coprocessor state register */ + if (strncmp(s, "%csr", 4) == 0) { + s += 4; + continue; + } + break; + + case 'b': /* next operand is a coprocessor register */ + case 'c': + case 'D': + if (*s++ == '%' && *s++ == 'c' && isdigit(*s)) { + mask = *s++; + if (isdigit(*s)) { + mask = 10 * (mask - '0') + (*s++ - '0'); + if (mask >= 32) { + break; + } + } else { + mask -= '0'; + } + switch (*args) { + + case 'b': + opcode |= mask << 14; + continue; + + case 'c': + opcode |= mask; + continue; + + case 'D': + opcode |= mask << 25; + continue; + } + } + break; + + case 'r': /* next operand must be a register */ + case '1': + case '2': + case 'd': + if (*s++ == '%') { + switch (c = *s++) { + + case 'f': /* frame pointer */ + if (*s++ == 'p') { + mask = 0x1e; + break; + } + goto error; + + case 'g': /* global register */ + if (isoctal(c = *s++)) { + mask = c - '0'; + break; + } + goto error; + + case 'i': /* in register */ + if (isoctal(c = *s++)) { + mask = c - '0' + 24; + break; + } + goto error; + + case 'l': /* local register */ + if (isoctal(c = *s++)) { + mask= (c - '0' + 16) ; + break; + } + goto error; + + case 'o': /* out register */ + if (isoctal(c = *s++)) { + mask= (c - '0' + 8) ; + break; + } + goto error; + + case 's': /* stack pointer */ + if (*s++ == 'p') { + mask= 0xe; + break; + } + goto error; + + 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'; + } + mask= c; + break; + + default: + goto error; + } + /* + * Got the register, now figure out where + * it goes in the opcode. + */ + switch (*args) { + + case '1': + opcode |= mask << 14; + continue; + + case '2': + opcode |= mask; + continue; + + case 'd': + opcode |= mask << 25; + continue; + + case 'r': + opcode |= (mask << 25) | (mask << 14); + continue; + } + } + break; + + case 'e': /* next operand is a floating point register */ + case 'f': + case 'g': + if (*s++ == '%' && *s++ == 'f' && isdigit(*s)) { + mask = *s++; + if (isdigit(*s)) { + mask = 10 * (mask - '0') + (*s++ - '0'); + if (mask >= 32) { + break; + } + } else { + mask -= '0'; + } + switch (*args) { + + case 'e': + opcode |= mask << 14; + continue; + + case 'f': + opcode |= mask; + continue; + + case 'g': + opcode |= mask << 25; + continue; + } + } + break; + + case 'F': + if (strncmp(s, "%fsr", 4) == 0) { + s += 4; + continue; + } + break; + + case 'h': /* high 22 bits */ + the_insn.reloc = RELOC_HI22; + goto immediate; + + case 'l': /* 22 bit PC relative immediate */ + the_insn.reloc = RELOC_WDISP22; + the_insn.pcrel = 1; + goto immediate; + + case 'L': /* 30 bit immediate */ + the_insn.reloc = RELOC_WDISP30; + the_insn.pcrel = 1; + goto immediate; + + case 'i': /* 13 bit immediate */ + the_insn.reloc = RELOC_BASE13; + + /*FALLTHROUGH*/ + + immediate: + if(*s==' ') + s++; + if (*s == '%') { + if ((c = s[1]) == 'h' && s[2] == 'i') { + the_insn.reloc = RELOC_HI22; + s+=3; + } else if (c == 'l' && s[2] == 'o') { + the_insn.reloc = RELOC_LO10; + s+=3; + } else + break; + } + /* Note that if the getExpression() fails, we will still have + created U entries in the symbol table for the 'symbols' + in the input string. Try not to create U symbols for + registers, etc. */ + { + /* This stuff checks to see if the expression ends + in +%reg If it does, it removes the register from + the expression, and re-sets 's' to point to the + right place */ + + char *s1; + + for(s1=s;*s1 && *s1!=','&& *s1!=']';s1++) + ; + + if(s1!=s && isdigit(s1[-1])) { + if(s1[-2]=='%' && s1[-3]=='+') { + s1-=3; + *s1='\0'; + (void)getExpression(s); + *s1='+'; + s=s1; + continue; + } else if(index("goli0123456789",s1[-2]) && s1[-3]=='%' && s1[-4]=='+') { + s1-=4; + *s1='\0'; + (void)getExpression(s); + *s1='+'; + s=s1; + continue; + } + } + } + (void)getExpression(s); + s = expr_end; + continue; + + case 'a': + if (*s++ == 'a') { + opcode |= ANNUL; + continue; + } + break; + + case 'A': /* alternate space */ + if (isdigit(*s)) { + long num; + + num=0; + while (isdigit(*s)) { + num= num*10 + *s-'0'; + ++s; + } + opcode |= num<<5; + continue; + } + break; + /* abort(); */ + + case 'p': + if (strncmp(s, "%psr", 4) == 0) { + s += 4; + continue; + } + break; + + case 'q': /* floating point queue */ + if (strncmp(s, "%fq", 3) == 0) { + s += 3; + continue; + } + break; + + case 'Q': /* coprocessor queue */ + if (strncmp(s, "%cq", 3) == 0) { + s += 3; + continue; + } + break; + + case 'S': + if (strcmp(str, "set") == 0) { + special_case = SPECIAL_CASE_SET; + continue; + } + break; + + case 't': + if (strncmp(s, "%tbr", 4) != 0) + break; + s += 4; + continue; + + case 'w': + if (strncmp(s, "%wim", 4) != 0) + break; + s += 4; + continue; + + case 'y': + if (strncmp(s, "%y", 2) != 0) + break; + s += 2; + continue; + + default: + abort(); + } + break; + } + error: + if (match == FALSE) + { + /* Args don't match. */ + if (&insn[1] - sparc_opcodes < NUMOPCODES + && !strcmp(insn->name, insn[1].name)) + { + ++insn; + s = argsStart; + continue; + } + else + { + as_warn("Illegal operands"); + return; + } + } + break; + } + + the_insn.opcode = opcode; + return; +} + +static int +getExpression(str) + char *str; +{ + char *save_in; + segT seg; + + save_in = input_line_pointer; + input_line_pointer = str; + switch (seg = expression(&the_insn.exp)) { + + case SEG_ABSOLUTE: + case SEG_TEXT: + case SEG_DATA: + case SEG_BSS: + case SEG_UNKNOWN: + case SEG_DIFFERENCE: + case SEG_BIG: + case SEG_NONE: + break; + + default: + the_insn.error = "bad segment"; + expr_end = input_line_pointer; + input_line_pointer=save_in; + return 1; + } + expr_end = input_line_pointer; + input_line_pointer = save_in; + return 0; +} + + +/* + This is identical to the md_atof in m68k.c. I think this is right, + but I'm not sure. + + 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(); + + switch(type) { + + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + 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--;) { + md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE)); + litP+=sizeof(LITTLENUM_TYPE); + } + return ""; /* Someone should teach Dean about null pointers */ +} + +/* + * Write out big-endian. + */ +void +md_number_to_chars(buf,val,n) + char *buf; + long val; + int n; +{ + + switch(n) { + + case 4: + *buf++ = val >> 24; + *buf++ = val >> 16; + case 2: + *buf++ = val >> 8; + case 1: + *buf = val; + break; + + default: + abort(); + } + return; +} + +void +md_number_to_imm(buf,val,n, fixP, seg_type) + char *buf; + long val; + int n; + fixS *fixP; + int seg_type; +{ + /* if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC) { */ + if ( (seg_type != N_TEXT && fixP->fx_r_type > RELOC_DISP32 ) + || fixP->fx_r_type == NO_RELOC) { + /* should never get here for current relocs ... */ + + switch (n) { + case 1: + *buf = val; + break; + case 2: + *buf++ = (val>>8); + *buf = val; + break; + case 4: + *buf++ = (val>>24); + *buf++ = (val>>16); + *buf++ = (val>>8); + *buf = val; + break; + default: + abort(); + } + return; + } + + assert(n == 4); + assert(fixP->fx_r_type < NO_RELOC); + + /* + * This is a hack. There should be a better way to + * handle this. + */ + if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) { + val += fixP->fx_where + fixP->fx_frag->fr_address; + } + + switch (fixP->fx_r_type) { + + case RELOC_32: + buf[0] = 0; /* val >> 24; */ + buf[1] = 0; /* val >> 16; */ + buf[2] = 0; /* val >> 8; */ + buf[3] = 0; /* val; */ + break; + +#if 0 + case RELOC_8: /* These don't seem to ever be needed. */ + case RELOC_16: + case RELOC_DISP8: + case RELOC_DISP16: + case RELOC_DISP32: +#endif + case RELOC_WDISP30: + val = (val >>= 2) + 1; + buf[0] |= (val >> 24) & 0x3f; + buf[1]= (val >> 16); + buf[2] = val >> 8; + buf[3] = val; + break; + + case RELOC_HI22: + if(!fixP->fx_addsy) { + buf[1] |= (val >> 26) & 0x3f; + buf[2] = val >> 18; + buf[3] = val >> 10; + } else { + buf[2]=0; + buf[3]=0; + } + break; +#if 0 + case RELOC_22: + case RELOC_13: +#endif + case RELOC_LO10: + if(!fixP->fx_addsy) { + buf[2] |= (val >> 8) & 0x03; + buf[3] = val; + } else + buf[3]=0; + break; +#if 0 + case RELOC_SFA_BASE: + case RELOC_SFA_OFF13: + case RELOC_BASE10: +#endif + case RELOC_BASE13: + buf[2] |= (val >> 8) & 0x1f; + buf[3] = val; + break; + + case RELOC_WDISP22: + val = (val >>= 2) + 1; + /* FALLTHROUGH */ + case RELOC_BASE22: + buf[1] |= (val >> 16) & 0x3f; + buf[2] = val >> 8; + buf[3] = val; + break; + +#if 0 + case RELOC_PC10: + case RELOC_PC22: + case RELOC_JMP_TBL: + case RELOC_SEGOFF16: + case RELOC_GLOB_DAT: + case RELOC_JMP_SLOT: + case RELOC_RELATIVE: +#endif + + case NO_RELOC: + default: + as_warn("bad relocation type: 0x%02x", fixP->fx_r_type); + break; + } + return; +} + +/* should never be called for sparc */ +void +md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + long from_addr, to_addr; +{ + fprintf(stderr, "sparc_create_short_jmp\n"); + abort(); +} + +/* should never be called for sparc */ +void +md_number_to_disp(buf,val,n) + char *buf; + long val; +{ + fprintf(stderr, "md_number_to_disp\n"); + abort(); +} + +/* should never be called for sparc */ +void +md_number_to_field(buf,val,fix) + char *buf; + long val; + void *fix; +{ + fprintf(stderr, "sparc_number_to_field\n"); + abort(); +} + +/* the bit-field entries in the relocation_info struct plays hell + with the byte-order problems of cross-assembly. So as a hack, + I added this mach. dependent ri twiddler. Ugly, but it gets + you there. -KWK */ +/* on sparc: first 4 bytes are normal unsigned long address, next three + bytes are index, most sig. byte first. Byte 7 is broken up with + bit 7 as external, bits 6 & 5 unused, and the lower + five bits as relocation type. Next 4 bytes are long int addend. */ +/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ +void +md_ri_to_chars(ri_p, ri) + struct reloc_info_sparc *ri_p, ri; +{ + unsigned char the_bytes[sizeof(*ri_p)]; + + /* this is easy */ + md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address)); + /* now the fun stuff */ + the_bytes[4] = (ri.r_index >> 16) & 0x0ff; + the_bytes[5] = (ri.r_index >> 8) & 0x0ff; + the_bytes[6] = ri.r_index & 0x0ff; + the_bytes[7] = ((ri.r_extern << 7) & 0x80) | (0 & 0x60) | (ri.r_type & 0x1F); + /* Also easy */ + md_number_to_chars(&the_bytes[8], ri.r_addend, sizeof(ri.r_addend)); + /* now put it back where you found it, Junior... */ + bcopy (the_bytes, (char *)ri_p, sizeof(*ri_p)); +} + +/* should never be called for sparc */ +void +md_convert_frag(fragP) + register fragS *fragP; +{ + fprintf(stderr, "sparc_convert_frag\n"); + abort(); +} + +/* should never be called for sparc */ +void +md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + long from_addr, + to_addr; + fragS *frag; + symbolS *to_symbol; +{ + fprintf(stderr, "sparc_create_long_jump\n"); + abort(); +} + +/* should never be called for sparc */ +int +md_estimate_size_before_relax(fragP, segtype) + register fragS *fragP; +{ + fprintf(stderr, "sparc_estimate_size_before_relax\n"); + abort(); + return 0; +} + +#if 0 +/* for debugging only */ +static void +print_insn(insn) + struct sparc_it *insn; +{ + char *Reloc[] = { + "RELOC_8", + "RELOC_16", + "RELOC_32", + "RELOC_DISP8", + "RELOC_DISP16", + "RELOC_DISP32", + "RELOC_WDISP30", + "RELOC_WDISP22", + "RELOC_HI22", + "RELOC_22", + "RELOC_13", + "RELOC_LO10", + "RELOC_SFA_BASE", + "RELOC_SFA_OFF13", + "RELOC_BASE10", + "RELOC_BASE13", + "RELOC_BASE22", + "RELOC_PC10", + "RELOC_PC22", + "RELOC_JMP_TBL", + "RELOC_SEGOFF16", + "RELOC_GLOB_DAT", + "RELOC_JMP_SLOT", + "RELOC_RELATIVE", + "NO_RELOC" + }; + + if (insn->error) { + fprintf(stderr, "ERROR: %s\n"); + } + fprintf(stderr, "opcode=0x%08x\n", insn->opcode); + fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]); + fprintf(stderr, "exp = {\n"); + fprintf(stderr, "\t\tX_add_symbol = %s\n", + insn->exp.X_add_symbol ? + (insn->exp.X_add_symbol->sy_name ? + insn->exp.X_add_symbol->sy_name : "???") : "0"); + fprintf(stderr, "\t\tX_sub_symbol = %s\n", + insn->exp.X_subtract_symbol ? + (insn->exp.X_subtract_symbol->sy_name ? + insn->exp.X_subtract_symbol->sy_name : "???") : "0"); + fprintf(stderr, "\t\tX_add_number = %d\n", + insn->exp.X_add_number); + fprintf(stderr, "}\n"); + return; +} +#endif + +/* + * Sparc relocations are completely different, so it needs + * this machine dependent routine to emit them. + */ +void +emit_relocations(fixP, segment_address_in_file) + register fixS *fixP; + relax_addressT segment_address_in_file; +{ + struct reloc_info_sparc ri; + register symbolS *symbolP; + extern char *next_object_file_charP; + long add_number; + + bzero((char *) &ri, sizeof(ri)); + for (; fixP; fixP = fixP->fx_next) { + + if (fixP->fx_r_type >= NO_RELOC) { + fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); + abort(); + } + + if ((symbolP = fixP->fx_addsy) != NULL) { + ri.r_address = fixP->fx_frag->fr_address + + fixP->fx_where - segment_address_in_file; + if ((symbolP->sy_type & N_TYPE) == N_UNDF) { + ri.r_extern = 1; + ri.r_index = symbolP->sy_number; + } else { + ri.r_extern = 0; + ri.r_index = symbolP->sy_type & N_TYPE; + } + if (symbolP && symbolP->sy_frag) { + ri.r_addend = symbolP->sy_frag->fr_address; + } + ri.r_type = fixP->fx_r_type; + if (fixP->fx_pcrel) { +/* ri.r_addend -= fixP->fx_where; */ + ri.r_addend -= ri.r_address; + } else { + ri.r_addend = fixP->fx_addnumber; + } + +/* md_ri_to_chars((char *) &ri, ri); */ + append(&next_object_file_charP, (char *)& ri, sizeof(ri)); + } + } + return; +} + +int +md_parse_option(argP,cntP,vecP) + char **argP; + int *cntP; + char ***vecP; +{ + return 1; +} + diff --git a/gnu/usr.bin/gas/config/sparc.h b/gnu/usr.bin/gas/config/sparc.h new file mode 100644 index 00000000000..ac89437b386 --- /dev/null +++ b/gnu/usr.bin/gas/config/sparc.h @@ -0,0 +1,52 @@ +/* sparc.h -- Header file for the SPARC + Copyright (C) 1989 Free Software Foundation, Inc. + +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 1, 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. */ + +/* + * The following enum and struct were borrowed from + * sunOS /usr/include/sun4/a.out.h + * + */ + +enum reloc_type +{ + RELOC_8, RELOC_16, RELOC_32, RELOC_DISP8, + RELOC_DISP16, RELOC_DISP32, RELOC_WDISP30, RELOC_WDISP22, + RELOC_HI22, RELOC_22, RELOC_13, RELOC_LO10, + RELOC_SFA_BASE, RELOC_SFA_OFF13, RELOC_BASE10, RELOC_BASE13, + RELOC_BASE22, RELOC_PC10, RELOC_PC22, RELOC_JMP_TBL, + RELOC_SEGOFF16, RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE, + + NO_RELOC +}; + +struct reloc_info_sparc +{ + unsigned long int r_address; +/* + * Using bit fields here is a bad idea because the order is not portable. :-( + */ + unsigned int r_index : 24; + unsigned int r_extern : 1; + unsigned int unused : 2; + enum reloc_type r_type : 5; + long int r_addend; +}; + +#define relocation_info reloc_info_sparc + diff --git a/gnu/usr.bin/gas/config/vax-inst.h b/gnu/usr.bin/gas/config/vax-inst.h new file mode 100644 index 00000000000..4a8947054fd --- /dev/null +++ b/gnu/usr.bin/gas/config/vax-inst.h @@ -0,0 +1,77 @@ +/* vax-inst.h - GNU - Part of vax.c + Copyright (C) 1987 Free Software Foundation, Inc. + +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 1, 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. */ + +/* + * This is part of vax-ins-parse.c & friends. + * We want to parse a vax instruction text into a tree defined here. + */ + +#define VIT_MAX_OPERANDS (6) /* maximum number of operands in one */ + /* single vax instruction */ + +struct vop /* vax instruction operand */ +{ + short int vop_ndx; /* -1, or index register. eg 7=[R7] */ + short int vop_reg; /* -1, or register number. eg @I^#=0xF */ + /* Helps distinguish "abs" from "abs(PC)". */ + short int vop_mode; /* addressing mode 4 bits. eg I^#=0x9 */ + char vop_short; /* operand displacement length as written */ + /* ' '=none, "bilsw"=B^I^L^S^W^. */ + char vop_access; /* 'b'branch ' 'no-instruction 'amrvw'norm */ + char vop_width; /* Operand width, one of "bdfghloqw" */ + char * vop_warn; /* warning message of this operand, if any */ + char * vop_error; /* say if operand is inappropriate */ + char * vop_expr_begin; /* Unparsed expression, 1st char ... */ + char * vop_expr_end; /* ... last char. */ + unsigned char vop_nbytes; /* number of bytes in datum */ +}; + + +typedef long int vax_opcodeT; /* For initialising array of opcodes */ + /* Some synthetic opcodes > 16 bits! */ + +#define VIT_OPCODE_SYNTHETIC 0x80000000 /* Not real hardware instruction. */ +#define VIT_OPCODE_SPECIAL 0x40000000 /* Not normal branch optimising. */ + /* Never set without ..._SYNTHETIC */ + +#define VAX_WIDTH_UNCONDITIONAL_JUMP '-' /* These are encoded into */ +#define VAX_WIDTH_CONDITIONAL_JUMP '?' /* vop_width when vop_access=='b' */ +#define VAX_WIDTH_WORD_JUMP '!' /* and VIT_OPCODE_SYNTHETIC set. */ +#define VAX_WIDTH_BYTE_JUMP ':' /* */ + +#define VAX_JMP (0x17) /* Useful for branch optimising. Jump instr*/ +#define VAX_PC_RELATIVE_MODE (0xef) /* Use it after VAX_JMP */ +#define VAX_ABSOLUTE_MODE (0x9F) /* Use as @#... */ +#define VAX_BRB (0x11) /* Canonical branch. */ +#define VAX_BRW (0x31) /* Another canonical branch */ +#define VAX_WIDEN_WORD (0x20) /* Add this to byte branch to get word br. */ +#define VAX_WIDEN_LONG (0x6) /* Add this to byte branch to get long jmp.*/ + /* Needs VAX_PC_RELATIVE_MODE byte after it*/ + +struct vit /* vax instruction tree */ +{ + /* vit_opcode is char[] for portability. */ + char vit_opcode [ sizeof (vax_opcodeT) ]; + unsigned char vit_opcode_nbytes; /* How long is _opcode? (chars) */ + unsigned char vit_operands;/* */ + struct vop vit_operand[VIT_MAX_OPERANDS]; /* operands */ + char * vit_error; /* "" or error text */ +}; + +/* end: vax-inst.h */ diff --git a/gnu/usr.bin/gas/config/vax-opcode.h b/gnu/usr.bin/gas/config/vax-opcode.h new file mode 100644 index 00000000000..d604e3f9c65 --- /dev/null +++ b/gnu/usr.bin/gas/config/vax-opcode.h @@ -0,0 +1,382 @@ +/* Vax opcde list. + Copyright (C) 1989, Free Software Foundation, Inc. + +This file is part of GDB and GAS. + +GDB and GAS are 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. + +GDB and GAS are 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 GDB or GAS; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef vax_opcodeT +#define vax_opcodeT int +#endif /* no vax_opcodeT */ + +struct vot_wot /* vax opcode table: wot to do with this */ + /* particular opcode */ +{ + char * args; /* how to compile said opcode */ + vax_opcodeT code; /* op-code (may be > 8 bits!) */ +}; + +struct vot /* vax opcode text */ +{ + char * name; /* opcode name: lowercase string [key] */ + struct vot_wot detail; /* rest of opcode table [datum] */ +}; + +#define vot_how args +#define vot_code code +#define vot_detail detail +#define vot_name name + +static const struct vot +votstrs[] = +{ +{ "halt", {"", 0x00 } }, +{ "nop", {"", 0x01 } }, +{ "rei", {"", 0x02 } }, +{ "bpt", {"", 0x03 } }, +{ "ret", {"", 0x04 } }, +{ "rsb", {"", 0x05 } }, +{ "ldpctx", {"", 0x06 } }, +{ "svpctx", {"", 0x07 } }, +{ "cvtps", {"rwabrwab", 0x08 } }, +{ "cvtsp", {"rwabrwab", 0x09 } }, +{ "index", {"rlrlrlrlrlwl", 0x0a } }, +{ "crc", {"abrlrwab", 0x0b } }, +{ "prober", {"rbrwab", 0x0c } }, +{ "probew", {"rbrwab", 0x0d } }, +{ "insque", {"abab", 0x0e } }, +{ "remque", {"abwl", 0x0f } }, +{ "bsbb", {"bb", 0x10 } }, +{ "brb", {"bb", 0x11 } }, +{ "bneq", {"bb", 0x12 } }, +{ "bnequ", {"bb", 0x12 } }, +{ "beql", {"bb", 0x13 } }, +{ "beqlu", {"bb", 0x13 } }, +{ "bgtr", {"bb", 0x14 } }, +{ "bleq", {"bb", 0x15 } }, +{ "jsb", {"ab", 0x16 } }, +{ "jmp", {"ab", 0x17 } }, +{ "bgeq", {"bb", 0x18 } }, +{ "blss", {"bb", 0x19 } }, +{ "bgtru", {"bb", 0x1a } }, +{ "blequ", {"bb", 0x1b } }, +{ "bvc", {"bb", 0x1c } }, +{ "bvs", {"bb", 0x1d } }, +{ "bcc", {"bb", 0x1e } }, +{ "bgequ", {"bb", 0x1e } }, +{ "blssu", {"bb", 0x1f } }, +{ "bcs", {"bb", 0x1f } }, +{ "addp4", {"rwabrwab", 0x20 } }, +{ "addp6", {"rwabrwabrwab", 0x21 } }, +{ "subp4", {"rwabrwab", 0x22 } }, +{ "subp6", {"rwabrwabrwab", 0x23 } }, +{ "cvtpt", {"rwababrwab", 0x24 } }, +{ "mulp", {"rwabrwabrwab", 0x25 } }, +{ "cvttp", {"rwababrwab", 0x26 } }, +{ "divp", {"rwabrwabrwab", 0x27 } }, +{ "movc3", {"rwabab", 0x28 } }, +{ "cmpc3", {"rwabab", 0x29 } }, +{ "scanc", {"rwababrb", 0x2a } }, +{ "spanc", {"rwababrb", 0x2b } }, +{ "movc5", {"rwabrbrwab", 0x2c } }, +{ "cmpc5", {"rwabrbrwab", 0x2d } }, +{ "movtc", {"rwabrbabrwab", 0x2e } }, +{ "movtuc", {"rwabrbabrwab", 0x2f } }, +{ "bsbw", {"bw", 0x30 } }, +{ "brw", {"bw", 0x31 } }, +{ "cvtwl", {"rwwl", 0x32 } }, +{ "cvtwb", {"rwwb", 0x33 } }, +{ "movp", {"rwabab", 0x34 } }, +{ "cmpp3", {"rwabab", 0x35 } }, +{ "cvtpl", {"rwabwl", 0x36 } }, +{ "cmpp4", {"rwabrwab", 0x37 } }, +{ "editpc", {"rwababab", 0x38 } }, +{ "matchc", {"rwabrwab", 0x39 } }, +{ "locc", {"rbrwab", 0x3a } }, +{ "skpc", {"rbrwab", 0x3b } }, +{ "movzwl", {"rwwl", 0x3c } }, +{ "acbw", {"rwrwmwbw", 0x3d } }, +{ "movaw", {"awwl", 0x3e } }, +{ "pushaw", {"aw", 0x3f } }, +{ "addf2", {"rfmf", 0x40 } }, +{ "addf3", {"rfrfwf", 0x41 } }, +{ "subf2", {"rfmf", 0x42 } }, +{ "subf3", {"rfrfwf", 0x43 } }, +{ "mulf2", {"rfmf", 0x44 } }, +{ "mulf3", {"rfrfwf", 0x45 } }, +{ "divf2", {"rfmf", 0x46 } }, +{ "divf3", {"rfrfwf", 0x47 } }, +{ "cvtfb", {"rfwb", 0x48 } }, +{ "cvtfw", {"rfww", 0x49 } }, +{ "cvtfl", {"rfwl", 0x4a } }, +{ "cvtrfl", {"rfwl", 0x4b } }, +{ "cvtbf", {"rbwf", 0x4c } }, +{ "cvtwf", {"rwwf", 0x4d } }, +{ "cvtlf", {"rlwf", 0x4e } }, +{ "acbf", {"rfrfmfbw", 0x4f } }, +{ "movf", {"rfwf", 0x50 } }, +{ "cmpf", {"rfrf", 0x51 } }, +{ "mnegf", {"rfwf", 0x52 } }, +{ "tstf", {"rf", 0x53 } }, +{ "emodf", {"rfrbrfwlwf", 0x54 } }, +{ "polyf", {"rfrwab", 0x55 } }, +{ "cvtfd", {"rfwd", 0x56 } }, + /* opcode 57 is not defined yet */ +{ "adawi", {"rwmw", 0x58 } }, + /* opcode 59 is not defined yet */ + /* opcode 5a is not defined yet */ + /* opcode 5b is not defined yet */ +{ "insqhi", {"abaq", 0x5c } }, +{ "insqti", {"abaq", 0x5d } }, +{ "remqhi", {"aqwl", 0x5e } }, +{ "remqti", {"aqwl", 0x5f } }, +{ "addd2", {"rdmd", 0x60 } }, +{ "addd3", {"rdrdwd", 0x61 } }, +{ "subd2", {"rdmd", 0x62 } }, +{ "subd3", {"rdrdwd", 0x63 } }, +{ "muld2", {"rdmd", 0x64 } }, +{ "muld3", {"rdrdwd", 0x65 } }, +{ "divd2", {"rdmd", 0x66 } }, +{ "divd3", {"rdrdwd", 0x67 } }, +{ "cvtdb", {"rdwb", 0x68 } }, +{ "cvtdw", {"rdww", 0x69 } }, +{ "cvtdl", {"rdwl", 0x6a } }, +{ "cvtrdl", {"rdwl", 0x6b } }, +{ "cvtbd", {"rbwd", 0x6c } }, +{ "cvtwd", {"rwwd", 0x6d } }, +{ "cvtld", {"rlwd", 0x6e } }, +{ "acbd", {"rdrdmdbw", 0x6f } }, +{ "movd", {"rdwd", 0x70 } }, +{ "cmpd", {"rdrd", 0x71 } }, +{ "mnegd", {"rdwd", 0x72 } }, +{ "tstd", {"rd", 0x73 } }, +{ "emodd", {"rdrbrdwlwd", 0x74 } }, +{ "polyd", {"rdrwab", 0x75 } }, +{ "cvtdf", {"rdwf", 0x76 } }, + /* opcode 77 is not defined yet */ +{ "ashl", {"rbrlwl", 0x78 } }, +{ "ashq", {"rbrqwq", 0x79 } }, +{ "emul", {"rlrlrlwq", 0x7a } }, +{ "ediv", {"rlrqwlwl", 0x7b } }, +{ "clrd", {"wd", 0x7c } }, +{ "clrg", {"wg", 0x7c } }, +{ "clrq", {"wd", 0x7c } }, +{ "movq", {"rqwq", 0x7d } }, +{ "movaq", {"aqwl", 0x7e } }, +{ "movad", {"adwl", 0x7e } }, +{ "pushaq", {"aq", 0x7f } }, +{ "pushad", {"ad", 0x7f } }, +{ "addb2", {"rbmb", 0x80 } }, +{ "addb3", {"rbrbwb", 0x81 } }, +{ "subb2", {"rbmb", 0x82 } }, +{ "subb3", {"rbrbwb", 0x83 } }, +{ "mulb2", {"rbmb", 0x84 } }, +{ "mulb3", {"rbrbwb", 0x85 } }, +{ "divb2", {"rbmb", 0x86 } }, +{ "divb3", {"rbrbwb", 0x87 } }, +{ "bisb2", {"rbmb", 0x88 } }, +{ "bisb3", {"rbrbwb", 0x89 } }, +{ "bicb2", {"rbmb", 0x8a } }, +{ "bicb3", {"rbrbwb", 0x8b } }, +{ "xorb2", {"rbmb", 0x8c } }, +{ "xorb3", {"rbrbwb", 0x8d } }, +{ "mnegb", {"rbwb", 0x8e } }, +{ "caseb", {"rbrbrb", 0x8f } }, +{ "movb", {"rbwb", 0x90 } }, +{ "cmpb", {"rbrb", 0x91 } }, +{ "mcomb", {"rbwb", 0x92 } }, +{ "bitb", {"rbrb", 0x93 } }, +{ "clrb", {"wb", 0x94 } }, +{ "tstb", {"rb", 0x95 } }, +{ "incb", {"mb", 0x96 } }, +{ "decb", {"mb", 0x97 } }, +{ "cvtbl", {"rbwl", 0x98 } }, +{ "cvtbw", {"rbww", 0x99 } }, +{ "movzbl", {"rbwl", 0x9a } }, +{ "movzbw", {"rbww", 0x9b } }, +{ "rotl", {"rbrlwl", 0x9c } }, +{ "acbb", {"rbrbmbbw", 0x9d } }, +{ "movab", {"abwl", 0x9e } }, +{ "pushab", {"ab", 0x9f } }, +{ "addw2", {"rwmw", 0xa0 } }, +{ "addw3", {"rwrwww", 0xa1 } }, +{ "subw2", {"rwmw", 0xa2 } }, +{ "subw3", {"rwrwww", 0xa3 } }, +{ "mulw2", {"rwmw", 0xa4 } }, +{ "mulw3", {"rwrwww", 0xa5 } }, +{ "divw2", {"rwmw", 0xa6 } }, +{ "divw3", {"rwrwww", 0xa7 } }, +{ "bisw2", {"rwmw", 0xa8 } }, +{ "bisw3", {"rwrwww", 0xa9 } }, +{ "bicw2", {"rwmw", 0xaa } }, +{ "bicw3", {"rwrwww", 0xab } }, +{ "xorw2", {"rwmw", 0xac } }, +{ "xorw3", {"rwrwww", 0xad } }, +{ "mnegw", {"rwww", 0xae } }, +{ "casew", {"rwrwrw", 0xaf } }, +{ "movw", {"rwww", 0xb0 } }, +{ "cmpw", {"rwrw", 0xb1 } }, +{ "mcomw", {"rwww", 0xb2 } }, +{ "bitw", {"rwrw", 0xb3 } }, +{ "clrw", {"ww", 0xb4 } }, +{ "tstw", {"rw", 0xb5 } }, +{ "incw", {"mw", 0xb6 } }, +{ "decw", {"mw", 0xb7 } }, +{ "bispsw", {"rw", 0xb8 } }, +{ "bicpsw", {"rw", 0xb9 } }, +{ "popr", {"rw", 0xba } }, +{ "pushr", {"rw", 0xbb } }, +{ "chmk", {"rw", 0xbc } }, +{ "chme", {"rw", 0xbd } }, +{ "chms", {"rw", 0xbe } }, +{ "chmu", {"rw", 0xbf } }, +{ "addl2", {"rlml", 0xc0 } }, +{ "addl3", {"rlrlwl", 0xc1 } }, +{ "subl2", {"rlml", 0xc2 } }, +{ "subl3", {"rlrlwl", 0xc3 } }, +{ "mull2", {"rlml", 0xc4 } }, +{ "mull3", {"rlrlwl", 0xc5 } }, +{ "divl2", {"rlml", 0xc6 } }, +{ "divl3", {"rlrlwl", 0xc7 } }, +{ "bisl2", {"rlml", 0xc8 } }, +{ "bisl3", {"rlrlwl", 0xc9 } }, +{ "bicl2", {"rlml", 0xca } }, +{ "bicl3", {"rlrlwl", 0xcb } }, +{ "xorl2", {"rlml", 0xcc } }, +{ "xorl3", {"rlrlwl", 0xcd } }, +{ "mnegl", {"rlwl", 0xce } }, +{ "casel", {"rlrlrl", 0xcf } }, +{ "movl", {"rlwl", 0xd0 } }, +{ "cmpl", {"rlrl", 0xd1 } }, +{ "mcoml", {"rlwl", 0xd2 } }, +{ "bitl", {"rlrl", 0xd3 } }, +{ "clrf", {"wf", 0xd4 } }, +{ "clrl", {"wl", 0xd4 } }, +{ "tstl", {"rl", 0xd5 } }, +{ "incl", {"ml", 0xd6 } }, +{ "decl", {"ml", 0xd7 } }, +{ "adwc", {"rlml", 0xd8 } }, +{ "sbwc", {"rlml", 0xd9 } }, +{ "mtpr", {"rlrl", 0xda } }, +{ "mfpr", {"rlwl", 0xdb } }, +{ "movpsl", {"wl", 0xdc } }, +{ "pushl", {"rl", 0xdd } }, +{ "moval", {"alwl", 0xde } }, +{ "movaf", {"afwl", 0xde } }, +{ "pushal", {"al", 0xdf } }, +{ "pushaf", {"af", 0xdf } }, +{ "bbs", {"rlabbb", 0xe0 } }, +{ "bbc", {"rlabbb", 0xe1 } }, +{ "bbss", {"rlabbb", 0xe2 } }, +{ "bbcs", {"rlabbb", 0xe3 } }, +{ "bbsc", {"rlabbb", 0xe4 } }, +{ "bbcc", {"rlabbb", 0xe5 } }, +{ "bbssi", {"rlabbb", 0xe6 } }, +{ "bbcci", {"rlabbb", 0xe7 } }, +{ "blbs", {"rlbb", 0xe8 } }, +{ "blbc", {"rlbb", 0xe9 } }, +{ "ffs", {"rlrbvbwl", 0xea } }, +{ "ffc", {"rlrbvbwl", 0xeb } }, +{ "cmpv", {"rlrbvbrl", 0xec } }, +{ "cmpzv", {"rlrbvbrl", 0xed } }, +{ "extv", {"rlrbvbwl", 0xee } }, +{ "extzv", {"rlrbvbwl", 0xef } }, +{ "insv", {"rlrlrbvb", 0xf0 } }, +{ "acbl", {"rlrlmlbw", 0xf1 } }, +{ "aoblss", {"rlmlbb", 0xf2 } }, +{ "aobleq", {"rlmlbb", 0xf3 } }, +{ "sobgeq", {"mlbb", 0xf4 } }, +{ "sobgtr", {"mlbb", 0xf5 } }, +{ "cvtlb", {"rlwb", 0xf6 } }, +{ "cvtlw", {"rlww", 0xf7 } }, +{ "ashp", {"rbrwabrbrwab", 0xf8 } }, +{ "cvtlp", {"rlrwab", 0xf9 } }, +{ "callg", {"abab", 0xfa } }, +{ "calls", {"rlab", 0xfb } }, +{ "xfc", {"", 0xfc } }, + /* undefined opcodes here */ +{ "cvtdh", {"rdwh", 0x32fd } }, +{ "cvtgf", {"rgwh", 0x33fd } }, +{ "addg2", {"rgmg", 0x40fd } }, +{ "addg3", {"rgrgwg", 0x41fd } }, +{ "subg2", {"rgmg", 0x42fd } }, +{ "subg3", {"rgrgwg", 0x43fd } }, +{ "mulg2", {"rgmg", 0x44fd } }, +{ "mulg3", {"rgrgwg", 0x45fd } }, +{ "divg2", {"rgmg", 0x46fd } }, +{ "divg3", {"rgrgwg", 0x47fd } }, +{ "cvtgb", {"rgwb", 0x48fd } }, +{ "cvtgw", {"rgww", 0x49fd } }, +{ "cvtgl", {"rgwl", 0x4afd } }, +{ "cvtrgl", {"rgwl", 0x4bfd } }, +{ "cvtbg", {"rbwg", 0x4cfd } }, +{ "cvtwg", {"rwwg", 0x4dfd } }, +{ "cvtlg", {"rlwg", 0x4efd } }, +{ "acbg", {"rgrgmgbw", 0x4ffd } }, +{ "movg", {"rgwg", 0x50fd } }, +{ "cmpg", {"rgrg", 0x51fd } }, +{ "mnegg", {"rgwg", 0x52fd } }, +{ "tstg", {"rg", 0x53fd } }, +{ "emodg", {"rgrwrgwlwg", 0x54fd } }, +{ "polyg", {"rgrwab", 0x55fd } }, +{ "cvtgh", {"rgwh", 0x56fd } }, + /* undefined opcodes here */ +{ "addh2", {"rhmh", 0x60fd } }, +{ "addh3", {"rhrhwh", 0x61fd } }, +{ "subh2", {"rhmh", 0x62fd } }, +{ "subh3", {"rhrhwh", 0x63fd } }, +{ "mulh2", {"rhmh", 0x64fd } }, +{ "mulh3", {"rhrhwh", 0x65fd } }, +{ "divh2", {"rhmh", 0x66fd } }, +{ "divh3", {"rhrhwh", 0x67fd } }, +{ "cvthb", {"rhwb", 0x68fd } }, +{ "cvthw", {"rhww", 0x69fd } }, +{ "cvthl", {"rhwl", 0x6afd } }, +{ "cvtrhl", {"rhwl", 0x6bfd } }, +{ "cvtbh", {"rbwh", 0x6cfd } }, +{ "cvtwh", {"rwwh", 0x6dfd } }, +{ "cvtlh", {"rlwh", 0x6efd } }, +{ "acbh", {"rhrhmhbw", 0x6ffd } }, +{ "movh", {"rhwh", 0x70fd } }, +{ "cmph", {"rhrh", 0x71fd } }, +{ "mnegh", {"rhwh", 0x72fd } }, +{ "tsth", {"rh", 0x73fd } }, +{ "emodh", {"rhrwrhwlwh", 0x74fd } }, +{ "polyh", {"rhrwab", 0x75fd } }, +{ "cvthg", {"rhwg", 0x76fd } }, + /* undefined opcodes here */ +{ "clrh", {"wh", 0x7cfd } }, +{ "clro", {"wo", 0x7cfd } }, +{ "movo", {"rowo", 0x7dfd } }, +{ "movah", {"ahwl", 0x7efd } }, +{ "movao", {"aowl", 0x7efd } }, +{ "pushah", {"ah", 0x7ffd } }, +{ "pushao", {"ao", 0x7ffd } }, + /* undefined opcodes here */ +{ "cvtfh", {"rfwh", 0x98fd } }, +{ "cvtfg", {"rfwg", 0x99fd } }, + /* undefined opcodes here */ +{ "cvthf", {"rhwf", 0xf6fd } }, +{ "cvthd", {"rhwd", 0xf7fd } }, + /* undefined opcodes here */ +{ "bugl", {"rl", 0xfdff } }, +{ "bugw", {"rw", 0xfeff } }, + /* undefined opcodes here */ + +{ "" , "" } /* empty is end sentinel */ + +}; /* votstrs */ + +/* end: vax.opcode.h */ diff --git a/gnu/usr.bin/gas/config/vax.c b/gnu/usr.bin/gas/config/vax.c new file mode 100644 index 00000000000..b8cd6ed1573 --- /dev/null +++ b/gnu/usr.bin/gas/config/vax.c @@ -0,0 +1,3364 @@ +/* vax.c - vax-specific - + Copyright (C) 1987 Free Software Foundation, Inc. + +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 1, 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. */ + +/* JF I moved almost all the vax specific stuff into this one file 'cuz RMS + seems to think its a good idea. I hope I managed to get all the VAX-isms */ + + +#include "as.h" +#include "read.h" +#include "flonum.h" +#include "vax-inst.h" +#include "md.h" +#include "obstack.h" /* For FRAG_APPEND_1_CHAR macro in "frags.h" */ +#include "frags.h" +#include "struc-symbol.h" +#include "expr.h" +#include "symbols.h" + +/* This is the number to put at the beginning of the a.out file */ +long omagic = OMAGIC; + +/* These chars start a comment anywhere in a source file (except inside + another comment */ +const char comment_chars[] = "#"; + +/* These chars only start a comment at the beginning of a line. */ +/* Note that for the VAX the are the same as comment_chars above. */ +const char line_comment_chars[] = "#"; + +/* Chars that can be used to separate mant from exp in floating point nums */ +const char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant */ +/* as in 0f123.456 */ +/* or 0H1.234E-12 (see exp chars above) */ +const char FLT_CHARS[] = "dDfFgGhH"; + +/* 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. + */ + +static expressionS /* Hold details of an operand expression */ + exp_of_operand[VIT_MAX_OPERANDS]; + +static struct vit + v; /* A vax instruction after decoding. */ + +LITTLENUM_TYPE big_operand_bits[VIT_MAX_OPERANDS][SIZE_OF_LARGE_NUMBER]; + /* Hold details of big operands. */ +FLONUM_TYPE float_operand[VIT_MAX_OPERANDS]; + /* Above is made to point into */ + /* big_operand_bits by md_begin(). */ + +/* + * For VAX, relative addresses of "just the right length" are easy. + * The branch displacement is always the last operand, even in + * synthetic instructions. + * For VAX, we encode the relax_substateTs (in e.g. fr_substate) as: + * + * 4 3 2 1 0 bit number + * ---/ /--+-------+-------+-------+-------+-------+ + * | what state ? | how long ? | + * ---/ /--+-------+-------+-------+-------+-------+ + * + * The "how long" bits are 00=byte, 01=word, 10=long. + * This is a Un*x convention. + * Not all lengths are legit for a given value of (what state). + * The "how long" refers merely to the displacement length. + * The address usually has some constant bytes in it as well. + * + +groups for VAX address relaxing. + +1. "foo" pc-relative. + length of byte, word, long + +2a. J<cond> where <cond> is a simple flag test. + length of byte, word, long. + VAX opcodes are: (Hex) + bneq/bnequ 12 + beql/beqlu 13 + bgtr 14 + bleq 15 + bgeq 18 + blss 19 + bgtru 1a + blequ 1b + bvc 1c + bvs 1d + bgequ/bcc 1e + blssu/bcs 1f + Always, you complement 0th bit to reverse condition. + Always, 1-byte opcode, then 1-byte displacement. + +2b. J<cond> where cond tests a memory bit. + length of byte, word, long. + Vax opcodes are: (Hex) + bbs e0 + bbc e1 + bbss e2 + bbcs e3 + bbsc e4 + bbcc e5 + bbssi e6 + bbcci e7 + Always, you complement 0th bit to reverse condition. + Always, 1-byte opcde, longword-address, byte-address, 1-byte-displacement + +2c. J<cond> where cond tests low-order memory bit + length of byte,word,long. + Vax opcodes are: (Hex) + blbs e8 + blbc e9 + Always, you complement 0th bit to reverse condition. + Always, 1-byte opcode, longword-address, 1-byte displacement. + +3. Jbs/Jbr. + length of byte,word,long. + Vax opcodes are: (Hex) + bsbb 10 + brb 11 + These are like (2) but there is no condition to reverse. + Always, 1 byte opcode, then displacement/absolute. + +4a. JacbX + length of word, long. + Vax opcodes are: (Hex) + acbw 3d + acbf 4f + acbd 6f + abcb 9d + acbl f1 + acbg 4ffd + acbh 6ffd + Always, we cannot reverse the sense of the branch; we have a word + displacement. + The double-byte op-codes don't hurt: we never want to modify the + opcode, so we don't care how many bytes are between the opcode and + the operand. + +4b. JXobXXX + length of long, long, byte. + Vax opcodes are: (Hex) + aoblss f2 + aobleq f3 + sobgeq f4 + sobgtr f5 + Always, we cannot reverse the sense of the branch; we have a byte + displacement. + +The only time we need to modify the opcode is for class 2 instructions. +After relax() we may complement the lowest order bit of such instruction +to reverse sense of branch. + +For class 2 instructions, we store context of "where is the opcode literal". +We can change an opcode's lowest order bit without breaking anything else. + +We sometimes store context in the operand literal. This way we can figure out +after relax() what the original addressing mode was. +*/ + + /* These displacements are relative to */ + /* the start address of the displacement. */ + /* The first letter is Byte, Word. */ + /* 2nd letter is Forward, Backward. */ +#define BF (1+ 127) +#define BB (1+-128) +#define WF (2+ 32767) +#define WB (2+-32768) + /* Dont need LF, LB because they always */ + /* reach. [They are coded as 0.] */ + + +#define C(a,b) ENCODE_RELAX(a,b) + /* This macro has no side-effects. */ +#define ENCODE_RELAX(what,length) (((what) << 2) + (length)) + +const relax_typeS +md_relax_table[] = +{ + { + 1, 1, 0, 0 + }, /* error sentinel 0,0 */ + { + 1, 1, 0, 0 + }, /* unused 0,1 */ + { + 1, 1, 0, 0 + }, /* unused 0,2 */ + { + 1, 1, 0, 0 + }, /* unused 0,3 */ + { + BF + 1, BB + 1, 2, C (1, 1) + }, /* B^"foo" 1,0 */ + { + WF + 1, WB + 1, 3, C (1, 2) + }, /* W^"foo" 1,1 */ + { + 0, 0, 5, 0 + }, /* L^"foo" 1,2 */ + { + 1, 1, 0, 0 + }, /* unused 1,3 */ + { + BF, BB, 1, C (2, 1) + }, /* b<cond> B^"foo" 2,0 */ + { + WF + 2, WB + 2, 4, C (2, 2) + }, /* br.+? brw X 2,1 */ + { + 0, 0, 7, 0 + }, /* br.+? jmp X 2,2 */ + { + 1, 1, 0, 0 + }, /* unused 2,3 */ + { + BF, BB, 1, C (3, 1) + }, /* brb B^foo 3,0 */ + { + WF, WB, 2, C (3, 2) + }, /* brw W^foo 3,1 */ + { + 0, 0, 5, 0 + }, /* Jmp L^foo 3,2 */ + { + 1, 1, 0, 0 + }, /* unused 3,3 */ + { + 1, 1, 0, 0 + }, /* unused 4,0 */ + { + WF, WB, 2, C (4, 2) + }, /* acb_ ^Wfoo 4,1 */ + { + 0, 0, 10, 0 + }, /* acb_,br,jmp L^foo4,2 */ + { + 1, 1, 0, 0 + }, /* unused 4,3 */ + { + BF, BB, 1, C (5, 1) + }, /* Xob___,,foo 5,0 */ + { + WF + 4, WB + 4, 6, C (5, 2) + }, /* Xob.+2,brb.+3,brw5,1 */ + { + 0, 0, 9, 0 + }, /* Xob.+2,brb.+6,jmp5,2 */ +}; + +#undef C +#undef BF +#undef BB +#undef WF +#undef WB + +void float_cons (); + +const pseudo_typeS md_pseudo_table[] = +{ + {"dfloat", float_cons, 'd'}, + {"ffloat", float_cons, 'f'}, + {"gfloat", float_cons, 'g'}, + {"hfloat", float_cons, 'h'}, + {0} +}; + +#define STATE_PC_RELATIVE (1) +#define STATE_CONDITIONAL_BRANCH (2) +#define STATE_ALWAYS_BRANCH (3) /* includes BSB... */ +#define STATE_COMPLEX_BRANCH (4) +#define STATE_COMPLEX_HOP (5) + +#define STATE_BYTE (0) +#define STATE_WORD (1) +#define STATE_LONG (2) +#define STATE_UNDF (3) /* Symbol undefined in pass1 */ + + +#define min(a, b) ((a) < (b) ? (a) : (b)) + + +void +md_begin () +{ + char *vip_begin (); + char *errtxt; + FLONUM_TYPE *fP; + int i; + + if (*(errtxt = vip_begin (TRUE, "$", "*", "`"))) + { + as_fatal ("VIP_BEGIN error:%s", errtxt); + } + + for (i = 0, fP = float_operand; + fP < float_operand + VIT_MAX_OPERANDS; + i++, fP++) + { + fP->low = &big_operand_bits[i][0]; + fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1]; + } +} + +void +md_end () +{ + vip_end (); +} + +void /* Knows about order of bytes in address. */ +md_number_to_chars (con, value, nbytes) + char con[]; /* Return 'nbytes' of chars here. */ + long int value; /* The value of the bits. */ + int nbytes; /* Number of bytes in the output. */ +{ + int n; + long v; + + n = nbytes; + v = value; + while (nbytes--) + { + *con++ = value; /* Lint wants & MASK_CHAR. */ + value >>= BITS_PER_CHAR; + } + /* XXX line number probably botched for this warning message. */ + if (value != 0 && value != -1) + as_warn ("Displacement (%ld) long for instruction field length (%d).", v, n); +} + +void /* Knows about order of bytes in address. */ +md_number_to_imm (con, value, nbytes) + char con[]; /* Return 'nbytes' of chars here. */ + long int value; /* The value of the bits. */ + int nbytes; /* Number of bytes in the output. */ +{ + int n; + long v; + + n = nbytes; + v = value; + while (nbytes--) + { + *con++ = value; /* Lint wants & MASK_CHAR. */ + value >>= BITS_PER_CHAR; + } + /* XXX line number probably botched for this warning message. */ + if (value != 0 && value != -1) + as_warn ("Displacement (%ld) too long for instruction field length (%d).", v, n); +} + +void /* Knows about order of bytes in address. */ +md_number_to_disp (con, value, nbytes) + char con[]; /* Return 'nbytes' of chars here. */ + long int value; /* The value of the bits. */ + int nbytes; /* Number of bytes in the output. */ +{ + abort (); + while (nbytes--) + { + *con++ = value; /* Lint wants & MASK_CHAR. */ + value >>= BITS_PER_CHAR; + } + /* XXX line number probably botched for this warning message. */ + if (value != 0 && value != -1) + as_warn ("Displacement too long for instruction field length."); +} + +void /* Knows about order of bytes in address. */ +md_number_to_field (con, value, nbytes) + char con[]; /* Return 'nbytes' of chars here. */ + long int value; /* The value of the bits. */ + int nbytes; /* Number of bytes in the output. */ +{ + abort (); + while (nbytes--) + { + *con++ = value; /* Lint wants & MASK_CHAR. */ + value >>= BITS_PER_CHAR; + } + /* XXX line number probably botched for this warning message. */ + if (value != 0 && value != -1) + as_warn ("Displacement too long for instruction field length."); +} + +long int /* Knows about the byte order in a word. */ +md_chars_to_number (con, nbytes) + unsigned char con[]; /* Low order byte 1st. */ + int nbytes; /* Number of bytes in the input. */ +{ + long int retval; + for (retval = 0, con += nbytes - 1; nbytes--; con--) + { + retval <<= BITS_PER_CHAR; + retval |= *con; + } + return retval; +} + +/* vax:md_assemble() emit frags for 1 instruction */ + +void +md_assemble (instruction_string) + char *instruction_string; /* A string: assemble 1 instruction. */ +{ + char *p; + register struct vop *operandP;/* An operand. Scans all operands. */ + char *save_input_line_pointer; + char c_save; /* What used to live after an expression. */ + struct frag *fragP; /* Fragment of code we just made. */ + register int goofed; /* TRUE: instruction_string bad for all passes. */ + register struct vop *end_operandP; /* -> slot just after last operand */ + /* Limit of the for (each operand). */ + register expressionS *expP; /* -> expression values for this operand */ + + /* These refer to an instruction operand expression. */ + segT to_seg; /* Target segment of the address. */ + register valueT this_add_number; + register struct symbol *this_add_symbol; /* +ve (minuend) symbol. */ + register struct symbol *this_subtract_symbol; /* -ve(subtrahend) symbol. */ + + long int opcode_as_number; /* As a number. */ + char *opcode_as_chars; /* Least significant byte 1st. */ + /* As an array of characters. */ + char *opcode_low_byteP; /* Least significant byte 1st */ + struct details *detP; /* The details of an ADxxx frag. */ + int length; /* length (bytes) meant by vop_short. */ + int at; /* 0, or 1 if '@' is in addressing mode. */ + int nbytes; /* From vop_nbytes: vax_operand_width (in bytes) */ + FLONUM_TYPE *floatP; + char *vip (); + LITTLENUM_TYPE literal_float[8]; + /* Big enough for any floating point literal. */ + + if (*(p = vip (&v, instruction_string))) + { + as_fatal ("vax_assemble\"%s\" in=\"%s\"", p, instruction_string); + } + /* + * Now we try to find as many as_warn()s as we can. If we do any as_warn()s + * then goofed=TRUE. Notice that we don't make any frags yet. + * Should goofed be TRUE, then this instruction will wedge in any pass, + * and we can safely flush it, without causing interpass symbol phase + * errors. That is, without changing label values in different passes. + */ + if (goofed = (*v.vit_error)) + { + as_warn ("Ignoring statement due to \"%s\"", v.vit_error); + } + /* + * We need to use expression() and friends, which require us to diddle + * input_line_pointer. So we save it and restore it later. + */ + save_input_line_pointer = input_line_pointer; + for (operandP = v.vit_operand, + expP = exp_of_operand, + floatP = float_operand, + end_operandP = v.vit_operand + v.vit_operands; + + operandP < end_operandP; + + operandP++, + expP++, + floatP++ + ) /* for each operand */ + { + if (*(operandP->vop_error)) + { + as_warn ("Ignoring statement because \"%s\"", (operandP->vop_error)); + goofed = TRUE; + } + else + { /* statement has no syntax goofs: lets sniff the expression */ + int can_be_short; /* TRUE if a bignum can be reduced to a short literal. */ + + input_line_pointer = operandP->vop_expr_begin; + c_save = operandP->vop_expr_end[1]; + operandP->vop_expr_end[1] = '\0'; + /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = TRUE. */ + switch (to_seg = expression (expP)) + { + case SEG_NONE: + /* for BSD4.2 compatibility, missing expression is absolute 0 */ + to_seg = expP->X_seg = SEG_ABSOLUTE; + expP->X_add_number = 0; + /* for SEG_ABSOLUTE, we shouldnt need to set X_subtract_symbol, X_add_symbol to any particular value. */ + /* But, we will program defensively. Since this situation occurs */ + /* rarely so it costs us little to do, and stops Dean */ + /* worrying about the origin of random bits in expressionS's. */ + expP->X_add_symbol = NULL; + expP->X_subtract_symbol = NULL; + case SEG_TEXT: + case SEG_DATA: + case SEG_BSS: + case SEG_ABSOLUTE: + case SEG_UNKNOWN: + break; + + case SEG_DIFFERENCE: + case SEG_PASS1: + /* + * Major bug. We can't handle the case of a + * SEG_DIFFERENCE expression in a VIT_OPCODE_SYNTHETIC + * variable-length instruction. + * We don't have a frag type that is smart enough to + * relax a SEG_DIFFERENCE, and so we just force all + * SEG_DIFFERENCEs to behave like SEG_PASS1s. + * Clearly, if there is a demand we can invent a new or + * modified frag type and then coding up a frag for this + * case will be easy. SEG_DIFFERENCE was invented for the + * .words after a CASE opcode, and was never intended for + * instruction operands. + */ + need_pass_2 = TRUE; + as_warn("Can't relocate expression"); + break; + + case SEG_BIG: + /* Preserve the bits. */ + if (expP->X_add_number > 0) + { + bignum_copy (generic_bignum, expP->X_add_number, + floatP->low, SIZE_OF_LARGE_NUMBER); + } + else + { + know (expP->X_add_number < 0); + flonum_copy (&generic_floating_point_number, + floatP); + if (index ("s i", operandP->vop_short)) + { /* Could possibly become S^# */ + flonum_gen2vax (-expP->X_add_number, floatP, literal_float); + switch (-expP->X_add_number) + { + case 'f': + can_be_short = + (literal_float[0] & 0xFC0F) == 0x4000 + && literal_float[1] == 0; + break; + + case 'd': + can_be_short = + (literal_float[0] & 0xFC0F) == 0x4000 + && literal_float[1] == 0 + && literal_float[2] == 0 + && literal_float[3] == 0; + break; + + case 'g': + can_be_short = + (literal_float[0] & 0xFF81) == 0x4000 + && literal_float[1] == 0 + && literal_float[2] == 0 + && literal_float[3] == 0; + break; + + case 'h': + can_be_short = + (literal_float[0] & 0xFFF8) == 0x4000 + && (literal_float[1] & 0xE000) == 0 + && literal_float[2] == 0 + && literal_float[3] == 0 + && literal_float[4] == 0 + && literal_float[5] == 0 + && literal_float[6] == 0 + && literal_float[7] == 0; + break; + + default: + BAD_CASE (-expP->X_add_number); + break; + } /* switch (float type) */ + } /* if (could want to become S^#...) */ + } /* bignum or flonum ? */ + + if (operandP->vop_short == 's' + || operandP->vop_short == 'i' + || (operandP->vop_short == ' ' + && operandP->vop_reg == 0xF + && (operandP->vop_mode & 0xE) == 0x8)) + { + /* Saw a '#'. */ + if (operandP->vop_short == ' ') + { /* We must chose S^ or I^. */ + if (expP->X_add_number > 0) + { /* Bignum: Short literal impossible. */ + operandP->vop_short = 'i'; + operandP->vop_mode = 8; + operandP->vop_reg = 0xF; /* VAX PC. */ + } + else + { /* Flonum: Try to do it. */ + if (can_be_short) + { + operandP->vop_short = 's'; + operandP->vop_mode = 0; + operandP->vop_ndx = -1; + operandP->vop_reg = -1; + /* JF hope this is the right thing */ + expP->X_seg = SEG_ABSOLUTE; + } + else + { + operandP->vop_short = 'i'; + operandP->vop_mode = 8; + operandP->vop_reg = 0xF; /* VAX PC */ + } + } /* bignum or flonum ? */ + } /* if #, but no S^ or I^ seen. */ + /* No more ' ' case: either 's' or 'i'. */ + if (operandP->vop_short == 's') + { + /* Wants to be a short literal. */ + if (expP->X_add_number > 0) + { + as_warn ("Bignum not permitted in short literal. Immediate mode assumed."); + operandP->vop_short = 'i'; + operandP->vop_mode = 8; + operandP->vop_reg = 0xF; /* VAX PC. */ + } + else + { + if (!can_be_short) + { + as_warn ("Can't do flonum short literal: immediate mode used."); + operandP->vop_short = 'i'; + operandP->vop_mode = 8; + operandP->vop_reg = 0xF; /* VAX PC. */ + } + else + { /* Encode short literal now. */ + register int temp; + + switch (-expP->X_add_number) + { + case 'f': + case 'd': + temp = literal_float[0] >> 4; + break; + + case 'g': + temp = literal_float[0] >> 1; + break; + + case 'h': + temp = ((literal_float[0] << 3) & 070) + | ((literal_float[1] >> 13) & 07); + break; + + default: + BAD_CASE (-expP->X_add_number); + break; + } + + floatP->low[0] = temp & 077; + floatP->low[1] = 0; + } /* if can be short literal float */ + } /* flonum or bignum ? */ + } + else + { /* I^# seen: set it up if float. */ + if (expP->X_add_number < 0) + { + bcopy (literal_float, floatP->low, sizeof (literal_float)); + } + } /* if S^# seen. */ + } + else + { + as_warn ("A bignum/flonum may not be a displacement: 0x%x used", + expP->X_add_number = 0x80000000); + /* Chosen so luser gets the most offset bits to patch later. */ + } + expP->X_add_number = floatP->low[0] + | ((LITTLENUM_MASK & (floatP->low[1])) << LITTLENUM_NUMBER_OF_BITS); +/* + * For the SEG_BIG case we have: + * If vop_short == 's' then a short floating literal is in the + * lowest 6 bits of floatP -> low [0], which is + * big_operand_bits [---] [0]. + * If vop_short == 'i' then the appropriate number of elements + * of big_operand_bits [---] [...] are set up with the correct + * bits. + * Also, just in case width is byte word or long, we copy the lowest + * 32 bits of the number to X_add_number. + */ + break; + + default: + BAD_CASE (to_seg); + break; + } + if (input_line_pointer != operandP->vop_expr_end + 1) + { + as_warn ("Junk at end of expression \"%s\"", input_line_pointer); + goofed = TRUE; + } + operandP->vop_expr_end[1] = c_save; + } + } /* for(each operand) */ + input_line_pointer = save_input_line_pointer; + + if (!need_pass_2 && !goofed) + { + /* We saw no errors in any operands - try to make frag(s) */ + int is_undefined; /* True if operand expression's */ + /* segment not known yet. */ + int length_code; + + /* Emit op-code. */ + /* Remember where it is, in case we want to modify the op-code later. */ + opcode_low_byteP = frag_more (v.vit_opcode_nbytes); + bcopy (v.vit_opcode, opcode_low_byteP, v.vit_opcode_nbytes); + opcode_as_number = md_chars_to_number (opcode_as_chars = v.vit_opcode, 4); + for (operandP = v.vit_operand, + expP = exp_of_operand, + floatP = float_operand, + end_operandP = v.vit_operand + v.vit_operands; + + operandP < end_operandP; + + operandP++, + floatP++, + expP++ + ) /* for each operand */ + { + if (operandP->vop_ndx >= 0) + { + /* indexed addressing byte */ + /* Legality of indexed mode already checked: it is OK */ + FRAG_APPEND_1_CHAR (0x40 + operandP->vop_ndx); + } /* if(vop_ndx>=0) */ + + /* Here to make main operand frag(s). */ + this_add_number = expP->X_add_number; + this_add_symbol = expP->X_add_symbol; + this_subtract_symbol = expP->X_subtract_symbol; + to_seg = expP->X_seg; + is_undefined = (to_seg == SEG_UNKNOWN); + know (to_seg == SEG_UNKNOWN \ + ||to_seg == SEG_ABSOLUTE \ + ||to_seg == SEG_DATA \ + ||to_seg == SEG_TEXT \ + ||to_seg == SEG_BSS \ + ||to_seg == SEG_BIG \ + ); + at = operandP->vop_mode & 1; + length = operandP->vop_short == 'b' ? 1 : operandP->vop_short == 'w' ? 2 : operandP->vop_short == 'l' ? 4 : 0; + nbytes = operandP->vop_nbytes; + if (operandP->vop_access == 'b') + { + if (to_seg == now_seg || is_undefined) + { /* If is_undefined, then it might BECOME now_seg. */ + if (nbytes) + { + p = frag_more (nbytes); + fix_new (frag_now, p - frag_now->fr_literal, nbytes, + this_add_symbol, 0, this_add_number, 1); + } + else + { /* to_seg==now_seg || to_seg == SEG_UNKNOWN */ + /* nbytes==0 */ + length_code = is_undefined ? STATE_UNDF : STATE_BYTE; + if (opcode_as_number & VIT_OPCODE_SPECIAL) + { + if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP) + { + /* br or jsb */ + frag_var (rs_machine_dependent, 5, 1, + ENCODE_RELAX (STATE_ALWAYS_BRANCH, length_code), + this_add_symbol, this_add_number, + opcode_low_byteP); + } + else + { + if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) + { + length_code = STATE_WORD; /* JF: There is no state_byte for this one! */ + frag_var (rs_machine_dependent, 10, 2, + ENCODE_RELAX (STATE_COMPLEX_BRANCH, length_code), + this_add_symbol, this_add_number, + opcode_low_byteP); + } + else + { + know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP); + frag_var (rs_machine_dependent, 9, 1, + ENCODE_RELAX (STATE_COMPLEX_HOP, length_code), + this_add_symbol, this_add_number, + opcode_low_byteP); + } + } + } + else + { + know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP); + frag_var (rs_machine_dependent, 7, 1, + ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, length_code), + this_add_symbol, this_add_number, + opcode_low_byteP); + } + } + } + else + { /* to_seg != now_seg && to_seg != SEG_UNKNOWN */ +/* + * --- SEG FLOAT MAY APPEAR HERE ---- + */ + if (to_seg == SEG_ABSOLUTE) + { + if (nbytes) + { + know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC)); + p = frag_more (nbytes); + /* Conventional relocation. */ + fix_new (frag_now, p - frag_now->fr_literal, + nbytes, &abs_symbol, 0, this_add_number, 1); + } + else + { + know (opcode_as_number & VIT_OPCODE_SYNTHETIC); + if (opcode_as_number & VIT_OPCODE_SPECIAL) + { + if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP) + { + /* br or jsb */ + *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG; + know (opcode_as_chars[1] == 0); + p = frag_more (5); + p[0] = VAX_ABSOLUTE_MODE; /* @#... */ + md_number_to_chars (p + 1, this_add_number, 4); + /* Now (eg) JMP @#foo or JSB @#foo. */ + } + else + { + if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) + { + p = frag_more (10); + p[0] = 2; + p[1] = 0; + p[2] = VAX_BRB; + p[3] = 6; + p[4] = VAX_JMP; + p[5] = VAX_ABSOLUTE_MODE; /* @#... */ + md_number_to_chars (p + 6, this_add_number, 4); + /* + * Now (eg) ACBx 1f + * BRB 2f + * 1: JMP @#foo + * 2: + */ + } + else + { + know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP); + p = frag_more (9); + p[0] = 2; + p[1] = VAX_BRB; + p[2] = 6; + p[3] = VAX_JMP; + p[4] = VAX_PC_RELATIVE_MODE + 1; /* @#... */ + md_number_to_chars (p + 5, this_add_number, 4); + /* + * Now (eg) xOBxxx 1f + * BRB 2f + * 1: JMP @#foo + * 2: + */ + } + } + } + else + { + /* b<cond> */ + *opcode_low_byteP ^= 1; /* To reverse the condition in a VAX branch, complement the lowest order bit. */ + p = frag_more (7); + p[0] = 6; + p[1] = VAX_JMP; + p[2] = VAX_ABSOLUTE_MODE; /* @#... */ + md_number_to_chars (p + 3, this_add_number, 4); + /* + * Now (eg) BLEQ 1f + * JMP @#foo + * 1: + */ + } + } + } + else + { /* to_seg != now_seg && to_seg != SEG_UNKNOWN && to_Seg != SEG_ABSOLUTE */ + if (nbytes > 0) + { + /* Pc-relative. Conventional relocation. */ + know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC)); + p = frag_more (nbytes); + fix_new (frag_now, p - frag_now->fr_literal, + nbytes, &abs_symbol, 0, this_add_number, 1); + } + else + { + know (opcode_as_number & VIT_OPCODE_SYNTHETIC); + if (opcode_as_number & VIT_OPCODE_SPECIAL) + { + if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP) + { + /* br or jsb */ + know (opcode_as_chars[1] == 0); + *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG; + p = frag_more (5); + p[0] = VAX_PC_RELATIVE_MODE; + fix_new (frag_now, + p + 1 - frag_now->fr_literal, 4, + this_add_symbol, 0, + this_add_number, 1); + /* Now eg JMP foo or JSB foo. */ + } + else + { + if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) + { + p = frag_more (10); + p[0] = 0; + p[1] = 2; + p[2] = VAX_BRB; + p[3] = 6; + p[4] = VAX_JMP; + p[5] = VAX_PC_RELATIVE_MODE; + fix_new (frag_now, + p + 6 - frag_now->fr_literal, 4, + this_add_symbol, 0, + this_add_number, 1); + /* + * Now (eg) ACBx 1f + * BRB 2f + * 1: JMP foo + * 2: + */ + } + else + { + know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP); + p = frag_more (10); + p[0] = 2; + p[1] = VAX_BRB; + p[2] = 6; + p[3] = VAX_JMP; + p[4] = VAX_PC_RELATIVE_MODE; + fix_new (frag_now, + p + 5 - frag_now->fr_literal, + 4, this_add_symbol, 0, + this_add_number, 1); + /* + * Now (eg) xOBxxx 1f + * BRB 2f + * 1: JMP foo + * 2: + */ + } + } + } + else + { + know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP); + *opcode_low_byteP ^= 1; /* Reverse branch condition. */ + p = frag_more (7); + p[0] = 6; + p[1] = VAX_JMP; + p[2] = VAX_PC_RELATIVE_MODE; + fix_new (frag_now, p + 3 - frag_now->fr_literal, + 4, this_add_symbol, 0, + this_add_number, 1); + } + } + } + } + } + else + { + know (operandP->vop_access != 'b'); /* So it is ordinary operand. */ + know (operandP->vop_access != ' '); /* ' ' target-independent: elsewhere. */ + know (operandP->vop_access == 'a' || operandP->vop_access == 'm' || operandP->vop_access == 'r' || operandP->vop_access == 'v' || operandP->vop_access == 'w'); + if (operandP->vop_short == 's') + { + if (to_seg == SEG_ABSOLUTE) + { + if (this_add_number < 0 || this_add_number >= 64) + { + as_warn ("Short literal overflow(%d.), immediate mode assumed.", this_add_number); + operandP->vop_short = 'i'; + operandP->vop_mode = 8; + operandP->vop_reg = 0xF; + } + } + else + { + as_warn ("Forced short literal to immediate mode. now_seg=%s to_seg=%s", seg_name[(int) now_seg], seg_name[(int) to_seg]); + operandP->vop_short = 'i'; + operandP->vop_mode = 8; + operandP->vop_reg = 0xF; + } + } + if (operandP->vop_reg >= 0 && (operandP->vop_mode < 8 || (operandP->vop_reg != 0xF && operandP->vop_mode < 10))) + { /* One byte operand. */ + know (operandP->vop_mode > 3); + FRAG_APPEND_1_CHAR (operandP->vop_mode << 4 | operandP->vop_reg); + /* All 1-bytes except S^# happen here. */ + } + else + { /* {@}{q^}foo{(Rn)} or S^#foo */ + if (operandP->vop_reg == -1 && operandP->vop_short != 's') + { /* "{@}{q^}foo" */ + if (to_seg == now_seg) + { + if (length == 0) + { + know (operandP->vop_short == ' '); + p = frag_var (rs_machine_dependent, 10, 2, + ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE), + this_add_symbol, this_add_number, + opcode_low_byteP); + know (operandP->vop_mode == 10 + at); + *p = at << 4; + /* At is the only context we need to carry to */ + /* other side of relax() process. */ + /* Must be in the correct bit position of VAX */ + /* operand spec. byte. */ + } + else + { + know (length); + know (operandP->vop_short != ' '); + p = frag_more (length + 1); + /* JF is this array stuff really going to work? */ + p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4); + fix_new (frag_now, p + 1 - frag_now->fr_literal, + length, this_add_symbol, 0, + this_add_number, 1); + } + } + else + { /* to_seg != now_seg */ + if (this_add_symbol == NULL) + { + know (to_seg == SEG_ABSOLUTE); + /* Do @#foo: simpler relocation than foo-.(pc) anyway. */ + p = frag_more (5); + p[0] = VAX_ABSOLUTE_MODE; /* @#... */ + md_number_to_chars (p + 1, this_add_number, 4); + if (length && length != 4) + { + as_warn ("Length specification ignored. Address mode 9F used"); + } + } + else + { + /* {@}{q^}other_seg */ + know ((length == 0 && operandP->vop_short == ' ') \ + ||(length > 0 && operandP->vop_short != ' ')); + if (is_undefined) + { + /* + * We have a SEG_UNKNOWN symbol. It might + * turn out to be in the same segment as + * the instruction, permitting relaxation. + */ + p = frag_var (rs_machine_dependent, 5, 2, + ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF), + this_add_symbol, this_add_number, + 0); + p[0] = at << 4; + } + else + { + if (length == 0) + { + know (operandP->vop_short == ' '); + length = 4; /* Longest possible. */ + } + p = frag_more (length + 1); + p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4); + md_number_to_chars (p + 1, this_add_number, length); + fix_new (frag_now, + p + 1 - frag_now->fr_literal, + length, this_add_symbol, 0, + this_add_number, 1); + } + } + } + } + else + { /* {@}{q^}foo(Rn) or S^# or I^# or # */ + if (operandP->vop_mode < 0xA) + { /* # or S^# or I^# */ + /* know( (length == 0 && operandP->vop_short == ' ') \ + || (length > 0 && operandP->vop_short != ' ')); */ + if (length == 0 + && to_seg == SEG_ABSOLUTE + && operandP->vop_mode == 8 /* No '@'. */ + && this_add_number < 64 + && this_add_number >= 0) + { + operandP->vop_short = 's'; + } + if (operandP->vop_short == 's') + { + FRAG_APPEND_1_CHAR (this_add_number); + } + else + { /* I^#... */ + know (nbytes); + p = frag_more (nbytes + 1); + know (operandP->vop_reg == 0xF); + p[0] = (operandP->vop_mode << 4) | 0xF; + if (to_seg == SEG_ABSOLUTE) + { +/* + * If nbytes > 4, then we are scrod. We don't know if the + * high order bytes are to be 0xFF or 0x00. + * BSD4.2 & RMS say use 0x00. OK --- but this + * assembler needs ANOTHER rewrite to + * cope properly with this bug. + */ + md_number_to_chars (p + 1, this_add_number, min (4, nbytes)); + if (nbytes > 4) + { + bzero (p + 5, nbytes - 4); + } + } + else + { + if (to_seg == SEG_BIG) + { +/* + * Problem here is to get the bytes in the right order. + * We stored our constant as LITTLENUMs, not bytes. + */ + LITTLENUM_TYPE *lP; + + lP = floatP->low; + if (nbytes & 1) + { + know (nbytes == 1); + p[1] = *lP; + } + else + { + for (p++; nbytes; nbytes -= 2, p += 2, lP++) + { + md_number_to_chars (p, *lP, 2); + } + } + } + else + { + fix_new (frag_now, p + 1 - frag_now->fr_literal, + nbytes, this_add_symbol, 0, + this_add_number, 0); + } + } + } + } + else + { /* {@}{q^}foo(Rn) */ + know ((length == 0 && operandP->vop_short == ' ') \ + ||(length > 0 && operandP->vop_short != ' ')); + if (length == 0) + { + if (to_seg == SEG_ABSOLUTE) + { + register long int test; + + test = this_add_number; + + if (test < 0) + test = ~test; + + length = test & 0xffff8000 ? 4 + : test & 0xffffff80 ? 2 + : 1; + } + else + { + length = 4; + } + } + p = frag_more (1 + length); + know (operandP->vop_reg >= 0); + p[0] = operandP->vop_reg + | ((at | "?\12\14?\16"[length]) << 4); + if (to_seg == SEG_ABSOLUTE) + { + md_number_to_chars (p + 1, this_add_number, length); + } + else + { + fix_new (frag_now, p + 1 - frag_now->fr_literal, + length, this_add_symbol, 0, + this_add_number, 0); + } + } + } + } /* if(single-byte-operand) */ + } + } /* for(operandP) */ + } /* if(!need_pass_2&&!goofed) */ +} /* vax_assemble() */ + +/* + * md_estimate_size_before_relax() + * + * Called just before relax(). + * Any symbol that is now undefined will not become defined. + * Return the correct fr_subtype in the frag. + * Return the initial "guess for fr_var" to caller. + * The guess for fr_var is ACTUALLY the growth beyond fr_fix. + * Whatever we do to grow fr_fix or fr_var contributes to our returned value. + * Although it may not be explicit in the frag, pretend fr_var starts with a + * 0 value. + */ +int +md_estimate_size_before_relax (fragP, segment_type) + register fragS *fragP; + register int segment_type; /* N_DATA or N_TEXT. */ +{ + register char *p; + register int old_fr_fix; + + old_fr_fix = fragP->fr_fix; + switch (fragP->fr_subtype) + { + case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF): + if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) + { /* A relaxable case. */ + fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE); + } + else + { + p = fragP->fr_literal + old_fr_fix; + p[0] |= VAX_PC_RELATIVE_MODE; /* Preserve @ bit. */ + fragP->fr_fix += 1 + 4; + fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0, + fragP->fr_offset, 1); + frag_wane (fragP); + } + break; + + case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF): + if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) + { + fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE); + } + else + { + p = fragP->fr_literal + old_fr_fix; + *fragP->fr_opcode ^= 1; /* Reverse sense of branch. */ + p[0] = 6; + p[1] = VAX_JMP; + p[2] = VAX_PC_RELATIVE_MODE; /* ...(PC) */ + fragP->fr_fix += 1 + 1 + 1 + 4; + fix_new (fragP, old_fr_fix + 3, 4, fragP->fr_symbol, 0, + fragP->fr_offset, 1); + frag_wane (fragP); + } + break; + + case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_UNDF): + if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) + { + fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD); + } + else + { + p = fragP->fr_literal + old_fr_fix; + p[0] = 2; + p[1] = 0; + p[2] = VAX_BRB; + p[3] = 6; + p[4] = VAX_JMP; + p[5] = VAX_PC_RELATIVE_MODE; /* ...(pc) */ + fragP->fr_fix += 2 + 2 + 1 + 1 + 4; + fix_new (fragP, old_fr_fix + 6, 4, fragP->fr_symbol, 0, + fragP->fr_offset, 1); + frag_wane (fragP); + } + break; + + case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_UNDF): + if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) + { + fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE); + } + else + { + p = fragP->fr_literal + old_fr_fix; + p[0] = 2; + p[1] = VAX_BRB; + p[2] = 6; + p[3] = VAX_JMP; + p[4] = VAX_PC_RELATIVE_MODE; /* ...(pc) */ + fragP->fr_fix += 1 + 2 + 1 + 1 + 4; + fix_new (fragP, old_fr_fix + 5, 4, fragP->fr_symbol, 0, + fragP->fr_offset, 1); + frag_wane (fragP); + } + break; + + case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF): + if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) + { + fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE); + } + else + { + p = fragP->fr_literal + old_fr_fix; + *fragP->fr_opcode += VAX_WIDEN_LONG; + p[0] = VAX_PC_RELATIVE_MODE; /* ...(PC) */ + fragP->fr_fix += 1 + 4; + fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0, + fragP->fr_offset, 1); + frag_wane (fragP); + } + break; + + default: + break; + } + return (fragP->fr_var + fragP->fr_fix - old_fr_fix); +} /* md_estimate_size_before_relax() */ + +/* + * md_convert_frag(); + * + * Called after relax() is finished. + * In: Address of frag. + * fr_type == rs_machine_dependent. + * fr_subtype is what the address relaxed to. + * + * Out: Any fixSs and constants are set up. + * Caller will turn frag into a ".space 0". + */ +void +md_convert_frag (fragP) + register fragS *fragP; +{ + register char *addressP; /* -> _var to change. */ + register char *opcodeP; /* -> opcode char(s) to change. */ + register short int length_code; /* 2=long 1=word 0=byte */ + register short int extension; /* Size of relaxed address. */ + /* Added to fr_fix: incl. ALL var chars. */ + register symbolS *symbolP; + register long int where; + register long int address_of_var; + /* Where, in file space, is _var of *fragP? */ + register long int target_address; + /* Where, in file space, does addr point? */ + + know (fragP->fr_type == rs_machine_dependent); + length_code = fragP->fr_subtype & 3; /* depends on ENCODE_RELAX() */ + know (length_code >= 0 && length_code < 3); + where = fragP->fr_fix; + addressP = fragP->fr_literal + where; + opcodeP = fragP->fr_opcode; + symbolP = fragP->fr_symbol; + know (symbolP); + target_address = symbolP->sy_value + fragP->fr_offset; + address_of_var = fragP->fr_address + where; + switch (fragP->fr_subtype) + { + case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE): + know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */ + addressP[0] |= 0xAF; /* Byte displacement. */ + addressP[1] = target_address - (address_of_var + 2); + extension = 2; + break; + + case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD): + know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */ + addressP[0] |= 0xCF; /* Word displacement. */ + md_number_to_chars (addressP + 1, target_address - (address_of_var + 3), 2); + extension = 3; + break; + + case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_LONG): + know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */ + addressP[0] |= 0xEF; /* Long word displacement. */ + md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4); + extension = 5; + break; + + case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE): + addressP[0] = target_address - (address_of_var + 1); + extension = 1; + break; + + case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD): + opcodeP[0] ^= 1; /* Reverse sense of test. */ + addressP[0] = 3; + addressP[1] = VAX_BRB + VAX_WIDEN_WORD; + md_number_to_chars (addressP + 2, target_address - (address_of_var + 4), 2); + extension = 4; + break; + + case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_LONG): + opcodeP[0] ^= 1; /* Reverse sense of test. */ + addressP[0] = 6; + addressP[1] = VAX_JMP; + addressP[2] = VAX_PC_RELATIVE_MODE; + md_number_to_chars (addressP + 3, target_address, 4); + extension = 7; + break; + + case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE): + addressP[0] = target_address - (address_of_var + 1); + extension = 1; + break; + + case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD): + opcodeP[0] += VAX_WIDEN_WORD; /* brb -> brw, bsbb -> bsbw */ + md_number_to_chars (addressP, target_address - (address_of_var + 2), 2); + extension = 2; + break; + + case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_LONG): + opcodeP[0] += VAX_WIDEN_LONG; /* brb -> jmp, bsbb -> jsb */ + addressP[0] = VAX_PC_RELATIVE_MODE; + md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4); + extension = 5; + break; + + case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD): + md_number_to_chars (addressP, target_address - (address_of_var + 2), 2); + extension = 2; + break; + + case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_LONG): + addressP[0] = 2; + addressP[1] = 0; + addressP[2] = VAX_BRB; + addressP[3] = 6; + addressP[4] = VAX_JMP; + addressP[5] = VAX_PC_RELATIVE_MODE; + md_number_to_chars (addressP + 6, target_address, 4); + extension = 10; + break; + + case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE): + addressP[0] = target_address - (address_of_var + 1); + extension = 1; + break; + + case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_WORD): + addressP[0] = 2; + addressP[1] = VAX_BRB; + addressP[2] = 3; + addressP[3] = VAX_BRW; + md_number_to_chars (addressP + 4, target_address - (address_of_var + 6), 2); + extension = 6; + break; + + case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_LONG): + addressP[0] = 2; + addressP[1] = VAX_BRB; + addressP[2] = 6; + addressP[3] = VAX_JMP; + addressP[4] = VAX_PC_RELATIVE_MODE; + md_number_to_chars (addressP + 5, target_address, 4); + extension = 9; + break; + + default: + BAD_CASE (fragP->fr_subtype); + break; + } + fragP->fr_fix += extension; +} + +/* the bit-field entries in the relocation_info struct plays hell + with the byte-order problems of cross-assembly. So as a hack, + I added this mach. dependent ri twiddler. Ugly, but it gets + you there. -KWK */ +/* on vax: first 4 bytes are normal unsigned long, next three bytes + are symbolnum, least sig. byte first. Last byte is broken up with + the upper nibble as nuthin, bit 3 as extern, bits 2 & 1 as length, and + bit 0 as pcrel. */ +void +md_ri_to_chars (ri_p, ri) + struct relocation_info *ri_p, ri; +{ + unsigned char the_bytes[8]; + + /* this is easy */ + md_number_to_chars (the_bytes, ri.r_address, sizeof (ri.r_address)); + /* now the fun stuff */ + the_bytes[6] = (ri.r_symbolnum >> 16) & 0x0ff; + the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff; + the_bytes[4] = ri.r_symbolnum & 0x0ff; + the_bytes[7] = (((ri.r_extern << 3) & 0x08) | ((ri.r_length << 1) & 0x06) | + ((ri.r_pcrel << 0) & 0x01)) & 0x0F; + /* now put it back where you found it */ + bcopy (the_bytes, (char *) ri_p, sizeof (struct relocation_info)); +} + + + + /* JF this used to be a separate file */ +/* vax_ins_parse.c - a part for a VAX assembler */ + +/* Copyright (C) 1987 Free Software Foundtation, Inc */ + +/* + * BUGS, GRIPES, APOLOGIA, etc. + * + * The opcode table 'votstrs' needs to be sorted on opcode frequency. + * That is, AFTER we hash it with hash_...(), we want most-used opcodes + * to come out of the hash table faster. + * + * I am sorry to inflict + * yet another VAX assembler on the world, but RMS says we must + * do everything from scratch, to prevent pin-heads restricting + * this software. + */ + +/* + * This is a vaguely modular set of routines in C to parse VAX + * assembly code using DEC mnemonics. It is NOT un*x specific. + * + * The idea here is that the assembler has taken care of all: + * labels + * macros + * listing + * pseudo-ops + * line continuation + * comments + * condensing any whitespace down to exactly one space + * and all we have to do is parse 1 line into a vax instruction + * partially formed. We will accept a line, and deliver: + * an error message (hopefully empty) + * a skeleton VAX instruction (tree structure) + * textual pointers to all the operand expressions + * a warning message that notes a silly operand (hopefully empty) + */ + +/* + * E D I T H I S T O R Y + * + * 17may86 Dean Elsner. Bug if line ends immediately after opcode. + * 30apr86 Dean Elsner. New vip_op() uses arg block so change call. + * 6jan86 Dean Elsner. Crock vip_begin() to call vip_op_defaults(). + * 2jan86 Dean Elsner. Invent synthetic opcodes. + * Widen vax_opcodeT to 32 bits. Use a bit for VIT_OPCODE_SYNTHETIC, + * which means this is not a real opcode, it is like a macro; it will + * be relax()ed into 1 or more instructions. + * Use another bit for VIT_OPCODE_SPECIAL if the op-code is not optimised + * like a regular branch instruction. Option added to vip_begin(): + * exclude synthetic opcodes. Invent synthetic_votstrs[]. + * 31dec85 Dean Elsner. Invent vit_opcode_nbytes. + * Also make vit_opcode into a char[]. We now have n-byte vax opcodes, + * so caller's don't have to know the difference between a 1-byte & a + * 2-byte op-code. Still need vax_opcodeT concept, so we know how + * big an object must be to hold an op.code. + * 30dec85 Dean Elsner. Widen typedef vax_opcodeT in "vax-inst.h" + * because vax opcodes may be 16 bits. Our crufty C compiler was + * happily initialising 8-bit vot_codes with 16-bit numbers! + * (Wouldn't the 'phone company like to compress data so easily!) + * 29dec85 Dean Elsner. New static table vax_operand_width_size[]. + * Invented so we know hw many bytes a "I^#42" needs in its immediate + * operand. Revised struct vop in "vax-inst.h": explicitly include + * byte length of each operand, and it's letter-code datum type. + * 17nov85 Dean Elsner. Name Change. + * Due to ar(1) truncating names, we learned the hard way that + * "vax-inst-parse.c" -> "vax-inst-parse." dropping the "o" off + * the archived object name. SO... we shortened the name of this + * source file, and changed the makefile. + */ + +/* #include <stdio.h> JF for one big happy file */ + +/* JF #include "vax-inst.h" /* define the tree we parse it into */ + + +static char *op_hash = NULL; /* handle of the OPCODE hash table */ + /* NULL means any use before vip_begin() */ + /* will crash */ + +/* + * In: 1 character, from "bdfghloqpw" being the data-type of an operand + * of a vax instruction. + * + * Out: the length of an operand of that type, in bytes. + * Special branch operands types "-?!" have length 0. + */ + +static const short int vax_operand_width_size[256] = +{ + +#define _ 0 + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16, /* ..b.d.fgh...l..o */ + _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, /* .q.....w........ */ + _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16, /* ..b.d.fgh...l..o */ + _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, /* .q.....w........ */ + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}; +#undef _ + +/* + * This perversion encodes all the vax opcodes as a bunch of strings. + * RMS says we should build our hash-table at run-time. Hmm. + * Please would someone arrange these in decreasing frequency of opcode? + * Because of the way hash_...() works, the most frequently used opcode + * should be textually first and so on. + * + * Input for this table was 'vax.opcodes', awk(1)ed by 'vax.opcodes.c.awk' . + * So change 'vax.opcodes', then re-generate this table. + */ + +#include "vax-opcode.h" + +/* + * This is a table of optional op-codes. All of them represent + * 'synthetic' instructions that seem popular. + * + * Here we make some pseudo op-codes. Every code has a bit set to say + * it is synthetic. This lets you catch them if you want to + * ban these opcodes. They are mnemonics for "elastic" instructions + * that are supposed to assemble into the fewest bytes needed to do a + * branch, or to do a conditional branch, or whatever. + * + * The opcode is in the usual place [low-order n*8 bits]. This means + * that if you mask off the bucky bits, the usual rules apply about + * how long the opcode is. + * + * All VAX branch displacements come at the end of the instruction. + * For simple branches (1-byte opcode + 1-byte displacement) the last + * operand is coded 'b?' where the "data type" '?' is a clue that we + * may reverse the sense of the branch (complement lowest order bit) + * and branch around a jump. This is by far the most common case. + * That is why the VIT_OPCODE_SYNTHETIC bit is set: it says this is + * a 0-byte op-code followed by 2 or more bytes of operand address. + * + * If the op-code has VIT_OPCODE_SPECIAL set, then we have a more unusual + * case. + * + * For JBSB & JBR the treatment is the similar, except (1) we have a 'bw' + * option before (2) we can directly JSB/JMP because there is no condition. + * These operands have 'b-' as their access/data type. + * + * That leaves a bunch of random opcodes: JACBx, JxOBxxx. In these + * cases, we do the same idea. JACBxxx are all marked with a 'b!' + * JAOBxxx & JSOBxxx are marked with a 'b:'. + * + */ +#if (VIT_OPCODE_SYNTHETIC != 0x80000000) +You have just broken the encoding below, which assumes the sign bit + means 'I am an imaginary instruction'. +#endif + +#if (VIT_OPCODE_SPECIAL != 0x40000000) + You have just broken the encoding below, which assumes the 0x40 M bit means + 'I am not to be "optimised" the way normal branches are'. +#endif + +static const struct vot + synthetic_votstrs[] = +{ + {"jbsb", + {"b-", 0xC0000010}}, /* BSD 4.2 */ + /* jsb used already */ + {"jbr", + {"b-", 0xC0000011}}, /* BSD 4.2 */ + {"jr", + {"b-", 0xC0000011}}, /* consistent */ + {"jneq", + {"b?", 0x80000012}}, + {"jnequ", + {"b?", 0x80000012}}, + {"jeql", + {"b?", 0x80000013}}, + {"jeqlu", + {"b?", 0x80000013}}, + {"jgtr", + {"b?", 0x80000014}}, + {"jleq", + {"b?", 0x80000015}}, + /* un-used opcodes here */ + {"jgeq", + {"b?", 0x80000018}}, + {"jlss", + {"b?", 0x80000019}}, + {"jgtru", + {"b?", 0x8000001a}}, + {"jlequ", + {"b?", 0x8000001b}}, + {"jvc", + {"b?", 0x8000001c}}, + {"jvs", + {"b?", 0x8000001d}}, + {"jgequ", + {"b?", 0x8000001e}}, + {"jcc", + {"b?", 0x8000001e}}, + {"jlssu", + {"b?", 0x8000001f}}, + {"jcs", + {"b?", 0x8000001f}}, + + {"jacbw", + {"rwrwmwb!", 0xC000003d}}, + {"jacbf", + {"rfrfmfb!", 0xC000004f}}, + {"jacbd", + {"rdrdmdb!", 0xC000006f}}, + {"jacbb", + {"rbrbmbb!", 0xC000009d}}, + {"jacbl", + {"rlrlmlb!", 0xC00000f1}}, + {"jacbg", + {"rgrgmgb!", 0xC0004ffd}}, + {"jacbh", + {"rhrhmhb!", 0xC0006ffd}}, + + {"jbs", + {"rlvbb?", 0x800000e0}}, + {"jbc", + {"rlvbb?", 0x800000e1}}, + {"jbss", + {"rlvbb?", 0x800000e2}}, + {"jbcs", + {"rlvbb?", 0x800000e3}}, + {"jbsc", + {"rlvbb?", 0x800000e4}}, + {"jbcc", + {"rlvbb?", 0x800000e5}}, + {"jbssi", + {"rlvbb?", 0x800000e6}}, + {"jbcci", + {"rlvbb?", 0x800000e7}}, + {"jlbs", + {"rlb?", 0x800000e8}}, /* JF changed from rlvbb? */ + {"jlbc", + {"rlb?", 0x800000e9}}, /* JF changed from rlvbb? */ + + {"jaoblss", + {"rlmlb:", 0xC00000f2}}, + {"jaobleq", + {"rlmlb:", 0xC00000f3}}, + {"jsobgeq", + {"mlb:", 0xC00000f4}}, /* JF was rlmlb: */ + {"jsobgtr", + {"mlb:", 0xC00000f5}}, /* JF was rlmlb: */ + +/* CASEx has no branch addresses in our conception of it. */ +/* You should use ".word ..." statements after the "case ...". */ + + {"", ""} /* empty is end sentinel */ + +}; /* synthetic_votstrs */ + +/* + * v i p _ b e g i n ( ) + * + * Call me once before you decode any lines. + * I decode votstrs into a hash table at op_hash (which I create). + * I return an error text: hopefully "". + * If you want, I will include the 'synthetic' jXXX instructions in the + * instruction table. + * You must nominate metacharacters for eg DEC's "#", "@", "^". + */ + +char * +vip_begin (synthetic_too, immediate, indirect, displen) + int synthetic_too; /* TRUE means include jXXX op-codes. */ + char *immediate, *indirect, *displen; +{ + register const struct vot *vP; /* scan votstrs */ + register char *retval; /* error text */ + + char *hash_insert (); /* */ + char *hash_new (); /* lies */ + + if ((op_hash = hash_new ())) + { + retval = ""; /* OK so far */ + for (vP = votstrs; *vP->vot_name && !*retval; vP++) + { + retval = hash_insert (op_hash, vP->vot_name, &vP->vot_detail); + } + if (synthetic_too) + { + for (vP = synthetic_votstrs; *vP->vot_name && !*retval; vP++) + { + retval = hash_insert (op_hash, vP->vot_name, &vP->vot_detail); + } + } + } + else + { + retval = "virtual memory exceeded"; + } +#ifndef CONST_TABLE + vip_op_defaults (immediate, indirect, displen); +#endif + + return (retval); +} + + +/* + * v i p _ e n d ( ) + * + * Call me once after you have decoded all lines. + * I do any cleaning-up needed. + * + * We don't have to do any cleanup ourselves: all of our operand + * symbol table is static, and free()ing it is naughty. + */ +vip_end () +{ +} + +/* + * v i p ( ) + * + * This converts a string into a vax instruction. + * The string must be a bare single instruction in dec-vax (with BSD4 frobs) + * format. + * It provides some error messages: at most one fatal error message (which + * stops the scan) and at most one warning message for each operand. + * The vax instruction is returned in exploded form, since we have no + * knowledge of how you parse (or evaluate) your expressions. + * We do however strip off and decode addressing modes and operation + * mnemonic. + * + * The exploded instruction is returned to a struct vit of your choice. + * #include "vax-inst.h" to know what a struct vit is. + * + * This function's value is a string. If it is not "" then an internal + * logic error was found: read this code to assign meaning to the string. + * No argument string should generate such an error string: + * it means a bug in our code, not in the user's text. + * + * You MUST have called vip_begin() once and vip_end() never before using + * this function. + */ + +char * /* "" or bug string */ +vip (vitP, instring) + struct vit *vitP; /* We build an exploded instruction here. */ + char *instring; /* Text of a vax instruction: we modify. */ +{ + register struct vot_wot *vwP; /* How to bit-encode this opcode. */ + register char *p; /* 1/skip whitespace.2/scan vot_how */ + register char *q; /* */ + register char *bug; /* "" or program logic error */ + register unsigned char count; /* counts number of operands seen */ + register struct vop *operandp;/* scan operands in struct vit */ + register char *alloperr; /* error over all operands */ + register char c; /* Remember char, (we clobber it */ + /* with '\0' temporarily). */ + register vax_opcodeT oc; /* Op-code of this instruction. */ + + struct vot_wot *hash_find (); + char *vip_op (); + + bug = ""; + if (*instring == ' ') + ++instring; /* Skip leading whitespace. */ + for (p = instring; *p && *p != ' '; p++) + ; /* MUST end in end-of-string or exactly 1 space. */ + /* Scanned up to end of operation-code. */ + /* Operation-code is ended with whitespace. */ + if (p - instring == 0) + { + vitP->vit_error = "No operator"; + count = 0; + bzero (vitP->vit_opcode, sizeof (vitP->vit_opcode)); + } + else + { + c = *p; + *p = '\0'; + /* + * Here with instring pointing to what better be an op-name, and p + * pointing to character just past that. + * We trust instring points to an op-name, with no whitespace. + */ + vwP = hash_find (op_hash, instring); + *p = c; /* Restore char after op-code. */ + if (vwP == 0) + { + vitP->vit_error = "Unknown operator"; + count = 0; + bzero (vitP->vit_opcode, sizeof (vitP->vit_opcode)); + } + else + { + /* + * We found a match! So lets pick up as many operands as the + * instruction wants, and even gripe if there are too many. + * We expect comma to seperate each operand. + * We let instring track the text, while p tracks a part of the + * struct vot. + */ + /* + * The lines below know about 2-byte opcodes starting FD,FE or FF. + * They also understand synthetic opcodes. Note: + * we return 32 bits of opcode, including bucky bits, BUT + * an opcode length is either 8 or 16 bits for vit_opcode_nbytes. + */ + oc = vwP->vot_code; /* The op-code. */ + vitP->vit_opcode_nbytes = (oc & 0xFF) >= 0xFD ? 2 : 1; + md_number_to_chars (vitP->vit_opcode, oc, 4); + count = 0; /* no operands seen yet */ + instring = p; /* point just past operation code */ + alloperr = ""; + for (p = vwP->vot_how, operandp = vitP->vit_operand; + !*alloperr && !*bug && *p; + operandp++, p += 2 + ) + { + /* + * Here to parse one operand. Leave instring pointing just + * past any one ',' that marks the end of this operand. + */ + if (!p[1]) + bug = "p"; /* ODD(!!) number of bytes in vot_how?? */ + else if (*instring) + { + for (q = instring; (c = *q) && c != ','; q++) + ; + /* + * Q points to ',' or '\0' that ends argument. C is that + * character. + */ + *q = 0; + operandp->vop_width = p[1]; + operandp->vop_nbytes = vax_operand_width_size[p[1]]; + operandp->vop_access = p[0]; + bug = vip_op (instring, operandp); + *q = c; /* Restore input text. */ + if (*(operandp->vop_error)) + alloperr = "Bad operand"; + instring = q + (c ? 1 : 0); /* next operand (if any) */ + count++; /* won another argument, may have an operr */ + } + else + alloperr = "Not enough operands"; + } + if (!*alloperr) + { + if (*instring == ' ') + instring++; /* Skip whitespace. */ + if (*instring) + alloperr = "Too many operands"; + } + vitP->vit_error = alloperr; + } + } + vitP->vit_operands = count; + return (bug); +} + +#ifdef test + +/* + * Test program for above. + */ + +struct vit myvit; /* build an exploded vax instruction here */ +char answer[100]; /* human types a line of vax assembler here */ +char *mybug; /* "" or an internal logic diagnostic */ +int mycount; /* number of operands */ +struct vop *myvop; /* scan operands from myvit */ +int mysynth; /* TRUE means want synthetic opcodes. */ +char my_immediate[200]; +char my_indirect[200]; +char my_displen[200]; + +char *vip (); + +main () +{ + char *p; + char *vip_begin (); + + printf ("0 means no synthetic instructions. "); + printf ("Value for vip_begin? "); + gets (answer); + sscanf (answer, "%d", &mysynth); + printf ("Synthetic opcodes %s be included.\n", mysynth ? "will" : "will not"); + printf ("enter immediate symbols eg enter # "); + gets (my_immediate); + printf ("enter indirect symbols eg enter @ "); + gets (my_indirect); + printf ("enter displen symbols eg enter ^ "); + gets (my_displen); + if (*(p = vip_begin (mysynth, my_immediate, my_indirect, my_displen))) + { + error ("vip_begin=%s", p); + } + printf ("An empty input line will quit you from the vax instruction parser\n"); + for (;;) + { + printf ("vax instruction: "); + fflush (stdout); + gets (answer); + if (!*answer) + { + break; /* out of for each input text loop */ + } + mybug = vip (&myvit, answer); + if (*mybug) + { + printf ("BUG:\"%s\"\n", mybug); + } + if (*myvit.vit_error) + { + printf ("ERR:\"%s\"\n", myvit.vit_error); + } + printf ("opcode="); + for (mycount = myvit.vit_opcode_nbytes, p = myvit.vit_opcode; + mycount; + mycount--, p++ + ) + { + printf ("%02x ", *p & 0xFF); + } + printf (" operand count=%d.\n", mycount = myvit.vit_operands); + for (myvop = myvit.vit_operand; mycount; mycount--, myvop++) + { + printf ("mode=%xx reg=%xx ndx=%xx len='%c'=%c%c%d. expr=\"", + myvop->vop_mode, myvop->vop_reg, myvop->vop_ndx, + myvop->vop_short, myvop->vop_access, myvop->vop_width, + myvop->vop_nbytes); + for (p = myvop->vop_expr_begin; p <= myvop->vop_expr_end; p++) + { + putchar (*p); + } + printf ("\"\n"); + if (*myvop->vop_error) + { + printf (" err:\"%s\"\n", myvop->vop_error); + } + if (*myvop->vop_warn) + { + printf (" wrn:\"%s\"\n", myvop->vop_warn); + } + } + } + vip_end (); + exit (); +} + +#endif /* #ifdef test */ + +/* end of vax_ins_parse.c */ + + /* JF this used to be a separate file also */ +/* vax_reg_parse.c - convert a VAX register name to a number */ + +/* Copyright (C) 1987 Free Software Foundation, Inc. A part of GNU. */ + +/* + * v a x _ r e g _ p a r s e ( ) + * + * Take 3 char.s, the last of which may be `\0` (non-existent) + * and return the VAX register number that they represent. + * + * Return -1 if they don't form a register name. Good names return + * a number from 0:15 inclusive. + * + * Case is not important in a name. + * + * Register names understood are: + * + * R0 + * R1 + * R2 + * R3 + * R4 + * R5 + * R6 + * R7 + * R8 + * R9 + * R10 + * R11 + * R12 AP + * R13 FP + * R14 SP + * R15 PC + * + */ + +#include <ctype.h> +#define AP (12) +#define FP (13) +#define SP (14) +#define PC (15) + +int /* return -1 or 0:15 */ +vax_reg_parse (c1, c2, c3) /* 3 chars of register name */ + char c1, c2, c3; /* c3 == 0 if 2-character reg name */ +{ + register int retval; /* return -1:15 */ + + retval = -1; + + if (isupper (c1)) + c1 = tolower (c1); + if (isupper (c2)) + c2 = tolower (c2); + if (isdigit (c2) && c1 == 'r') + { + retval = c2 - '0'; + if (isdigit (c3)) + { + retval = retval * 10 + c3 - '0'; + retval = (retval > 15) ? -1 : retval; + /* clamp the register value to 1 hex digit */ + } + else if (c3) + retval = -1; /* c3 must be '\0' or a digit */ + } + else if (c3) /* There are no three letter regs */ + retval = -1; + else if (c2 == 'p') + { + switch (c1) + { + case 's': + retval = SP; + break; + case 'f': + retval = FP; + break; + case 'a': + retval = AP; + break; + default: + retval = -1; + } + } + else if (c1 == 'p' && c2 == 'c') + retval = PC; + else + retval = -1; + return (retval); +} + +/* end: vax_reg_parse.c */ + + /* JF this was another separate prog */ +/* vip_op.c - parse 1 VAX instr's operand.(C)1986 Free Software Foundation. */ + +/* JF #include <ctype.h> */ +/* #include "vax_inst.h" */ + +/* + * v i p _ o p ( ) + * + * Parse a vax operand in DEC assembler notation. + * For speed, expect a string of whitespace to be reduced to a single ' '. + * This is the case for GNU AS, and is easy for other DEC-compatible + * assemblers. + * + * Knowledge about DEC VAX assembler operand notation lives here. + * This doesn't even know what a register name is, except it believes + * all register names are 2 or 3 characters, and lets vax_reg_parse() say + * what number each name represents. + * It does, however, know that PC, SP etc are special registers so it can + * detect addressing modes that are silly for those registers. + * + * Where possible, it delivers 1 fatal or 1 warning message if the operand + * is suspect. Exactly what we test for is still evolving. + */ + +/* + * B u g s + * + * Arg block. + * + * There were a number of 'mismatched argument type' bugs to vip_op. + * The most general solution is to typedef each (of many) arguments. + * We used instead a typedef'd argument block. This is less modular + * than using seperate return pointers for each result, but runs faster + * on most engines, and seems to keep programmers happy. It will have + * to be done properly if we ever want to use vip_op as a general-purpose + * module (it was designed to be). + * + * G^ + * + * Doesn't support DEC "G^" format operands. These always take 5 bytes + * to express, and code as modes 8F or 9F. Reason: "G^" deprives you of + * optimising to (say) a "B^" if you are lucky in the way you link. + * When someone builds a linker smart enough to convert "G^" to "B^", "W^" + * whenever possible, then we should implement it. + * If there is some other use for "G^", feel free to code it in! + * + * + * speed + * + * If I nested if()s more, I could avoid testing (*err) which would save + * time, space and page faults. I didn't nest all those if()s for clarity + * and because I think the mode testing can be re-arranged 1st to test the + * commoner constructs 1st. Does anybody have statistics on this? + * + * + * + * error messages + * + * In future, we should be able to 'compose' error messages in a scratch area + * and give the user MUCH more informative error messages. Although this takes + * a little more code at run-time, it will make this module much more self- + * documenting. As an example of what sucks now: most error messages have + * hardwired into them the DEC VAX metacharacters "#^@" which are nothing like + * the Un*x characters "$`*", that most users will expect from this AS. + */ + +/* + * The input is a string, ending with '\0'. + * + * We also require a 'hint' of what kind of operand is expected: so + * we can remind caller not to write into literals for instance. + * + * The output is a skeletal instruction. + * + * The algorithm has two parts. + * 1. extract the syntactic features (parse off all the @^#-()+[] mode crud); + * 2. express the @^#-()+[] as some parameters suited to further analysis. + * + * 2nd step is where we detect the googles of possible invalid combinations + * a human (or compiler) might write. Note that if we do a half-way + * decent assembler, we don't know how long to make (eg) displacement + * fields when we first meet them (because they may not have defined values). + * So we must wait until we know how many bits are needed for each address, + * then we can know both length and opcodes of instructions. + * For reason(s) above, we will pass to our caller a 'broken' instruction + * of these major components, from which our caller can generate instructions: + * - displacement length I^ S^ L^ B^ W^ unspecified + * - mode (many) + * - register R0-R15 or absent + * - index register R0-R15 or absent + * - expression text what we don't parse + * - error text(s) why we couldn't understand the operand + */ + +/* + * To decode output of this, test errtxt. If errtxt[0] == '\0', then + * we had no errors that prevented parsing. Also, if we ever report + * an internal bug, errtxt[0] is set non-zero. So one test tells you + * if the other outputs are to be taken seriously. + */ + + + /* vax registers we need to know */ +/* JF #define SP (14) +/* JF for one big happy file #define PC (15) */ + + /* useful ideas */ +/* #define TRUE (1) */ +/* #define FALSE (0) */ + +/* + * Because this module is useful for both VMS and UN*X style assemblers + * and because of the variety of UN*X assemblers we must recognise + * the different conventions for assembler operand notation. For example + * VMS says "#42" for immediate mode, while most UN*X say "$42". + * We permit arbitrary sets of (single) characters to represent the + * 3 concepts that DEC writes '#', '@', '^'. + */ + + /* character tests */ +#define VIP_IMMEDIATE 01 /* Character is like DEC # */ +#define VIP_INDIRECT 02 /* Char is like DEC @ */ +#define VIP_DISPLEN 04 /* Char is like DEC ^ */ + +#define IMMEDIATEP(c) (vip_metacharacters [(c)&0xff]&VIP_IMMEDIATE) +#define INDIRECTP(c) (vip_metacharacters [(c)&0xff]&VIP_INDIRECT) +#define DISPLENP(c) (vip_metacharacters [(c)&0xff]&VIP_DISPLEN) + +/* We assume 8 bits per byte. Use vip_op_defaults() to set these up BEFORE we + * are ever called. + */ + +#if defined(CONST_TABLE) +#define _ 0, +#define I VIP_IMMEDIATE, +#define S VIP_INDIRECT, +#define D VIP_DISPLEN, +static const char +vip_metacharacters[256] = { +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O*/ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^ ^_*/ +_ _ _ _ I _ _ _ _ _ S _ _ _ _ _/*sp ! " # $ % & ' ( ) * + , - . /*/ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*0 1 2 3 4 5 6 7 8 9 : ; < = > ?*/ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*@ A B C D E F G H I J K L M N O*/ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*P Q R S T U V W X Y Z [ \ ] ^ _*/ +D _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*` a b c d e f g h i j k l m n o*/ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*p q r s t u v w x y z { | } ~ ^?*/ + +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +}; +#undef _ +#undef I +#undef S +#undef D +#else +static char vip_metacharacters[256]; + +/* Macro is faster under GCC; The constant table is faster yet, but only works with ASCII */ +#if 0 +static +#ifdef __GNUC__ +inline +#endif +static void +vip_op_1(bit,syms) +int bit; +char *syms; +{ + unsigned char t; + + while(t= *syms++) + vip_metacharacters[t]|=bit; +} +#else +#define vip_op_1(bit,syms) { \ + unsigned char t; \ + char *table=vip_metacharacters; \ + while(t= *syms++) \ + table[t]|=bit; \ + } +#endif + +vip_op_defaults (immediate, indirect, displen) /* can be called any time */ + char *immediate, /* Strings of characters for each job. */ + *indirect, *displen; /* more arguments may appear in future! */ +{ + vip_op_1 (VIP_IMMEDIATE, immediate); + vip_op_1 (VIP_INDIRECT, indirect); + vip_op_1 (VIP_DISPLEN, displen); +} +#endif + + +/* + * Dec defines the semantics of address modes (and values) + * by a two-letter code, explained here. + * + * letter 1: access type + * + * a address calculation - no data access, registers forbidden + * b branch displacement + * m read - let go of bus - write back "modify" + * r read + * v bit field address: like 'a' but registers are OK + * w write + * space no operator (eg ".long foo") [our convention] + * + * letter 2: data type (i.e. width, alignment) + * + * b byte + * d double precision floating point (D format) + * f single precision floating point (F format) + * g G format floating + * h H format floating + * l longword + * o octaword + * q quadword + * w word + * ? simple synthetic branch operand + * - unconditional synthetic JSB/JSR operand + * ! complex synthetic branch operand + * + * The '-?!' letter 2's are not for external consumption. They are used + * for various assemblers. Generally, all unknown widths are assumed 0. + * We don't limit your choice of width character. + * + * DEC operands are hard work to parse. For example, '@' as the first + * character means indirect (deferred) mode but elswhere it is a shift + * operator. + * The long-winded explanation of how this is supposed to work is + * cancelled. Read a DEC vax manual. + * We try hard not to parse anything that MIGHT be part of the expression + * buried in that syntax. For example if we see @...(Rn) we don't check + * for '-' before the '(' because mode @-(Rn) does not exist. + * + * After parsing we have: + * + * at TRUE if leading '@' (or Un*x '*') + * len takes one value from " bilsw". eg B^ -> 'b'. + * hash TRUE if leading '#' (or Un*x '$') + * expr_begin, expr_end the expression we did not parse + * even though we don't interpret it, we make use + * of its presence or absence. + * sign -1: -(Rn) 0: absent +1: (Rn)+ + * paren TRUE if () are around register + * reg major register number 0:15 -1 means absent + * ndx index register number 0:15 -1 means absent + * + * Again, I dare not explain it: just trace ALL the code! + */ + +char * /* (code here) bug message, "" = OK */ + /* our code bug, NOT bad assembly language */ +vip_op (optext, vopP) + char *optext; /* user's input string e.g.: */ + /* "@B^foo@bar(AP)[FP]:" */ + struct vop *vopP; /* In: vop_access, vop_width. */ + /* Out: _ndx, _reg, _mode, _short, _warn, */ + /* _error _expr_begin, _expr_end, _nbytes. */ + /* vop_nbytes : number of bytes in a datum. */ +{ + char *p; /* track operand text forward */ + char *q; /* track operand text backward */ + int at; /* TRUE if leading '@' ('*') seen */ + char len; /* one of " bilsw" */ + int hash; /* TRUE if leading '#' ('$') seen */ + int sign; /* -1, 0 or +1 */ + int paren; /* TRUE if () surround register */ + int reg; /* register number, -1:absent */ + int ndx; /* index register number -1:absent */ + char *bug; /* report any logic error in here, ""==OK */ + char *err; /* report illegal operand, ""==OK */ + /* " " is a FAKE error: means we won */ + /* ANY err that begins with ' ' is a fake. */ + /* " " is converted to "" before return */ + char *wrn; /* warn about weird modes pf address */ + char *oldq; /* preserve q in case we backup */ + int mode; /* build up 4-bit operand mode here */ + /* note: index mode is in ndx, this is */ + /* the major mode of operand address */ +/* + * Notice how we move wrong-arg-type bugs INSIDE this module: if we + * get the types wrong below, we lose at compile time rather than at + * lint or run time. + */ + char access; /* vop_access. */ + char width; /* vop_width. */ + + int vax_reg_parse (); /* returns 0:15 or -1 if not a register */ + + access = vopP->vop_access; + width = vopP->vop_width; + bug = /* none of our code bugs (yet) */ + err = /* no user text errors */ + wrn = ""; /* no warnings even */ + + p = optext; + + if (*p == ' ') /* Expect all whitespace reduced to ' '. */ + p++; /* skip over whitespace */ + + if (at = INDIRECTP (*p)) + { /* TRUE if *p=='@'(or '*' for Un*x) */ + p++; /* at is determined */ + if (*p == ' ') /* Expect all whitespace reduced to ' '. */ + p++; /* skip over whitespace */ + } + + /* + * This code is subtle. It tries to detect all legal (letter)'^' + * but it doesn't waste time explicitly testing for premature '\0' because + * this case is rejected as a mismatch against either (letter) or '^'. + */ + { + register char c; + + c = *p; + if (isupper (c)) + c = tolower (c); + if (DISPLENP (p[1]) && index ("bilws", len = c)) + p += 2; /* skip (letter) '^' */ + else /* no (letter) '^' seen */ + len = ' '; /* len is determined */ + } + + if (*p == ' ') /* Expect all whitespace reduced to ' '. */ + p++; /* skip over whitespace */ + + if (hash = IMMEDIATEP (*p)) /* TRUE if *p=='#' ('$' for Un*x) */ + p++; /* hash is determined */ + + /* + * p points to what may be the beginning of an expression. + * We have peeled off the front all that is peelable. + * We know at, len, hash. + * + * Lets point q at the end of the text and parse that (backwards). + */ + + for (q = p; *q; q++) + ; + q--; /* now q points at last char of text */ + + if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */ + q--; + /* reverse over whitespace, but don't */ + /* run back over *p */ + + /* + * As a matter of policy here, we look for [Rn], although both Rn and S^# + * forbid [Rn]. This is because it is easy, and because only a sick + * cyborg would have [...] trailing an expression in a VAX-like assembler. + * A meticulous parser would first check for Rn followed by '(' or '[' + * and not parse a trailing ']' if it found another. We just ban expressions + * ending in ']'. + */ + if (*q == ']') + { + while (q >= p && *q != '[') + q--; + /* either q<p or we got matching '[' */ + if (q < p) + err = "no '[' to match ']'"; + else + { + /* + * Confusers like "[]" will eventually lose with a bad register + * name error. So again we don't need to check for early '\0'. + */ + if (q[3] == ']') + ndx = vax_reg_parse (q[1], q[2], 0); + else if (q[4] == ']') + ndx = vax_reg_parse (q[1], q[2], q[3]); + else + ndx = -1; + /* + * Since we saw a ']' we will demand a register name in the []. + * If luser hasn't given us one: be rude. + */ + if (ndx < 0) + err = "bad register in []"; + else if (ndx == PC) + err = "[PC] index banned"; + else + q--; /* point q just before "[...]" */ + } + } + else + ndx = -1; /* no ']', so no iNDeX register */ + + /* + * If err = "..." then we lost: run away. + * Otherwise ndx == -1 if there was no "[...]". + * Otherwise, ndx is index register number, and q points before "[...]". + */ + + if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */ + q--; + /* reverse over whitespace, but don't */ + /* run back over *p */ + if (!*err) + { + sign = 0; /* no ()+ or -() seen yet */ + + if (q > p + 3 && *q == '+' && q[-1] == ')') + { + sign = 1; /* we saw a ")+" */ + q--; /* q points to ')' */ + } + + if (*q == ')' && q > p + 2) + { + paren = TRUE; /* assume we have "(...)" */ + while (q >= p && *q != '(') + q--; + /* either q<p or we got matching '(' */ + if (q < p) + err = "no '(' to match ')'"; + else + { + /* + * Confusers like "()" will eventually lose with a bad register + * name error. So again we don't need to check for early '\0'. + */ + if (q[3] == ')') + reg = vax_reg_parse (q[1], q[2], 0); + else if (q[4] == ')') + reg = vax_reg_parse (q[1], q[2], q[3]); + else + reg = -1; + /* + * Since we saw a ')' we will demand a register name in the ')'. + * This is nasty: why can't our hypothetical assembler permit + * parenthesised expressions? BECAUSE I AM LAZY! That is why. + * Abuse luser if we didn't spy a register name. + */ + if (reg < 0) + { + /* JF allow parenthasized expressions. I hope this works */ + paren = FALSE; + while (*q != ')') + q++; + /* err = "unknown register in ()"; */ + } + else + q--; /* point just before '(' of "(...)" */ + /* + * If err == "..." then we lost. Run away. + * Otherwise if reg >= 0 then we saw (Rn). + */ + } + /* + * If err == "..." then we lost. + * Otherwise paren==TRUE and reg = register in "()". + */ + } + else + paren = FALSE; + /* + * If err == "..." then we lost. + * Otherwise, q points just before "(Rn)", if any. + * If there was a "(...)" then paren==TRUE, and reg is the register. + */ + + /* + * We should only seek '-' of "-(...)" if: + * we saw "(...)" paren == TRUE + * we have no errors so far ! *err + * we did not see '+' of "(...)+" sign < 1 + * We don't check len. We want a specific error message later if + * user tries "x^...-(Rn)". This is a feature not a bug. + */ + if (!*err) + { + if (paren && sign < 1)/* !sign is adequate test */ + { + if (*q == '-') + { + sign = -1; + q--; + } + } + /* + * We have back-tracked over most + * of the crud at the end of an operand. + * Unless err, we know: sign, paren. If paren, we know reg. + * The last case is of an expression "Rn". + * This is worth hunting for if !err, !paren. + * We wouldn't be here if err. + * We remember to save q, in case we didn't want "Rn" anyway. + */ + if (!paren) + { + if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */ + q--; + /* reverse over whitespace, but don't */ + /* run back over *p */ + if (q > p && q < p + 3) /* room for Rn or Rnn exactly? */ + reg = vax_reg_parse (p[0], p[1], q < p + 2 ? 0 : p[2]); + else + reg = -1; /* always comes here if no register at all */ + /* + * Here with a definitive reg value. + */ + if (reg >= 0) + { + oldq = q; + q = p - 1; + } + } + } + } + /* + * have reg. -1:absent; else 0:15 + */ + + /* + * We have: err, at, len, hash, ndx, sign, paren, reg. + * Also, any remaining expression is from *p through *q inclusive. + * Should there be no expression, q==p-1. So expression length = q-p+1. + * This completes the first part: parsing the operand text. + */ + + /* + * We now want to boil the data down, checking consistency on the way. + * We want: len, mode, reg, ndx, err, p, q, wrn, bug. + * We will deliver a 4-bit reg, and a 4-bit mode. + */ + + /* + * Case of branch operand. Different. No L^B^W^I^S^ allowed for instance. + * + * in: at ? + * len ? + * hash ? + * p:q ? + * sign ? + * paren ? + * reg ? + * ndx ? + * + * out: mode 0 + * reg -1 + * len ' ' + * p:q whatever was input + * ndx -1 + * err " " or error message, and other outputs trashed + */ + /* branch operands have restricted forms */ + if (!*err && access == 'b') + { + if (at || hash || sign || paren || ndx >= 0 || reg >= 0 || len != ' ') + err = "invalid branch operand"; + else + err = " "; + } + +/* Since nobody seems to use it: comment this 'feature'(?) out for now. */ +#ifdef NEVER + /* + * Case of stand-alone operand. e.g. ".long foo" + * + * in: at ? + * len ? + * hash ? + * p:q ? + * sign ? + * paren ? + * reg ? + * ndx ? + * + * out: mode 0 + * reg -1 + * len ' ' + * p:q whatever was input + * ndx -1 + * err " " or error message, and other outputs trashed + */ + if (!*err) + { + if (access == ' ') + { /* addresses have restricted forms */ + if (at) + err = "address prohibits @"; + else + { + if (hash) + err = "address prohibits #"; + else + { + if (sign) + { + if (sign < 0) + err = "address prohibits -()"; + else + err = "address prohibits ()+"; + } + else + { + if (paren) + err = "address prohibits ()"; + else + { + if (ndx >= 0) + err = "address prohibits []"; + else + { + if (reg >= 0) + err = "address prohibits register"; + else + { + if (len != ' ') + err = "address prohibits displacement length specifier"; + else + { + err = " "; /* succeed */ + mode = 0; + } + } + } + } + } + } + } + } + } +#endif /*#Ifdef NEVER*/ + + /* + * Case of S^#. + * + * in: at FALSE + * len 's' definition + * hash TRUE demand + * p:q demand not empty + * sign 0 by paren==FALSE + * paren FALSE by "()" scan logic because "S^" seen + * reg -1 or nn by mistake + * ndx -1 + * + * out: mode 0 + * reg -1 + * len 's' + * exp + * ndx -1 + */ + if (!*err && len == 's') + { + if (!hash || paren || at || ndx >= 0) + err = "invalid operand of S^#"; + else + { + if (reg >= 0) + { + /* + * SHIT! we saw S^#Rnn ! put the Rnn back in + * expression. KLUDGE! Use oldq so we don't + * need to know exact length of reg name. + */ + q = oldq; + reg = 0; + } + /* + * We have all the expression we will ever get. + */ + if (p > q) + err = "S^# needs expression"; + else if (access == 'r') + { + err = " "; /* WIN! */ + mode = 0; + } + else + err = "S^# may only read-access"; + } + } + + /* + * Case of -(Rn), which is weird case. + * + * in: at FALSE + * len ' + * hash FALSE + * p:q q<p + * sign -1 by definition + * paren TRUE by definition + * reg present by definition + * ndx optional + * + * out: mode 7 + * reg present + * len ' ' + * exp "" enforce empty expression + * ndx optional warn if same as reg + */ + if (!*err && sign < 0) + { + if (len != ' ' || hash || at || p <= q) + err = "invalid operand of -()"; + else + { + err = " "; /* win */ + mode = 7; + if (reg == PC) + wrn = "-(PC) unpredictable"; + else if (reg == ndx) + wrn = "[]index same as -()register: unpredictable"; + } + } + + /* + * We convert "(Rn)" to "@Rn" for our convenience. + * (I hope this is convenient: has someone got a better way to parse this?) + * A side-effect of this is that "@Rn" is a valid operand. + */ + if (paren && !sign && !hash && !at && len == ' ' && p > q) + { + at = TRUE; + paren = FALSE; + } + + /* + * Case of (Rn)+, which is slightly different. + * + * in: at + * len ' ' + * hash FALSE + * p:q q<p + * sign +1 by definition + * paren TRUE by definition + * reg present by definition + * ndx optional + * + * out: mode 8+@ + * reg present + * len ' ' + * exp "" enforce empty expression + * ndx optional warn if same as reg + */ + if (!*err && sign > 0) + { + if (len != ' ' || hash || p <= q) + err = "invalid operand of ()+"; + else + { + err = " "; /* win */ + mode = 8 + (at ? 1 : 0); + if (reg == PC) + wrn = "(PC)+ unpredictable"; + else if (reg == ndx) + wrn = "[]index same as ()+register: unpredictable"; + } + } + + /* + * Case of #, without S^. + * + * in: at + * len ' ' or 'i' + * hash TRUE by definition + * p:q + * sign 0 + * paren FALSE + * reg absent + * ndx optional + * + * out: mode 8+@ + * reg PC + * len ' ' or 'i' + * exp + * ndx optional + */ + if (!*err && hash) + { + if (len != 'i' && len != ' ') + err = "# conflicts length"; + else if (paren) + err = "# bars register"; + else + { + if (reg >= 0) + { + /* + * SHIT! we saw #Rnn! Put the Rnn back into the expression. + * By using oldq, we don't need to know how long Rnn was. + * KLUDGE! + */ + q = oldq; + reg = -1; /* no register any more */ + } + err = " "; /* win */ + + /* JF a bugfix, I think! */ + if(at && access=='a') + vopP->vop_nbytes=4; + + mode = (at ? 9 : 8); + reg = PC; + if ((access == 'm' || access == 'w') && !at) + wrn = "writing or modifying # is unpredictable"; + } + } + /* + * If !*err, then sign == 0 + * hash == FALSE + */ + + /* + * Case of Rn. We seperate this one because it has a few special + * errors the remaining modes lack. + * + * in: at optional + * len ' ' + * hash FALSE by program logic + * p:q empty + * sign 0 by program logic + * paren FALSE by definition + * reg present by definition + * ndx optional + * + * out: mode 5+@ + * reg present + * len ' ' enforce no length + * exp "" enforce empty expression + * ndx optional warn if same as reg + */ + if (!*err && !paren && reg >= 0) + { + if (len != ' ') + err = "length not needed"; + else if (at) + { + err = " "; /* win */ + mode = 6; /* @Rn */ + } + else if (ndx >= 0) + err = "can't []index a register, because it has no address"; + else if (access == 'a') + err = "a register has no address"; + else + { + /* + * Idea here is to detect from length of datum + * and from register number if we will touch PC. + * Warn if we do. + * vop_nbytes is number of bytes in operand. + * Compute highest byte affected, compare to PC0. + */ + if ((vopP->vop_nbytes + reg * 4) > 60) + wrn = "PC part of operand unpredictable"; + err = " "; /* win */ + mode = 5; /* Rn */ + } + } + /* + * If !*err, sign == 0 + * hash == FALSE + * paren == TRUE OR reg==-1 + */ + + /* + * Rest of cases fit into one bunch. + * + * in: at optional + * len ' ' or 'b' or 'w' or 'l' + * hash FALSE by program logic + * p:q expected (empty is not an error) + * sign 0 by program logic + * paren optional + * reg optional + * ndx optional + * + * out: mode 10 + @ + len + * reg optional + * len ' ' or 'b' or 'w' or 'l' + * exp maybe empty + * ndx optional warn if same as reg + */ + if (!*err) + { + err = " "; /* win (always) */ + mode = 10 + (at ? 1 : 0); + switch (len) + { + case 'l': + mode += 2; + case 'w': + mode += 2; + case ' ': /* assumed B^ until our caller changes it */ + case 'b': + break; + } + } + + /* + * here with completely specified mode + * len + * reg + * expression p,q + * ndx + */ + + if (*err == ' ') + err = ""; /* " " is no longer an error */ + + vopP->vop_mode = mode; + vopP->vop_reg = reg; + vopP->vop_short = len; + vopP->vop_expr_begin = p; + vopP->vop_expr_end = q; + vopP->vop_ndx = ndx; + vopP->vop_error = err; + vopP->vop_warn = wrn; + return (bug); + +} /* vip_op() */ + +/* + +Summary of vip_op outputs. + + mode reg len ndx +(Rn) => @Rn +{@}Rn 5+@ n ' ' optional +branch operand 0 -1 ' ' -1 +S^#foo 0 -1 's' -1 +-(Rn) 7 n ' ' optional +{@}(Rn)+ 8+@ n ' ' optional +{@}#foo, no S^ 8+@ PC " i" optional +{@}{q^}{(Rn)} 10+@+q option " bwl" optional + +*/ + +#ifdef TEST /* #Define to use this testbed. */ + +/* + * Follows a test program for this function. + * We declare arrays non-local in case some of our tiny-minded machines + * default to small stacks. Also, helps with some debuggers. + */ + +#include <stdio.h> + +char answer[100]; /* human types into here */ +char *p; /* */ +char *myerr; +char *mywrn; +char *mybug; +char myaccess; +char mywidth; +char mymode; +char myreg; +char mylen; +char *myleft; +char *myright; +char myndx; +int my_operand_length; +char my_immediate[200]; +char my_indirect[200]; +char my_displen[200]; + +main () +{ + char *vip_op (); /* make cc happy */ + + printf ("enter immediate symbols eg enter # "); + gets (my_immediate); + printf ("enter indirect symbols eg enter @ "); + gets (my_indirect); + printf ("enter displen symbols eg enter ^ "); + gets (my_displen); + vip_op_defaults (my_immediate, my_indirect, my_displen); + for (;;) + { + printf ("access,width (eg 'ab' or 'wh') [empty line to quit] : "); + fflush (stdout); + gets (answer); + if (!answer[0]) + exit (0); + myaccess = answer[0]; + mywidth = answer[1]; + switch (mywidth) + { + case 'b': + my_operand_length = 1; + break; + case 'd': + my_operand_length = 8; + break; + case 'f': + my_operand_length = 4; + break; + case 'g': + my_operand_length = 16; + break; + case 'h': + my_operand_length = 32; + break; + case 'l': + my_operand_length = 4; + break; + case 'o': + my_operand_length = 16; + break; + case 'q': + my_operand_length = 8; + break; + case 'w': + my_operand_length = 2; + break; + case '!': + case '?': + case '-': + my_operand_length = 0; + break; + + default: + my_operand_length = 2; + printf ("I dn't understand access width %c\n", mywidth); + break; + } + printf ("VAX assembler instruction operand: "); + fflush (stdout); + gets (answer); + mybug = vip_op (answer, myaccess, mywidth, my_operand_length, + &mymode, &myreg, &mylen, &myleft, &myright, &myndx, + &myerr, &mywrn); + if (*myerr) + { + printf ("error: \"%s\"\n", myerr); + if (*mybug) + printf (" bug: \"%s\"\n", mybug); + } + else + { + if (*mywrn) + printf ("warning: \"%s\"\n", mywrn); + mumble ("mode", mymode); + mumble ("register", myreg); + mumble ("index", myndx); + printf ("width:'%c' ", mylen); + printf ("expression: \""); + while (myleft <= myright) + putchar (*myleft++); + printf ("\"\n"); + } + } +} + +mumble (text, value) + char *text; + int value; +{ + printf ("%s:", text); + if (value >= 0) + printf ("%xx", value); + else + printf ("ABSENT"); + printf (" "); +} + +#endif /* ifdef TEST */ + +/* end: vip_op.c */ + +/* end: vax.c */ + +/* JF: new routines */ + +const int md_short_jump_size = 3; + +const int md_long_jump_size = 6; + +void +md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + long from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + long offset; + + offset = to_addr - (from_addr + 1); + *ptr++ = 0x31; + md_number_to_chars (ptr, offset, 2); +} + +void +md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + long from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + long offset; + + offset = to_addr - to_symbol->sy_value; + *ptr++ = 0x17; + *ptr++ = 0x9F; + md_number_to_chars (ptr, offset, 4); + fix_new (frag, ptr - frag->fr_literal, 4, to_symbol, (symbolS *) 0, (long int) 0, 0); +} + +int +md_parse_option (argP, cntP, vecP) + char **argP; + int *cntP; + char ***vecP; +{ + char *temp_name; /* name for -t or -d options */ + char opt; + + switch (**argP) + { + case 'J': + /* as_warn ("I can do better than -J!"); */ + break; + + case 'S': + as_warn ("SYMBOL TABLE not implemented"); + break; /* SYMBOL TABLE not implemented */ + + case 'T': + as_warn ("TOKEN TRACE not implemented"); + break; /* TOKEN TRACE not implemented */ + + case 'd': + case 't': + opt= **argP; + if (**argP) + { /* Rest of argument is filename. */ + temp_name = *argP; + while (**argP) + (*argP)++; + } + else if (*cntP) + { + while (**argP) + (*argP)++; + --(*cntP); + temp_name = *++(*vecP); + **vecP = NULL; /* Remember this is not a file-name. */ + } + else + { + as_warn ("I expected a filename after -%c.",opt); + temp_name = "{absent}"; + } + + if(opt=='d') + as_warn ("Displacement length %s ignored!", temp_name); + else + as_warn ("I don't need or use temp. file \"%s\".", temp_name); + break; + + case 'V': + as_warn ("I don't use an interpass file! -V ignored"); + break; + +#ifdef VMS + case '+': /* For g++ */ + break; + + case 'h': /* No hashing of mixed-case names */ + break; + + case 'H': /* Show new symbol after hash truncation */ + break; +#endif + + default: + return 0; + + } + return 1; +} |
