diff options
Diffstat (limited to 'gas/config/tc-tic30.c')
-rw-r--r-- | gas/config/tc-tic30.c | 1888 |
1 files changed, 0 insertions, 1888 deletions
diff --git a/gas/config/tc-tic30.c b/gas/config/tc-tic30.c deleted file mode 100644 index 255c06a381d..00000000000 --- a/gas/config/tc-tic30.c +++ /dev/null @@ -1,1888 +0,0 @@ -/* tc-c30.c -- Assembly code for the Texas Instruments TMS320C30 - Copyright (C) 1998, 1999 Free Software Foundation. - 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) - any later version. - - GAS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -/* - Texas Instruments TMS320C30 machine specific gas. - Written by Steven Haworth (steve@pm.cse.rmit.edu.au). - Bugs & suggestions are completely welcome. This is free software. - Please help us make it better. - */ - -#include "as.h" -#include "opcode/tic30.h" - -/* put here all non-digit non-letter charcters that may occur in an operand */ -static char operand_special_chars[] = "%$-+(,)*._~/<>&^!:[@]"; -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 line_separator_chars[] = ""; - -const char *md_shortopts = ""; -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 */ -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 */ -static char opcode_chars[256]; -static char register_chars[256]; -static char operand_chars[256]; -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]) - -const pseudo_typeS md_pseudo_table[] = -{ - {0, 0, 0} -}; - -#undef USE_STDOUT -#define USE_STDOUT 1 - -#ifdef USE_STDARG - -#include <stdarg.h> - -int -debug (const char *string,...) -{ - if (flag_debug) - { - va_list argptr; - char str[100]; - - va_start (argptr, string); - vsprintf (str, string, argptr); - if (str[0] == '\0') - return (0); - va_end (argptr); - fputs (str, USE_STDOUT ? stdout : stderr); - return strlen (str); - } - else - return 0; -} -#else -int -debug (string, va_alist) - const char *string; - va_dcl -{ - if (flag_debug) - { - va_list argptr; - char str[100]; - int cnt; - - va_start (argptr, string); - cnt = vsprintf (str, string, argptr); - if (str[0] == NULL) - return (0); - va_end (argptr); - fputs (str, USE_STDOUT ? stdout : stderr); - return (cnt); - } - else - return 0; -} -#endif - -/* hash table for opcode lookup */ -static struct hash_control *op_hash; -/* hash table for parallel opcode lookup */ -static struct hash_control *parop_hash; -/* hash table for register lookup */ -static struct hash_control *reg_hash; -/* hash table for indirect addressing lookup */ -static struct hash_control *ind_hash; - -void -md_begin () -{ - 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); - if (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); - if (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); - if (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); - if (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 */ - { - register int c; - register char *p; - - for (c = 0; c < 256; c++) - { - if (islower (c) || isdigit (c)) - { - opcode_chars[c] = c; - register_chars[c] = c; - } - else if (isupper (c)) - { - opcode_chars[c] = tolower (c); - register_chars[c] = opcode_chars[c]; - } - else if (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; - } - for (p = operand_special_chars; *p != '\0'; p++) - operand_chars[(unsigned char) *p] = *p; - } -} - -/* 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 */ -#define PC_Register 0x00000000 -#define PC_Relative 0x02000000 - -typedef struct -{ - unsigned op_type; - struct - { - int resolved; - unsigned address; - char *label; - expressionS direct_expr; - } - direct; - struct - { - unsigned mod; - int ARnum; - unsigned char disp; - } - indirect; - struct - { - unsigned opcode; - } - reg; - struct - { - int resolved; - int decimal_found; - float f_number; - int s_number; - unsigned int u_number; - char *label; - expressionS imm_expr; - } - 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 */ - 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 */ - }; - -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; - 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; /* after white space */ - 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; /* 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) - { - 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); /* 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) - { - int i; - 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); - { - 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"); -} - -struct tic30_par_insn -{ - partemplate *tm; /* Template of current parallel instruction */ - int 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 */ -}; - -struct tic30_par_insn p_insn; - -int -tic30_parallel_insn (char *token) -{ - static partemplate *p_opcode; - char *current_posn = token; - char *token_start; - char save_char; - - 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 */ - save_char = *current_posn; - *current_posn = '\0'; - p_opcode = (partemplate *) hash_find (parop_hash, token); - if (p_opcode) - { - debug ("Found instruction %s\n", p_opcode->name); - p_insn.tm = p_opcode; - } - else - { - char first_opcode[6] = - {0}; - char second_opcode[6] = - {0}; - int i; - int current_opcode = -1; - int char_ptr = 0; - - 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: - first_opcode[char_ptr++] = ch; - break; - case 1: - second_opcode[char_ptr++] = ch; - 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); - p_insn.tm = p_opcode; - p_insn.swap_operands = 1; - } - else - return 0; - } - *current_posn = save_char; - } - { /* 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) - { - if (!is_space_char (*current_posn) && *current_posn != PARALLEL_SEPARATOR) - { - as_bad ("Invalid character %s before %s operand", - output_invalid (*current_posn), - ordinal_names[insn.operands]); - return 1; - } - if (*current_posn == PARALLEL_SEPARATOR) - found_separator = 1; - current_posn++; - } - token_start = current_posn; /* after white space */ - 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 1; - } - else - break; /* we are done */ - } - else if (*current_posn == PARALLEL_SEPARATOR) - { - while (is_space_char (*(current_posn - 1))) - current_posn--; - 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 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 */ - p_insn.operands[found_separator]++; - if (p_insn.operands[found_separator] > MAX_OPERANDS) - { - as_bad ("Spurious operands; (%d operands/instruction max)", - MAX_OPERANDS); - return 1; - } - /* 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] = - tic30_operand (token_start); - *current_posn = save_char; - if (!p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1]) - return 1; - } - else - { - if (expecting_operand) - { - as_bad ("Expecting operand after ','; got nothing"); - return 1; - } - if (*current_posn == ',') - { - as_bad ("Expecting operand before ','; got nothing"); - return 1; - } - } - /* 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 1; - } - expecting_operand = 1; - } - } - while (*current_posn != END_OF_INSN); /* until we get end of insn */ - } - if (p_insn.swap_operands) - { - int temp_num, i; - operand *temp_op; - - temp_num = p_insn.operands[0]; - p_insn.operands[0] = p_insn.operands[1]; - p_insn.operands[1] = temp_num; - for (i = 0; i < MAX_OPERANDS; i++) - { - temp_op = p_insn.operand_type[0][i]; - p_insn.operand_type[0][i] = p_insn.operand_type[1][i]; - 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 */ - int count; - int num_rn = 0; - int num_ind = 0; - for (count = 0; count < 2; count++) - { - int i; - for (i = 0; i < p_insn.operands[count]; i++) - { - 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); - 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. */ - 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) - num_ind++; - } - } - if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) == (Indirect | Rn)) - { - /* 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 */ - 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)) - { - 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)) - { - as_bad ("destination for add/subtract can only be R2 or R3"); - return 1; - } - /* 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 */ - else if (p_insn.operand_type[1][0]->op_type & Indirect) - p_insn.p_field = 0x01000000; /* Ind * Rn, Ind +/- Rn */ - else - 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 */ - 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 */ - 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; - } - else - { - operand *temp; - 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; - } - } - } - } - 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. */ - { - 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); - } - { - 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; -{ - int count; - char ind_buffer[strlen (token)]; - operand *current_op; - - 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 >= 0 && 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[(int) *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[(int) (c = *line)] && *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; - segT segment; -{ - debug ("In md_estimate_size_before_relax()\n"); - return 0; -} - -void -md_convert_frag (abfd, sec, fragP) - bfd *abfd; - segT sec; - register fragS *fragP; -{ - debug ("In md_convert_frag()\n"); -} - -int -md_apply_fix (fixP, valP) - fixS *fixP; - valueT *valP; -{ - 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); - } - return 1; -} - -int -md_parse_option (c, arg) - int c; - char *arg; -{ - int i; - - debug ("In md_parse_option()\n"); - for (i = 0; i < c; i++) - { - printf ("%c\n", arg[c]); - } - return 0; -} - -void -md_show_usage (stream) - FILE *stream; -{ - debug ("In md_show_usage()\n"); -} - -symbolS * -md_undefined_symbol (name) - char *name; -{ - debug ("In md_undefined_symbol()\n"); - return (symbolS *) 0; -} - -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; -} - -long -md_pcrel_from (fixP) - 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 (what_statement_type, literalP, sizeP) - int what_statement_type; - char *literalP; - int *sizeP; -{ - int prec; - char *token; - char keepval; - unsigned long value; - /* char *atof_ieee (); */ - 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) *input_line_pointer] && (*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; - 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; - } - else - { - exp -= 0x7F000000; - if (sign) - { - 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 (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; - 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 = (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; - if (fixP->fx_pcrel) - rel->addend = fixP->fx_addnumber; - else - 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 = "<unknown>"; - as_fatal ("Cannot generate relocation type for symbol %s, code %s", name, bfd_get_reloc_code_name (code)); - } - return rel; -} - -void -tc_aout_pre_write_hook () -{ - debug ("In tc_aout_pre_write_hook()\n"); -} - -void -md_operand (expressionP) - expressionS *expressionP; -{ - debug ("In md_operand()\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; -} |