From 4d5f9b2a9c969142fe6a1ddec2d7a2886c023c69 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 23 Mar 2005 11:18:14 +0000 Subject: [PATCH] Convert to ISO C90 formatting --- gas/ChangeLog | 7 + gas/config/atof-vax.c | 348 +++--- gas/config/tc-pdp11.c | 798 +++++-------- gas/config/tc-tic30.c | 2653 ++++++++++++++++++++++------------------- gas/config/tc-tic30.h | 22 +- 5 files changed, 1837 insertions(+), 1991 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index ec121e1d8d1..ad73b79f0eb 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2005-03-23 Nick Clifton + + * config/tc-tic30.c: Convert to ISO C90 formatting. + * config/tc-tic30.h: Convert to ISO C90 formatting. + * config/tc-pdp11.c: Convert to ISO C90 formatting. + * config/atof-vax.c: Convert to ISO C90 formatting. + 2005-03-21 Maciej W. Rozycki * config/tc-mips.c (mips_frob_file): Sort BFD_RELOC_MIPS16_LO16 diff --git a/gas/config/atof-vax.c b/gas/config/atof-vax.c index 7c9f04e7fd1..b94e5609f91 100644 --- a/gas/config/atof-vax.c +++ b/gas/config/atof-vax.c @@ -1,5 +1,5 @@ /* atof_vax.c - turn a Flonum into a VAX floating point number - Copyright 1987, 1992, 1993, 1995, 1997, 1999, 2000 + Copyright 1987, 1992, 1993, 1995, 1997, 1999, 2000, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -21,37 +21,28 @@ #include "as.h" -static int atof_vax_sizeof PARAMS ((int)); -static int next_bits PARAMS ((int)); -static void make_invalid_floating_point_number PARAMS ((LITTLENUM_TYPE *)); -static int what_kind_of_float PARAMS ((int, int *, long *)); -static char *atof_vax PARAMS ((char *, int, LITTLENUM_TYPE *)); - /* Precision in LittleNums. */ -#define MAX_PRECISION (8) -#define H_PRECISION (8) -#define G_PRECISION (4) -#define D_PRECISION (4) -#define F_PRECISION (2) +#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) +#define GUARD 2 -int flonum_gen2vax PARAMS ((int format_letter, FLONUM_TYPE * f, - LITTLENUM_TYPE * words)); +int flonum_gen2vax (int, FLONUM_TYPE *, LITTLENUM_TYPE *); /* Number of chars in flonum type 'letter'. */ + static int -atof_vax_sizeof (letter) - int letter; +atof_vax_sizeof (int 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! - */ + /* 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': @@ -75,8 +66,9 @@ atof_vax_sizeof (letter) return_value = 0; break; } - return (return_value); -} /* atof_vax_sizeof */ + + return return_value; +} static const long mask[] = { @@ -116,14 +108,13 @@ static const long mask[] = }; -/* Shared between flonum_gen2vax and next_bits */ +/* 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; +next_bits (int number_of_bits) { int return_value; @@ -144,23 +135,22 @@ next_bits (number_of_bits) bits_left_in_littlenum -= number_of_bits; return_value = mask[number_of_bits] & ((*littlenum_pointer) >> bits_left_in_littlenum); } - return (return_value); + return return_value; } static void -make_invalid_floating_point_number (words) - LITTLENUM_TYPE *words; +make_invalid_floating_point_number (LITTLENUM_TYPE *words) { - *words = 0x8000; /* Floating Reserved Operand Code */ + *words = 0x8000; /* Floating Reserved Operand Code. */ } + static int /* 0 means letter is OK. */ -what_kind_of_float (letter, precisionP, exponent_bitsP) - int letter; /* In: lowercase please. What kind of float? */ - int *precisionP; /* Number of 16-bit words in the float. */ - long *exponent_bitsP; /* Number of exponent bits. */ +what_kind_of_float (int letter, /* In: lowercase please. What kind of float? */ + int *precisionP, /* Number of 16-bit words in the float. */ + long *exponent_bitsP) /* Number of exponent bits. */ { - int retval; /* 0: OK. */ + int retval; retval = 0; switch (letter) @@ -189,29 +179,24 @@ what_kind_of_float (letter, precisionP, exponent_bitsP) retval = 69; break; } - return (retval); + 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! * - * * - \***********************************************************************/ - -static char * /* Return pointer past text consumed. */ -atof_vax (str, what_kind, words) - char *str; /* Text to convert to binary. */ - int what_kind; /* 'd', 'f', 'g', 'h' */ - LITTLENUM_TYPE *words; /* Build the binary here. */ +/* 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! */ + +static char * +atof_vax (char *str, /* Text to convert to binary. */ + int 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. */ + /* 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 exponent_bits; @@ -225,7 +210,7 @@ atof_vax (str, what_kind, words) if (what_kind_of_float (what_kind, &precision, &exponent_bits)) { - return_value = NULL; /* We lost. */ + return_value = NULL; make_invalid_floating_point_number (words); } @@ -233,37 +218,30 @@ atof_vax (str, what_kind, words) { memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); - /* Use more LittleNums than seems */ - /* necessary: the highest flonum may have */ - /* 15 leading 0 bits, so could be useless. */ + /* 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_value = NULL; } + else if (flonum_gen2vax (what_kind, &f, words)) + return_value = NULL; } - return (return_value); -} /* atof_vax() */ + + 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) - int format_letter; /* One of 'd' 'f' 'g' 'h'. */ - FLONUM_TYPE *f; - LITTLENUM_TYPE *words; /* Deliver answer here. */ +/* In: a flonum, a vax floating point format. + Out: a vax floating-point bit pattern. */ + +int +flonum_gen2vax (int format_letter, /* One of 'd' 'f' 'g' 'h'. */ + FLONUM_TYPE *f, + LITTLENUM_TYPE *words) /* Deliver answer here. */ { LITTLENUM_TYPE *lp; int precision; @@ -273,16 +251,14 @@ flonum_gen2vax (format_letter, f, words) return_value = what_kind_of_float (format_letter, &precision, &exponent_bits); if (return_value != 0) - { - make_invalid_floating_point_number (words); - } + make_invalid_floating_point_number (words); + else { if (f->low > f->leader) - { - /* 0.0e0 seen. */ - memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision); - } + /* 0.0e0 seen. */ + memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision); + else { long exponent_1; @@ -292,49 +268,31 @@ flonum_gen2vax (format_letter, f, words) int exponent_skippage; LITTLENUM_TYPE word1; - /* JF: Deal with new Nan, +Inf and -Inf codes */ + /* 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 + + /* 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. */ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; littlenum_pointer = f->leader; littlenum_end = f->low; - /* Seek (and forget) 1st significant bit */ + /* Seek (and forget) 1st significant bit. */ for (exponent_skippage = 0; !next_bits (1); exponent_skippage++);; @@ -350,24 +308,19 @@ flonum_gen2vax (format_letter, f, words) if (exponent_4 & ~mask[exponent_bits]) { - /* - * Exponent overflow. Lose immediately. - */ - + /* 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. - */ + /* 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. */ + /* 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)); @@ -375,32 +328,26 @@ flonum_gen2vax (format_letter, f, words) /* The rest of the words are just mantissa bits. */ for (; lp < words + precision; lp++) - { - *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); - } + *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? - */ - + /* 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 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 - */ + #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--) @@ -413,68 +360,61 @@ flonum_gen2vax (format_letter, f, words) 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. - */ + /* 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); -} /* flonum_gen2vax() */ - -/* 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 0. - * Floating point literal. - * Number of chars we used for the literal. - */ - -#define MAXIMUM_NUMBER_OF_LITTLENUMS (8) /* For .hfloats. */ + } + } + } + } + return return_value; +} + +/* JF this used to be in vax.c but this looks like a better place for it. */ + +/* 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 0. + Floating point literal. + Number of chars we used for the literal. */ + +#define MAXIMUM_NUMBER_OF_LITTLENUMS 8 /* For .hfloats. */ char * -md_atof (what_statement_type, literalP, sizeP) - int what_statement_type; - char *literalP; - int *sizeP; +md_atof (int 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 *littlenumP; + char kind_of_float; + int number_of_chars; + LITTLENUM_TYPE *littlenumP; switch (what_statement_type) { - case 'F': /* .float */ - case 'f': /* .ffloat */ + case 'F': + case 'f': kind_of_float = 'f'; break; - case 'D': /* .double */ - case 'd': /* .dfloat */ + case 'D': + case 'd': kind_of_float = 'd'; break; - case 'g': /* .gfloat */ + case 'g': kind_of_float = 'g'; break; - case 'h': /* .hfloat */ + case 'h': kind_of_float = 'h'; break; @@ -485,17 +425,15 @@ md_atof (what_statement_type, literalP, sizeP) if (kind_of_float) { - register LITTLENUM_TYPE *limit; + LITTLENUM_TYPE *limit; 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. - */ + /* 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)); @@ -506,12 +444,8 @@ md_atof (what_statement_type, literalP, sizeP) }; } else - { - number_of_chars = 0; - }; + number_of_chars = 0; *sizeP = number_of_chars; return kind_of_float ? NULL : _("Bad call to md_atof()"); } - -/* end of atof-vax.c */ diff --git a/gas/config/tc-pdp11.c b/gas/config/tc-pdp11.c index 71870bdf315..19311e6d75c 100644 --- a/gas/config/tc-pdp11.c +++ b/gas/config/tc-pdp11.c @@ -17,37 +17,22 @@ along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* - Apparently unused functions: - md_convert_frag - md_estimate_size_before_relax - md_create_short_jump - md_create_long_jump -*/ - #include "as.h" #include "safe-ctype.h" #include "opcode/pdp11.h" -static int set_option PARAMS ((char *arg)); -static int set_cpu_model PARAMS ((char *arg)); -static int set_machine_model PARAMS ((char *arg)); - -extern int flonum_gen2vax PARAMS ((char format_letter, FLONUM_TYPE * f, - LITTLENUM_TYPE * words)); +extern int flonum_gen2vax (int, FLONUM_TYPE * f, LITTLENUM_TYPE *); -#define TRUE 1 +#define TRUE 1 #define FALSE 0 -/* - * A representation for PDP-11 machine code. - */ +/* A representation for PDP-11 machine code. */ struct pdp11_code { char *error; int code; - int additional; /* is there an additional word? */ - int word; /* additional word, if any */ + int additional; /* Is there an additional word? */ + int word; /* Additional word, if any. */ struct { bfd_reloc_code_real_type type; @@ -56,17 +41,13 @@ struct pdp11_code } reloc; }; -/* - * Instruction set extensions. - * - * If you change this from an array to something else, please update - * the "PDP-11 instruction set extensions" comment in pdp11.h. - */ +/* Instruction set extensions. + + If you change this from an array to something else, please update + the "PDP-11 instruction set extensions" comment in pdp11.h. */ int pdp11_extension[PDP11_EXT_NUM]; -/* - * Assembly options. - */ +/* Assembly options. */ #define ASM_OPT_PIC 1 #define ASM_OPT_NUM 2 @@ -74,7 +55,7 @@ int pdp11_extension[PDP11_EXT_NUM]; int asm_option[ASM_OPT_NUM]; /* These chars start a comment anywhere in a source file (except inside - another comment */ + another comment. */ const char comment_chars[] = "#/"; /* These chars only start a comment at the beginning of a line. */ @@ -82,12 +63,12 @@ const char line_comment_chars[] = "#/"; const char line_separator_chars[] = ";"; -/* Chars that can be used to separate mant from exp in floating point nums */ +/* 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) */ +/* 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[] = "dDfF"; void pseudo_even (int); @@ -100,8 +81,94 @@ const pseudo_typeS md_pseudo_table[] = { 0, 0, 0 }, }; +static struct hash_control *insn_hash = NULL; + +static int +set_option (char *arg) +{ + int yes = 1; + + if (strcmp (arg, "all-extensions") == 0 + || strcmp (arg, "all") == 0) + { + memset (pdp11_extension, ~0, sizeof pdp11_extension); + pdp11_extension[PDP11_NONE] = 0; + return 1; + } + else if (strcmp (arg, "no-extensions") == 0) + { + memset (pdp11_extension, 0, sizeof pdp11_extension); + pdp11_extension[PDP11_BASIC] = 1; + return 1; + } + + if (strncmp (arg, "no-", 3) == 0) + { + yes = 0; + arg += 3; + } + + /* Commersial instructions. */ + if (strcmp (arg, "cis") == 0) + pdp11_extension[PDP11_CIS] = yes; + /* Call supervisor mode. */ + else if (strcmp (arg, "csm") == 0) + pdp11_extension[PDP11_CSM] = yes; + /* Extended instruction set. */ + else if (strcmp (arg, "eis") == 0) + pdp11_extension[PDP11_EIS] = pdp11_extension[PDP11_LEIS] = yes; + /* KEV11 floating-point. */ + else if (strcmp (arg, "fis") == 0 + || strcmp (arg, "kev11") == 0 + || strcmp (arg, "kev-11") == 0) + pdp11_extension[PDP11_FIS] = yes; + /* FP-11 floating-point. */ + else if (strcmp (arg, "fpp") == 0 + || strcmp (arg, "fpu") == 0 + || strcmp (arg, "fp11") == 0 + || strcmp (arg, "fp-11") == 0 + || strcmp (arg, "fpj11") == 0 + || strcmp (arg, "fp-j11") == 0 + || strcmp (arg, "fpj-11") == 0) + pdp11_extension[PDP11_FPP] = yes; + /* Limited extended insns. */ + else if (strcmp (arg, "limited-eis") == 0) + { + pdp11_extension[PDP11_LEIS] = yes; + if (!pdp11_extension[PDP11_LEIS]) + pdp11_extension[PDP11_EIS] = 0; + } + /* Move from processor type. */ + else if (strcmp (arg, "mfpt") == 0) + pdp11_extension[PDP11_MFPT] = yes; + /* Multiprocessor insns: */ + else if (strncmp (arg, "mproc", 5) == 0 + /* TSTSET, WRTLCK */ + || strncmp (arg, "multiproc", 9) == 0) + pdp11_extension[PDP11_MPROC] = yes; + /* Move from/to proc status. */ + else if (strcmp (arg, "mxps") == 0) + pdp11_extension[PDP11_MXPS] = yes; + /* Position-independent code. */ + else if (strcmp (arg, "pic") == 0) + asm_option[ASM_OPT_PIC] = yes; + /* Set priority level. */ + else if (strcmp (arg, "spl") == 0) + pdp11_extension[PDP11_SPL] = yes; + /* Microcode instructions: */ + else if (strcmp (arg, "ucode") == 0 + /* LDUB, MED, XFC */ + || strcmp (arg, "microcode") == 0) + pdp11_extension[PDP11_UCODE] = yes; + else + return 0; + + return 1; +} + + static void -init_defaults () +init_defaults (void) { static int first = 1; @@ -113,10 +180,8 @@ init_defaults () } } -static struct hash_control *insn_hash = NULL; - void -md_begin () +md_begin (void) { int i; @@ -127,21 +192,17 @@ md_begin () as_fatal ("Virtual memory exhausted"); for (i = 0; i < pdp11_num_opcodes; i++) - hash_insert (insn_hash, pdp11_opcodes[i].name, (PTR)(pdp11_opcodes + i)); + hash_insert (insn_hash, pdp11_opcodes[i].name, (void *) (pdp11_opcodes + i)); for (i = 0; i < pdp11_num_aliases; i++) - hash_insert (insn_hash, pdp11_aliases[i].name, (PTR)(pdp11_aliases + i)); + hash_insert (insn_hash, pdp11_aliases[i].name, (void *) (pdp11_aliases + i)); } void -md_number_to_chars (con, value, nbytes) - char con[]; - valueT value; - int nbytes; +md_number_to_chars (char con[], valueT value, int nbytes) { /* On a PDP-11, 0x1234 is stored as "\x12\x34", and - * 0x12345678 is stored as "\x56\x78\x12\x34". It's - * anyones guess what 0x123456 would be stored like. - */ + 0x12345678 is stored as "\x56\x78\x12\x34". It's + anyones guess what 0x123456 would be stored like. */ switch (nbytes) { @@ -151,13 +212,13 @@ md_number_to_chars (con, value, nbytes) con[0] = value & 0xff; break; case 2: - con[0] = value & 0xff; + con[0] = value & 0xff; con[1] = (value >> 8) & 0xff; break; case 4: con[0] = (value >> 16) & 0xff; con[1] = (value >> 24) & 0xff; - con[2] = value & 0xff; + con[2] = value & 0xff; con[3] = (value >> 8) & 0xff; break; default: @@ -169,10 +230,9 @@ md_number_to_chars (con, value, nbytes) that they reference. Knows about order of bytes in address. */ void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, + valueT * valP, + segT seg ATTRIBUTE_UNUSED) { valueT code; valueT mask; @@ -223,10 +283,8 @@ md_chars_to_number (con, nbytes) int nbytes; /* Number of bytes in the input. */ { /* On a PDP-11, 0x1234 is stored as "\x12\x34", and - * 0x12345678 is stored as "\x56\x78\x12\x34". It's - * anyones guess what 0x123456 would be stored like. - */ - + 0x12345678 is stored as "\x56\x78\x12\x34". It's + anyones guess what 0x123456 would be stored like. */ switch (nbytes) { case 0: @@ -237,8 +295,8 @@ md_chars_to_number (con, nbytes) return (con[1] << BITS_PER_CHAR) | con[0]; case 4: return - (((con[1] << BITS_PER_CHAR) | con[0]) << (2 * BITS_PER_CHAR)) | - ((con[3] << BITS_PER_CHAR) | con[2]); + (((con[1] << BITS_PER_CHAR) | con[0]) << (2 * BITS_PER_CHAR)) + |((con[3] << BITS_PER_CHAR) | con[2]); default: BAD_CASE (nbytes); return 0; @@ -280,14 +338,14 @@ parse_reg (char *str, struct pdp11_code *operand) return str - 1; } } - else if (strncmp (str, "sp", 2) == 0 || - strncmp (str, "SP", 2) == 0) + else if (strncmp (str, "sp", 2) == 0 + || strncmp (str, "SP", 2) == 0) { operand->code = 6; str += 2; } - else if (strncmp (str, "pc", 2) == 0 || - strncmp (str, "PC", 2) == 0) + else if (strncmp (str, "pc", 2) == 0 + || strncmp (str, "PC", 2) == 0) { operand->code = 7; str += 2; @@ -305,10 +363,10 @@ static char * parse_ac5 (char *str, struct pdp11_code *operand) { str = skip_whitespace (str); - if (strncmp (str, "fr", 2) == 0 || - strncmp (str, "FR", 2) == 0 || - strncmp (str, "ac", 2) == 0 || - strncmp (str, "AC", 2) == 0) + if (strncmp (str, "fr", 2) == 0 + || strncmp (str, "FR", 2) == 0 + || strncmp (str, "ac", 2) == 0 + || strncmp (str, "AC", 2) == 0) { str += 2; switch (*str) @@ -400,7 +458,8 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand) } break; - case '#': /* immediate */ + /* Immediate. */ + case '#': case '$': str = parse_expression (str + 1, operand); if (operand->error) @@ -423,7 +482,7 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand) operand->error = "Error in expression"; break; } - /* it's a floating literal... */ + /* It's a floating literal... */ know (operand->reloc.exp.X_add_number < 0); flonum_gen2vax ('f', &generic_floating_point_number, literal_float); operand->word = literal_float[0]; @@ -437,7 +496,8 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand) operand->code = 027; break; - default: /* label, d(rn), -(rn) */ + /* label, d(rn), -(rn) */ + default: { char *old = str; @@ -463,7 +523,7 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand) str = skip_whitespace (str); - if (*str != '(') /* label */ + if (*str != '(') { if (operand->reloc.exp.X_op != O_symbol) { @@ -478,7 +538,8 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand) break; } - str++; /* d(rn) */ + /* d(rn) */ + str++; str = parse_reg (str, operand); if (operand->error) return str; @@ -507,9 +568,8 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand) operand->word = operand->reloc.exp.X_add_number; } else - { - operand->word = operand->reloc.exp.X_add_number; - } + operand->word = operand->reloc.exp.X_add_number; + break; default: BAD_CASE (operand->reloc.exp.X_op); @@ -591,8 +651,7 @@ parse_separator (char *str, int *error) } void -md_assemble (instruction_string) - char *instruction_string; +md_assemble (char *instruction_string) { const struct pdp11_opcode *op; struct pdp11_code insn, op1, op2; @@ -957,18 +1016,16 @@ md_assemble (instruction_string) } int -md_estimate_size_before_relax (fragP, segment) - fragS *fragP ATTRIBUTE_UNUSED; - segT segment ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, + segT segment ATTRIBUTE_UNUSED) { return 0; } void -md_convert_frag (headers, seg, fragP) - bfd *headers ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; - fragS *fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd *headers ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED, + fragS *fragP ATTRIBUTE_UNUSED) { } @@ -976,98 +1033,25 @@ int md_short_jump_size = 2; int md_long_jump_size = 4; void -md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr ATTRIBUTE_UNUSED; - addressT from_addr ATTRIBUTE_UNUSED; - addressT to_addr ATTRIBUTE_UNUSED; - fragS *frag ATTRIBUTE_UNUSED; - symbolS *to_symbol ATTRIBUTE_UNUSED; +md_create_short_jump (char *ptr ATTRIBUTE_UNUSED, + addressT from_addr ATTRIBUTE_UNUSED, + addressT to_addr ATTRIBUTE_UNUSED, + fragS *frag ATTRIBUTE_UNUSED, + symbolS *to_symbol ATTRIBUTE_UNUSED) { } void -md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr ATTRIBUTE_UNUSED; - addressT from_addr ATTRIBUTE_UNUSED; - addressT to_addr ATTRIBUTE_UNUSED; - fragS *frag ATTRIBUTE_UNUSED; - symbolS *to_symbol ATTRIBUTE_UNUSED; +md_create_long_jump (char *ptr ATTRIBUTE_UNUSED, + addressT from_addr ATTRIBUTE_UNUSED, + addressT to_addr ATTRIBUTE_UNUSED, + fragS *frag ATTRIBUTE_UNUSED, + symbolS *to_symbol ATTRIBUTE_UNUSED) { } static int -set_option (arg) - char *arg; -{ - int yes = 1; - - if (strcmp (arg, "all-extensions") == 0 || - strcmp (arg, "all") == 0) - { - memset (pdp11_extension, ~0, sizeof pdp11_extension); - pdp11_extension[PDP11_NONE] = 0; - return 1; - } - else if (strcmp (arg, "no-extensions") == 0) - { - memset (pdp11_extension, 0, sizeof pdp11_extension); - pdp11_extension[PDP11_BASIC] = 1; - return 1; - } - - if (strncmp (arg, "no-", 3) == 0) - { - yes = 0; - arg += 3; - } - - if (strcmp (arg, "cis") == 0) /* commersial instructions */ - pdp11_extension[PDP11_CIS] = yes; - else if (strcmp (arg, "csm") == 0) /* call supervisor mode */ - pdp11_extension[PDP11_CSM] = yes; - else if (strcmp (arg, "eis") == 0) /* extended instruction set */ - pdp11_extension[PDP11_EIS] = pdp11_extension[PDP11_LEIS] = yes; - else if (strcmp (arg, "fis") == 0 || /* KEV11 floating-point */ - strcmp (arg, "kev11") == 0 || - strcmp (arg, "kev-11") == 0) - pdp11_extension[PDP11_FIS] = yes; - else if (strcmp (arg, "fpp") == 0 || /* FP-11 floating-point */ - strcmp (arg, "fpu") == 0 || - strcmp (arg, "fp11") == 0 || - strcmp (arg, "fp-11") == 0 || - strcmp (arg, "fpj11") == 0 || - strcmp (arg, "fp-j11") == 0 || - strcmp (arg, "fpj-11") == 0) - pdp11_extension[PDP11_FPP] = yes; - else if (strcmp (arg, "limited-eis") == 0) /* limited extended insns */ - { - pdp11_extension[PDP11_LEIS] = yes; - if (!pdp11_extension[PDP11_LEIS]) - pdp11_extension[PDP11_EIS] = 0; - } - else if (strcmp (arg, "mfpt") == 0) /* move from processor type */ - pdp11_extension[PDP11_MFPT] = yes; - else if (strncmp (arg, "mproc", 5) == 0 || /* multiprocessor insns: */ - strncmp (arg, "multiproc", 9) == 0 ) /* TSTSET, WRTLCK */ - pdp11_extension[PDP11_MPROC] = yes; - else if (strcmp (arg, "mxps") == 0) /* move from/to proc status */ - pdp11_extension[PDP11_MXPS] = yes; - else if (strcmp (arg, "pic") == 0) /* position-independent code */ - asm_option[ASM_OPT_PIC] = yes; - else if (strcmp (arg, "spl") == 0) /* set priority level */ - pdp11_extension[PDP11_SPL] = yes; - else if (strcmp (arg, "ucode") == 0 || /* microcode instructions: */ - strcmp (arg, "microcode") == 0) /* LDUB, MED, XFC */ - pdp11_extension[PDP11_UCODE] = yes; - else - return 0; - - return 1; -} - -static int -set_cpu_model (arg) - char *arg; +set_cpu_model (char *arg) { char buf[4]; char *model = buf; @@ -1082,8 +1066,7 @@ set_cpu_model (arg) if (model[-1] == 'd') { - if (arg[0] == 'f' || - arg[0] == 'j') + if (arg[0] == 'f' || arg[0] == 'j') model[-1] = *arg++; } else if (model[-1] == 'x') @@ -1105,7 +1088,7 @@ set_cpu_model (arg) return 0; } - /* allow up to two revision letters */ + /* Allow up to two revision letters. */ if (arg[0] != 0) *model++ = *arg++; if (arg[0] != 0) @@ -1115,70 +1098,80 @@ set_cpu_model (arg) set_option ("no-extensions"); - if (strncmp (buf, "a", 1) == 0) /* KA11 (11/15/20) */ - return 1; /* no extensions */ + /* KA11 (11/15/20). */ + if (strncmp (buf, "a", 1) == 0) + return 1; /* No extensions. */ - else if (strncmp (buf, "b", 1) == 0) /* KB11 (11/45/50/55/70) */ - return set_option ("eis") && - set_option ("spl"); + /* KB11 (11/45/50/55/70). */ + else if (strncmp (buf, "b", 1) == 0) + return set_option ("eis") && set_option ("spl"); - else if (strncmp (buf, "da", 2) == 0) /* KD11-A (11/35/40) */ + /* KD11-A (11/35/40). */ + else if (strncmp (buf, "da", 2) == 0) return set_option ("limited-eis"); - else if (strncmp (buf, "db", 2) == 0 || /* KD11-B (11/05/10) */ - strncmp (buf, "dd", 2) == 0) /* KD11-D (11/04) */ + /* KD11-B (11/05/10). */ + else if (strncmp (buf, "db", 2) == 0 + /* KD11-D (11/04). */ + || strncmp (buf, "dd", 2) == 0) return 1; /* no extensions */ - else if (strncmp (buf, "de", 2) == 0) /* KD11-E (11/34) */ - return set_option ("eis") && - set_option ("mxps"); - - else if (strncmp (buf, "df", 2) == 0 || /* KD11-F (11/03) */ - strncmp (buf, "dh", 2) == 0 || /* KD11-H (11/03) */ - strncmp (buf, "dq", 2) == 0) /* KD11-Q (11/03) */ - return set_option ("limited-eis") && - set_option ("mxps"); - - else if (strncmp (buf, "dk", 2) == 0) /* KD11-K (11/60) */ - return set_option ("eis") && - set_option ("mxps") && - set_option ("ucode"); - - else if (strncmp (buf, "dz", 2) == 0) /* KD11-Z (11/44) */ - return set_option ("csm") && - set_option ("eis") && - set_option ("mfpt") && - set_option ("mxps") && - set_option ("spl"); - - else if (strncmp (buf, "f", 1) == 0) /* F11 (11/23/24) */ - return set_option ("eis") && - set_option ("mfpt") && - set_option ("mxps"); - - else if (strncmp (buf, "j", 1) == 0) /* J11 (11/53/73/83/84/93/94)*/ - return set_option ("csm") && - set_option ("eis") && - set_option ("mfpt") && - set_option ("multiproc") && - set_option ("mxps") && - set_option ("spl"); - - else if (strncmp (buf, "t", 1) == 0) /* T11 (11/21) */ - return set_option ("limited-eis") && - set_option ("mxps"); + /* KD11-E (11/34). */ + else if (strncmp (buf, "de", 2) == 0) + return set_option ("eis") && set_option ("mxps"); + + /* KD11-F (11/03). */ + else if (strncmp (buf, "df", 2) == 0 + /* KD11-H (11/03). */ + || strncmp (buf, "dh", 2) == 0 + /* KD11-Q (11/03). */ + || strncmp (buf, "dq", 2) == 0) + return set_option ("limited-eis") && set_option ("mxps"); + + /* KD11-K (11/60). */ + else if (strncmp (buf, "dk", 2) == 0) + return set_option ("eis") + && set_option ("mxps") + && set_option ("ucode"); + + /* KD11-Z (11/44). */ + else if (strncmp (buf, "dz", 2) == 0) + return set_option ("csm") + && set_option ("eis") + && set_option ("mfpt") + && set_option ("mxps") + && set_option ("spl"); + + /* F11 (11/23/24). */ + else if (strncmp (buf, "f", 1) == 0) + return set_option ("eis") + && set_option ("mfpt") + && set_option ("mxps"); + + /* J11 (11/53/73/83/84/93/94). */ + else if (strncmp (buf, "j", 1) == 0) + return set_option ("csm") + && set_option ("eis") + && set_option ("mfpt") + && set_option ("multiproc") + && set_option ("mxps") + && set_option ("spl"); + + /* T11 (11/21). */ + else if (strncmp (buf, "t", 1) == 0) + return set_option ("limited-eis") + && set_option ("mxps"); else return 0; } static int -set_machine_model (arg) - char *arg; +set_machine_model (char *arg) { - if (strncmp (arg, "pdp-11/", 7) != 0 && - strncmp (arg, "pdp11/", 6) != 0 && - strncmp (arg, "11/", 3) != 0) + if (strncmp (arg, "pdp-11/", 7) != 0 + && strncmp (arg, "pdp11/", 6) != 0 + && strncmp (arg, "11/", 3) != 0) return 0; if (strncmp (arg, "pdp", 3) == 0) @@ -1188,56 +1181,56 @@ set_machine_model (arg) if (strncmp (arg, "11/", 3) == 0) arg += 3; - if (strcmp (arg, "03") == 0) /* 11/03 */ - return set_cpu_model ("kd11f"); /* KD11-F */ + if (strcmp (arg, "03") == 0) + return set_cpu_model ("kd11f"); + + else if (strcmp (arg, "04") == 0) + return set_cpu_model ("kd11d"); - else if (strcmp (arg, "04") == 0) /* 11/04 */ - return set_cpu_model ("kd11d"); /* KD11-D */ + else if (strcmp (arg, "05") == 0 + || strcmp (arg, "10") == 0) + return set_cpu_model ("kd11b"); - else if (strcmp (arg, "05") == 0 || /* 11/05 or 11/10 */ - strcmp (arg, "10") == 0) - return set_cpu_model ("kd11b"); /* KD11-B */ + else if (strcmp (arg, "15") == 0 + || strcmp (arg, "20") == 0) + return set_cpu_model ("ka11"); - else if (strcmp (arg, "15") == 0 || /* 11/15 or 11/20 */ - strcmp (arg, "20") == 0) - return set_cpu_model ("ka11"); /* KA11 */ + else if (strcmp (arg, "21") == 0) + return set_cpu_model ("t11"); - else if (strcmp (arg, "21") == 0) /* 11/21 */ - return set_cpu_model ("t11"); /* T11 */ + else if (strcmp (arg, "23") == 0 + || strcmp (arg, "24") == 0) + return set_cpu_model ("f11"); - else if (strcmp (arg, "23") == 0 || /* 11/23 or 11/24 */ - strcmp (arg, "24") == 0) - return set_cpu_model ("f11"); /* F11 */ + else if (strcmp (arg, "34") == 0 + || strcmp (arg, "34a") == 0) + return set_cpu_model ("kd11e"); - else if (strcmp (arg, "34") == 0 || /* 11/34 or 11/34a */ - strcmp (arg, "34a") == 0) - return set_cpu_model ("kd11e"); /* KD11-E */ + else if (strcmp (arg, "35") == 0 + || strcmp (arg, "40") == 0) + return set_cpu_model ("kd11da"); - else if (strcmp (arg, "35") == 0 || /* 11/35 or 11/40 */ - strcmp (arg, "40") == 0) - return set_cpu_model ("kd11da"); /* KD11-A */ + else if (strcmp (arg, "44") == 0) + return set_cpu_model ("kd11dz"); - else if (strcmp (arg, "44") == 0) /* 11/44 */ - return set_cpu_model ("kd11dz"); /* KD11-Z */ + else if (strcmp (arg, "45") == 0 + || strcmp (arg, "50") == 0 + || strcmp (arg, "55") == 0 + || strcmp (arg, "70") == 0) + return set_cpu_model ("kb11"); - else if (strcmp (arg, "45") == 0 || /* 11/45/50/55/70 */ - strcmp (arg, "50") == 0 || - strcmp (arg, "55") == 0 || - strcmp (arg, "70") == 0) - return set_cpu_model ("kb11"); /* KB11 */ + else if (strcmp (arg, "60") == 0) + return set_cpu_model ("kd11k"); - else if (strcmp (arg, "60") == 0) /* 11/60 */ - return set_cpu_model ("kd11k"); /* KD11-K */ /* FPP? */ + else if (strcmp (arg, "53") == 0 + || strcmp (arg, "73") == 0 + || strcmp (arg, "83") == 0 + || strcmp (arg, "84") == 0 + || strcmp (arg, "93") == 0 + || strcmp (arg, "94") == 0) + return set_cpu_model ("j11") + && set_option ("fpp"); - else if (strcmp (arg, "53") == 0 || /* 11/53/73/83/84/93/94 */ - strcmp (arg, "73") == 0 || - strcmp (arg, "83") == 0 || - strcmp (arg, "84") == 0 || - strcmp (arg, "93") == 0 || - strcmp (arg, "94") == 0) - return set_cpu_model ("j11") && /* J11 */ - set_option ("fpp"); /* All J11 machines come */ - /* with FPP installed. */ else return 0; } @@ -1257,16 +1250,11 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); -/* - * md_parse_option - * Invocation line includes a switch not recognized by the base assembler. - * See if it's a processor-specific option. - */ +/* Invocation line includes a switch not recognized by the base assembler. + See if it's a processor-specific option. */ int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, char *arg) { init_defaults (); @@ -1303,249 +1291,8 @@ md_parse_option (c, arg) return 0; } -/* -One possible way of parsing options. - -enum -{ - OPTION_CSM, - OPTION_CIS, - ... -}; - -struct -{ - const char *pattern; - int opt; - const char *description; -} options; - -static struct options extension_opts[] = -{ - { "Ncsm", OPTION_CSM, - "allow (disallow) CSM instruction" }, - { "Ncis", OPTION_CIS, - "allow (disallow) commersial instruction set" }, - { "Neis", OPTION_EIS, - "allow (disallow) extended instruction set" }, - ... - { "all-extensions", OPTION_ALL_EXTENSIONS, - "allow all instruction set extensions\n\ - (this is the default)" }, - { "no-extensions", OPTION_NO_EXTENSIONS, - "disallow all instruction set extensions" }, - { "pic", OPTION_PIC, - "position-independent code" }, -}; - -static struct options cpu_opts[] = -{ - { "Ka_11_*", OPTION_KA11, "KA11 CPU. ..." }, - { "Kb_11_*", OPTION_KB11, "KB11 CPU. ..." }, - { "Kd_11_a*", OPTION_KD11A, "KD11-A CPU. ..." }, - { "Kd_11_b*", OPTION_KD11B, "KD11-B CPU. ..." }, - { "Kd_11_d*", OPTION_KD11D, "KD11-D CPU. ..." }, - { "Kd_11_e*", OPTION_KD11E, "KD11-E CPU. ..." }, - { "Kd_11_f*", OPTION_KD11F, "KD11-F CPU. ..." }, - { "Kd_11_h*", OPTION_KD11H, "KD11-H CPU. ..." }, - { "Kd_11_q*", OPTION_KD11Q, "KD11-Q CPU. ..." }, - { "Kd_11_z*", OPTION_KD11Z, "KD11-Z CPU. ..." }, - { "Df_11_*", OPTION_F11, "F11 CPU. ..." }, - { "Dj_11_*", OPTION_J11, "J11 CPU. ..." }, - { "Dt_11_*", OPTION_T11, "T11 CPU. ..." }, -}; - -static struct options model_opts[] = -{ - { "P03", OPTION_PDP11_03, "same as ..." }, - { "P04", OPTION_PDP11_04, "same as ..." }, - { "P05", OPTION_PDP11_05, "same as ..." }, - { "P10", OPTION_PDP11_10, "same as ..." }, - { "P15", OPTION_PDP11_15, "same as ..." }, - { "P20", OPTION_PDP11_20, "same as ..." }, - { "P21", OPTION_PDP11_21, "same as ..." }, - { "P24", OPTION_PDP11_24, "same as ..." }, - { "P34", OPTION_PDP11_34, "same as ..." }, - { "P34a", OPTION_PDP11_34A, "same as ..." }, - { "P40", OPTION_PDP11_40, "same as ..." }, - { "P44", OPTION_PDP11_44, "same as ..." }, - { "P45", OPTION_PDP11_45, "same as ..." }, - { "P50", OPTION_PDP11_50, "same as ..." }, - { "P53", OPTION_PDP11_53, "same as ..." }, - { "P55", OPTION_PDP11_55, "same as ..." }, - { "P60", OPTION_PDP11_60, "same as ..." }, - { "P70", OPTION_PDP11_70, "same as ..." }, - { "P73", OPTION_PDP11_73, "same as ..." }, - { "P83", OPTION_PDP11_83, "same as ..." }, - { "P84", OPTION_PDP11_84, "same as ..." }, - { "P93", OPTION_PDP11_93, "same as ..." }, - { "P94", OPTION_PDP11_94, "same as ..." }, -}; - -struct -{ - const char *title; - struct options *opts; - int num; -} all_opts[] = -{ - { "PDP-11 instruction set extentions", - extension_opts, - sizeof extension_opts / sizeof extension_opts[0] }, - { "PDP-11 CPU model options", - cpu_opts, - sizeof cpu_opts / sizeof cpu_opts[0] }, - { "PDP-11 machine model options", - model_opts, - sizeof model_opts / sizeof model_opts[0] }, -}; - -int -parse_match (char *arg, char *pattern) -{ - int yes = 1; - - while (*pattern) - { - switch (*pattern++) - { - case 'N': - if (strncmp (arg, "no-") == 0) - { - yes = 0; - arg += 3; - } - break; - - case 'K': - if (arg[0] == 'k') - arg++; - break; - - case 'D': - if (strncmp (arg, "kd", 2) == 0) - arg +=2; - break; - - case 'P': - if (strncmp (arg, "pdp-11/", 7) == 0) - arg += 7; - else if (strncmp (arg, "pdp11/", 6) == 0) - arg += 6; - else if (strncmp (arg, "11/", 3) == 0) - arg += 3; - break; - - case '_': - if (arg[0] == "-") - { - if (*++arg == 0) - return 0; - } - break; - - case '*': - return 1; - - default: - if (*arg++ != pattern[-1]) - return 0; - } - } - - return arg[0] == 0; -} - -int -fprint_opt (stream, pattern) - FILE *stream; - const char *pattern; -{ - int n; - - while (*pattern) - { - switch (*pattern++) - { - case 'N': - n += fprintf (stream, "(no-)"); - break; - - case 'K': - n += fprintf (stream, "k"); - break; - - case 'P': - n += fprintf (stream "11/"); - break; - - case 'D': - case '_': - case '*': - break; - - default: - fputc (pattern[-1], stream); - n++; - } - } - - return n; -} - -int -parse_option (char *arg) -{ - int i, j; - - for (i = 0; i < sizeof all_opts / sizeof all_opts[0]; i++) - { - for (j = 0; j < all_opts[i].num; j++) - { - if (parse_match (arg, all_opts[i].opts[j].pattern)) - { - set_option (all_opts[i].opts[j].opt); - return 1; - } - } - } - - return 0; -} - -static void -fprint_space (stream, n) - FILE *stream; - int n; -{ - while (n--) - fputc (' ', stream); -} - void -md_show_usage (stream) - FILE *stream; -{ - int i, j, n; - - for (i = 0; i < sizeof all_opts / sizeof all_opts[0]; i++) - { - fprintf (stream "\n%s:\n\n", all_opts[i].title); - - for (j = 0; j < all_opts[i].num; j++) - { - fprintf (stream, "-m"); - n = fprintf_opt (stream, all_opts[i].opts[j].pattern); - fprint_space (stream, 22 - n); - fprintf (stream, "%s\n", all_opts[i].opts[j].description); - } - } -} -*/ - -void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, "\ \n\ @@ -1619,40 +1366,37 @@ PDP-11 machine model options:\n\ } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } valueT -md_section_align (segment, size) - segT segment ATTRIBUTE_UNUSED; - valueT size; +md_section_align (segT segment ATTRIBUTE_UNUSED, + valueT size) { return (size + 1) & ~1; } long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size; } /* Translate internal representation of relocation info to BFD target format. */ + arelent * -tc_gen_reloc (section, fixp) - asection *section ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, + fixS *fixp) { arelent *reloc; bfd_reloc_code_real_type code; - reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc = xmalloc (sizeof (* reloc)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; @@ -1691,8 +1435,7 @@ tc_gen_reloc (section, fixp) } void -pseudo_bss (c) - int c ATTRIBUTE_UNUSED; +pseudo_bss (int c ATTRIBUTE_UNUSED) { int temp; @@ -1702,12 +1445,9 @@ pseudo_bss (c) } void -pseudo_even (c) - int c ATTRIBUTE_UNUSED; +pseudo_even (int c ATTRIBUTE_UNUSED) { int alignment = 1; /* 2^1 */ frag_align (alignment, 0, 1); record_alignment (now_seg, alignment); } - -/* end of tc-pdp11.c */ diff --git a/gas/config/tc-tic30.c b/gas/config/tc-tic30.c index 7234741c9b8..40baefc21bf 100644 --- a/gas/config/tc-tic30.c +++ b/gas/config/tc-tic30.c @@ -37,33 +37,35 @@ /* Put here all non-digit non-letter characters that may occur in an operand. */ static char operand_special_chars[] = "%$-+(,)*._~/<>&^!:[@]"; -static char *ordinal_names[] = { +static char *ordinal_names[] = +{ "first", "second", "third", "fourth", "fifth" }; const int md_reloc_size = 0; -const char comment_chars[] = ";"; -const char line_comment_chars[] = "*"; +const char comment_chars[] = ";"; +const char line_comment_chars[] = "*"; const char line_separator_chars[] = ""; const char *md_shortopts = ""; -struct option md_longopts[] = { +struct option md_longopts[] = +{ {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); -/* Chars that mean this number is a floating point constant. */ -/* As in 0f12.456 */ -/* or 0d1.2345e12 */ +/* Chars that mean this number is a floating point constant. + As in 0f12.456 + or 0d1.2345e12. */ const char FLT_CHARS[] = "fFdDxX"; /* Chars that can be used to separate mant from exp in floating point nums. */ const char EXP_CHARS[] = "eE"; -/* tables for lexical analysis */ +/* Tables for lexical analysis. */ static char opcode_chars[256]; static char register_chars[256]; static char operand_chars[256]; @@ -71,22 +73,21 @@ static char space_chars[256]; static char identifier_chars[256]; static char digit_chars[256]; -/* lexical macros */ -#define is_opcode_char(x) (opcode_chars[(unsigned char) x]) -#define is_operand_char(x) (operand_chars[(unsigned char) x]) -#define is_register_char(x) (register_chars[(unsigned char) x]) -#define is_space_char(x) (space_chars[(unsigned char) x]) -#define is_identifier_char(x) (identifier_chars[(unsigned char) x]) -#define is_digit_char(x) (digit_chars[(unsigned char) x]) +/* Lexical macros. */ +#define is_opcode_char(x) (opcode_chars [(unsigned char) x]) +#define is_operand_char(x) (operand_chars [(unsigned char) x]) +#define is_register_char(x) (register_chars [(unsigned char) x]) +#define is_space_char(x) (space_chars [(unsigned char) x]) +#define is_identifier_char(x) (identifier_chars [(unsigned char) x]) +#define is_digit_char(x) (digit_chars [(unsigned char) x]) -const pseudo_typeS md_pseudo_table[] = { +const pseudo_typeS md_pseudo_table[] = +{ {0, 0, 0} }; -int debug PARAMS ((const char *string, ...)); - -int -debug VPARAMS ((const char *string, ...)) +static int +debug (const char *string, ...) { if (flag_debug) { @@ -105,64 +106,85 @@ debug VPARAMS ((const char *string, ...)) return 0; } -/* hash table for opcode lookup */ +/* Hash table for opcode lookup. */ static struct hash_control *op_hash; -/* hash table for parallel opcode lookup */ +/* Hash table for parallel opcode lookup. */ static struct hash_control *parop_hash; -/* hash table for register lookup */ +/* Hash table for register lookup. */ static struct hash_control *reg_hash; -/* hash table for indirect addressing lookup */ +/* Hash table for indirect addressing lookup. */ static struct hash_control *ind_hash; void -md_begin () +md_begin (void) { const char *hash_err; + debug ("In md_begin()\n"); op_hash = hash_new (); + { const template *current_optab = tic30_optab; + for (; current_optab < tic30_optab_end; current_optab++) { - hash_err = hash_insert (op_hash, current_optab->name, (char *) current_optab); + hash_err = hash_insert (op_hash, current_optab->name, + (char *) current_optab); if (hash_err) - as_fatal ("Internal Error: Can't Hash %s: %s", current_optab->name, hash_err); + as_fatal ("Internal Error: Can't Hash %s: %s", + current_optab->name, hash_err); } } + parop_hash = hash_new (); + { const partemplate *current_parop = tic30_paroptab; + for (; current_parop < tic30_paroptab_end; current_parop++) { - hash_err = hash_insert (parop_hash, current_parop->name, (char *) current_parop); + hash_err = hash_insert (parop_hash, current_parop->name, + (char *) current_parop); if (hash_err) - as_fatal ("Internal Error: Can't Hash %s: %s", current_parop->name, hash_err); + as_fatal ("Internal Error: Can't Hash %s: %s", + current_parop->name, hash_err); } } + reg_hash = hash_new (); + { const reg *current_reg = tic30_regtab; + for (; current_reg < tic30_regtab_end; current_reg++) { - hash_err = hash_insert (reg_hash, current_reg->name, (char *) current_reg); + hash_err = hash_insert (reg_hash, current_reg->name, + (char *) current_reg); if (hash_err) - as_fatal ("Internal Error: Can't Hash %s: %s", current_reg->name, hash_err); + as_fatal ("Internal Error: Can't Hash %s: %s", + current_reg->name, hash_err); } } + ind_hash = hash_new (); + { const ind_addr_type *current_ind = tic30_indaddr_tab; + for (; current_ind < tic30_indaddrtab_end; current_ind++) { - hash_err = hash_insert (ind_hash, current_ind->syntax, (char *) current_ind); + hash_err = hash_insert (ind_hash, current_ind->syntax, + (char *) current_ind); if (hash_err) - as_fatal ("Internal Error: Can't Hash %s: %s", current_ind->syntax, hash_err); + as_fatal ("Internal Error: Can't Hash %s: %s", + current_ind->syntax, hash_err); } } - /* fill in lexical tables: opcode_chars, operand_chars, space_chars */ + + /* Fill in lexical tables: opcode_chars, operand_chars, space_chars. */ { - register int c; - register char *p; + int c; + char *p; for (c = 0; c < 256; c++) { @@ -177,17 +199,20 @@ md_begin () register_chars[c] = opcode_chars[c]; } else if (c == ')' || c == '(') - { - register_chars[c] = c; - } + register_chars[c] = c; + if (ISUPPER (c) || ISLOWER (c) || ISDIGIT (c)) operand_chars[c] = c; + if (ISDIGIT (c) || c == '-') digit_chars[c] = c; + if (ISALPHA (c) || c == '_' || c == '.' || ISDIGIT (c)) identifier_chars[c] = c; + if (c == ' ' || c == '\t') space_chars[c] = c; + if (c == '_') opcode_chars[c] = c; } @@ -196,34 +221,39 @@ md_begin () } } -/* Address Mode OR values */ +/* Address Mode OR values. */ #define AM_Register 0x00000000 #define AM_Direct 0x00200000 #define AM_Indirect 0x00400000 #define AM_Immediate 0x00600000 #define AM_NotReq 0xFFFFFFFF -/* PC Relative OR values */ +/* PC Relative OR values. */ #define PC_Register 0x00000000 #define PC_Relative 0x02000000 -typedef struct { +typedef struct +{ unsigned op_type; - struct { + struct + { int resolved; unsigned address; char *label; expressionS direct_expr; } direct; - struct { + struct + { unsigned mod; int ARnum; unsigned char disp; } indirect; - struct { + struct + { unsigned opcode; } reg; - struct { + struct + { int resolved; int decimal_found; float f_number; @@ -234,564 +264,403 @@ typedef struct { } immediate; } operand; -int tic30_parallel_insn PARAMS ((char *)); -operand *tic30_operand PARAMS ((char *)); -char *tic30_find_parallel_insn PARAMS ((char *, char *)); - template *opcode; -struct tic30_insn { - template *tm; /* Template of current instruction */ - unsigned opcode; /* Final opcode */ - unsigned int operands; /* Number of given operands */ - /* Type of operand given in instruction */ +struct tic30_insn +{ + template *tm; /* Template of current instruction. */ + unsigned opcode; /* Final opcode. */ + unsigned int operands; /* Number of given operands. */ + /* Type of operand given in instruction. */ operand *operand_type[MAX_OPERANDS]; - unsigned addressing_mode; /* Final addressing mode of instruction */ + unsigned addressing_mode; /* Final addressing mode of instruction. */ }; struct tic30_insn insn; static int found_parallel_insn; -void -md_assemble (line) - char *line; -{ - template *opcode; - char *current_posn; - char *token_start; - char save_char; - unsigned int count; +static char output_invalid_buf[8]; - debug ("In md_assemble() with argument %s\n", line); - memset (&insn, '\0', sizeof (insn)); - if (found_parallel_insn) - { - debug ("Line is second part of parallel instruction\n\n"); - found_parallel_insn = 0; - return; - } - if ((current_posn = tic30_find_parallel_insn (line, input_line_pointer + 1)) == NULL) - current_posn = line; +static char * +output_invalid (char c) +{ + if (ISPRINT (c)) + sprintf (output_invalid_buf, "'%c'", c); else - found_parallel_insn = 1; - while (is_space_char (*current_posn)) - current_posn++; - token_start = current_posn; - if (!is_opcode_char (*current_posn)) - { - as_bad ("Invalid character %s in opcode", output_invalid (*current_posn)); - return; - } - /* Check if instruction is a parallel instruction by seeing if the first - character is a q. */ - if (*token_start == 'q') + sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); + return output_invalid_buf; +} + +/* next_line points to the next line after the current instruction + (current_line). Search for the parallel bars, and if found, merge two + lines into internal syntax for a parallel instruction: + q_[INSN1]_[INSN2] [OPERANDS1] | [OPERANDS2] + By this stage, all comments are scrubbed, and only the bare lines are + given. */ + +#define NONE 0 +#define START_OPCODE 1 +#define END_OPCODE 2 +#define START_OPERANDS 3 +#define END_OPERANDS 4 + +static char * +tic30_find_parallel_insn (char *current_line, char *next_line) +{ + int found_parallel = 0; + char first_opcode[256]; + char second_opcode[256]; + char first_operands[256]; + char second_operands[256]; + char *parallel_insn; + + debug ("In tic30_find_parallel_insn()\n"); + while (!is_end_of_line[(unsigned char) *next_line]) { - if (tic30_parallel_insn (token_start)) + if (*next_line == PARALLEL_SEPARATOR + && *(next_line + 1) == PARALLEL_SEPARATOR) { - if (found_parallel_insn) - free (token_start); - return; + found_parallel = 1; + next_line++; + break; } + next_line++; } - while (is_opcode_char (*current_posn)) - current_posn++; - { /* Find instruction */ - save_char = *current_posn; - *current_posn = '\0'; - opcode = (template *) hash_find (op_hash, token_start); - if (opcode) - { - debug ("Found instruction %s\n", opcode->name); - insn.tm = opcode; - } - else + if (!found_parallel) + return NULL; + debug ("Found a parallel instruction\n"); + + { + int i; + char *opcode, *operands, *line; + + for (i = 0; i < 2; i++) { - debug ("Didn't find insn\n"); - as_bad ("Unknown TMS320C30 instruction: %s", token_start); - return; - } - *current_posn = save_char; - } - if (*current_posn != END_OF_INSN) - { /* Find operands */ - int paren_not_balanced; - int expecting_operand = 0; - int this_operand; - do + if (i == 0) + { + opcode = &first_opcode[0]; + operands = &first_operands[0]; + line = current_line; + } + else + { + opcode = &second_opcode[0]; + operands = &second_operands[0]; + line = next_line; + } + { - /* skip optional white space before operand */ - while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN) - { - if (!is_space_char (*current_posn)) - { - as_bad ("Invalid character %s before %s operand", - output_invalid (*current_posn), - ordinal_names[insn.operands]); - return; - } - current_posn++; - } - token_start = current_posn; /* after white space */ - paren_not_balanced = 0; - while (paren_not_balanced || *current_posn != ',') + int search_status = NONE; + int char_ptr = 0; + char c; + + while (!is_end_of_line[(unsigned char) (c = *line)]) { - if (*current_posn == END_OF_INSN) - { - if (paren_not_balanced) - { - as_bad ("Unbalanced parenthesis in %s operand.", - ordinal_names[insn.operands]); - return; - } - else - break; /* we are done */ - } - else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn)) - { - as_bad ("Invalid character %s in %s operand", - output_invalid (*current_posn), - ordinal_names[insn.operands]); - return; - } - if (*current_posn == '(') - ++paren_not_balanced; - if (*current_posn == ')') - --paren_not_balanced; - current_posn++; - } - if (current_posn != token_start) - { /* yes, we've read in another operand */ - this_operand = insn.operands++; - if (insn.operands > MAX_OPERANDS) + if (is_opcode_char (c) && search_status == NONE) { - as_bad ("Spurious operands; (%d operands/instruction max)", - MAX_OPERANDS); - return; + opcode[char_ptr++] = TOLOWER (c); + search_status = START_OPCODE; } - /* now parse operand adding info to 'insn' as we go along */ - save_char = *current_posn; - *current_posn = '\0'; - insn.operand_type[this_operand] = tic30_operand (token_start); - *current_posn = save_char; - if (insn.operand_type[this_operand] == NULL) - return; - } - else - { - if (expecting_operand) + else if (is_opcode_char (c) && search_status == START_OPCODE) + opcode[char_ptr++] = TOLOWER (c); + else if (!is_opcode_char (c) && search_status == START_OPCODE) { - as_bad ("Expecting operand after ','; got nothing"); - return; + opcode[char_ptr] = '\0'; + char_ptr = 0; + search_status = END_OPCODE; } - if (*current_posn == ',') + else if (is_operand_char (c) && search_status == START_OPERANDS) + operands[char_ptr++] = c; + + if (is_operand_char (c) && search_status == END_OPCODE) { - as_bad ("Expecting operand before ','; got nothing"); - return; - } - } - /* now *current_posn must be either ',' or END_OF_INSN */ - if (*current_posn == ',') - { - if (*++current_posn == END_OF_INSN) - { /* just skip it, if it's \n complain */ - as_bad ("Expecting operand after ','; got nothing"); - return; + operands[char_ptr++] = c; + search_status = START_OPERANDS; } - expecting_operand = 1; + + line++; } + if (search_status != START_OPERANDS) + return NULL; + operands[char_ptr] = '\0'; } - while (*current_posn != END_OF_INSN); /* until we get end of insn */ - } - debug ("Number of operands found: %d\n", insn.operands); - /* Check that number of operands is correct */ - if (insn.operands != insn.tm->operands) + } + } + parallel_insn = malloc (strlen (first_opcode) + strlen (first_operands) + + strlen (second_opcode) + strlen (second_operands) + 8); + sprintf (parallel_insn, "q_%s_%s %s | %s", + first_opcode, second_opcode, + first_operands, second_operands); + debug ("parallel insn = %s\n", parallel_insn); + return parallel_insn; +} + +#undef NONE +#undef START_OPCODE +#undef END_OPCODE +#undef START_OPERANDS +#undef END_OPERANDS + +static operand * +tic30_operand (char *token) +{ + unsigned int count; + char ind_buffer[strlen (token)]; + operand *current_op; + + debug ("In tic30_operand with %s\n", token); + current_op = malloc (sizeof (* current_op)); + memset (current_op, '\0', sizeof (operand)); + + if (*token == DIRECT_REFERENCE) { - unsigned int i; - unsigned int numops = insn.tm->operands; - /* If operands are not the same, then see if any of the operands are not - required. Then recheck with number of given operands. If they are still not - the same, then give an error, otherwise carry on. */ - for (i = 0; i < insn.tm->operands; i++) - if (insn.tm->operand_types[i] & NotReq) - numops--; - if (insn.operands != numops) + char *token_posn = token + 1; + int direct_label = 0; + + debug ("Found direct reference\n"); + while (*token_posn) { - as_bad ("Incorrect number of operands given"); - return; + if (!is_digit_char (*token_posn)) + direct_label = 1; + token_posn++; } - } - insn.addressing_mode = AM_NotReq; - for (count = 0; count < insn.operands; count++) - { - if (insn.operand_type[count]->op_type & insn.tm->operand_types[count]) + + if (direct_label) { - debug ("Operand %d matches\n", count + 1); - /* If instruction has two operands and has an AddressMode modifier then set - addressing mode type for instruction */ - if (insn.tm->opcode_modifier == AddressMode) + char *save_input_line_pointer; + segT retval; + + debug ("Direct reference is a label\n"); + current_op->direct.label = token + 1; + save_input_line_pointer = input_line_pointer; + input_line_pointer = token + 1; + debug ("Current input_line_pointer: %s\n", input_line_pointer); + retval = expression (¤t_op->direct.direct_expr); + + debug ("Expression type: %d\n", + current_op->direct.direct_expr.X_op); + debug ("Expression addnum: %d\n", + current_op->direct.direct_expr.X_add_number); + debug ("Segment: %d\n", retval); + + input_line_pointer = save_input_line_pointer; + + if (current_op->direct.direct_expr.X_op == O_constant) { - int addr_insn = 0; - /* Store instruction uses the second operand for the address mode. */ - if ((insn.tm->operand_types[1] & (Indirect | Direct)) == (Indirect | Direct)) - addr_insn = 1; - if (insn.operand_type[addr_insn]->op_type & (AllReg)) - insn.addressing_mode = AM_Register; - else if (insn.operand_type[addr_insn]->op_type & Direct) - insn.addressing_mode = AM_Direct; - else if (insn.operand_type[addr_insn]->op_type & Indirect) - insn.addressing_mode = AM_Indirect; - else - insn.addressing_mode = AM_Immediate; + current_op->direct.address = + current_op->direct.direct_expr.X_add_number; + current_op->direct.resolved = 1; } } else { - as_bad ("The %s operand doesn't match", ordinal_names[count]); - return; + debug ("Direct reference is a number\n"); + current_op->direct.address = atoi (token + 1); + current_op->direct.resolved = 1; } + current_op->op_type = Direct; } - /* Now set the addressing mode for 3 operand instructions. */ - if ((insn.tm->operand_types[0] & op3T1) && (insn.tm->operand_types[1] & op3T2)) + else if (*token == INDIRECT_REFERENCE) { - /* Set the addressing mode to the values used for 2 operand instructions in the - G addressing field of the opcode. */ - char *p; - switch (insn.operand_type[0]->op_type) - { - case Rn: - case ARn: - case DPReg: - case OtherReg: - if (insn.operand_type[1]->op_type & (AllReg)) - insn.addressing_mode = AM_Register; - else if (insn.operand_type[1]->op_type & Indirect) - insn.addressing_mode = AM_Direct; - else - { - /* Shouldn't make it to this stage */ - as_bad ("Incompatible first and second operands in instruction"); - return; - } - break; - case Indirect: - if (insn.operand_type[1]->op_type & (AllReg)) - insn.addressing_mode = AM_Indirect; - else if (insn.operand_type[1]->op_type & Indirect) - insn.addressing_mode = AM_Immediate; - else - { - /* Shouldn't make it to this stage */ - as_bad ("Incompatible first and second operands in instruction"); - return; - } - break; - } - /* Now make up the opcode for the 3 operand instructions. As in parallel - instructions, there will be no unresolved values, so they can be fully formed - and added to the frag table. */ - insn.opcode = insn.tm->base_opcode; - if (insn.operand_type[0]->op_type & Indirect) - { - insn.opcode |= (insn.operand_type[0]->indirect.ARnum); - insn.opcode |= (insn.operand_type[0]->indirect.mod << 3); - } - else - insn.opcode |= (insn.operand_type[0]->reg.opcode); - if (insn.operand_type[1]->op_type & Indirect) - { - insn.opcode |= (insn.operand_type[1]->indirect.ARnum << 8); - insn.opcode |= (insn.operand_type[1]->indirect.mod << 11); - } - else - insn.opcode |= (insn.operand_type[1]->reg.opcode << 8); - if (insn.operands == 3) - insn.opcode |= (insn.operand_type[2]->reg.opcode << 16); - insn.opcode |= insn.addressing_mode; - p = frag_more (INSN_SIZE); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { /* Not a three operand instruction */ - char *p; - int am_insn = -1; - insn.opcode = insn.tm->base_opcode; - /* Create frag for instruction - all instructions are 4 bytes long. */ - p = frag_more (INSN_SIZE); - if ((insn.operands > 0) && (insn.tm->opcode_modifier == AddressMode)) + /* Indirect reference operand. */ + int found_ar = 0; + int found_disp = 0; + int ar_number = -1; + int disp_number = 0; + int buffer_posn = 1; + ind_addr_type *ind_addr_op; + + debug ("Found indirect reference\n"); + ind_buffer[0] = *token; + + for (count = 1; count < strlen (token); count++) { - insn.opcode |= insn.addressing_mode; - if (insn.addressing_mode == AM_Indirect) - { - /* Determine which operand gives the addressing mode */ - if (insn.operand_type[0]->op_type & Indirect) - am_insn = 0; - if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Indirect)) - am_insn = 1; - insn.opcode |= (insn.operand_type[am_insn]->indirect.disp); - insn.opcode |= (insn.operand_type[am_insn]->indirect.ARnum << 8); - insn.opcode |= (insn.operand_type[am_insn]->indirect.mod << 11); - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.addressing_mode == AM_Register) - { - insn.opcode |= (insn.operand_type[0]->reg.opcode); - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.addressing_mode == AM_Direct) + /* Strip operand. */ + ind_buffer[buffer_posn] = TOLOWER (*(token + count)); + + if ((*(token + count - 1) == 'a' || *(token + count - 1) == 'A') + && (*(token + count) == 'r' || *(token + count) == 'R')) { - if (insn.operand_type[0]->op_type & Direct) - am_insn = 0; - if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Direct)) - am_insn = 1; - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16); - if (insn.operand_type[am_insn]->direct.resolved == 1) + /* AR reference is found, so get its number and remove + it from the buffer so it can pass through hash_find(). */ + if (found_ar) { - /* Resolved values can be placed straight into instruction word, and output */ - insn.opcode |= (insn.operand_type[am_insn]->direct.address & 0x0000FFFF); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + as_bad ("More than one AR register found in indirect reference"); + return NULL; } - else - { /* Unresolved direct addressing mode instruction */ - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[am_insn]->direct.direct_expr, 0, 0); + if (*(token + count + 1) < '0' || *(token + count + 1) > '7') + { + as_bad ("Illegal AR register in indirect reference"); + return NULL; } + ar_number = *(token + count + 1) - '0'; + found_ar = 1; + count++; } - else if (insn.addressing_mode == AM_Immediate) + + if (*(token + count) == '(') { - if (insn.operand_type[0]->immediate.resolved == 1) + /* Parenthesis found, so check if a displacement value is + inside. If so, get the value and remove it from the + buffer. */ + if (is_digit_char (*(token + count + 1))) { - char *keeploc; - int size; - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); - switch (insn.tm->imm_arg_type) + char disp[10]; + int disp_posn = 0; + + if (found_disp) { - case Imm_Float: - debug ("Floating point first operand\n"); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - keeploc = input_line_pointer; - input_line_pointer = insn.operand_type[0]->immediate.label; - if (md_atof ('f', p + 2, &size) != 0) - { - as_bad ("invalid short form floating point immediate operand"); - return; - } - input_line_pointer = keeploc; - break; - case Imm_UInt: - debug ("Unsigned int first operand\n"); - if (insn.operand_type[0]->immediate.decimal_found) - as_warn ("rounding down first operand float to unsigned int"); - if (insn.operand_type[0]->immediate.u_number > 0xFFFF) - as_warn ("only lower 16-bits of first operand are used"); - insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x0000FFFFL); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - break; - case Imm_SInt: - debug ("Int first operand\n"); - if (insn.operand_type[0]->immediate.decimal_found) - as_warn ("rounding down first operand float to signed int"); - if (insn.operand_type[0]->immediate.s_number < -32768 || - insn.operand_type[0]->immediate.s_number > 32767) + as_bad ("More than one displacement found in indirect reference"); + return NULL; + } + count++; + while (*(token + count) != ')') + { + if (!is_digit_char (*(token + count))) { - as_bad ("first operand is too large for 16-bit signed int"); - return; + as_bad ("Invalid displacement in indirect reference"); + return NULL; } - insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFFL); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - break; + disp[disp_posn++] = *(token + (count++)); } - } - else - { /* Unresolved immediate label */ - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 0, 0); + disp[disp_posn] = '\0'; + disp_number = atoi (disp); + count--; + found_disp = 1; } } + buffer_posn++; } - else if (insn.tm->opcode_modifier == PCRel) + + ind_buffer[buffer_posn] = '\0'; + if (!found_ar) { - /* Conditional Branch and Call instructions */ - if ((insn.tm->operand_types[0] & (AllReg | Disp)) == (AllReg | Disp)) + as_bad ("AR register not found in indirect reference"); + return NULL; + } + + ind_addr_op = (ind_addr_type *) hash_find (ind_hash, ind_buffer); + if (ind_addr_op) + { + debug ("Found indirect reference: %s\n", ind_addr_op->syntax); + if (ind_addr_op->displacement == IMPLIED_DISP) { - if (insn.operand_type[0]->op_type & (AllReg)) - { - insn.opcode |= (insn.operand_type[0]->reg.opcode); - insn.opcode |= PC_Register; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - insn.opcode |= PC_Relative; - if (insn.operand_type[0]->immediate.resolved == 1) - { - insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFF); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 1, 0); - } - } + found_disp = 1; + disp_number = 1; } - else if ((insn.tm->operand_types[0] & ARn) == ARn) + else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp) { - /* Decrement and Branch instructions */ - insn.opcode |= ((insn.operand_type[0]->reg.opcode - 0x08) << 22); - if (insn.operand_type[1]->op_type & (AllReg)) - { - insn.opcode |= (insn.operand_type[1]->reg.opcode); - insn.opcode |= PC_Register; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.operand_type[1]->immediate.resolved == 1) - { - if (insn.operand_type[0]->immediate.decimal_found) - { - as_bad ("first operand is floating point"); - return; - } - if (insn.operand_type[0]->immediate.s_number < -32768 || - insn.operand_type[0]->immediate.s_number > 32767) - { - as_bad ("first operand is too large for 16-bit signed int"); - return; - } - insn.opcode |= (insn.operand_type[1]->immediate.s_number); - insn.opcode |= PC_Relative; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - insn.opcode |= PC_Relative; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 2 - frag_now->fr_literal, 2, &insn.operand_type[1]->immediate.imm_expr, 1, 0); - } + /* Maybe an implied displacement of 1 again. */ + as_bad ("required displacement wasn't given in indirect reference"); + return 0; } } - else if (insn.tm->operand_types[0] == IVector) + else { - /* Trap instructions */ - if (insn.operand_type[0]->op_type & IVector) - insn.opcode |= (insn.operand_type[0]->immediate.u_number); - else - { /* Shouldn't get here */ - as_bad ("interrupt vector for trap instruction out of range"); - return; - } - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + as_bad ("illegal indirect reference"); + return NULL; } - else if (insn.tm->opcode_modifier == StackOp || insn.tm->opcode_modifier == Rotate) + + if (found_disp && (disp_number < 0 || disp_number > 255)) { - /* Push, Pop and Rotate instructions */ - insn.opcode |= (insn.operand_type[0]->reg.opcode << 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + as_bad ("displacement must be an unsigned 8-bit number"); + return NULL; } - else if ((insn.tm->operand_types[0] & (Abs24 | Direct)) == (Abs24 | Direct)) + + current_op->indirect.mod = ind_addr_op->modfield; + current_op->indirect.disp = disp_number; + current_op->indirect.ARnum = ar_number; + current_op->op_type = Indirect; + } + else + { + reg *regop = (reg *) hash_find (reg_hash, token); + + if (regop) { - /* LDP Instruction needs to be tested for before the next section */ - if (insn.operand_type[0]->op_type & Direct) - { - if (insn.operand_type[0]->direct.resolved == 1) - { - /* Direct addressing uses lower 8 bits of direct address */ - insn.opcode |= (insn.operand_type[0]->direct.address & 0x00FF0000) >> 16; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - fixS *fix; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->direct.direct_expr, 0, 0); - /* Ensure that the assembler doesn't complain about fitting a 24-bit - address into 8 bits. */ - fix->fx_no_overflow = 1; - } - } + debug ("Found register operand: %s\n", regop->name); + if (regop->regtype == REG_ARn) + current_op->op_type = ARn; + else if (regop->regtype == REG_Rn) + current_op->op_type = Rn; + else if (regop->regtype == REG_DP) + current_op->op_type = DPReg; else - { - if (insn.operand_type[0]->immediate.resolved == 1) - { - /* Immediate addressing uses upper 8 bits of address */ - if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF) - { - as_bad ("LDP instruction needs a 24-bit operand"); - return; - } - insn.opcode |= ((insn.operand_type[0]->immediate.u_number & 0x00FF0000) >> 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - fixS *fix; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->immediate.imm_expr, 0, 0); - fix->fx_no_overflow = 1; - } - } + current_op->op_type = OtherReg; + current_op->reg.opcode = regop->opcode; } - else if (insn.tm->operand_types[0] & (Imm24)) + else { - /* Unconditional Branch and Call instructions */ - if (insn.operand_type[0]->immediate.resolved == 1) + if (!is_digit_char (*token) + || *(token + 1) == 'x' + || strchr (token, 'h')) { - if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF) - as_warn ("first operand is too large for a 24-bit displacement"); - insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x00FFFFFF); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + char *save_input_line_pointer; + segT retval; + + debug ("Probably a label: %s\n", token); + current_op->immediate.label = malloc (strlen (token) + 1); + strcpy (current_op->immediate.label, token); + current_op->immediate.label[strlen (token)] = '\0'; + save_input_line_pointer = input_line_pointer; + input_line_pointer = token; + + debug ("Current input_line_pointer: %s\n", input_line_pointer); + retval = expression (¤t_op->immediate.imm_expr); + debug ("Expression type: %d\n", + current_op->immediate.imm_expr.X_op); + debug ("Expression addnum: %d\n", + current_op->immediate.imm_expr.X_add_number); + debug ("Segment: %d\n", retval); + input_line_pointer = save_input_line_pointer; + + if (current_op->immediate.imm_expr.X_op == O_constant) + { + current_op->immediate.s_number + = current_op->immediate.imm_expr.X_add_number; + current_op->immediate.u_number + = (unsigned int) current_op->immediate.imm_expr.X_add_number; + current_op->immediate.resolved = 1; + } } else { - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 1 - (frag_now->fr_literal), 3, &insn.operand_type[0]->immediate.imm_expr, 0, 0); + unsigned count; + + debug ("Found a number or displacement\n"); + for (count = 0; count < strlen (token); count++) + if (*(token + count) == '.') + current_op->immediate.decimal_found = 1; + current_op->immediate.label = malloc (strlen (token) + 1); + strcpy (current_op->immediate.label, token); + current_op->immediate.label[strlen (token)] = '\0'; + current_op->immediate.f_number = (float) atof (token); + current_op->immediate.s_number = (int) atoi (token); + current_op->immediate.u_number = (unsigned int) atoi (token); + current_op->immediate.resolved = 1; } - } - else if (insn.tm->operand_types[0] & NotReq) - { - /* Check for NOP instruction without arguments. */ - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.tm->operands == 0) - { - /* Check for instructions without operands. */ - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + current_op->op_type = Disp | Abs24 | Imm16 | Imm24; + if (current_op->immediate.u_number <= 31) + current_op->op_type |= IVector; } } - debug ("Addressing mode: %08X\n", insn.addressing_mode); - { - unsigned int i; - for (i = 0; i < insn.operands; i++) - { - if (insn.operand_type[i]->immediate.label) - free (insn.operand_type[i]->immediate.label); - free (insn.operand_type[i]); - } - } - debug ("Final opcode: %08X\n", insn.opcode); - debug ("\n"); + return current_op; } -struct tic30_par_insn { - partemplate *tm; /* Template of current parallel instruction */ - unsigned operands[2]; /* Number of given operands for each insn */ - /* Type of operand given in instruction */ +struct tic30_par_insn +{ + partemplate *tm; /* Template of current parallel instruction. */ + unsigned operands[2]; /* Number of given operands for each insn. */ + /* Type of operand given in instruction. */ operand *operand_type[2][MAX_OPERANDS]; int swap_operands; /* Whether to swap operands around. */ - unsigned p_field; /* Value of p field in multiply add/sub instructions */ - unsigned opcode; /* Final opcode */ + unsigned p_field; /* Value of p field in multiply add/sub instructions. */ + unsigned opcode; /* Final opcode. */ }; struct tic30_par_insn p_insn; -int +static int tic30_parallel_insn (char *token) { static partemplate *p_opcode; @@ -801,9 +670,11 @@ tic30_parallel_insn (char *token) debug ("In tic30_parallel_insn with %s\n", token); memset (&p_insn, '\0', sizeof (p_insn)); + while (is_opcode_char (*current_posn)) current_posn++; - { /* Find instruction */ + { + /* Find instruction. */ save_char = *current_posn; *current_posn = '\0'; p_opcode = (partemplate *) hash_find (parop_hash, token); @@ -814,10 +685,8 @@ tic30_parallel_insn (char *token) } else { - char first_opcode[6] = - {0}; - char second_opcode[6] = - {0}; + char first_opcode[6] = {0}; + char second_opcode[6] = {0}; unsigned int i; int current_opcode = -1; int char_ptr = 0; @@ -825,17 +694,20 @@ tic30_parallel_insn (char *token) for (i = 0; i < strlen (token); i++) { char ch = *(token + i); + if (ch == '_' && current_opcode == -1) { current_opcode = 0; continue; } + if (ch == '_' && current_opcode == 0) { current_opcode = 1; char_ptr = 0; continue; } + switch (current_opcode) { case 0: @@ -846,10 +718,12 @@ tic30_parallel_insn (char *token) break; } } + debug ("first_opcode = %s\n", first_opcode); debug ("second_opcode = %s\n", second_opcode); sprintf (token, "q_%s_%s", second_opcode, first_opcode); p_opcode = (partemplate *) hash_find (parop_hash, token); + if (p_opcode) { debug ("Found instruction %s\n", p_opcode->name); @@ -861,16 +735,21 @@ tic30_parallel_insn (char *token) } *current_posn = save_char; } - { /* Find operands */ + + { + /* Find operands. */ int paren_not_balanced; int expecting_operand = 0; int found_separator = 0; + do { - /* skip optional white space before operand */ - while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN) + /* Skip optional white space before operand. */ + while (!is_operand_char (*current_posn) + && *current_posn != END_OF_INSN) { - if (!is_space_char (*current_posn) && *current_posn != PARALLEL_SEPARATOR) + if (!is_space_char (*current_posn) + && *current_posn != PARALLEL_SEPARATOR) { as_bad ("Invalid character %s before %s operand", output_invalid (*current_posn), @@ -881,8 +760,10 @@ tic30_parallel_insn (char *token) found_separator = 1; current_posn++; } - token_start = current_posn; /* after white space */ + + token_start = current_posn; paren_not_balanced = 0; + while (paren_not_balanced || *current_posn != ',') { if (*current_posn == END_OF_INSN) @@ -894,7 +775,7 @@ tic30_parallel_insn (char *token) return 1; } else - break; /* we are done */ + break; } else if (*current_posn == PARALLEL_SEPARATOR) { @@ -902,21 +783,25 @@ tic30_parallel_insn (char *token) current_posn--; break; } - else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn)) + else if (!is_operand_char (*current_posn) + && !is_space_char (*current_posn)) { as_bad ("Invalid character %s in %s operand", output_invalid (*current_posn), ordinal_names[insn.operands]); return 1; } + if (*current_posn == '(') ++paren_not_balanced; if (*current_posn == ')') --paren_not_balanced; current_posn++; } + if (current_posn != token_start) - { /* yes, we've read in another operand */ + { + /* Yes, we've read in another operand. */ p_insn.operands[found_separator]++; if (p_insn.operands[found_separator] > MAX_OPERANDS) { @@ -924,7 +809,8 @@ tic30_parallel_insn (char *token) MAX_OPERANDS); return 1; } - /* now parse operand adding info to 'insn' as we go along */ + + /* Now parse operand adding info to 'insn' as we go along. */ save_char = *current_posn; *current_posn = '\0'; p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1] = @@ -946,19 +832,22 @@ tic30_parallel_insn (char *token) return 1; } } - /* now *current_posn must be either ',' or END_OF_INSN */ + + /* Now *current_posn must be either ',' or END_OF_INSN. */ if (*current_posn == ',') { if (*++current_posn == END_OF_INSN) - { /* just skip it, if it's \n complain */ + { + /* Just skip it, if it's \n complain. */ as_bad ("Expecting operand after ','; got nothing"); return 1; } expecting_operand = 1; } } - while (*current_posn != END_OF_INSN); /* until we get end of insn */ + while (*current_posn != END_OF_INSN); } + if (p_insn.swap_operands) { int temp_num, i; @@ -974,22 +863,28 @@ tic30_parallel_insn (char *token) p_insn.operand_type[1][i] = temp_op; } } + if (p_insn.operands[0] != p_insn.tm->operands_1) { as_bad ("incorrect number of operands given in the first instruction"); return 1; } + if (p_insn.operands[1] != p_insn.tm->operands_2) { as_bad ("incorrect number of operands given in the second instruction"); return 1; } + debug ("Number of operands in first insn: %d\n", p_insn.operands[0]); debug ("Number of operands in second insn: %d\n", p_insn.operands[1]); - { /* Now check if operands are correct */ + + { + /* Now check if operands are correct. */ int count; int num_rn = 0; int num_ind = 0; + for (count = 0; count < 2; count++) { unsigned int i; @@ -998,64 +893,76 @@ tic30_parallel_insn (char *token) if ((p_insn.operand_type[count][i]->op_type & p_insn.tm->operand_types[count][i]) == 0) { - as_bad ("%s instruction, operand %d doesn't match", ordinal_names[count], i + 1); + as_bad ("%s instruction, operand %d doesn't match", + ordinal_names[count], i + 1); return 1; } - /* Get number of R register and indirect reference contained within the first - two operands of each instruction. This is required for the multiply - parallel instructions which require two R registers and two indirect - references, but not in any particular place. */ + + /* Get number of R register and indirect reference contained + within the first two operands of each instruction. This is + required for the multiply parallel instructions which require + two R registers and two indirect references, but not in any + particular place. */ if ((p_insn.operand_type[count][i]->op_type & Rn) && i < 2) num_rn++; - else if ((p_insn.operand_type[count][i]->op_type & Indirect) && i < 2) + else if ((p_insn.operand_type[count][i]->op_type & Indirect) + && i < 2) num_ind++; } } - if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) == (Indirect | Rn)) + + if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) + == (Indirect | Rn)) { - /* Check for the multiply instructions */ + /* Check for the multiply instructions. */ if (num_rn != 2) { as_bad ("incorrect format for multiply parallel instruction"); return 1; } + if (num_ind != 2) - { /* Shouldn't get here */ + { + /* Shouldn't get here. */ as_bad ("incorrect format for multiply parallel instruction"); return 1; } - if ((p_insn.operand_type[0][2]->reg.opcode != 0x00) && - (p_insn.operand_type[0][2]->reg.opcode != 0x01)) + + if ((p_insn.operand_type[0][2]->reg.opcode != 0x00) + && (p_insn.operand_type[0][2]->reg.opcode != 0x01)) { as_bad ("destination for multiply can only be R0 or R1"); return 1; } - if ((p_insn.operand_type[1][2]->reg.opcode != 0x02) && - (p_insn.operand_type[1][2]->reg.opcode != 0x03)) + + if ((p_insn.operand_type[1][2]->reg.opcode != 0x02) + && (p_insn.operand_type[1][2]->reg.opcode != 0x03)) { as_bad ("destination for add/subtract can only be R2 or R3"); return 1; } - /* Now determine the P field for the instruction */ + + /* Now determine the P field for the instruction. */ if (p_insn.operand_type[0][0]->op_type & Indirect) { if (p_insn.operand_type[0][1]->op_type & Indirect) - p_insn.p_field = 0x00000000; /* Ind * Ind, Rn +/- Rn */ + p_insn.p_field = 0x00000000; /* Ind * Ind, Rn +/- Rn. */ else if (p_insn.operand_type[1][0]->op_type & Indirect) - p_insn.p_field = 0x01000000; /* Ind * Rn, Ind +/- Rn */ + p_insn.p_field = 0x01000000; /* Ind * Rn, Ind +/- Rn. */ else - p_insn.p_field = 0x03000000; /* Ind * Rn, Rn +/- Ind */ + p_insn.p_field = 0x03000000; /* Ind * Rn, Rn +/- Ind. */ } else { if (p_insn.operand_type[0][1]->op_type & Rn) - p_insn.p_field = 0x02000000; /* Rn * Rn, Ind +/- Ind */ + p_insn.p_field = 0x02000000; /* Rn * Rn, Ind +/- Ind. */ else if (p_insn.operand_type[1][0]->op_type & Indirect) { operand *temp; - p_insn.p_field = 0x01000000; /* Rn * Ind, Ind +/- Rn */ - /* Need to swap the two multiply operands around so that everything is in - its place for the opcode makeup ie so Ind * Rn, Ind +/- Rn */ + p_insn.p_field = 0x01000000; /* Rn * Ind, Ind +/- Rn. */ + /* Need to swap the two multiply operands around so that + everything is in its place for the opcode makeup. + ie so Ind * Rn, Ind +/- Rn. */ temp = p_insn.operand_type[0][0]; p_insn.operand_type[0][0] = p_insn.operand_type[0][1]; p_insn.operand_type[0][1] = temp; @@ -1063,7 +970,7 @@ tic30_parallel_insn (char *token) else { operand *temp; - p_insn.p_field = 0x03000000; /* Rn * Ind, Rn +/- Ind */ + p_insn.p_field = 0x03000000; /* Rn * Ind, Rn +/- Ind. */ temp = p_insn.operand_type[0][0]; p_insn.operand_type[0][0] = p_insn.operand_type[0][1]; p_insn.operand_type[0][1] = temp; @@ -1071,772 +978,1034 @@ tic30_parallel_insn (char *token) } } } + debug ("P field: %08X\n", p_insn.p_field); - /* Finalise opcode. This is easier for parallel instructions as they have to be - fully resolved, there are no memory addresses allowed, except through indirect - addressing, so there are no labels to resolve. */ + + /* Finalise opcode. This is easier for parallel instructions as they have + to be fully resolved, there are no memory addresses allowed, except + through indirect addressing, so there are no labels to resolve. */ + p_insn.opcode = p_insn.tm->base_opcode; + + switch (p_insn.tm->oporder) + { + case OO_4op1: + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22); + break; + + case OO_4op2: + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 19); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22); + if (p_insn.operand_type[1][1]->reg.opcode == p_insn.operand_type[0][1]->reg.opcode) + as_warn ("loading the same register in parallel operation"); + break; + + case OO_4op3: + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 22); + break; + + case OO_5op1: + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); + p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22); + break; + + case OO_5op2: + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19); + p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22); + break; + + case OO_PField: + p_insn.opcode |= p_insn.p_field; + if (p_insn.operand_type[0][2]->reg.opcode == 0x01) + p_insn.opcode |= 0x00800000; + if (p_insn.operand_type[1][2]->reg.opcode == 0x03) + p_insn.opcode |= 0x00400000; + + switch (p_insn.p_field) + { + case 0x00000000: + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 19); + break; + case 0x01000000: + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); + break; + case 0x02000000: + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19); + break; + case 0x03000000: + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); + break; + } + break; + } + { - p_insn.opcode = p_insn.tm->base_opcode; - switch (p_insn.tm->oporder) - { - case OO_4op1: - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22); - break; - case OO_4op2: - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 19); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22); - if (p_insn.operand_type[1][1]->reg.opcode == p_insn.operand_type[0][1]->reg.opcode) - as_warn ("loading the same register in parallel operation"); - break; - case OO_4op3: - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 22); - break; - case OO_5op1: - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); - p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22); - break; - case OO_5op2: - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19); - p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22); - break; - case OO_PField: - p_insn.opcode |= p_insn.p_field; - if (p_insn.operand_type[0][2]->reg.opcode == 0x01) - p_insn.opcode |= 0x00800000; - if (p_insn.operand_type[1][2]->reg.opcode == 0x03) - p_insn.opcode |= 0x00400000; - switch (p_insn.p_field) - { - case 0x00000000: - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 19); - break; - case 0x01000000: - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); - break; - case 0x02000000: - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19); - break; - case 0x03000000: - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); - break; - } - break; - } - } /* Opcode is finalised at this point for all parallel instructions. */ - { /* Output opcode */ char *p; + p = frag_more (INSN_SIZE); md_number_to_chars (p, (valueT) p_insn.opcode, INSN_SIZE); } + { unsigned int i, j; + for (i = 0; i < 2; i++) for (j = 0; j < p_insn.operands[i]; j++) free (p_insn.operand_type[i][j]); } + debug ("Final opcode: %08X\n", p_insn.opcode); debug ("\n"); + return 1; } -operand * -tic30_operand (token) - char *token; +/* In order to get gas to ignore any | chars at the start of a line, + this function returns true if a | is found in a line. */ + +int +tic30_unrecognized_line (int c) { - unsigned int count; - char ind_buffer[strlen (token)]; - operand *current_op; + debug ("In tc_unrecognized_line\n"); + return (c == PARALLEL_SEPARATOR); +} - debug ("In tic30_operand with %s\n", token); - current_op = (operand *) malloc (sizeof (operand)); - memset (current_op, '\0', sizeof (operand)); - if (*token == DIRECT_REFERENCE) - { - char *token_posn = token + 1; - int direct_label = 0; - debug ("Found direct reference\n"); - while (*token_posn) - { - if (!is_digit_char (*token_posn)) - direct_label = 1; - token_posn++; - } - if (direct_label) - { - char *save_input_line_pointer; - segT retval; - debug ("Direct reference is a label\n"); - current_op->direct.label = token + 1; - save_input_line_pointer = input_line_pointer; - input_line_pointer = token + 1; - debug ("Current input_line_pointer: %s\n", input_line_pointer); - retval = expression (¤t_op->direct.direct_expr); - debug ("Expression type: %d\n", current_op->direct.direct_expr.X_op); - debug ("Expression addnum: %d\n", current_op->direct.direct_expr.X_add_number); - debug ("Segment: %d\n", retval); - input_line_pointer = save_input_line_pointer; - if (current_op->direct.direct_expr.X_op == O_constant) +int +md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, + segT segment ATTRIBUTE_UNUSED) +{ + debug ("In md_estimate_size_before_relax()\n"); + return 0; +} + +void +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + register fragS *fragP ATTRIBUTE_UNUSED) +{ + debug ("In md_convert_frag()\n"); +} + +void +md_apply_fix3 (fixS *fixP, + valueT *valP, + segT seg ATTRIBUTE_UNUSED) +{ + valueT value = *valP; + + debug ("In md_apply_fix() with value = %ld\n", (long) value); + debug ("Values in fixP\n"); + debug ("fx_size = %d\n", fixP->fx_size); + debug ("fx_pcrel = %d\n", fixP->fx_pcrel); + debug ("fx_where = %d\n", fixP->fx_where); + debug ("fx_offset = %d\n", (int) fixP->fx_offset); + { + char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; + + value /= INSN_SIZE; + if (fixP->fx_size == 1) + /* Special fix for LDP instruction. */ + value = (value & 0x00FF0000) >> 16; + + debug ("new value = %ld\n", (long) value); + md_number_to_chars (buf, value, fixP->fx_size); + } + + if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) + fixP->fx_done = 1; +} + +int +md_parse_option (int c ATTRIBUTE_UNUSED, + char *arg ATTRIBUTE_UNUSED) +{ + debug ("In md_parse_option()\n"); + return 0; +} + +void +md_show_usage (FILE *stream ATTRIBUTE_UNUSED) +{ + debug ("In md_show_usage()\n"); +} + +symbolS * +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) +{ + debug ("In md_undefined_symbol()\n"); + return (symbolS *) 0; +} + +valueT +md_section_align (segT segment, valueT size) +{ + debug ("In md_section_align() segment = %d and size = %d\n", + segment, size); + size = (size + 3) / 4; + size *= 4; + debug ("New size value = %d\n", size); + return size; +} + +long +md_pcrel_from (fixS *fixP) +{ + int offset; + + debug ("In md_pcrel_from()\n"); + debug ("fx_where = %d\n", fixP->fx_where); + debug ("fx_size = %d\n", fixP->fx_size); + /* Find the opcode that represents the current instruction in the + fr_literal storage area, and check bit 21. Bit 21 contains whether the + current instruction is a delayed one or not, and then set the offset + value appropriately. */ + if (fixP->fx_frag->fr_literal[fixP->fx_where - fixP->fx_size + 1] & 0x20) + offset = 3; + else + offset = 1; + debug ("offset = %d\n", offset); + /* PC Relative instructions have a format: + displacement = Label - (PC + offset) + This function returns PC + offset where: + fx_where - fx_size = PC + INSN_SIZE * offset = offset number of instructions. */ + return fixP->fx_where - fixP->fx_size + (INSN_SIZE * offset); +} + +char * +md_atof (int what_statement_type, + char *literalP, + int *sizeP) +{ + int prec; + char *token; + char keepval; + unsigned long value; + float float_value; + + debug ("In md_atof()\n"); + debug ("precision = %c\n", what_statement_type); + debug ("literal = %s\n", literalP); + debug ("line = "); + token = input_line_pointer; + while (!is_end_of_line[(unsigned char) *input_line_pointer] + && (*input_line_pointer != ',')) + { + debug ("%c", *input_line_pointer); + input_line_pointer++; + } + + keepval = *input_line_pointer; + *input_line_pointer = '\0'; + debug ("\n"); + float_value = (float) atof (token); + *input_line_pointer = keepval; + debug ("float_value = %f\n", float_value); + + switch (what_statement_type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + + if (float_value == 0.0) + value = (prec == 2) ? 0x00008000L : 0x80000000L; + else + { + unsigned long exp, sign, mant, tmsfloat; + union + { + float f; + long l; + } + converter; + + converter.f = float_value; + tmsfloat = converter.l; + sign = tmsfloat & 0x80000000; + mant = tmsfloat & 0x007FFFFF; + exp = tmsfloat & 0x7F800000; + exp <<= 1; + if (exp == 0xFF000000) + { + if (mant == 0) + value = 0x7F7FFFFF; + else if (sign == 0) + value = 0x7F7FFFFF; + else + value = 0x7F800000; + } + else + { + exp -= 0x7F000000; + if (sign) { - current_op->direct.address = current_op->direct.direct_expr.X_add_number; - current_op->direct.resolved = 1; + mant = mant & 0x007FFFFF; + mant = -mant; + mant = mant & 0x00FFFFFF; + if (mant == 0) + { + mant |= 0x00800000; + exp = (long) exp - 0x01000000; + } + } + tmsfloat = exp | mant; + value = tmsfloat; + } + if (prec == 2) + { + long exp, mant; + + if (tmsfloat == 0x80000000) + value = 0x8000; + else + { + value = 0; + exp = (tmsfloat & 0xFF000000); + exp >>= 24; + mant = tmsfloat & 0x007FFFFF; + if (tmsfloat & 0x00800000) + { + mant |= 0xFF000000; + mant += 0x00000800; + mant >>= 12; + mant |= 0x00000800; + mant &= 0x0FFF; + if (exp > 7) + value = 0x7800; + } + else + { + mant |= 0x00800000; + mant += 0x00000800; + exp += (mant >> 24); + mant >>= 12; + mant &= 0x07FF; + if (exp > 7) + value = 0x77FF; + } + if (exp < -8) + value = 0x8000; + if (value == 0) + { + mant = (exp << 12) | mant; + value = mant & 0xFFFF; + } + } + } + } + md_number_to_chars (literalP, value, prec); + *sizeP = prec; + return 0; +} + +void +md_number_to_chars (char *buf, valueT val, int n) +{ + debug ("In md_number_to_chars()\n"); + number_to_chars_bigendian (buf, val, n); +} + +#define F(SZ,PCREL) (((SZ) << 1) + (PCREL)) +#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break + +arelent * +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) +{ + arelent *rel; + bfd_reloc_code_real_type code = 0; + + debug ("In tc_gen_reloc()\n"); + debug ("fixP.size = %d\n", fixP->fx_size); + debug ("fixP.pcrel = %d\n", fixP->fx_pcrel); + debug ("addsy.name = %s\n", S_GET_NAME (fixP->fx_addsy)); + + switch (F (fixP->fx_size, fixP->fx_pcrel)) + { + MAP (1, 0, BFD_RELOC_TIC30_LDP); + MAP (2, 0, BFD_RELOC_16); + MAP (3, 0, BFD_RELOC_24); + MAP (2, 1, BFD_RELOC_16_PCREL); + MAP (4, 0, BFD_RELOC_32); + default: + as_bad ("Can not do %d byte %srelocation", fixP->fx_size, + fixP->fx_pcrel ? "pc-relative " : ""); + } +#undef MAP +#undef F + + rel = xmalloc (sizeof (* rel)); + assert (rel != 0); + rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *rel->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); + rel->address = fixP->fx_frag->fr_address + fixP->fx_where; + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (stdoutput, code); + if (!rel->howto) + { + const char *name; + + name = S_GET_NAME (fixP->fx_addsy); + if (name == NULL) + name = ""; + as_fatal ("Cannot generate relocation type for symbol %s, code %s", + name, bfd_get_reloc_code_name (code)); + } + return rel; +} + +void +md_operand (expressionS *expressionP ATTRIBUTE_UNUSED) +{ + debug ("In md_operand()\n"); +} + +void +md_assemble (char *line) +{ + template *opcode; + char *current_posn; + char *token_start; + char save_char; + unsigned int count; + + debug ("In md_assemble() with argument %s\n", line); + memset (&insn, '\0', sizeof (insn)); + if (found_parallel_insn) + { + debug ("Line is second part of parallel instruction\n\n"); + found_parallel_insn = 0; + return; + } + if ((current_posn = + tic30_find_parallel_insn (line, input_line_pointer + 1)) == NULL) + current_posn = line; + else + found_parallel_insn = 1; + + while (is_space_char (*current_posn)) + current_posn++; + + token_start = current_posn; + + if (!is_opcode_char (*current_posn)) + { + as_bad ("Invalid character %s in opcode", + output_invalid (*current_posn)); + return; + } + /* Check if instruction is a parallel instruction + by seeing if the first character is a q. */ + if (*token_start == 'q') + { + if (tic30_parallel_insn (token_start)) + { + if (found_parallel_insn) + free (token_start); + return; + } + } + while (is_opcode_char (*current_posn)) + current_posn++; + { + /* Find instruction. */ + save_char = *current_posn; + *current_posn = '\0'; + opcode = (template *) hash_find (op_hash, token_start); + if (opcode) + { + debug ("Found instruction %s\n", opcode->name); + insn.tm = opcode; + } + else + { + debug ("Didn't find insn\n"); + as_bad ("Unknown TMS320C30 instruction: %s", token_start); + return; + } + *current_posn = save_char; + } + + if (*current_posn != END_OF_INSN) + { + /* Find operands. */ + int paren_not_balanced; + int expecting_operand = 0; + int this_operand; + do + { + /* Skip optional white space before operand. */ + while (!is_operand_char (*current_posn) + && *current_posn != END_OF_INSN) + { + if (!is_space_char (*current_posn)) + { + as_bad ("Invalid character %s before %s operand", + output_invalid (*current_posn), + ordinal_names[insn.operands]); + return; + } + current_posn++; + } + token_start = current_posn; + paren_not_balanced = 0; + while (paren_not_balanced || *current_posn != ',') + { + if (*current_posn == END_OF_INSN) + { + if (paren_not_balanced) + { + as_bad ("Unbalanced parenthesis in %s operand.", + ordinal_names[insn.operands]); + return; + } + else + break; + } + else if (!is_operand_char (*current_posn) + && !is_space_char (*current_posn)) + { + as_bad ("Invalid character %s in %s operand", + output_invalid (*current_posn), + ordinal_names[insn.operands]); + return; + } + if (*current_posn == '(') + ++paren_not_balanced; + if (*current_posn == ')') + --paren_not_balanced; + current_posn++; + } + if (current_posn != token_start) + { + /* Yes, we've read in another operand. */ + this_operand = insn.operands++; + if (insn.operands > MAX_OPERANDS) + { + as_bad ("Spurious operands; (%d operands/instruction max)", + MAX_OPERANDS); + return; + } + + /* Now parse operand adding info to 'insn' as we go along. */ + save_char = *current_posn; + *current_posn = '\0'; + insn.operand_type[this_operand] = tic30_operand (token_start); + *current_posn = save_char; + if (insn.operand_type[this_operand] == NULL) + return; } - } - else - { - debug ("Direct reference is a number\n"); - current_op->direct.address = atoi (token + 1); - current_op->direct.resolved = 1; - } - current_op->op_type = Direct; - } - else if (*token == INDIRECT_REFERENCE) - { /* Indirect reference operand */ - int found_ar = 0; - int found_disp = 0; - int ar_number = -1; - int disp_number = 0; - int buffer_posn = 1; - ind_addr_type *ind_addr_op; - debug ("Found indirect reference\n"); - ind_buffer[0] = *token; - for (count = 1; count < strlen (token); count++) - { /* Strip operand */ - ind_buffer[buffer_posn] = TOLOWER (*(token + count)); - if ((*(token + count - 1) == 'a' || *(token + count - 1) == 'A') && - (*(token + count) == 'r' || *(token + count) == 'R')) + else { - /* AR reference is found, so get its number and remove it from the buffer - so it can pass through hash_find() */ - if (found_ar) + if (expecting_operand) { - as_bad ("More than one AR register found in indirect reference"); - return NULL; + as_bad ("Expecting operand after ','; got nothing"); + return; } - if (*(token + count + 1) < '0' || *(token + count + 1) > '7') + if (*current_posn == ',') { - as_bad ("Illegal AR register in indirect reference"); - return NULL; + as_bad ("Expecting operand before ','; got nothing"); + return; } - ar_number = *(token + count + 1) - '0'; - found_ar = 1; - count++; } - if (*(token + count) == '(') + + /* Now *current_posn must be either ',' or END_OF_INSN. */ + if (*current_posn == ',') { - /* Parenthesis found, so check if a displacement value is inside. If so, get - the value and remove it from the buffer. */ - if (is_digit_char (*(token + count + 1))) + if (*++current_posn == END_OF_INSN) { - char disp[10]; - int disp_posn = 0; - - if (found_disp) - { - as_bad ("More than one displacement found in indirect reference"); - return NULL; - } - count++; - while (*(token + count) != ')') - { - if (!is_digit_char (*(token + count))) - { - as_bad ("Invalid displacement in indirect reference"); - return NULL; - } - disp[disp_posn++] = *(token + (count++)); - } - disp[disp_posn] = '\0'; - disp_number = atoi (disp); - count--; - found_disp = 1; + /* Just skip it, if it's \n complain. */ + as_bad ("Expecting operand after ','; got nothing"); + return; } + expecting_operand = 1; } - buffer_posn++; } - ind_buffer[buffer_posn] = '\0'; - if (!found_ar) + while (*current_posn != END_OF_INSN); + } + + debug ("Number of operands found: %d\n", insn.operands); + + /* Check that number of operands is correct. */ + if (insn.operands != insn.tm->operands) + { + unsigned int i; + unsigned int numops = insn.tm->operands; + + /* If operands are not the same, then see if any of the operands are + not required. Then recheck with number of given operands. If they + are still not the same, then give an error, otherwise carry on. */ + for (i = 0; i < insn.tm->operands; i++) + if (insn.tm->operand_types[i] & NotReq) + numops--; + if (insn.operands != numops) { - as_bad ("AR register not found in indirect reference"); - return NULL; + as_bad ("Incorrect number of operands given"); + return; } - ind_addr_op = (ind_addr_type *) hash_find (ind_hash, ind_buffer); - if (ind_addr_op) + } + insn.addressing_mode = AM_NotReq; + for (count = 0; count < insn.operands; count++) + { + if (insn.operand_type[count]->op_type & insn.tm->operand_types[count]) { - debug ("Found indirect reference: %s\n", ind_addr_op->syntax); - if (ind_addr_op->displacement == IMPLIED_DISP) - { - found_disp = 1; - disp_number = 1; - } - else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp) + debug ("Operand %d matches\n", count + 1); + /* If instruction has two operands and has an AddressMode + modifier then set addressing mode type for instruction. */ + if (insn.tm->opcode_modifier == AddressMode) { - /* Maybe an implied displacement of 1 again */ - as_bad ("required displacement wasn't given in indirect reference"); - return 0; + int addr_insn = 0; + /* Store instruction uses the second + operand for the address mode. */ + if ((insn.tm->operand_types[1] & (Indirect | Direct)) + == (Indirect | Direct)) + addr_insn = 1; + + if (insn.operand_type[addr_insn]->op_type & (AllReg)) + insn.addressing_mode = AM_Register; + else if (insn.operand_type[addr_insn]->op_type & Direct) + insn.addressing_mode = AM_Direct; + else if (insn.operand_type[addr_insn]->op_type & Indirect) + insn.addressing_mode = AM_Indirect; + else + insn.addressing_mode = AM_Immediate; } } else { - as_bad ("illegal indirect reference"); - return NULL; - } - if (found_disp && (disp_number < 0 || disp_number > 255)) - { - as_bad ("displacement must be an unsigned 8-bit number"); - return NULL; + as_bad ("The %s operand doesn't match", ordinal_names[count]); + return; } - current_op->indirect.mod = ind_addr_op->modfield; - current_op->indirect.disp = disp_number; - current_op->indirect.ARnum = ar_number; - current_op->op_type = Indirect; } - else + + /* Now set the addressing mode for 3 operand instructions. */ + if ((insn.tm->operand_types[0] & op3T1) + && (insn.tm->operand_types[1] & op3T2)) { - reg *regop = (reg *) hash_find (reg_hash, token); - if (regop) + /* Set the addressing mode to the values used for 2 operand + instructions in the G addressing field of the opcode. */ + char *p; + switch (insn.operand_type[0]->op_type) { - debug ("Found register operand: %s\n", regop->name); - if (regop->regtype == REG_ARn) - current_op->op_type = ARn; - else if (regop->regtype == REG_Rn) - current_op->op_type = Rn; - else if (regop->regtype == REG_DP) - current_op->op_type = DPReg; + case Rn: + case ARn: + case DPReg: + case OtherReg: + if (insn.operand_type[1]->op_type & (AllReg)) + insn.addressing_mode = AM_Register; + else if (insn.operand_type[1]->op_type & Indirect) + insn.addressing_mode = AM_Direct; else - current_op->op_type = OtherReg; - current_op->reg.opcode = regop->opcode; - } - else - { - if (!is_digit_char (*token) || *(token + 1) == 'x' || strchr (token, 'h')) { - char *save_input_line_pointer; - segT retval; - debug ("Probably a label: %s\n", token); - current_op->immediate.label = (char *) malloc (strlen (token) + 1); - strcpy (current_op->immediate.label, token); - current_op->immediate.label[strlen (token)] = '\0'; - save_input_line_pointer = input_line_pointer; - input_line_pointer = token; - debug ("Current input_line_pointer: %s\n", input_line_pointer); - retval = expression (¤t_op->immediate.imm_expr); - debug ("Expression type: %d\n", current_op->immediate.imm_expr.X_op); - debug ("Expression addnum: %d\n", current_op->immediate.imm_expr.X_add_number); - debug ("Segment: %d\n", retval); - input_line_pointer = save_input_line_pointer; - if (current_op->immediate.imm_expr.X_op == O_constant) - { - current_op->immediate.s_number = current_op->immediate.imm_expr.X_add_number; - current_op->immediate.u_number = (unsigned int) current_op->immediate.imm_expr.X_add_number; - current_op->immediate.resolved = 1; - } + /* Shouldn't make it to this stage. */ + as_bad ("Incompatible first and second operands in instruction"); + return; } + break; + case Indirect: + if (insn.operand_type[1]->op_type & (AllReg)) + insn.addressing_mode = AM_Indirect; + else if (insn.operand_type[1]->op_type & Indirect) + insn.addressing_mode = AM_Immediate; else { - unsigned count; - debug ("Found a number or displacement\n"); - for (count = 0; count < strlen (token); count++) - if (*(token + count) == '.') - current_op->immediate.decimal_found = 1; - current_op->immediate.label = (char *) malloc (strlen (token) + 1); - strcpy (current_op->immediate.label, token); - current_op->immediate.label[strlen (token)] = '\0'; - current_op->immediate.f_number = (float) atof (token); - current_op->immediate.s_number = (int) atoi (token); - current_op->immediate.u_number = (unsigned int) atoi (token); - current_op->immediate.resolved = 1; - } - current_op->op_type = Disp | Abs24 | Imm16 | Imm24; - if (current_op->immediate.u_number <= 31) - current_op->op_type |= IVector; - } - } - return current_op; -} - -/* next_line points to the next line after the current instruction (current_line). - Search for the parallel bars, and if found, merge two lines into internal syntax - for a parallel instruction: - q_[INSN1]_[INSN2] [OPERANDS1] | [OPERANDS2] - By this stage, all comments are scrubbed, and only the bare lines are given. - */ - -#define NONE 0 -#define START_OPCODE 1 -#define END_OPCODE 2 -#define START_OPERANDS 3 -#define END_OPERANDS 4 - -char * -tic30_find_parallel_insn (current_line, next_line) - char *current_line; - char *next_line; -{ - int found_parallel = 0; - char first_opcode[256]; - char second_opcode[256]; - char first_operands[256]; - char second_operands[256]; - char *parallel_insn; - - debug ("In tic30_find_parallel_insn()\n"); - while (!is_end_of_line[(unsigned char) *next_line]) - { - if (*next_line == PARALLEL_SEPARATOR && *(next_line + 1) == PARALLEL_SEPARATOR) - { - found_parallel = 1; - next_line++; - break; - } - next_line++; - } - if (!found_parallel) - return NULL; - debug ("Found a parallel instruction\n"); - { - int i; - char *opcode, *operands, *line; - - for (i = 0; i < 2; i++) - { - if (i == 0) - { - opcode = &first_opcode[0]; - operands = &first_operands[0]; - line = current_line; - } - else - { - opcode = &second_opcode[0]; - operands = &second_operands[0]; - line = next_line; - } + /* Shouldn't make it to this stage. */ + as_bad ("Incompatible first and second operands in instruction"); + return; + } + break; + } + /* Now make up the opcode for the 3 operand instructions. As in + parallel instructions, there will be no unresolved values, so they + can be fully formed and added to the frag table. */ + insn.opcode = insn.tm->base_opcode; + if (insn.operand_type[0]->op_type & Indirect) { - int search_status = NONE; - int char_ptr = 0; - char c; + insn.opcode |= (insn.operand_type[0]->indirect.ARnum); + insn.opcode |= (insn.operand_type[0]->indirect.mod << 3); + } + else + insn.opcode |= (insn.operand_type[0]->reg.opcode); - while (!is_end_of_line[(unsigned char) (c = *line)]) + if (insn.operand_type[1]->op_type & Indirect) + { + insn.opcode |= (insn.operand_type[1]->indirect.ARnum << 8); + insn.opcode |= (insn.operand_type[1]->indirect.mod << 11); + } + else + insn.opcode |= (insn.operand_type[1]->reg.opcode << 8); + + if (insn.operands == 3) + insn.opcode |= (insn.operand_type[2]->reg.opcode << 16); + + insn.opcode |= insn.addressing_mode; + p = frag_more (INSN_SIZE); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + /* Not a three operand instruction. */ + char *p; + int am_insn = -1; + insn.opcode = insn.tm->base_opcode; + /* Create frag for instruction - all instructions are 4 bytes long. */ + p = frag_more (INSN_SIZE); + if ((insn.operands > 0) && (insn.tm->opcode_modifier == AddressMode)) + { + insn.opcode |= insn.addressing_mode; + if (insn.addressing_mode == AM_Indirect) { - if (is_opcode_char (c) && search_status == NONE) - { - opcode[char_ptr++] = TOLOWER (c); - search_status = START_OPCODE; - } - else if (is_opcode_char (c) && search_status == START_OPCODE) - { - opcode[char_ptr++] = TOLOWER (c); - } - else if (!is_opcode_char (c) && search_status == START_OPCODE) - { - opcode[char_ptr] = '\0'; - char_ptr = 0; - search_status = END_OPCODE; - } - else if (is_operand_char (c) && search_status == START_OPERANDS) + /* Determine which operand gives the addressing mode. */ + if (insn.operand_type[0]->op_type & Indirect) + am_insn = 0; + if ((insn.operands > 1) + && (insn.operand_type[1]->op_type & Indirect)) + am_insn = 1; + insn.opcode |= (insn.operand_type[am_insn]->indirect.disp); + insn.opcode |= (insn.operand_type[am_insn]->indirect.ARnum << 8); + insn.opcode |= (insn.operand_type[am_insn]->indirect.mod << 11); + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.addressing_mode == AM_Register) + { + insn.opcode |= (insn.operand_type[0]->reg.opcode); + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.addressing_mode == AM_Direct) + { + if (insn.operand_type[0]->op_type & Direct) + am_insn = 0; + if ((insn.operands > 1) + && (insn.operand_type[1]->op_type & Direct)) + am_insn = 1; + if (insn.operands > 1) + insn.opcode |= + (insn.operand_type[! am_insn]->reg.opcode << 16); + if (insn.operand_type[am_insn]->direct.resolved == 1) { - operands[char_ptr++] = c; + /* Resolved values can be placed straight + into instruction word, and output. */ + insn.opcode |= + (insn.operand_type[am_insn]->direct.address & 0x0000FFFF); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); } - if (is_operand_char (c) && search_status == END_OPCODE) + else { - operands[char_ptr++] = c; - search_status = START_OPERANDS; + /* Unresolved direct addressing mode instruction. */ + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, + & insn.operand_type[am_insn]->direct.direct_expr, + 0, 0); } - line++; } - if (search_status != START_OPERANDS) - return NULL; - operands[char_ptr] = '\0'; - } - } - } - parallel_insn = (char *) malloc (strlen (first_opcode) + strlen (first_operands) + - strlen (second_opcode) + strlen (second_operands) + 8); - sprintf (parallel_insn, "q_%s_%s %s | %s", first_opcode, second_opcode, first_operands, second_operands); - debug ("parallel insn = %s\n", parallel_insn); - return parallel_insn; -} - -#undef NONE -#undef START_OPCODE -#undef END_OPCODE -#undef START_OPERANDS -#undef END_OPERANDS - -/* In order to get gas to ignore any | chars at the start of a line, - this function returns true if a | is found in a line. */ - -int -tic30_unrecognized_line (c) - int c; -{ - debug ("In tc_unrecognized_line\n"); - return (c == PARALLEL_SEPARATOR); -} - -int -md_estimate_size_before_relax (fragP, segment) - fragS *fragP ATTRIBUTE_UNUSED; - segT segment ATTRIBUTE_UNUSED; -{ - debug ("In md_estimate_size_before_relax()\n"); - return 0; -} - -void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - register fragS *fragP ATTRIBUTE_UNUSED; -{ - debug ("In md_convert_frag()\n"); -} - -void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg ATTRIBUTE_UNUSED; -{ - valueT value = *valP; - - debug ("In md_apply_fix() with value = %ld\n", (long) value); - debug ("Values in fixP\n"); - debug ("fx_size = %d\n", fixP->fx_size); - debug ("fx_pcrel = %d\n", fixP->fx_pcrel); - debug ("fx_where = %d\n", fixP->fx_where); - debug ("fx_offset = %d\n", (int) fixP->fx_offset); - { - char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; - - value /= INSN_SIZE; - if (fixP->fx_size == 1) - /* Special fix for LDP instruction. */ - value = (value & 0x00FF0000) >> 16; - - debug ("new value = %ld\n", (long) value); - md_number_to_chars (buf, value, fixP->fx_size); - } - - if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) - fixP->fx_done = 1; -} - -int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char *arg ATTRIBUTE_UNUSED; -{ - debug ("In md_parse_option()\n"); - return 0; -} + else if (insn.addressing_mode == AM_Immediate) + { + if (insn.operand_type[0]->immediate.resolved == 1) + { + char *keeploc; + int size; -void -md_show_usage (stream) - FILE *stream ATTRIBUTE_UNUSED; -{ - debug ("In md_show_usage()\n"); -} + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); -symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; -{ - debug ("In md_undefined_symbol()\n"); - return (symbolS *) 0; -} + switch (insn.tm->imm_arg_type) + { + case Imm_Float: + debug ("Floating point first operand\n"); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); -valueT -md_section_align (segment, size) - segT segment; - valueT size; -{ - debug ("In md_section_align() segment = %d and size = %d\n", segment, size); - size = (size + 3) / 4; - size *= 4; - debug ("New size value = %d\n", size); - return size; -} + keeploc = input_line_pointer; + input_line_pointer = + insn.operand_type[0]->immediate.label; -long -md_pcrel_from (fixP) - fixS *fixP; -{ - int offset; + if (md_atof ('f', p + 2, & size) != 0) + { + as_bad ("invalid short form floating point immediate operand"); + return; + } - debug ("In md_pcrel_from()\n"); - debug ("fx_where = %d\n", fixP->fx_where); - debug ("fx_size = %d\n", fixP->fx_size); - /* Find the opcode that represents the current instruction in the fr_literal - storage area, and check bit 21. Bit 21 contains whether the current instruction - is a delayed one or not, and then set the offset value appropriately. */ - if (fixP->fx_frag->fr_literal[fixP->fx_where - fixP->fx_size + 1] & 0x20) - offset = 3; - else - offset = 1; - debug ("offset = %d\n", offset); - /* PC Relative instructions have a format: - displacement = Label - (PC + offset) - This function returns PC + offset where: - fx_where - fx_size = PC - INSN_SIZE * offset = offset number of instructions - */ - return fixP->fx_where - fixP->fx_size + (INSN_SIZE * offset); -} + input_line_pointer = keeploc; + break; -char * -md_atof (what_statement_type, literalP, sizeP) - int what_statement_type; - char *literalP; - int *sizeP; -{ - int prec; - char *token; - char keepval; - unsigned long value; - float float_value; - debug ("In md_atof()\n"); - debug ("precision = %c\n", what_statement_type); - debug ("literal = %s\n", literalP); - debug ("line = "); - token = input_line_pointer; - while (!is_end_of_line[(unsigned char) *input_line_pointer] - && (*input_line_pointer != ',')) - { - debug ("%c", *input_line_pointer); - input_line_pointer++; - } - keepval = *input_line_pointer; - *input_line_pointer = '\0'; - debug ("\n"); - float_value = (float) atof (token); - *input_line_pointer = keepval; - debug ("float_value = %f\n", float_value); - switch (what_statement_type) - { - case 'f': - case 'F': - case 's': - case 'S': - prec = 2; - break; + case Imm_UInt: + debug ("Unsigned int first operand\n"); + if (insn.operand_type[0]->immediate.decimal_found) + as_warn ("rounding down first operand float to unsigned int"); + if (insn.operand_type[0]->immediate.u_number > 0xFFFF) + as_warn ("only lower 16-bits of first operand are used"); + insn.opcode |= + (insn.operand_type[0]->immediate.u_number & 0x0000FFFFL); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + break; - case 'd': - case 'D': - case 'r': - case 'R': - prec = 4; - break; + case Imm_SInt: + debug ("Int first operand\n"); - default: - *sizeP = 0; - return "Bad call to MD_ATOF()"; - } - if (float_value == 0.0) - { - value = (prec == 2) ? 0x00008000L : 0x80000000L; - } - else - { - unsigned long exp, sign, mant, tmsfloat; - tmsfloat = *((long *) &float_value); - sign = tmsfloat & 0x80000000; - mant = tmsfloat & 0x007FFFFF; - exp = tmsfloat & 0x7F800000; - exp <<= 1; - if (exp == 0xFF000000) - { - if (mant == 0) - value = 0x7F7FFFFF; - else if (sign == 0) - value = 0x7F7FFFFF; - else - value = 0x7F800000; + if (insn.operand_type[0]->immediate.decimal_found) + as_warn ("rounding down first operand float to signed int"); + + if (insn.operand_type[0]->immediate.s_number < -32768 || + insn.operand_type[0]->immediate.s_number > 32767) + { + as_bad ("first operand is too large for 16-bit signed int"); + return; + } + insn.opcode |= + (insn.operand_type[0]->immediate.s_number & 0x0000FFFFL); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + break; + } + } + else + { + /* Unresolved immediate label. */ + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, + & insn.operand_type[0]->immediate.imm_expr, + 0, 0); + } + } } - else + else if (insn.tm->opcode_modifier == PCRel) { - exp -= 0x7F000000; - if (sign) + /* Conditional Branch and Call instructions. */ + if ((insn.tm->operand_types[0] & (AllReg | Disp)) + == (AllReg | Disp)) { - mant = mant & 0x007FFFFF; - mant = -mant; - mant = mant & 0x00FFFFFF; - if (mant == 0) + if (insn.operand_type[0]->op_type & (AllReg)) { - mant |= 0x00800000; - exp = (long) exp - 0x01000000; + insn.opcode |= (insn.operand_type[0]->reg.opcode); + insn.opcode |= PC_Register; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + insn.opcode |= PC_Relative; + if (insn.operand_type[0]->immediate.resolved == 1) + { + insn.opcode |= + (insn.operand_type[0]->immediate.s_number & 0x0000FFFF); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), + 2, & insn.operand_type[0]->immediate.imm_expr, + 1, 0); + } + } + } + else if ((insn.tm->operand_types[0] & ARn) == ARn) + { + /* Decrement and Branch instructions. */ + insn.opcode |= ((insn.operand_type[0]->reg.opcode - 0x08) << 22); + if (insn.operand_type[1]->op_type & (AllReg)) + { + insn.opcode |= (insn.operand_type[1]->reg.opcode); + insn.opcode |= PC_Register; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.operand_type[1]->immediate.resolved == 1) + { + if (insn.operand_type[0]->immediate.decimal_found) + { + as_bad ("first operand is floating point"); + return; + } + if (insn.operand_type[0]->immediate.s_number < -32768 || + insn.operand_type[0]->immediate.s_number > 32767) + { + as_bad ("first operand is too large for 16-bit signed int"); + return; + } + insn.opcode |= (insn.operand_type[1]->immediate.s_number); + insn.opcode |= PC_Relative; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + insn.opcode |= PC_Relative; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 2 - frag_now->fr_literal, 2, + & insn.operand_type[1]->immediate.imm_expr, + 1, 0); } } - tmsfloat = exp | mant; - value = tmsfloat; } - if (prec == 2) + else if (insn.tm->operand_types[0] == IVector) { - long exp, mant; - - if (tmsfloat == 0x80000000) + /* Trap instructions. */ + if (insn.operand_type[0]->op_type & IVector) + insn.opcode |= (insn.operand_type[0]->immediate.u_number); + else { - value = 0x8000; + /* Shouldn't get here. */ + as_bad ("interrupt vector for trap instruction out of range"); + return; } - else + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.tm->opcode_modifier == StackOp + || insn.tm->opcode_modifier == Rotate) + { + /* Push, Pop and Rotate instructions. */ + insn.opcode |= (insn.operand_type[0]->reg.opcode << 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if ((insn.tm->operand_types[0] & (Abs24 | Direct)) + == (Abs24 | Direct)) + { + /* LDP Instruction needs to be tested + for before the next section. */ + if (insn.operand_type[0]->op_type & Direct) { - value = 0; - exp = (tmsfloat & 0xFF000000); - exp >>= 24; - mant = tmsfloat & 0x007FFFFF; - if (tmsfloat & 0x00800000) + if (insn.operand_type[0]->direct.resolved == 1) { - mant |= 0xFF000000; - mant += 0x00000800; - mant >>= 12; - mant |= 0x00000800; - mant &= 0x0FFF; - if (exp > 7) - value = 0x7800; + /* Direct addressing uses lower 8 bits of direct address. */ + insn.opcode |= + (insn.operand_type[0]->direct.address & 0x00FF0000) >> 16; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); } else { - mant |= 0x00800000; - mant += 0x00000800; - exp += (mant >> 24); - mant >>= 12; - mant &= 0x07FF; - if (exp > 7) - value = 0x77FF; + fixS *fix; + + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), + 1, &insn.operand_type[0]->direct.direct_expr, 0, 0); + /* Ensure that the assembler doesn't complain + about fitting a 24-bit address into 8 bits. */ + fix->fx_no_overflow = 1; } - if (exp < -8) - value = 0x8000; - if (value == 0) + } + else + { + if (insn.operand_type[0]->immediate.resolved == 1) { - mant = (exp << 12) | mant; - value = mant & 0xFFFF; + /* Immediate addressing uses upper 8 bits of address. */ + if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF) + { + as_bad ("LDP instruction needs a 24-bit operand"); + return; + } + insn.opcode |= + ((insn.operand_type[0]->immediate.u_number & 0x00FF0000) >> 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + fixS *fix; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), + 1, &insn.operand_type[0]->immediate.imm_expr, + 0, 0); + fix->fx_no_overflow = 1; } } } - } - md_number_to_chars (literalP, value, prec); - *sizeP = prec; - return 0; -} - -void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; -{ - debug ("In md_number_to_chars()\n"); - number_to_chars_bigendian (buf, val, n); - /* number_to_chars_littleendian(buf,val,n); */ -} - -#define F(SZ,PCREL) (((SZ) << 1) + (PCREL)) -#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break - -arelent * -tc_gen_reloc (section, fixP) - asection *section ATTRIBUTE_UNUSED; - fixS *fixP; -{ - arelent *rel; - bfd_reloc_code_real_type code = 0; - - debug ("In tc_gen_reloc()\n"); - debug ("fixP.size = %d\n", fixP->fx_size); - debug ("fixP.pcrel = %d\n", fixP->fx_pcrel); - debug ("addsy.name = %s\n", S_GET_NAME (fixP->fx_addsy)); - switch (F (fixP->fx_size, fixP->fx_pcrel)) - { - MAP (1, 0, BFD_RELOC_TIC30_LDP); - MAP (2, 0, BFD_RELOC_16); - MAP (3, 0, BFD_RELOC_24); - MAP (2, 1, BFD_RELOC_16_PCREL); - MAP (4, 0, BFD_RELOC_32); - default: - as_bad ("Can not do %d byte %srelocation", fixP->fx_size, - fixP->fx_pcrel ? "pc-relative " : ""); - } -#undef MAP -#undef F + else if (insn.tm->operand_types[0] & (Imm24)) + { + /* Unconditional Branch and Call instructions. */ + if (insn.operand_type[0]->immediate.resolved == 1) + { + if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF) + as_warn ("first operand is too large for a 24-bit displacement"); + insn.opcode |= + (insn.operand_type[0]->immediate.u_number & 0x00FFFFFF); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 1 - (frag_now->fr_literal), 3, + & insn.operand_type[0]->immediate.imm_expr, 0, 0); + } + } + else if (insn.tm->operand_types[0] & NotReq) + /* Check for NOP instruction without arguments. */ + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - rel = (arelent *) xmalloc (sizeof (arelent)); - assert (rel != 0); - rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); - *rel->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); - rel->address = fixP->fx_frag->fr_address + fixP->fx_where; - rel->addend = 0; - rel->howto = bfd_reloc_type_lookup (stdoutput, code); - if (!rel->howto) - { - const char *name; - name = S_GET_NAME (fixP->fx_addsy); - if (name == NULL) - name = ""; - as_fatal ("Cannot generate relocation type for symbol %s, code %s", name, bfd_get_reloc_code_name (code)); + else if (insn.tm->operands == 0) + /* Check for instructions without operands. */ + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); } - return rel; -} + debug ("Addressing mode: %08X\n", insn.addressing_mode); + { + unsigned int i; -void -md_operand (expressionP) - expressionS *expressionP ATTRIBUTE_UNUSED; -{ - debug ("In md_operand()\n"); + for (i = 0; i < insn.operands; i++) + { + if (insn.operand_type[i]->immediate.label) + free (insn.operand_type[i]->immediate.label); + free (insn.operand_type[i]); + } + } + debug ("Final opcode: %08X\n", insn.opcode); + debug ("\n"); } -char output_invalid_buf[8]; - -char * -output_invalid (c) - char c; -{ - if (ISPRINT (c)) - sprintf (output_invalid_buf, "'%c'", c); - else - sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); - return output_invalid_buf; -} diff --git a/gas/config/tc-tic30.h b/gas/config/tc-tic30.h index 039671b57d6..c6cb16935fd 100644 --- a/gas/config/tc-tic30.h +++ b/gas/config/tc-tic30.h @@ -1,5 +1,5 @@ /* tc-tic30.h -- Header file for tc-tic30.c - Copyright 1998, 2000, 2002 Free Software Foundation, Inc. + Copyright 1998, 2000, 2002, 2005 Free Software Foundation, Inc. Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au) This file is part of GAS, the GNU Assembler. @@ -30,27 +30,23 @@ #define TARGET_ARCH bfd_arch_tic30 #define TARGET_BYTES_BIG_ENDIAN 1 - #define WORKING_DOT_WORD - -char *output_invalid PARAMS ((int c)); - -#define END_OF_INSN '\0' -#define MAX_OPERANDS 6 -#define DIRECT_REFERENCE '@' -#define INDIRECT_REFERENCE '*' -#define PARALLEL_SEPARATOR '|' -#define INSN_SIZE 4 +#define END_OF_INSN '\0' +#define MAX_OPERANDS 6 +#define DIRECT_REFERENCE '@' +#define INDIRECT_REFERENCE '*' +#define PARALLEL_SEPARATOR '|' +#define INSN_SIZE 4 /* Define this to 1 if you want the debug output to be on stdout, otherwise stderr will be used. If stderr is used, there will be a better synchronisation with the as_bad outputs, but you can't capture the output. */ -#define USE_STDOUT 0 +#define USE_STDOUT 0 #define tc_unrecognized_line tic30_unrecognized_line -extern int tic30_unrecognized_line PARAMS ((int)); +extern int tic30_unrecognized_line (int); #define tc_aout_pre_write_hook {} -- 2.30.2