X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-tic30.c;h=725691c3acaaa40922bae2bd64015896ec2a2ebc;hb=c1f61bd2b0644fc710dcfbb378a63f0b34be8903;hp=7234741c9b81990cd643ebd45c8a6264921ce8c6;hpb=aef6203bd6d412d65f539a41f1abd07b14d7a05d;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-tic30.c b/gas/config/tc-tic30.c index 7234741c9b..725691c3ac 100644 --- a/gas/config/tc-tic30.c +++ b/gas/config/tc-tic30.c @@ -1,13 +1,12 @@ /* tc-c30.c -- Assembly code for the Texas Instruments TMS320C30 - Copyright 1998, 1999, 2000, 2001, 2002, 2003 - Free Software Foundation, Inc. + Copyright (C) 1998-2016 Free Software Foundation, Inc. Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au) This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -17,8 +16,8 @@ You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ /* Texas Instruments TMS320C30 machine specific gas. Written by Steven Haworth (steve@pm.cse.rmit.edu.au). @@ -28,42 +27,37 @@ #include "as.h" #include "safe-ctype.h" #include "opcode/tic30.h" -#ifdef ANSI_PROTOTYPES -#include -#else -#include -#endif /* Put here all non-digit non-letter characters that may occur in an operand. */ static char operand_special_chars[] = "%$-+(,)*._~/<>&^!:[@]"; -static char *ordinal_names[] = { - "first", "second", "third", "fourth", "fifth" +static const char *ordinal_names[] = +{ + N_("first"), N_("second"), N_("third"), N_("fourth"), N_("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,31 +65,30 @@ 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 ATTRIBUTE_PRINTF_1 +debug (const char *string, ...) { if (flag_debug) { char str[100]; + va_list argptr; - VA_OPEN (argptr, string); - VA_FIXEDARG (argptr, const char *, string); + va_start (argptr, string); vsprintf (str, string, argptr); - VA_CLOSE (argptr); + va_end (argptr); if (str[0] == '\0') return (0); fputs (str, USE_STDOUT ? stdout : stderr); @@ -105,64 +98,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; + const insn_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 +191,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 +213,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 +256,409 @@ 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; +insn_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 +{ + 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[sizeof (unsigned char) * 2 + 6]; - 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)) + snprintf (output_invalid_buf, sizeof (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') + snprintf (output_invalid_buf, sizeof (output_invalid_buf), + "(0x%x)", (unsigned char) 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 *op, *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) + { + op = &first_opcode[0]; + operands = &first_operands[0]; + line = current_line; + } + else + { + op = &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; + op[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) + op[char_ptr++] = TOLOWER (c); + else if (!is_opcode_char (c) && search_status == START_OPCODE) { - as_bad ("Expecting operand after ','; got nothing"); - return; + op[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; + operand *current_op; + + debug ("In tic30_operand with %s\n", token); + current_op = XCNEW (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) - { - 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 ("The %s operand doesn't match", ordinal_names[count]); - return; - } - } - /* Now set the addressing mode for 3 operand instructions. */ - if ((insn.tm->operand_types[0] & op3T1) && (insn.tm->operand_types[1] & op3T2)) - { - /* 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 + 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: %ld\n", + (long) current_op->direct.direct_expr.X_add_number); + debug ("Segment: %p\n", retval); + + input_line_pointer = save_input_line_pointer; + + if (current_op->direct.direct_expr.X_op == O_constant) { - /* Shouldn't make it to this stage */ - as_bad ("Incompatible first and second operands in instruction"); - return; + current_op->direct.address = + current_op->direct.direct_expr.X_add_number; + current_op->direct.resolved = 1; } - 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); + debug ("Direct reference is a number\n"); + current_op->direct.address = atoi (token + 1); + current_op->direct.resolved = 1; } - 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); + current_op->op_type = Direct; } - 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)) + 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; + char * ind_buffer; + + ind_buffer = XNEWVEC (char, strlen (token)); + + 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")); + free (ind_buffer); + 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")); + free (ind_buffer); + 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")); + free (ind_buffer); + 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")); + free (ind_buffer); + 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")); + free (ind_buffer); + 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")); + free (ind_buffer); + return NULL; } } - 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")); + free (ind_buffer); + 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")); + free (ind_buffer); + 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; + free (ind_buffer); + } + 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 = xstrdup (token); + 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: %ld\n", + (long) current_op->immediate.imm_expr.X_add_number); + debug ("Segment: %p\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); + 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 = xstrdup (token); + 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 +668,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 +683,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 +692,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 +716,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,18 +733,23 @@ 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", + as_bad (_("Invalid character %s before %s operand"), output_invalid (*current_posn), ordinal_names[insn.operands]); return 1; @@ -881,20 +758,22 @@ 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) { if (paren_not_balanced) { - as_bad ("Unbalanced parenthesis in %s operand.", + as_bad (_("Unbalanced parenthesis in %s operand."), ordinal_names[insn.operands]); return 1; } else - break; /* we are done */ + break; } else if (*current_posn == PARALLEL_SEPARATOR) { @@ -902,29 +781,34 @@ 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", + 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) { - as_bad ("Spurious operands; (%d operands/instruction max)", + as_bad (_("Spurious operands; (%d operands/instruction max)"), 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] = @@ -937,28 +821,31 @@ tic30_parallel_insn (char *token) { if (expecting_operand) { - as_bad ("Expecting operand after ','; got nothing"); + as_bad (_("Expecting operand after ','; got nothing")); return 1; } if (*current_posn == ',') { - as_bad ("Expecting operand before ','; got nothing"); + as_bad (_("Expecting operand before ','; got nothing")); 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 */ - as_bad ("Expecting operand after ','; got nothing"); + { + /* 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 +861,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"); + 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"); + 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 +891,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"); + as_bad (_("incorrect format for multiply parallel instruction")); return 1; } + if (num_ind != 2) - { /* Shouldn't get here */ - as_bad ("incorrect format for multiply parallel instruction"); + { + /* 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"); + 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"); + 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 +968,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,476 +976,161 @@ 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) - { - current_op->direct.address = current_op->direct.direct_expr.X_add_number; - current_op->direct.resolved = 1; - } - } - 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')) - { - /* AR reference is found, so get its number and remove it from the buffer - so it can pass through hash_find() */ - if (found_ar) - { - as_bad ("More than one AR register found in indirect reference"); - return NULL; - } - 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++; - } - if (*(token + count) == '(') - { - /* 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 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; - } - } - buffer_posn++; - } - ind_buffer[buffer_posn] = '\0'; - if (!found_ar) - { - 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) - { - found_disp = 1; - disp_number = 1; - } - else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp) - { - /* Maybe an implied displacement of 1 again */ - as_bad ("required displacement wasn't given in indirect reference"); - return 0; - } - } - 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; - } - 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) - { - 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 - 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; - } - } - 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; - } - { - int search_status = NONE; - int char_ptr = 0; - char c; - - while (!is_end_of_line[(unsigned char) (c = *line)]) - { - 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) - { - operands[char_ptr++] = c; - } - if (is_operand_char (c) && search_status == END_OPCODE) - { - operands[char_ptr++] = c; - search_status = START_OPERANDS; - } - 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; -} +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 (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - register fragS *fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + 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; +md_apply_fix (fixS *fixP, + valueT *valP, + segT seg ATTRIBUTE_UNUSED) { valueT value = *valP; @@ -1548,7 +1138,7 @@ md_apply_fix3 (fixP, valP, seg) 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_where = %ld\n", fixP->fx_where); debug ("fx_offset = %d\n", (int) fixP->fx_offset); { char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; @@ -1567,53 +1157,49 @@ md_apply_fix3 (fixP, valP, seg) } int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, + const char *arg ATTRIBUTE_UNUSED) { debug ("In md_parse_option()\n"); return 0; } void -md_show_usage (stream) - FILE *stream ATTRIBUTE_UNUSED; +md_show_usage (FILE *stream ATTRIBUTE_UNUSED) { debug ("In md_show_usage()\n"); } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { debug ("In md_undefined_symbol()\n"); return (symbolS *) 0; } valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { - debug ("In md_section_align() segment = %d and size = %d\n", segment, size); + debug ("In md_section_align() segment = %p and size = %lu\n", + segment, (unsigned long) size); size = (size + 3) / 4; size *= 4; - debug ("New size value = %d\n", size); + debug ("New size value = %lu\n", (unsigned long) size); return size; } long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { int offset; debug ("In md_pcrel_from()\n"); - debug ("fx_where = %d\n", fixP->fx_where); + debug ("fx_where = %ld\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. */ + /* 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 @@ -1623,22 +1209,21 @@ md_pcrel_from (fixP) displacement = Label - (PC + offset) This function returns PC + offset where: fx_where - fx_size = PC - INSN_SIZE * offset = offset number of instructions - */ + INSN_SIZE * offset = offset number of instructions. */ return fixP->fx_where - fixP->fx_size + (INSN_SIZE * offset); } -char * -md_atof (what_statement_type, literalP, sizeP) - int what_statement_type; - char *literalP; - int *sizeP; +const 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); @@ -1650,12 +1235,14 @@ md_atof (what_statement_type, literalP, sizeP) 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': @@ -1674,16 +1261,23 @@ md_atof (what_statement_type, literalP, sizeP) default: *sizeP = 0; - return "Bad call to MD_ATOF()"; + return _("Unrecognized or unsupported floating point constant"); } + if (float_value == 0.0) - { - value = (prec == 2) ? 0x00008000L : 0x80000000L; - } + value = (prec == 2) ? 0x00008000L : 0x80000000L; else { unsigned long exp, sign, mant, tmsfloat; - tmsfloat = *((long *) &float_value); + union + { + float f; + long l; + } + converter; + + converter.f = float_value; + tmsfloat = converter.l; sign = tmsfloat & 0x80000000; mant = tmsfloat & 0x007FFFFF; exp = tmsfloat & 0x7F800000; @@ -1716,71 +1310,63 @@ md_atof (what_statement_type, literalP, sizeP) } if (prec == 2) { - long exp, mant; + long expon, mantis; if (tmsfloat == 0x80000000) - { - value = 0x8000; - } + value = 0x8000; else { value = 0; - exp = (tmsfloat & 0xFF000000); - exp >>= 24; - mant = tmsfloat & 0x007FFFFF; + expon = (tmsfloat & 0xFF000000); + expon >>= 24; + mantis = tmsfloat & 0x007FFFFF; if (tmsfloat & 0x00800000) { - mant |= 0xFF000000; - mant += 0x00000800; - mant >>= 12; - mant |= 0x00000800; - mant &= 0x0FFF; - if (exp > 7) + mantis |= 0xFF000000; + mantis += 0x00000800; + mantis >>= 12; + mantis |= 0x00000800; + mantis &= 0x0FFF; + if (expon > 7) value = 0x7800; } else { - mant |= 0x00800000; - mant += 0x00000800; - exp += (mant >> 24); - mant >>= 12; - mant &= 0x07FF; - if (exp > 7) + mantis |= 0x00800000; + mantis += 0x00000800; + expon += (mantis >> 24); + mantis >>= 12; + mantis &= 0x07FF; + if (expon > 7) value = 0x77FF; } - if (exp < -8) + if (expon < -8) value = 0x8000; if (value == 0) { - mant = (exp << 12) | mant; - value = mant & 0xFFFF; + mantis = (expon << 12) | mantis; + value = mantis & 0xFFFF; } } } } md_number_to_chars (literalP, value, prec); *sizeP = prec; - return 0; + return NULL; } void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (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; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) { arelent *rel; bfd_reloc_code_real_type code = 0; @@ -1789,6 +1375,7 @@ tc_gen_reloc (section, fixP) 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); @@ -1797,15 +1384,15 @@ tc_gen_reloc (section, fixP) 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 " : ""); + as_bad (_("Can not do %d byte %srelocation"), fixP->fx_size, + fixP->fx_pcrel ? _("pc-relative ") : ""); } #undef MAP #undef F - rel = (arelent *) xmalloc (sizeof (arelent)); - assert (rel != 0); - rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + rel = XNEW (arelent); + gas_assert (rel != 0); + rel->sym_ptr_ptr = XNEW (asymbol *); *rel->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); rel->address = fixP->fx_frag->fr_address + fixP->fx_where; rel->addend = 0; @@ -1813,30 +1400,609 @@ tc_gen_reloc (section, fixP) 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)); + as_fatal ("Cannot generate relocation type for symbol %s, code %s", + name, bfd_get_reloc_code_name (code)); } return rel; } void -md_operand (expressionP) - expressionS *expressionP ATTRIBUTE_UNUSED; +md_operand (expressionS *expressionP ATTRIBUTE_UNUSED) { debug ("In md_operand()\n"); } -char output_invalid_buf[8]; - -char * -output_invalid (c) - char c; +void +md_assemble (char *line) { - if (ISPRINT (c)) - sprintf (output_invalid_buf, "'%c'", c); + insn_template *op; + 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 - sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); - return output_invalid_buf; + 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'; + op = (insn_template *) hash_find (op_hash, token_start); + if (op) + { + debug ("Found instruction %s\n", op->name); + insn.tm = op; + } + 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 + { + if (expecting_operand) + { + as_bad (_("Expecting operand after ','; got nothing")); + return; + } + if (*current_posn == ',') + { + 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; + } + expecting_operand = 1; + } + } + 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 (_("Incorrect number of operands given")); + return; + } + } + 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 ("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) + { + 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 (_("The %s operand doesn't match"), ordinal_names[count]); + return; + } + } + + /* Now set the addressing mode for 3 operand instructions. */ + if ((insn.tm->operand_types[0] & op3T1) + && (insn.tm->operand_types[1] & op3T2)) + { + /* 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)) + { + 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) + { + 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) + { + /* 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); + } + 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); + } + } + else if (insn.addressing_mode == AM_Immediate) + { + if (insn.operand_type[0]->immediate.resolved == 1) + { + char *keeploc; + int size; + + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); + + 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); + + 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 (_("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 if (insn.tm->opcode_modifier == PCRel) + { + /* Conditional Branch and Call instructions. */ + if ((insn.tm->operand_types[0] & (AllReg | Disp)) + == (AllReg | 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); + } + } + } + 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); + } + } + } + else if (insn.tm->operand_types[0] == IVector) + { + /* 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); + } + 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) + { + 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; + } + } + 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; + } + } + } + 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); + + else if (insn.tm->operands == 0) + /* Check for instructions without operands. */ + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + 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"); }