13595Sksrini/* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X 23900Sksrini Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 33595Sksrini 2009, 2010 Free Software Foundation, Inc. 43595Sksrini Contributed by Timothy Wall (twall@cygnus.com) 53595Sksrini 63595Sksrini This file is part of GAS, the GNU Assembler. 73595Sksrini 83595Sksrini GAS is free software; you can redistribute it and/or modify 93595Sksrini it under the terms of the GNU General Public License as published by 103595Sksrini the Free Software Foundation; either version 3, or (at your option) 113595Sksrini any later version. 123595Sksrini 133595Sksrini GAS is distributed in the hope that it will be useful, 143595Sksrini but WITHOUT ANY WARRANTY; without even the implied warranty of 153595Sksrini MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 163595Sksrini GNU General Public License for more details. 173595Sksrini 183595Sksrini You should have received a copy of the GNU General Public License 193595Sksrini along with GAS; see the file COPYING. If not, write to the Free 203595Sksrini Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 213595Sksrini 02110-1301, USA. */ 223595Sksrini 233595Sksrini/* Texas Instruments TMS320C54X machine specific gas. 243595Sksrini Written by Timothy Wall (twall@alum.mit.edu). 253595Sksrini 263595Sksrini Valuable things to do: 273595Sksrini Pipeline conflict warnings 283595Sksrini We encode/decode "ld #_label, dp" differently in relocatable files 293595Sksrini This means we're not compatible with TI output containing those 303595Sksrini expressions. We store the upper nine bits; TI stores the lower nine 313595Sksrini bits. How they recover the original upper nine bits is beyond me. 323595Sksrini 334073Sksrini Tests to add to expect testsuite: 343595Sksrini '=' and '==' with .if, .elseif, and .break 353595Sksrini 363595Sksrini Incompatibilities (mostly trivial): 373595Sksrini We don't allow ''' 383595Sksrini We fill text section with zeroes instead of "nop"s 393595Sksrini We don't convert '' or "" to a single instance 403595Sksrini We don't convert '' to '\0' 413595Sksrini We don't allow strings with .byte/.half/.short/.long 423595Sksrini Probably details of the subsym stuff are different 433595Sksrini TI sets labels to be data type 4 (T_INT); GAS uses T_NULL. 443595Sksrini 453595Sksrini COFF1 limits section names to 8 characters. 463595Sksrini Some of the default behavior changed from COFF1 to COFF2. */ 473595Sksrini 483595Sksrini#include <limits.h> 493595Sksrini#include "as.h" 503595Sksrini#include "safe-ctype.h" 513595Sksrini#include "sb.h" 523595Sksrini#include "macro.h" 533595Sksrini#include "subsegs.h" 543595Sksrini#include "struc-symbol.h" 553595Sksrini#include "opcode/tic54x.h" 563595Sksrini#include "obj-coff.h" 574066Sksrini#include <math.h> 583595Sksrini 593595Sksrini 603595Sksrinistatic struct stag 613595Sksrini{ 623595Sksrini symbolS *sym; /* Symbol for this stag; value is offset. */ 633595Sksrini const char *name; /* Shortcut to symbol name. */ 643595Sksrini bfd_vma size; /* Size of struct/union. */ 654066Sksrini int current_bitfield_offset; /* Temporary for tracking fields. */ 663595Sksrini int is_union; 673595Sksrini struct stag_field /* List of fields. */ 684066Sksrini { 694066Sksrini const char *name; 703595Sksrini bfd_vma offset; /* Of start of this field. */ 713595Sksrini int bitfield_offset; /* Of start of this field. */ 723595Sksrini struct stag *stag; /* If field is struct/union. */ 733595Sksrini struct stag_field *next; 743595Sksrini } *field; 753595Sksrini /* For nesting; used only in stag construction. */ 763595Sksrini struct stag *inner; /* Enclosed .struct. */ 773595Sksrini struct stag *outer; /* Enclosing .struct. */ 784066Sksrini} *current_stag = NULL; 794073Sksrini 803900Sksrini#define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm. */ 814066Sksrini 823691Sksrinitypedef struct _tic54x_insn 833595Sksrini{ 843595Sksrini const insn_template *tm; /* Opcode template. */ 853900Sksrini 863595Sksrini char mnemonic[MAX_LINE]; /* Opcode name/mnemonic. */ 873595Sksrini char parmnemonic[MAX_LINE]; /* 2nd mnemonic of parallel insn. */ 883595Sksrini 893595Sksrini int opcount; 903595Sksrini struct opstruct 913595Sksrini { 923595Sksrini char buf[MAX_LINE]; 933595Sksrini enum optype type; 943595Sksrini expressionS exp; 953595Sksrini } operands[MAX_OPERANDS]; 963595Sksrini 973595Sksrini int paropcount; 983595Sksrini struct opstruct paroperands[MAX_OPERANDS]; 993595Sksrini 1003595Sksrini int is_lkaddr; 1013595Sksrini int lkoperand; 1023595Sksrini int words; /* Size of insn in 16-bit words. */ 1033595Sksrini int using_default_dst; /* Do we need to explicitly set an 1043595Sksrini omitted OP_DST operand? */ 1053595Sksrini struct 1063595Sksrini { 1073595Sksrini unsigned short word; /* Final encoded opcode data. */ 1083595Sksrini int unresolved; 1093595Sksrini int r_nchars; /* Relocation size. */ 1103595Sksrini bfd_reloc_code_real_type r_type; /* Relocation type. */ 1113595Sksrini expressionS addr_expr; /* Storage for unresolved expressions. */ 1123595Sksrini } opcode[3]; 1133595Sksrini} tic54x_insn; 1143595Sksrini 1153595Sksrinienum cpu_version 1163595Sksrini{ 1173595Sksrini VNONE = 0, V541 = 1, V542 = 2, V543 = 3, V545 = 5, V548 = 8, V549 = 9, 1183595Sksrini V545LP = 15, V546LP = 16 1193595Sksrini}; 1203595Sksrini 1213595Sksrinienum address_mode 1223595Sksrini{ 1233595Sksrini c_mode, /* 16-bit addresses. */ 1243595Sksrini far_mode /* >16-bit addresses. */ 1253595Sksrini}; 1263595Sksrini 1273595Sksrinistatic segT stag_saved_seg; 1283595Sksrinistatic subsegT stag_saved_subseg; 1293595Sksrini 1303595Sksriniconst char comment_chars[] = ";"; 1313595Sksriniconst char line_comment_chars[] = ";*#"; /* At column zero only. */ 1323595Sksriniconst char line_separator_chars[] = ""; /* Not permitted. */ 1333595Sksrini 1343595Sksriniint emitting_long = 0; 1353595Sksrini 1363595Sksrini/* Characters which indicate that this is a floating point constant. */ 1373595Sksriniconst char FLT_CHARS[] = "fF"; 1383595Sksrini 1393595Sksrini/* Characters that can be used to separate mantissa from exp in FP 1403595Sksrini nums. */ 1413595Sksriniconst char EXP_CHARS[] = "eE"; 1423595Sksrini 1433595Sksriniconst char *md_shortopts = ""; 1443595Sksrini 1453786Sksrini#define OPTION_ADDRESS_MODE (OPTION_MD_BASE) 1463595Sksrini#define OPTION_CPU_VERSION (OPTION_ADDRESS_MODE + 1) 1473595Sksrini#define OPTION_COFF_VERSION (OPTION_CPU_VERSION + 1) 1483595Sksrini#define OPTION_STDERR_TO_FILE (OPTION_COFF_VERSION + 1) 1493595Sksrini 1503595Sksrinistruct option md_longopts[] = 1513595Sksrini{ 1523595Sksrini { "mfar-mode", no_argument, NULL, OPTION_ADDRESS_MODE }, 1533595Sksrini { "mf", no_argument, NULL, OPTION_ADDRESS_MODE }, 1543595Sksrini { "mcpu", required_argument, NULL, OPTION_CPU_VERSION }, 1553595Sksrini { "merrors-to-file", required_argument, NULL, OPTION_STDERR_TO_FILE }, 1563595Sksrini { "me", required_argument, NULL, OPTION_STDERR_TO_FILE }, 1573595Sksrini { NULL, no_argument, NULL, 0}, 1583595Sksrini}; 1593595Sksrini 1603595Sksrinisize_t md_longopts_size = sizeof (md_longopts); 1613595Sksrini 1623595Sksrinistatic int assembly_begun = 0; 1633595Sksrini/* Addressing mode is not entirely implemented; the latest rev of the Other 1644066Sksrini assembler doesn't seem to make any distinction whatsoever; all relocations 1653595Sksrini are stored as extended relocatiosn. Older versions used REL16 vs RELEXT16, 1663595Sksrini but now it seems all relocations are RELEXT16. We use all RELEXT16. 1673691Sksrini 1684066Sksrini The cpu version is kind of a waste of time as well. There is one 1693595Sksrini instruction (RND) for LP devices only, and several for devices with 1703595Sksrini extended addressing only. We include it for compatibility. */ 1713595Sksrinistatic enum address_mode amode = c_mode; 1723595Sksrinistatic enum cpu_version cpu = VNONE; 1733595Sksrini 1743595Sksrini/* Include string substitutions in listing? */ 1753595Sksrinistatic int listing_sslist = 0; 1763595Sksrini 1773595Sksrini/* Did we do subsym substitutions on the line? */ 1783595Sksrinistatic int substitution_line = 0; 1793595Sksrini 1803595Sksrini/* Last label seen. */ 1813595Sksrinistatic symbolS *last_label_seen = NULL; 1823595Sksrini 1833595Sksrini/* This ensures that all new labels are unique. */ 1843595Sksrinistatic int local_label_id; 1853595Sksrini 1863595Sksrinistatic struct hash_control *subsym_recurse_hash; /* Prevent infinite recurse. */ 1873595Sksrinistatic struct hash_control *math_hash; /* Built-in math functions. */ 1883595Sksrini/* Allow maximum levels of macro nesting; level 0 is the main substitution 1893595Sksrini symbol table. The other assembler only does 32 levels, so there! */ 1903595Sksrinistatic struct hash_control *subsym_hash[100]; 1913595Sksrini 1923595Sksrini/* Keep track of local labels so we can substitute them before GAS sees them 1933595Sksrini since macros use their own 'namespace' for local labels, use a separate hash 1943595Sksrini 1953595Sksrini We do our own local label handling 'cuz it's subtly different from the 1963595Sksrini stock GAS handling. 1973595Sksrini 1983595Sksrini We use our own macro nesting counter, since GAS overloads it when expanding 1993595Sksrini other things (like conditionals and repeat loops). */ 2003595Sksrinistatic int macro_level = 0; 2013595Sksrinistatic struct hash_control *local_label_hash[100]; 2023595Sksrini/* Keep track of struct/union tags. */ 2033595Sksrinistatic struct hash_control *stag_hash; 2043595Sksrinistatic struct hash_control *op_hash; 2053595Sksrinistatic struct hash_control *parop_hash; 2063595Sksrinistatic struct hash_control *reg_hash; 2073595Sksrinistatic struct hash_control *mmreg_hash; 2083595Sksrinistatic struct hash_control *cc_hash; 2093595Sksrinistatic struct hash_control *cc2_hash; 2103595Sksrinistatic struct hash_control *cc3_hash; 2113595Sksrinistatic struct hash_control *sbit_hash; 2123691Sksrinistatic struct hash_control *misc_symbol_hash; 2134066Sksrini 2144066Sksrini/* Only word (et al.), align, or conditionals are allowed within 2153691Sksrini .struct/.union. */ 2164066Sksrini#define ILLEGAL_WITHIN_STRUCT() \ 2174066Sksrini do \ 2184066Sksrini if (current_stag != NULL) \ 2194066Sksrini { \ 2204066Sksrini as_bad (_("pseudo-op illegal within .struct/.union")); \ 2214066Sksrini return; \ 2224066Sksrini } \ 2234066Sksrini while (0) 2244066Sksrini 2254066Sksrini 2264066Sksrinistatic void subsym_create_or_replace (char *, char *); 2274066Sksrinistatic char *subsym_lookup (char *, int); 2284066Sksrinistatic char *subsym_substitute (char *, int); 2293595Sksrini 2303595Sksrini 2313595Sksrinivoid 2323595Sksrinimd_show_usage (FILE *stream) 2333595Sksrini{ 2343595Sksrini fprintf (stream, _("C54x-specific command line options:\n")); 2353595Sksrini fprintf (stream, _("-mfar-mode | -mf Use extended addressing\n")); 2363595Sksrini fprintf (stream, _("-mcpu=<CPU version> Specify the CPU version\n")); 2373595Sksrini fprintf (stream, _("-merrors-to-file <filename>\n")); 2383595Sksrini fprintf (stream, _("-me <filename> Redirect errors to a file\n")); 2393595Sksrini} 2403595Sksrini 2413595Sksrini/* Output a single character (upper octect is zero). */ 2423595Sksrini 2433595Sksrinistatic void 2443595Sksrinitic54x_emit_char (char c) 2453595Sksrini{ 2463595Sksrini expressionS expn; 2473595Sksrini 2483595Sksrini expn.X_op = O_constant; 2493786Sksrini expn.X_add_number = c; 2503595Sksrini emit_expr (&expn, 2); 2513786Sksrini} 2523786Sksrini 2533786Sksrini/* Walk backwards in the frag chain. */ 2543786Sksrini 2553786Sksrinistatic fragS * 2563786Sksrinifrag_prev (fragS *frag, segT seg) 2573786Sksrini{ 2583786Sksrini segment_info_type *seginfo = seg_info (seg); 2593786Sksrini fragS *fragp; 2603786Sksrini 2613786Sksrini for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next) 2623786Sksrini if (fragp->fr_next == frag) 2633786Sksrini return fragp; 2643786Sksrini 2653786Sksrini return NULL; 2663786Sksrini} 2673786Sksrini 2683786Sksrinistatic fragS * 2693786Sksrinibit_offset_frag (fragS *frag, segT seg) 2703786Sksrini{ 2713595Sksrini while (frag != NULL) 2723595Sksrini { 2733595Sksrini if (frag->fr_fix == 0 2743595Sksrini && frag->fr_opcode == NULL 2753595Sksrini && frag->tc_frag_data == 0) 2763595Sksrini frag = frag_prev (frag, seg); 2773595Sksrini else 2783786Sksrini return frag; 2793595Sksrini } 2803595Sksrini return NULL; 2813595Sksrini} 2823595Sksrini 2833595Sksrini/* Return the number of bits allocated in the most recent word, or zero if 2843595Sksrini none. .field/.space/.bes may leave words partially allocated. */ 2853595Sksrini 2863595Sksrinistatic int 2873786Sksrinifrag_bit_offset (fragS *frag, segT seg) 2883786Sksrini{ 2893786Sksrini frag = bit_offset_frag (frag, seg); 2903595Sksrini 2913595Sksrini if (frag) 2923595Sksrini return frag->fr_opcode != NULL ? -1 : frag->tc_frag_data; 2933595Sksrini 2943595Sksrini return 0; 2953595Sksrini} 2963786Sksrini 2973595Sksrini/* Read an expression from a C string; returns a pointer past the end of the 2983786Sksrini expression. */ 2993786Sksrini 3003786Sksrinistatic char * 3013786Sksriniparse_expression (char *str, expressionS *expn) 3023786Sksrini{ 3033786Sksrini char *s; 3043786Sksrini char *tmp; 3053786Sksrini 3063786Sksrini tmp = input_line_pointer; /* Save line pointer. */ 3073595Sksrini input_line_pointer = str; 3083595Sksrini expression (expn); 3093595Sksrini s = input_line_pointer; 3103595Sksrini input_line_pointer = tmp; /* Restore line pointer. */ 3113595Sksrini return s; /* Return pointer to where parsing stopped. */ 3123786Sksrini} 3133595Sksrini 3143595Sksrini/* .asg "character-string"|character-string, symbol 3153595Sksrini 3163595Sksrini .eval is the only pseudo-op allowed to perform arithmetic on substitution 3173595Sksrini symbols. all other use of symbols defined with .asg are currently 3183595Sksrini unsupported. */ 3193595Sksrini 3203595Sksrinistatic void 3213595Sksrinitic54x_asg (int x ATTRIBUTE_UNUSED) 3223595Sksrini{ 3233595Sksrini int c; 3243595Sksrini char *name; 3253595Sksrini char *str; 3263595Sksrini char *tmp; 3273595Sksrini int quoted = *input_line_pointer == '"'; 3283595Sksrini 3293595Sksrini ILLEGAL_WITHIN_STRUCT (); 3303595Sksrini 3313595Sksrini if (quoted) 3323595Sksrini { 3333595Sksrini int len; 3343595Sksrini str = demand_copy_C_string (&len); 3353595Sksrini c = *input_line_pointer; 3363595Sksrini } 3373595Sksrini else 3383595Sksrini { 3393595Sksrini str = input_line_pointer; 3403595Sksrini while ((c = *input_line_pointer) != ',') 3413691Sksrini { 3423595Sksrini if (is_end_of_line[(int) *input_line_pointer]) 3433691Sksrini break; 3443595Sksrini ++input_line_pointer; 3453595Sksrini } 3463595Sksrini *input_line_pointer = 0; 3473595Sksrini } 3483595Sksrini if (c != ',') 3493595Sksrini { 3503595Sksrini as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'")); 3513595Sksrini ignore_rest_of_line (); 3523595Sksrini return; 3533595Sksrini } 3543595Sksrini 3553595Sksrini name = ++input_line_pointer; 3563595Sksrini c = get_symbol_end (); /* Get terminator. */ 3573595Sksrini if (!ISALPHA (*name)) 3583595Sksrini { 3593595Sksrini as_bad (_("symbols assigned with .asg must begin with a letter")); 3603595Sksrini ignore_rest_of_line (); 3613595Sksrini return; 3623595Sksrini } 3634066Sksrini 3644066Sksrini tmp = xmalloc (strlen (str) + 1); 3654066Sksrini strcpy (tmp, str); 3664066Sksrini str = tmp; 3674066Sksrini tmp = xmalloc (strlen (name) + 1); 3684066Sksrini strcpy (tmp, name); 3694066Sksrini name = tmp; 3704066Sksrini subsym_create_or_replace (name, str); 3714066Sksrini *input_line_pointer = c; 3724066Sksrini demand_empty_rest_of_line (); 3734066Sksrini} 3744066Sksrini 3754066Sksrini/* .eval expression, symbol 3764066Sksrini There's something screwy about this. The other assembler sometimes does and 3774066Sksrini sometimes doesn't substitute symbols defined with .eval. 3784066Sksrini We'll put the symbols into the subsym table as well as the normal symbol 3794066Sksrini table, since that's what works best. */ 3804066Sksrini 3814066Sksrinistatic void 3824066Sksrinitic54x_eval (int x ATTRIBUTE_UNUSED) 3834066Sksrini{ 3844066Sksrini char c; 3854066Sksrini int value; 3864066Sksrini char *name; 3874066Sksrini symbolS *symbolP; 3884066Sksrini char valuestr[32], *tmp; 3894066Sksrini int quoted; 3904066Sksrini 3914066Sksrini ILLEGAL_WITHIN_STRUCT (); 3924066Sksrini 3934066Sksrini SKIP_WHITESPACE (); 3944066Sksrini 3954066Sksrini quoted = *input_line_pointer == '"'; 3964066Sksrini if (quoted) 3974066Sksrini ++input_line_pointer; 3984066Sksrini value = get_absolute_expression (); 3994066Sksrini if (quoted) 4004066Sksrini { 4014066Sksrini if (*input_line_pointer != '"') 4024066Sksrini { 4034066Sksrini as_bad (_("Unterminated string after absolute expression")); 4044066Sksrini ignore_rest_of_line (); 4054066Sksrini return; 4064066Sksrini } 4074066Sksrini ++input_line_pointer; 4084066Sksrini } 4093595Sksrini if (*input_line_pointer++ != ',') 4103691Sksrini { 4113595Sksrini as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'")); 4123595Sksrini ignore_rest_of_line (); 4133595Sksrini return; 4143595Sksrini } 4153595Sksrini name = input_line_pointer; 4163595Sksrini c = get_symbol_end (); /* Get terminator. */ 4174066Sksrini tmp = xmalloc (strlen (name) + 1); 4184066Sksrini name = strcpy (tmp, name); 4193691Sksrini *input_line_pointer = c; 4203691Sksrini 4214066Sksrini if (!ISALPHA (*name)) 4224066Sksrini { 4234066Sksrini as_bad (_("symbols assigned with .eval must begin with a letter")); 4243595Sksrini ignore_rest_of_line (); 4254066Sksrini return; 4264066Sksrini } 4274066Sksrini symbolP = symbol_new (name, absolute_section, 4283595Sksrini (valueT) value, &zero_address_frag); 4293595Sksrini SF_SET_LOCAL (symbolP); 4303595Sksrini symbol_table_insert (symbolP); 4313595Sksrini 4323595Sksrini /* The "other" assembler sometimes doesn't put .eval's in the subsym table 4333595Sksrini But since there's not written rule as to when, don't even bother trying 4343595Sksrini to match their behavior. */ 4353595Sksrini sprintf (valuestr, "%d", value); 4363595Sksrini tmp = xmalloc (strlen (valuestr) + 1); 4373595Sksrini strcpy (tmp, valuestr); 4383595Sksrini subsym_create_or_replace (name, tmp); 4393595Sksrini 4403827Smcimadamore demand_empty_rest_of_line (); 4413595Sksrini} 4423595Sksrini 4433595Sksrini/* .bss symbol, size [, [blocking flag] [, alignment flag] 4443595Sksrini 4453595Sksrini alignment is to a longword boundary; blocking is to 128-word boundary. 4463595Sksrini 4473595Sksrini 1) if there is a hole in memory, this directive should attempt to fill it 4483595Sksrini (not yet implemented). 4493595Sksrini 4503595Sksrini 2) if the blocking flag is not set, allocate at the current SPC 4513595Sksrini otherwise, check to see if the current SPC plus the space to be 4523595Sksrini allocated crosses the page boundary (128 words). 4533595Sksrini if there's not enough space, create a hole and align with the next page 4543595Sksrini boundary. 4553595Sksrini (not yet implemented). */ 4563595Sksrini 4573595Sksrinistatic void 4583595Sksrinitic54x_bss (int x ATTRIBUTE_UNUSED) 4593595Sksrini{ 4603595Sksrini char c; 4613595Sksrini char *name; 4623595Sksrini char *p; 4633595Sksrini int words; 4643595Sksrini segT current_seg; 4653595Sksrini subsegT current_subseg; 4663595Sksrini symbolS *symbolP; 4673595Sksrini int block = 0; 4683595Sksrini int align = 0; 4693595Sksrini 4703595Sksrini ILLEGAL_WITHIN_STRUCT (); 4713595Sksrini 4723595Sksrini current_seg = now_seg; /* Save current seg. */ 4733595Sksrini current_subseg = now_subseg; /* Save current subseg. */ 4743595Sksrini 4753595Sksrini name = input_line_pointer; 4763595Sksrini c = get_symbol_end (); /* Get terminator. */ 4773595Sksrini if (c != ',') 4783595Sksrini { 4793595Sksrini as_bad (_(".bss size argument missing\n")); 4803595Sksrini ignore_rest_of_line (); 4813595Sksrini return; 4823595Sksrini } 4833595Sksrini 4843595Sksrini ++input_line_pointer; 4853595Sksrini words = get_absolute_expression (); 4863595Sksrini if (words < 0) 4873827Smcimadamore { 4883595Sksrini as_bad (_(".bss size %d < 0!"), words); 4893595Sksrini ignore_rest_of_line (); 4903595Sksrini return; 4913595Sksrini } 4923595Sksrini 4933595Sksrini if (*input_line_pointer == ',') 4943595Sksrini { 4953595Sksrini /* The blocking flag may be missing. */ 4963595Sksrini ++input_line_pointer; 4973595Sksrini if (*input_line_pointer != ',') 4983595Sksrini block = get_absolute_expression (); 4993595Sksrini else 5003595Sksrini block = 0; 5013595Sksrini 5023595Sksrini if (*input_line_pointer == ',') 5033595Sksrini { 5043595Sksrini ++input_line_pointer; 5053595Sksrini align = get_absolute_expression (); 5063595Sksrini } 5073691Sksrini else 5083595Sksrini align = 0; 5093595Sksrini } 5103827Smcimadamore else 5113595Sksrini block = align = 0; 5123595Sksrini 5133595Sksrini subseg_set (bss_section, 0); 5143595Sksrini symbolP = symbol_find_or_make (name); 5153595Sksrini 5163595Sksrini if (S_GET_SEGMENT (symbolP) == bss_section) 5173595Sksrini symbolP->sy_frag->fr_symbol = (symbolS *) NULL; 5184066Sksrini 5194066Sksrini symbol_set_frag (symbolP, frag_now); 5204066Sksrini p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, 5213691Sksrini (offsetT) (words * OCTETS_PER_BYTE), (char *) 0); 5224066Sksrini *p = 0; /* Fill char. */ 5234066Sksrini 5243595Sksrini S_SET_SEGMENT (symbolP, bss_section); 5254073Sksrini 5264073Sksrini /* The symbol may already have been created with a preceding 5274073Sksrini ".globl" directive -- be careful not to step on storage class 5284073Sksrini in that case. Otherwise, set it to static. */ 5294073Sksrini if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) 5304066Sksrini S_SET_STORAGE_CLASS (symbolP, C_STAT); 5314073Sksrini 5324066Sksrini if (align) 5334073Sksrini { 5344066Sksrini /* s_align eats end of line; restore it */ 5354066Sksrini s_align_bytes (4); 5364073Sksrini --input_line_pointer; 5374073Sksrini } 5384073Sksrini 5394073Sksrini if (block) 5404066Sksrini bss_section->flags |= SEC_TIC54X_BLOCK; 5414066Sksrini 5424066Sksrini subseg_set (current_seg, current_subseg); /* Restore current seg. */ 5434066Sksrini demand_empty_rest_of_line (); 5444066Sksrini} 5454066Sksrini 5464066Sksrinistatic void 5474066Sksrinistag_add_field_symbols (struct stag *stag, 5484066Sksrini const char *path, 5494066Sksrini bfd_vma base_offset, 5504066Sksrini symbolS *rootsym, 5514066Sksrini const char *root_stag_name) 5524066Sksrini{ 5534066Sksrini char prefix[strlen (path) + 2]; 5544066Sksrini struct stag_field *field = stag->field; 5553595Sksrini 5564066Sksrini /* Construct a symbol for every field contained within this structure 5574066Sksrini including fields within structure fields. */ 5584066Sksrini strcpy (prefix, path); 5593595Sksrini if (*path) 5603595Sksrini strcat (prefix, "."); 5613595Sksrini 5623595Sksrini while (field != NULL) 5633595Sksrini { 5643595Sksrini int len = strlen (prefix) + strlen (field->name) + 2; 5653595Sksrini char *name = xmalloc (len); 5664073Sksrini strcpy (name, prefix); 5674073Sksrini strcat (name, field->name); 5683595Sksrini 5693595Sksrini if (rootsym == NULL) 5703595Sksrini { 5714073Sksrini symbolS *sym; 5723595Sksrini sym = symbol_new (name, absolute_section, 5733595Sksrini (field->stag ? field->offset : 5744073Sksrini (valueT) (base_offset + field->offset)), 5754073Sksrini &zero_address_frag); 5764073Sksrini SF_SET_LOCAL (sym); 5774073Sksrini symbol_table_insert (sym); 5784073Sksrini } 5794073Sksrini else 5804073Sksrini { 5814073Sksrini char *replacement = xmalloc (strlen (name) 5824073Sksrini + strlen (stag->name) + 2); 5834073Sksrini strcpy (replacement, S_GET_NAME (rootsym)); 5843595Sksrini strcat (replacement, "+"); 5853595Sksrini strcat (replacement, root_stag_name); 5863595Sksrini strcat (replacement, name + strlen (S_GET_NAME (rootsym))); 5873595Sksrini hash_insert (subsym_hash[0], name, replacement); 5883595Sksrini } 5894073Sksrini 5904073Sksrini /* Recurse if the field is a structure. 5914073Sksrini Note the field offset is relative to the outermost struct. */ 5924073Sksrini if (field->stag != NULL) 5934073Sksrini stag_add_field_symbols (field->stag, name, 5944073Sksrini field->offset, 5954073Sksrini rootsym, root_stag_name); 5964073Sksrini field = field->next; 5974073Sksrini } 5984073Sksrini} 5994073Sksrini 6004073Sksrini/* Keep track of stag fields so that when structures are nested we can add the 6014073Sksrini complete dereferencing symbols to the symbol table. */ 6024073Sksrini 6034073Sksrinistatic void 6044073Sksrinistag_add_field (struct stag *parent, 6054073Sksrini const char *name, 6064073Sksrini bfd_vma offset, 6074073Sksrini struct stag *stag) 6084073Sksrini{ 6094073Sksrini struct stag_field *sfield = xmalloc (sizeof (struct stag_field)); 6104073Sksrini 6113595Sksrini memset (sfield, 0, sizeof (*sfield)); 6123595Sksrini sfield->name = strcpy (xmalloc (strlen (name) + 1), name); 6133595Sksrini sfield->offset = offset; 6143595Sksrini sfield->bitfield_offset = parent->current_bitfield_offset; 6153595Sksrini sfield->stag = stag; 6163595Sksrini if (parent->field == NULL) 6173595Sksrini parent->field = sfield; 6183595Sksrini else 6193595Sksrini { 6203595Sksrini struct stag_field *sf = parent->field; 6213595Sksrini while (sf->next != NULL) 6223595Sksrini sf = sf->next; 6233786Sksrini sf->next = sfield; 6243595Sksrini } 6253595Sksrini /* Only create a symbol for this field if the parent has no name. */ 6263595Sksrini if (!strncmp (".fake", parent->name, 5)) 6273595Sksrini { 6283595Sksrini symbolS *sym = symbol_new (name, absolute_section, 6293595Sksrini (valueT) offset, &zero_address_frag); 6303595Sksrini SF_SET_LOCAL (sym); 6313595Sksrini symbol_table_insert (sym); 6323595Sksrini } 6333595Sksrini} 6343595Sksrini 6353595Sksrini/* [STAG] .struct [OFFSET] 6363595Sksrini Start defining structure offsets (symbols in absolute section). */ 6373595Sksrini 6383595Sksrinistatic void 6393595Sksrinitic54x_struct (int arg) 6403595Sksrini{ 6413595Sksrini int start_offset = 0; 6423595Sksrini int is_union = arg; 6433595Sksrini 6443595Sksrini if (!current_stag) 6453595Sksrini { 6463595Sksrini /* Starting a new struct, switch to absolute section. */ 6473595Sksrini stag_saved_seg = now_seg; 6483595Sksrini stag_saved_subseg = now_subseg; 6493691Sksrini subseg_set (absolute_section, 0); 6503595Sksrini } 6513691Sksrini /* Align the current pointer. */ 6524066Sksrini else if (current_stag->current_bitfield_offset != 0) 6534066Sksrini { 6544073Sksrini ++abs_section_offset; 6554073Sksrini current_stag->current_bitfield_offset = 0; 6564073Sksrini } 6574066Sksrini 6584073Sksrini /* Offset expression is only meaningful for global .structs. */ 6594073Sksrini if (!is_union) 6604073Sksrini { 6614073Sksrini /* Offset is ignored in inner structs. */ 6623691Sksrini SKIP_WHITESPACE (); 6633595Sksrini if (!is_end_of_line[(int) *input_line_pointer]) 6643595Sksrini start_offset = get_absolute_expression (); 6653595Sksrini else 6663595Sksrini start_offset = 0; 6673691Sksrini } 6683715Sksrini 6693595Sksrini if (current_stag) 6703595Sksrini { 6713595Sksrini /* Nesting, link to outer one. */ 6723715Sksrini current_stag->inner = (struct stag *) xmalloc (sizeof (struct stag)); 6733715Sksrini memset (current_stag->inner, 0, sizeof (struct stag)); 6743715Sksrini current_stag->inner->outer = current_stag; 6753595Sksrini current_stag = current_stag->inner; 6763595Sksrini if (start_offset) 6773595Sksrini as_warn (_("Offset on nested structures is ignored")); 6783715Sksrini start_offset = abs_section_offset; 6793715Sksrini } 6803715Sksrini else 6813715Sksrini { 6823715Sksrini current_stag = (struct stag *) xmalloc (sizeof (struct stag)); 6833595Sksrini memset (current_stag, 0, sizeof (struct stag)); 6843595Sksrini abs_section_offset = start_offset; 6853715Sksrini } 6863715Sksrini current_stag->is_union = is_union; 6873715Sksrini 6883715Sksrini if (line_label == NULL) 6893715Sksrini { 6903595Sksrini static int struct_count = 0; 6913595Sksrini char fake[] = ".fake_stagNNNNNNN"; 6923595Sksrini sprintf (fake, ".fake_stag%d", struct_count++); 6933595Sksrini current_stag->sym = symbol_new (fake, absolute_section, 6943595Sksrini (valueT) abs_section_offset, 6953595Sksrini &zero_address_frag); 6963595Sksrini } 6973595Sksrini else 6983595Sksrini { 6993595Sksrini char label[strlen (S_GET_NAME (line_label)) + 1]; 7003595Sksrini strcpy (label, S_GET_NAME (line_label)); 7013595Sksrini current_stag->sym = symbol_new (label, absolute_section, 7023595Sksrini (valueT) abs_section_offset, 7033595Sksrini &zero_address_frag); 7043595Sksrini } 7053595Sksrini current_stag->name = S_GET_NAME (current_stag->sym); 7063595Sksrini SF_SET_LOCAL (current_stag->sym); 7073595Sksrini /* Nested .structs don't go into the symbol table. */ 7083595Sksrini if (current_stag->outer == NULL) 7093595Sksrini symbol_table_insert (current_stag->sym); 7103595Sksrini 7113595Sksrini line_label = NULL; 7123595Sksrini} 7133595Sksrini 7143595Sksrini/* [LABEL] .endstruct 7153595Sksrini finish defining structure offsets; optional LABEL's value will be the size 7163595Sksrini of the structure. */ 7173595Sksrini 7183595Sksrinistatic void 7193595Sksrinitic54x_endstruct (int is_union) 7203595Sksrini{ 7213595Sksrini int size; 7223824Sjlahoda const char *path = 7233824Sjlahoda !strncmp (current_stag->name, ".fake", 5) ? "" : current_stag->name; 7243595Sksrini 7253595Sksrini if (!current_stag || current_stag->is_union != is_union) 7263595Sksrini { 7273595Sksrini as_bad (_(".end%s without preceding .%s"), 7283595Sksrini is_union ? "union" : "struct", 7293595Sksrini is_union ? "union" : "struct"); 7303595Sksrini ignore_rest_of_line (); 7313595Sksrini return; 7323595Sksrini } 7333595Sksrini 7343595Sksrini /* Align end of structures. */ 7353595Sksrini if (current_stag->current_bitfield_offset) 7363824Sjlahoda { 7373595Sksrini ++abs_section_offset; 7383595Sksrini current_stag->current_bitfield_offset = 0; 7393715Sksrini } 7403595Sksrini 7413595Sksrini if (current_stag->is_union) 7423595Sksrini size = current_stag->size; 7433595Sksrini else 7443595Sksrini size = abs_section_offset - S_GET_VALUE (current_stag->sym); 7453595Sksrini if (line_label != NULL) 7463595Sksrini { 7473595Sksrini S_SET_VALUE (line_label, size); 7483595Sksrini symbol_table_insert (line_label); 7493691Sksrini line_label = NULL; 7503595Sksrini } 7513595Sksrini 7523691Sksrini /* Union size has already been calculated. */ 7533595Sksrini if (!current_stag->is_union) 7543595Sksrini current_stag->size = size; 7553595Sksrini /* Nested .structs don't get put in the stag table. */ 7563595Sksrini if (current_stag->outer == NULL) 7573595Sksrini { 7583595Sksrini hash_insert (stag_hash, current_stag->name, current_stag); 7593595Sksrini stag_add_field_symbols (current_stag, path, 7604073Sksrini S_GET_VALUE (current_stag->sym), 7613595Sksrini NULL, NULL); 7623595Sksrini } 7633595Sksrini current_stag = current_stag->outer; 7643595Sksrini 7653595Sksrini /* If this is a nested .struct/.union, add it as a field to the enclosing 7663595Sksrini one. otherwise, restore the section we were in. */ 7673595Sksrini if (current_stag != NULL) 7683595Sksrini { 7693691Sksrini stag_add_field (current_stag, current_stag->inner->name, 7703595Sksrini S_GET_VALUE (current_stag->inner->sym), 7713595Sksrini current_stag->inner); 7723595Sksrini } 7733595Sksrini else 7743595Sksrini subseg_set (stag_saved_seg, stag_saved_subseg); 7753595Sksrini} 7763595Sksrini 7773595Sksrini/* [LABEL] .tag STAG 7783595Sksrini Reference a structure within a structure, as a sized field with an optional 7793691Sksrini label. 7803595Sksrini If used outside of a .struct/.endstruct, overlays the given structure 7813786Sksrini format on the existing allocated space. */ 7823595Sksrini 7833595Sksrinistatic void 7843595Sksrinitic54x_tag (int ignore ATTRIBUTE_UNUSED) 7853595Sksrini{ 7863595Sksrini char *name = input_line_pointer; 7873691Sksrini int c = get_symbol_end (); 7883595Sksrini struct stag *stag = (struct stag *) hash_find (stag_hash, name); 7893595Sksrini 7903691Sksrini if (!stag) 7913691Sksrini { 7923595Sksrini if (*name) 7933595Sksrini as_bad (_("Unrecognized struct/union tag '%s'"), name); 7943595Sksrini else 7953691Sksrini as_bad (_(".tag requires a structure tag")); 7963595Sksrini ignore_rest_of_line (); 7973595Sksrini return; 7983595Sksrini } 7993595Sksrini if (line_label == NULL) 8003691Sksrini { 8013691Sksrini as_bad (_("Label required for .tag")); 8023595Sksrini ignore_rest_of_line (); 8033595Sksrini return; 8043595Sksrini } 8053595Sksrini else 8063691Sksrini { 8073691Sksrini char label[strlen (S_GET_NAME (line_label)) + 1]; 8083691Sksrini 8093595Sksrini strcpy (label, S_GET_NAME (line_label)); 8103595Sksrini if (current_stag != NULL) 8113595Sksrini stag_add_field (current_stag, label, 8123595Sksrini abs_section_offset - S_GET_VALUE (current_stag->sym), 8133595Sksrini stag); 8143595Sksrini else 8153595Sksrini { 8163595Sksrini symbolS *sym = symbol_find (label); 8173595Sksrini 8183595Sksrini if (!sym) 8193595Sksrini { 8203595Sksrini as_bad (_(".tag target '%s' undefined"), label); 8213595Sksrini ignore_rest_of_line (); 8223691Sksrini return; 8233595Sksrini } 8243595Sksrini stag_add_field_symbols (stag, S_GET_NAME (sym), 8253595Sksrini S_GET_VALUE (stag->sym), sym, stag->name); 8263595Sksrini } 8273595Sksrini } 8283595Sksrini 8293595Sksrini /* Bump by the struct size, but only if we're within a .struct section. */ 8303595Sksrini if (current_stag != NULL && !current_stag->is_union) 8313595Sksrini abs_section_offset += stag->size; 8323595Sksrini 8333595Sksrini *input_line_pointer = c; 8343691Sksrini demand_empty_rest_of_line (); 8353595Sksrini line_label = NULL; 8363691Sksrini} 8373691Sksrini 8383595Sksrini/* Handle all .byte, .char, .double, .field, .float, .half, .int, .long, 8393595Sksrini .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword, 8403595Sksrini and .word. */ 8413595Sksrini 8423595Sksrinistatic void 8433595Sksrinitic54x_struct_field (int type) 8443595Sksrini{ 8454066Sksrini int size; 8464066Sksrini int count = 1; 8473595Sksrini int new_bitfield_offset = 0; 8483595Sksrini int field_align = current_stag->current_bitfield_offset != 0; 8493595Sksrini int longword_align = 0; 8504066Sksrini 8514073Sksrini SKIP_WHITESPACE (); 8524073Sksrini if (!is_end_of_line[(int) *input_line_pointer]) 8534073Sksrini count = get_absolute_expression (); 8544073Sksrini 8554073Sksrini switch (type) 8563691Sksrini { 8573595Sksrini case 'b': 8583595Sksrini case 'B': 8593595Sksrini case 'c': 8603595Sksrini case 'C': 8613595Sksrini case 'h': 8623595Sksrini case 'H': 8633595Sksrini case 'i': 8643595Sksrini case 'I': 8653595Sksrini case 's': 8663595Sksrini case 'S': 8673595Sksrini case 'w': 8683595Sksrini case 'W': 8693595Sksrini case '*': /* String. */ 8703595Sksrini size = 1; 8713595Sksrini break; 8723595Sksrini case 'f': 8734066Sksrini case 'l': 8744066Sksrini case 'L': 8754066Sksrini longword_align = 1; 8763595Sksrini size = 2; 8773595Sksrini break; 8783595Sksrini case '.': /* Bitfield. */ 8794066Sksrini size = 0; 8803595Sksrini if (count < 1 || count > 32) 8813595Sksrini { 8823595Sksrini as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count); 8833595Sksrini ignore_rest_of_line (); 8844066Sksrini return; 8853595Sksrini } 8864066Sksrini if (current_stag->current_bitfield_offset + count > 16) 8873691Sksrini { 8883691Sksrini /* Set the appropriate size and new field offset. */ 8894066Sksrini if (count == 32) 8904066Sksrini { 8914066Sksrini size = 2; 8924066Sksrini count = 1; 8934066Sksrini } 8944066Sksrini else if (count > 16) 8954066Sksrini { 8964066Sksrini size = 1; 8974066Sksrini count = 1; 8984066Sksrini new_bitfield_offset = count - 16; 8994066Sksrini } 9004066Sksrini else 9014066Sksrini new_bitfield_offset = count; 9024066Sksrini } 9034066Sksrini else 9044066Sksrini { 9054066Sksrini field_align = 0; 9064066Sksrini new_bitfield_offset = current_stag->current_bitfield_offset + count; 9074066Sksrini } 9084066Sksrini break; 9094066Sksrini default: 9104066Sksrini as_bad (_("Unrecognized field type '%c'"), type); 9114066Sksrini ignore_rest_of_line (); 9124066Sksrini return; 9134066Sksrini } 9144066Sksrini 9154066Sksrini if (field_align) 9163691Sksrini { 9173770Sjjg /* Align to the actual starting position of the field. */ 9183691Sksrini current_stag->current_bitfield_offset = 0; 9193691Sksrini ++abs_section_offset; 9203691Sksrini } 9213691Sksrini /* Align to longword boundary. */ 9223595Sksrini if (longword_align && (abs_section_offset & 0x1)) 9233595Sksrini ++abs_section_offset; 9243595Sksrini 9253595Sksrini if (line_label == NULL) 9263595Sksrini { 9273595Sksrini static int fieldno = 0; 9283595Sksrini char fake[] = ".fake_fieldNNNNN"; 9293595Sksrini 9303595Sksrini sprintf (fake, ".fake_field%d", fieldno++); 9313595Sksrini stag_add_field (current_stag, fake, 9323595Sksrini abs_section_offset - S_GET_VALUE (current_stag->sym), 9333595Sksrini NULL); 9343595Sksrini } 9353595Sksrini else 9363595Sksrini { 9373595Sksrini char label[strlen (S_GET_NAME (line_label) + 1)]; 9383595Sksrini 9393595Sksrini strcpy (label, S_GET_NAME (line_label)); 9403595Sksrini stag_add_field (current_stag, label, 9413595Sksrini abs_section_offset - S_GET_VALUE (current_stag->sym), 9423595Sksrini NULL); 9433595Sksrini } 9443595Sksrini 9453595Sksrini if (current_stag->is_union) 9463595Sksrini { 9473595Sksrini /* Note we treat the element as if it were an array of COUNT. */ 9483595Sksrini if (current_stag->size < (unsigned) size * count) 9493595Sksrini current_stag->size = size * count; 9503595Sksrini } 9513595Sksrini else 9523595Sksrini { 9533595Sksrini abs_section_offset += (unsigned) size * count; 9543595Sksrini current_stag->current_bitfield_offset = new_bitfield_offset; 9553595Sksrini } 9563786Sksrini line_label = NULL; 9573595Sksrini} 9583595Sksrini 9593595Sksrini/* Handle .byte, .word. .int, .long and all variants. */ 9603595Sksrini 9613786Sksrinistatic void 9623595Sksrinitic54x_cons (int type) 9633595Sksrini{ 9643595Sksrini unsigned int c; 9653691Sksrini int octets; 9663691Sksrini 9673691Sksrini /* If we're within a .struct construct, don't actually allocate space. */ 9683691Sksrini if (current_stag != NULL) 9693595Sksrini { 9703595Sksrini tic54x_struct_field (type); 9713595Sksrini return; 9723595Sksrini } 9733595Sksrini 9743595Sksrini#ifdef md_flush_pending_output 9753595Sksrini md_flush_pending_output (); 9763595Sksrini#endif 9773595Sksrini 9783595Sksrini generate_lineno_debug (); 9793595Sksrini 9803786Sksrini /* Align long words to long word boundaries (4 octets). */ 9813595Sksrini if (type == 'l' || type == 'L') 9823595Sksrini { 9833595Sksrini frag_align (2, 0, 2); 9843786Sksrini /* If there's a label, assign it to the first allocated word. */ 9853900Sksrini if (line_label != NULL) 9863786Sksrini { 9873786Sksrini symbol_set_frag (line_label, frag_now); 9883786Sksrini S_SET_VALUE (line_label, frag_now_fix ()); 9893595Sksrini } 9903786Sksrini } 9913786Sksrini 9923786Sksrini switch (type) 9933786Sksrini { 9943786Sksrini case 'l': 9953786Sksrini case 'L': 9963786Sksrini case 'x': 9973786Sksrini octets = 4; 9983595Sksrini break; 9993786Sksrini case 'b': 10003786Sksrini case 'B': 10013786Sksrini case 'c': 10023786Sksrini case 'C': 10033786Sksrini octets = 1; 10043786Sksrini break; 10053625Sjlahoda default: 10063595Sksrini octets = 2; 10073786Sksrini break; 10083786Sksrini } 10093786Sksrini 10103786Sksrini do 10113786Sksrini { 10123786Sksrini if (*input_line_pointer == '"') 10133786Sksrini { 10143786Sksrini input_line_pointer++; 10153786Sksrini while (is_a_char (c = next_char_of_string ())) 10163786Sksrini tic54x_emit_char (c); 10173786Sksrini know (input_line_pointer[-1] == '\"'); 10183786Sksrini } 10193786Sksrini else 10203786Sksrini { 10213786Sksrini expressionS expn; 10223595Sksrini 10233595Sksrini input_line_pointer = parse_expression (input_line_pointer, &expn); 10243625Sjlahoda if (expn.X_op == O_constant) 10253786Sksrini { 10263786Sksrini offsetT value = expn.X_add_number; 10273595Sksrini /* Truncate overflows. */ 10283595Sksrini switch (octets) 10293625Sjlahoda { 10303786Sksrini case 1: 10313786Sksrini if ((value > 0 && value > 0xFF) 10323595Sksrini || (value < 0 && value < - 0x100)) 10333595Sksrini as_warn (_("Overflow in expression, truncated to 8 bits")); 10343595Sksrini break; 10353786Sksrini case 2: 10363595Sksrini if ((value > 0 && value > 0xFFFF) 10373595Sksrini || (value < 0 && value < - 0x10000)) 10383595Sksrini as_warn (_("Overflow in expression, truncated to 16 bits")); 10393595Sksrini break; 10403595Sksrini } 10413595Sksrini } 10423595Sksrini if (expn.X_op != O_constant && octets < 2) 10433595Sksrini { 10443595Sksrini /* Disallow .byte with a non constant expression that will 10453625Sjlahoda require relocation. */ 10463595Sksrini as_bad (_("Relocatable values require at least WORD storage")); 10473595Sksrini ignore_rest_of_line (); 10483595Sksrini return; 10493595Sksrini } 10503595Sksrini 10513625Sjlahoda if (expn.X_op != O_constant 10523595Sksrini && amode == c_mode 10533595Sksrini && octets == 4) 10543595Sksrini { 10553595Sksrini /* FIXME -- at one point TI tools used to output REL16 10563595Sksrini relocations, but I don't think the latest tools do at all 10573625Sjlahoda The current tools output extended relocations regardless of 10583595Sksrini the addressing mode (I actually think that ".c_mode" is 10593595Sksrini totally ignored in the latest tools). */ 10603595Sksrini amode = far_mode; 10613595Sksrini emitting_long = 1; 10623786Sksrini emit_expr (&expn, 4); 10633595Sksrini emitting_long = 0; 10643595Sksrini amode = c_mode; 10653595Sksrini } 10663595Sksrini else 10673595Sksrini { 10683595Sksrini emitting_long = octets == 4; 10693595Sksrini emit_expr (&expn, (octets == 1) ? 2 : octets); 10703595Sksrini emitting_long = 0; 10713595Sksrini } 10723595Sksrini } 10733595Sksrini } 10743595Sksrini while (*input_line_pointer++ == ','); 10753595Sksrini 10763595Sksrini input_line_pointer--; /* Put terminator back into stream. */ 10773595Sksrini demand_empty_rest_of_line (); 10783595Sksrini} 10793595Sksrini 10803595Sksrini/* .global <symbol>[,...,<symbolN>] 10813595Sksrini .def <symbol>[,...,<symbolN>] 10823595Sksrini .ref <symbol>[,...,<symbolN>] 10833595Sksrini 10843595Sksrini These all identify global symbols. 10853595Sksrini 10863625Sjlahoda .def means the symbol is defined in the current module and can be accessed 10873595Sksrini by other files. The symbol should be placed in the symbol table. 10883595Sksrini 10893595Sksrini .ref means the symbol is used in the current module but defined in another 10903786Sksrini module. The linker is to resolve this symbol's definition at link time. 10913595Sksrini 10923595Sksrini .global should act as a .ref or .def, as needed. 10933595Sksrini 10943595Sksrini global, def and ref all have symbol storage classes of C_EXT. 10953595Sksrini 10963595Sksrini I can't identify any difference in how the "other" c54x assembler treats 10973595Sksrini these, so we ignore the type here. */ 10983595Sksrini 10993595Sksrinivoid 11003595Sksrinitic54x_global (int type) 11013595Sksrini{ 11023595Sksrini char *name; 11033595Sksrini int c; 11043625Sjlahoda symbolS *symbolP; 11053595Sksrini 11063595Sksrini if (type == 'r') 11073595Sksrini as_warn (_("Use of .def/.ref is deprecated. Use .global instead")); 11083595Sksrini 11093595Sksrini ILLEGAL_WITHIN_STRUCT (); 11103595Sksrini 11113595Sksrini do 11123595Sksrini { 11133595Sksrini name = input_line_pointer; 11143595Sksrini c = get_symbol_end (); 11153595Sksrini symbolP = symbol_find_or_make (name); 11163595Sksrini 11173595Sksrini *input_line_pointer = c; 11183595Sksrini S_SET_STORAGE_CLASS (symbolP, C_EXT); 11193595Sksrini if (c == ',') 11203595Sksrini { 11213595Sksrini input_line_pointer++; 11223595Sksrini if (is_end_of_line[(int) *input_line_pointer]) 11233595Sksrini c = *input_line_pointer; 11243595Sksrini } 11253595Sksrini } 11263595Sksrini while (c == ','); 11273595Sksrini 11283595Sksrini demand_empty_rest_of_line (); 11293595Sksrini} 11303595Sksrini 11313595Sksrini/* Remove the symbol from the local label hash lookup. */ 11323595Sksrini 11333595Sksrinistatic void 11343595Sksrinitic54x_remove_local_label (const char *key, void *value ATTRIBUTE_UNUSED) 11353595Sksrini{ 11363595Sksrini void *elem = hash_delete (local_label_hash[macro_level], key, FALSE); 11373595Sksrini free (elem); 11383595Sksrini} 11393595Sksrini 11403595Sksrini/* Reset all local labels. */ 11413595Sksrini 11423595Sksrinistatic void 11433595Sksrinitic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED) 11443595Sksrini{ 11453595Sksrini hash_traverse (local_label_hash[macro_level], tic54x_remove_local_label); 11463595Sksrini} 11473595Sksrini 11483595Sksrini/* .text 11493595Sksrini .data 11503595Sksrini .sect "section name" 11513595Sksrini 11523595Sksrini Initialized section 11533595Sksrini make sure local labels get cleared when changing sections 11543595Sksrini 11553595Sksrini ARG is 't' for text, 'd' for data, or '*' for a named section 11563595Sksrini 11573595Sksrini For compatibility, '*' sections are SEC_CODE if instructions are 11583595Sksrini encountered, or SEC_DATA if not. 11593595Sksrini*/ 11603595Sksrini 11613595Sksrinistatic void 11623595Sksrinitic54x_sect (int arg) 11633595Sksrini{ 11643595Sksrini ILLEGAL_WITHIN_STRUCT (); 11653595Sksrini 11663595Sksrini /* Local labels are cleared when changing sections. */ 11673595Sksrini tic54x_clear_local_labels (0); 11683595Sksrini 11693595Sksrini if (arg == 't') 11703595Sksrini s_text (0); 11713595Sksrini else if (arg == 'd') 11723595Sksrini s_data (0); 11733595Sksrini else 11743595Sksrini { 11753595Sksrini char *name = NULL; 11763595Sksrini int len; 11773595Sksrini 11783595Sksrini /* If there are quotes, remove them. */ 11793595Sksrini if (*input_line_pointer == '"') 11803595Sksrini { 11813595Sksrini name = demand_copy_C_string (&len); 11823595Sksrini demand_empty_rest_of_line (); 11833595Sksrini name = strcpy (xmalloc (len + 10), name); 11843595Sksrini } 11853595Sksrini else 11863595Sksrini { 11873595Sksrini int c; 11883595Sksrini name = input_line_pointer; 11893595Sksrini c = get_symbol_end (); 11903595Sksrini len = strlen(name); 11913595Sksrini name = strcpy (xmalloc (len + 10), name); 11923595Sksrini *input_line_pointer = c; 11933595Sksrini demand_empty_rest_of_line (); 11943595Sksrini } 11953595Sksrini /* Make sure all named initialized sections flagged properly. If we 11963595Sksrini encounter instructions, we'll flag it with SEC_CODE as well. */ 11973595Sksrini strcat (name, ",\"w\"\n"); 11983595Sksrini input_scrub_insert_line (name); 11993595Sksrini obj_coff_section (0); 12003595Sksrini 12013595Sksrini /* If there was a line label, make sure that it gets assigned the proper 12023595Sksrini section. This is for compatibility, even though the actual behavior 12033595Sksrini is not explicitly defined. For consistency, we make .sect behave 12043595Sksrini like .usect, since that is probably what people expect. */ 12053595Sksrini if (line_label != NULL) 12063595Sksrini { 12073595Sksrini S_SET_SEGMENT (line_label, now_seg); 12083595Sksrini symbol_set_frag (line_label, frag_now); 12093595Sksrini S_SET_VALUE (line_label, frag_now_fix ()); 12103595Sksrini if (S_GET_STORAGE_CLASS (line_label) != C_EXT) 12113595Sksrini S_SET_STORAGE_CLASS (line_label, C_LABEL); 12123595Sksrini } 12133595Sksrini } 12143595Sksrini} 12153595Sksrini 12163595Sksrini/* [symbol] .space space_in_bits 12173595Sksrini [symbol] .bes space_in_bits 12183595Sksrini BES puts the symbol at the *last* word allocated 12193595Sksrini 12203595Sksrini cribbed from s_space. */ 12213595Sksrini 12223595Sksrinistatic void 12233595Sksrinitic54x_space (int arg) 12243595Sksrini{ 12253595Sksrini expressionS expn; 12263595Sksrini char *p = 0; 12273595Sksrini int octets = 0; 12283595Sksrini long words; 12293595Sksrini int bits_per_byte = (OCTETS_PER_BYTE * 8); 12303595Sksrini int bit_offset = 0; 12313595Sksrini symbolS *label = line_label; 12323595Sksrini int bes = arg; 12333595Sksrini 12343595Sksrini ILLEGAL_WITHIN_STRUCT (); 12353595Sksrini 12363595Sksrini#ifdef md_flush_pending_output 12373595Sksrini md_flush_pending_output (); 12383595Sksrini#endif 12393595Sksrini 12403595Sksrini /* Read the bit count. */ 12413595Sksrini expression (&expn); 12423595Sksrini 12433595Sksrini /* Some expressions are unresolvable until later in the assembly pass; 12443595Sksrini postpone until relaxation/fixup. we also have to postpone if a previous 12453595Sksrini partial allocation has not been completed yet. */ 12463595Sksrini if (expn.X_op != O_constant || frag_bit_offset (frag_now, now_seg) == -1) 12473595Sksrini { 12483595Sksrini struct bit_info *bi = xmalloc (sizeof (struct bit_info)); 12493595Sksrini 12503595Sksrini bi->seg = now_seg; 12513595Sksrini bi->type = bes; 12523595Sksrini bi->sym = label; 12533595Sksrini p = frag_var (rs_machine_dependent, 12543595Sksrini 65536 * 2, 1, (relax_substateT) 0, 12553595Sksrini make_expr_symbol (&expn), (offsetT) 0, 12563595Sksrini (char *) bi); 12573595Sksrini if (p) 12583595Sksrini *p = 0; 12593595Sksrini 12603595Sksrini return; 12613595Sksrini } 12623595Sksrini 12633595Sksrini /* Reduce the required size by any bit offsets currently left over 12643595Sksrini from a previous .space/.bes/.field directive. */ 12653595Sksrini bit_offset = frag_now->tc_frag_data; 12663595Sksrini if (bit_offset != 0 && bit_offset < 16) 12673595Sksrini { 12683595Sksrini int spare_bits = bits_per_byte - bit_offset; 12693595Sksrini 12703595Sksrini if (spare_bits >= expn.X_add_number) 12713595Sksrini { 12723595Sksrini /* Don't have to do anything; sufficient bits have already been 12733595Sksrini allocated; just point the label to the right place. */ 12743595Sksrini if (label != NULL) 12753595Sksrini { 12763595Sksrini symbol_set_frag (label, frag_now); 12773595Sksrini S_SET_VALUE (label, frag_now_fix () - 1); 12783595Sksrini label = NULL; 12793595Sksrini } 12803595Sksrini frag_now->tc_frag_data += expn.X_add_number; 12813595Sksrini goto getout; 12823595Sksrini } 12833595Sksrini expn.X_add_number -= spare_bits; 12843595Sksrini /* Set the label to point to the first word allocated, which in this 12853595Sksrini case is the previous word, which was only partially filled. */ 12863595Sksrini if (!bes && label != NULL) 12873595Sksrini { 12883595Sksrini symbol_set_frag (label, frag_now); 12893595Sksrini S_SET_VALUE (label, frag_now_fix () - 1); 12903595Sksrini label = NULL; 12913595Sksrini } 12923595Sksrini } 12933595Sksrini /* Convert bits to bytes/words and octets, rounding up. */ 12943595Sksrini words = ((expn.X_add_number + bits_per_byte - 1) / bits_per_byte); 12953595Sksrini /* How many do we have left over? */ 12963595Sksrini bit_offset = expn.X_add_number % bits_per_byte; 12973595Sksrini octets = words * OCTETS_PER_BYTE; 12983595Sksrini if (octets < 0) 12993595Sksrini { 1300 as_warn (_(".space/.bes repeat count is negative, ignored")); 1301 goto getout; 1302 } 1303 else if (octets == 0) 1304 { 1305 as_warn (_(".space/.bes repeat count is zero, ignored")); 1306 goto getout; 1307 } 1308 1309 /* If we are in the absolute section, just bump the offset. */ 1310 if (now_seg == absolute_section) 1311 { 1312 abs_section_offset += words; 1313 if (bes && label != NULL) 1314 S_SET_VALUE (label, abs_section_offset - 1); 1315 frag_now->tc_frag_data = bit_offset; 1316 goto getout; 1317 } 1318 1319 if (!need_pass_2) 1320 p = frag_var (rs_fill, 1, 1, 1321 (relax_substateT) 0, (symbolS *) 0, 1322 (offsetT) octets, (char *) 0); 1323 1324 /* Make note of how many bits of this word we've allocated so far. */ 1325 frag_now->tc_frag_data = bit_offset; 1326 1327 /* .bes puts label at *last* word allocated. */ 1328 if (bes && label != NULL) 1329 { 1330 symbol_set_frag (label, frag_now); 1331 S_SET_VALUE (label, frag_now_fix () - 1); 1332 } 1333 1334 if (p) 1335 *p = 0; 1336 1337 getout: 1338 1339 demand_empty_rest_of_line (); 1340} 1341 1342/* [symbol] .usect "section-name", size-in-words 1343 [, [blocking-flag] [, alignment-flag]] 1344 1345 Uninitialized section. 1346 Non-zero blocking means that if the section would cross a page (128-word) 1347 boundary, it will be page-aligned. 1348 Non-zero alignment aligns on a longword boundary. 1349 1350 Has no effect on the current section. */ 1351 1352static void 1353tic54x_usect (int x ATTRIBUTE_UNUSED) 1354{ 1355 char c; 1356 char *name; 1357 char *section_name; 1358 char *p; 1359 segT seg; 1360 int size, blocking_flag, alignment_flag; 1361 segT current_seg; 1362 subsegT current_subseg; 1363 flagword flags; 1364 1365 ILLEGAL_WITHIN_STRUCT (); 1366 1367 current_seg = now_seg; /* Save current seg. */ 1368 current_subseg = now_subseg; /* Save current subseg. */ 1369 1370 if (*input_line_pointer == '"') 1371 input_line_pointer++; 1372 section_name = input_line_pointer; 1373 c = get_symbol_end (); /* Get terminator. */ 1374 input_line_pointer++; /* Skip null symbol terminator. */ 1375 name = xmalloc (input_line_pointer - section_name + 1); 1376 strcpy (name, section_name); 1377 1378 if (*input_line_pointer == ',') 1379 ++input_line_pointer; 1380 else if (c != ',') 1381 { 1382 as_bad (_("Missing size argument")); 1383 ignore_rest_of_line (); 1384 return; 1385 } 1386 1387 size = get_absolute_expression (); 1388 1389 /* Read a possibly present third argument (blocking flag). */ 1390 if (*input_line_pointer == ',') 1391 { 1392 ++input_line_pointer; 1393 if (*input_line_pointer != ',') 1394 blocking_flag = get_absolute_expression (); 1395 else 1396 blocking_flag = 0; 1397 1398 /* Read a possibly present fourth argument (alignment flag). */ 1399 if (*input_line_pointer == ',') 1400 { 1401 ++input_line_pointer; 1402 alignment_flag = get_absolute_expression (); 1403 } 1404 else 1405 alignment_flag = 0; 1406 } 1407 else 1408 blocking_flag = alignment_flag = 0; 1409 1410 seg = subseg_new (name, 0); 1411 flags = bfd_get_section_flags (stdoutput, seg) | SEC_ALLOC; 1412 1413 if (alignment_flag) 1414 { 1415 /* s_align eats end of line; restore it. */ 1416 s_align_bytes (4); 1417 --input_line_pointer; 1418 } 1419 1420 if (line_label != NULL) 1421 { 1422 S_SET_SEGMENT (line_label, seg); 1423 symbol_set_frag (line_label, frag_now); 1424 S_SET_VALUE (line_label, frag_now_fix ()); 1425 /* Set scl to label, since that's what TI does. */ 1426 if (S_GET_STORAGE_CLASS (line_label) != C_EXT) 1427 S_SET_STORAGE_CLASS (line_label, C_LABEL); 1428 } 1429 1430 seg_info (seg)->bss = 1; /* Uninitialized data. */ 1431 1432 p = frag_var (rs_fill, 1, 1, 1433 (relax_substateT) 0, (symbolS *) line_label, 1434 size * OCTETS_PER_BYTE, (char *) 0); 1435 *p = 0; 1436 1437 if (blocking_flag) 1438 flags |= SEC_TIC54X_BLOCK; 1439 1440 if (!bfd_set_section_flags (stdoutput, seg, flags)) 1441 as_warn (_("Error setting flags for \"%s\": %s"), name, 1442 bfd_errmsg (bfd_get_error ())); 1443 1444 subseg_set (current_seg, current_subseg); /* Restore current seg. */ 1445 demand_empty_rest_of_line (); 1446} 1447 1448static enum cpu_version 1449lookup_version (const char *ver) 1450{ 1451 enum cpu_version version = VNONE; 1452 1453 if (ver[0] == '5' && ver[1] == '4') 1454 { 1455 if (strlen (ver) == 3 1456 && (ver[2] == '1' || ver[2] == '2' || ver[2] == '3' 1457 || ver[2] == '5' || ver[2] == '8' || ver[2] == '9')) 1458 version = ver[2] - '0'; 1459 else if (strlen (ver) == 5 1460 && TOUPPER (ver[3]) == 'L' 1461 && TOUPPER (ver[4]) == 'P' 1462 && (ver[2] == '5' || ver[2] == '6')) 1463 version = ver[2] - '0' + 10; 1464 } 1465 1466 return version; 1467} 1468 1469static void 1470set_cpu (enum cpu_version version) 1471{ 1472 cpu = version; 1473 if (version == V545LP || version == V546LP) 1474 { 1475 symbolS *symbolP = symbol_new ("__allow_lp", absolute_section, 1476 (valueT) 1, &zero_address_frag); 1477 SF_SET_LOCAL (symbolP); 1478 symbol_table_insert (symbolP); 1479 } 1480} 1481 1482/* .version cpu-version 1483 cpu-version may be one of the following: 1484 541 1485 542 1486 543 1487 545 1488 545LP 1489 546LP 1490 548 1491 549 1492 1493 This is for compatibility only. It currently has no affect on assembly. */ 1494static int cpu_needs_set = 1; 1495 1496static void 1497tic54x_version (int x ATTRIBUTE_UNUSED) 1498{ 1499 enum cpu_version version = VNONE; 1500 enum cpu_version old_version = cpu; 1501 int c; 1502 char *ver; 1503 1504 ILLEGAL_WITHIN_STRUCT (); 1505 1506 SKIP_WHITESPACE (); 1507 ver = input_line_pointer; 1508 while (!is_end_of_line[(int) *input_line_pointer]) 1509 ++input_line_pointer; 1510 c = *input_line_pointer; 1511 *input_line_pointer = 0; 1512 1513 version = lookup_version (ver); 1514 1515 if (cpu != VNONE && cpu != version) 1516 as_warn (_("CPU version has already been set")); 1517 1518 if (version == VNONE) 1519 { 1520 as_bad (_("Unrecognized version '%s'"), ver); 1521 ignore_rest_of_line (); 1522 return; 1523 } 1524 else if (assembly_begun && version != old_version) 1525 { 1526 as_bad (_("Changing of CPU version on the fly not supported")); 1527 ignore_rest_of_line (); 1528 return; 1529 } 1530 1531 set_cpu (version); 1532 1533 *input_line_pointer = c; 1534 demand_empty_rest_of_line (); 1535} 1536 1537/* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */ 1538 1539static void 1540tic54x_float_cons (int type) 1541{ 1542 if (current_stag != 0) 1543 tic54x_struct_field ('f'); 1544 1545#ifdef md_flush_pending_output 1546 md_flush_pending_output (); 1547#endif 1548 1549 /* Align to long word boundary (4 octets) unless it's ".xfloat". */ 1550 if (type != 'x') 1551 { 1552 frag_align (2, 0, 2); 1553 /* If there's a label, assign it to the first allocated word. */ 1554 if (line_label != NULL) 1555 { 1556 symbol_set_frag (line_label, frag_now); 1557 S_SET_VALUE (line_label, frag_now_fix ()); 1558 } 1559 } 1560 1561 float_cons ('f'); 1562} 1563 1564/* The argument is capitalized if it should be zero-terminated 1565 's' is normal string with upper 8-bits zero-filled, 'p' is packed. 1566 Code copied from stringer, and slightly modified so that strings are packed 1567 and encoded into the correct octets. */ 1568 1569static void 1570tic54x_stringer (int type) 1571{ 1572 unsigned int c; 1573 int append_zero = type == 'S' || type == 'P'; 1574 int packed = type == 'p' || type == 'P'; 1575 int last_char = -1; /* Packed strings need two bytes at a time to encode. */ 1576 1577 if (current_stag != NULL) 1578 { 1579 tic54x_struct_field ('*'); 1580 return; 1581 } 1582 1583#ifdef md_flush_pending_output 1584 md_flush_pending_output (); 1585#endif 1586 1587 c = ','; /* Do loop. */ 1588 while (c == ',') 1589 { 1590 SKIP_WHITESPACE (); 1591 switch (*input_line_pointer) 1592 { 1593 default: 1594 { 1595 unsigned short value = get_absolute_expression (); 1596 FRAG_APPEND_1_CHAR ( value & 0xFF); 1597 FRAG_APPEND_1_CHAR ((value >> 8) & 0xFF); 1598 break; 1599 } 1600 case '\"': 1601 ++input_line_pointer; /* -> 1st char of string. */ 1602 while (is_a_char (c = next_char_of_string ())) 1603 { 1604 if (!packed) 1605 { 1606 FRAG_APPEND_1_CHAR (c); 1607 FRAG_APPEND_1_CHAR (0); 1608 } 1609 else 1610 { 1611 /* Packed strings are filled MS octet first. */ 1612 if (last_char == -1) 1613 last_char = c; 1614 else 1615 { 1616 FRAG_APPEND_1_CHAR (c); 1617 FRAG_APPEND_1_CHAR (last_char); 1618 last_char = -1; 1619 } 1620 } 1621 } 1622 if (append_zero) 1623 { 1624 if (packed && last_char != -1) 1625 { 1626 FRAG_APPEND_1_CHAR (0); 1627 FRAG_APPEND_1_CHAR (last_char); 1628 last_char = -1; 1629 } 1630 else 1631 { 1632 FRAG_APPEND_1_CHAR (0); 1633 FRAG_APPEND_1_CHAR (0); 1634 } 1635 } 1636 know (input_line_pointer[-1] == '\"'); 1637 break; 1638 } 1639 SKIP_WHITESPACE (); 1640 c = *input_line_pointer; 1641 if (!is_end_of_line[c]) 1642 ++input_line_pointer; 1643 } 1644 1645 /* Finish up any leftover packed string. */ 1646 if (packed && last_char != -1) 1647 { 1648 FRAG_APPEND_1_CHAR (0); 1649 FRAG_APPEND_1_CHAR (last_char); 1650 } 1651 demand_empty_rest_of_line (); 1652} 1653 1654static void 1655tic54x_p2align (int arg ATTRIBUTE_UNUSED) 1656{ 1657 as_bad (_("p2align not supported on this target")); 1658} 1659 1660static void 1661tic54x_align_words (int arg) 1662{ 1663 /* Only ".align" with no argument is allowed within .struct/.union. */ 1664 int count = arg; 1665 1666 if (!is_end_of_line[(int) *input_line_pointer]) 1667 { 1668 if (arg == 2) 1669 as_warn (_("Argument to .even ignored")); 1670 else 1671 count = get_absolute_expression (); 1672 } 1673 1674 if (current_stag != NULL && arg == 128) 1675 { 1676 if (current_stag->current_bitfield_offset != 0) 1677 { 1678 current_stag->current_bitfield_offset = 0; 1679 ++abs_section_offset; 1680 } 1681 demand_empty_rest_of_line (); 1682 return; 1683 } 1684 1685 ILLEGAL_WITHIN_STRUCT (); 1686 1687 s_align_bytes (count << 1); 1688} 1689 1690/* Initialize multiple-bit fields withing a single word of memory. */ 1691 1692static void 1693tic54x_field (int ignore ATTRIBUTE_UNUSED) 1694{ 1695 expressionS expn; 1696 int size = 16; 1697 char *p; 1698 valueT value; 1699 symbolS *label = line_label; 1700 1701 if (current_stag != NULL) 1702 { 1703 tic54x_struct_field ('.'); 1704 return; 1705 } 1706 1707 input_line_pointer = parse_expression (input_line_pointer, &expn); 1708 1709 if (*input_line_pointer == ',') 1710 { 1711 ++input_line_pointer; 1712 size = get_absolute_expression (); 1713 if (size < 1 || size > 32) 1714 { 1715 as_bad (_("Invalid field size, must be from 1 to 32")); 1716 ignore_rest_of_line (); 1717 return; 1718 } 1719 } 1720 1721 /* Truncate values to the field width. */ 1722 if (expn.X_op != O_constant) 1723 { 1724 /* If the expression value is relocatable, the field size *must* 1725 be 16. */ 1726 if (size != 16) 1727 { 1728 as_bad (_("field size must be 16 when value is relocatable")); 1729 ignore_rest_of_line (); 1730 return; 1731 } 1732 1733 frag_now->tc_frag_data = 0; 1734 emit_expr (&expn, 2); 1735 } 1736 else 1737 { 1738 unsigned long fmask = (size == 32) ? 0xFFFFFFFF : (1ul << size) - 1; 1739 1740 value = expn.X_add_number; 1741 expn.X_add_number &= fmask; 1742 if (value != (valueT) expn.X_add_number) 1743 as_warn (_("field value truncated")); 1744 value = expn.X_add_number; 1745 /* Bits are stored MS first. */ 1746 while (size >= 16) 1747 { 1748 frag_now->tc_frag_data = 0; 1749 p = frag_more (2); 1750 md_number_to_chars (p, (value >> (size - 16)) & 0xFFFF, 2); 1751 size -= 16; 1752 } 1753 if (size > 0) 1754 { 1755 int bit_offset = frag_bit_offset (frag_now, now_seg); 1756 1757 fragS *alloc_frag = bit_offset_frag (frag_now, now_seg); 1758 if (bit_offset == -1) 1759 { 1760 struct bit_info *bi = xmalloc (sizeof (struct bit_info)); 1761 /* We don't know the previous offset at this time, so store the 1762 info we need and figure it out later. */ 1763 expressionS size_exp; 1764 1765 size_exp.X_op = O_constant; 1766 size_exp.X_add_number = size; 1767 bi->seg = now_seg; 1768 bi->type = TYPE_FIELD; 1769 bi->value = value; 1770 p = frag_var (rs_machine_dependent, 1771 4, 1, (relax_substateT) 0, 1772 make_expr_symbol (&size_exp), (offsetT) 0, 1773 (char *) bi); 1774 goto getout; 1775 } 1776 else if (bit_offset == 0 || bit_offset + size > 16) 1777 { 1778 /* Align a new field. */ 1779 p = frag_more (2); 1780 frag_now->tc_frag_data = 0; 1781 alloc_frag = frag_now; 1782 } 1783 else 1784 { 1785 /* Put the new value entirely within the existing one. */ 1786 p = alloc_frag == frag_now ? 1787 frag_now->fr_literal + frag_now_fix_octets () - 2 : 1788 alloc_frag->fr_literal; 1789 if (label != NULL) 1790 { 1791 symbol_set_frag (label, alloc_frag); 1792 if (alloc_frag == frag_now) 1793 S_SET_VALUE (label, frag_now_fix () - 1); 1794 label = NULL; 1795 } 1796 } 1797 value <<= 16 - alloc_frag->tc_frag_data - size; 1798 1799 /* OR in existing value. */ 1800 if (alloc_frag->tc_frag_data) 1801 value |= ((unsigned short) p[1] << 8) | p[0]; 1802 md_number_to_chars (p, value, 2); 1803 alloc_frag->tc_frag_data += size; 1804 if (alloc_frag->tc_frag_data == 16) 1805 alloc_frag->tc_frag_data = 0; 1806 } 1807 } 1808 getout: 1809 demand_empty_rest_of_line (); 1810} 1811 1812/* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't 1813 available yet. seg_info ()->bss is the next best thing. */ 1814 1815static int 1816tic54x_initialized_section (segT seg) 1817{ 1818 return !seg_info (seg)->bss; 1819} 1820 1821/* .clink ["section name"] 1822 1823 Marks the section as conditionally linked (link only if contents are 1824 referenced elsewhere. 1825 Without a name, refers to the current initialized section. 1826 Name is required for uninitialized sections. */ 1827 1828static void 1829tic54x_clink (int ignored ATTRIBUTE_UNUSED) 1830{ 1831 segT seg = now_seg; 1832 1833 ILLEGAL_WITHIN_STRUCT (); 1834 1835 if (*input_line_pointer == '\"') 1836 { 1837 char *section_name = ++input_line_pointer; 1838 char *name; 1839 1840 while (is_a_char (next_char_of_string ())) 1841 ; 1842 know (input_line_pointer[-1] == '\"'); 1843 input_line_pointer[-1] = 0; 1844 name = xmalloc (input_line_pointer - section_name + 1); 1845 strcpy (name, section_name); 1846 1847 seg = bfd_get_section_by_name (stdoutput, name); 1848 if (seg == NULL) 1849 { 1850 as_bad (_("Unrecognized section '%s'"), section_name); 1851 ignore_rest_of_line (); 1852 return; 1853 } 1854 } 1855 else 1856 { 1857 if (!tic54x_initialized_section (seg)) 1858 { 1859 as_bad (_("Current section is unitialized, " 1860 "section name required for .clink")); 1861 ignore_rest_of_line (); 1862 return; 1863 } 1864 } 1865 1866 seg->flags |= SEC_TIC54X_CLINK; 1867 1868 demand_empty_rest_of_line (); 1869} 1870 1871/* Change the default include directory to be the current source file's 1872 directory, instead of the current working directory. If DOT is non-zero, 1873 set to "." instead. */ 1874 1875static void 1876tic54x_set_default_include (int dot) 1877{ 1878 char *dir = "."; 1879 char *tmp = NULL; 1880 1881 if (!dot) 1882 { 1883 char *curfile; 1884 unsigned lineno; 1885 1886 as_where (&curfile, &lineno); 1887 dir = strcpy (xmalloc (strlen (curfile) + 1), curfile); 1888 tmp = strrchr (dir, '/'); 1889 } 1890 if (tmp != NULL) 1891 { 1892 int len; 1893 1894 *tmp = '\0'; 1895 len = strlen (dir); 1896 if (include_dir_count == 0) 1897 { 1898 include_dirs = (char **) xmalloc (sizeof (*include_dirs)); 1899 include_dir_count = 1; 1900 } 1901 include_dirs[0] = dir; 1902 if (len > include_dir_maxlen) 1903 include_dir_maxlen = len; 1904 } 1905 else if (include_dirs != NULL) 1906 include_dirs[0] = "."; 1907} 1908 1909/* .include "filename" | filename 1910 .copy "filename" | filename 1911 1912 FIXME 'include' file should be omitted from any output listing, 1913 'copy' should be included in any output listing 1914 FIXME -- prevent any included files from changing listing (compat only) 1915 FIXME -- need to include source file directory in search path; what's a 1916 good way to do this? 1917 1918 Entering/exiting included/copied file clears all local labels. */ 1919 1920static void 1921tic54x_include (int ignored ATTRIBUTE_UNUSED) 1922{ 1923 char newblock[] = " .newblock\n"; 1924 char *filename; 1925 char *input; 1926 int len, c = -1; 1927 1928 ILLEGAL_WITHIN_STRUCT (); 1929 1930 SKIP_WHITESPACE (); 1931 1932 if (*input_line_pointer == '"') 1933 { 1934 filename = demand_copy_C_string (&len); 1935 demand_empty_rest_of_line (); 1936 } 1937 else 1938 { 1939 filename = input_line_pointer; 1940 while (!is_end_of_line[(int) *input_line_pointer]) 1941 ++input_line_pointer; 1942 c = *input_line_pointer; 1943 *input_line_pointer = '\0'; 1944 filename = strcpy (xmalloc (strlen (filename) + 1), filename); 1945 *input_line_pointer = c; 1946 demand_empty_rest_of_line (); 1947 } 1948 /* Insert a partial line with the filename (for the sake of s_include) 1949 and a .newblock. 1950 The included file will be inserted before the newblock, so that the 1951 newblock is executed after the included file is processed. */ 1952 input = xmalloc (sizeof (newblock) + strlen (filename) + 4); 1953 sprintf (input, "\"%s\"\n%s", filename, newblock); 1954 input_scrub_insert_line (input); 1955 1956 tic54x_clear_local_labels (0); 1957 1958 tic54x_set_default_include (0); 1959 1960 s_include (0); 1961} 1962 1963static void 1964tic54x_message (int type) 1965{ 1966 char *msg; 1967 char c; 1968 int len; 1969 1970 ILLEGAL_WITHIN_STRUCT (); 1971 1972 if (*input_line_pointer == '"') 1973 msg = demand_copy_C_string (&len); 1974 else 1975 { 1976 msg = input_line_pointer; 1977 while (!is_end_of_line[(int) *input_line_pointer]) 1978 ++input_line_pointer; 1979 c = *input_line_pointer; 1980 *input_line_pointer = 0; 1981 msg = strcpy (xmalloc (strlen (msg) + 1), msg); 1982 *input_line_pointer = c; 1983 } 1984 1985 switch (type) 1986 { 1987 case 'm': 1988 as_tsktsk ("%s", msg); 1989 break; 1990 case 'w': 1991 as_warn ("%s", msg); 1992 break; 1993 case 'e': 1994 as_bad ("%s", msg); 1995 break; 1996 } 1997 1998 demand_empty_rest_of_line (); 1999} 2000 2001/* .label <symbol> 2002 Define a special symbol that refers to the loadtime address rather than the 2003 runtime address within the current section. 2004 2005 This symbol gets a special storage class so that when it is resolved, it is 2006 resolved relative to the load address (lma) of the section rather than the 2007 run address (vma). */ 2008 2009static void 2010tic54x_label (int ignored ATTRIBUTE_UNUSED) 2011{ 2012 char *name = input_line_pointer; 2013 symbolS *symbolP; 2014 int c; 2015 2016 ILLEGAL_WITHIN_STRUCT (); 2017 2018 c = get_symbol_end (); 2019 symbolP = colon (name); 2020 S_SET_STORAGE_CLASS (symbolP, C_STATLAB); 2021 2022 *input_line_pointer = c; 2023 demand_empty_rest_of_line (); 2024} 2025 2026/* .mmregs 2027 Install all memory-mapped register names into the symbol table as 2028 absolute local symbols. */ 2029 2030static void 2031tic54x_mmregs (int ignored ATTRIBUTE_UNUSED) 2032{ 2033 symbol *sym; 2034 2035 ILLEGAL_WITHIN_STRUCT (); 2036 2037 for (sym = (symbol *) mmregs; sym->name; sym++) 2038 { 2039 symbolS *symbolP = symbol_new (sym->name, absolute_section, 2040 (valueT) sym->value, &zero_address_frag); 2041 SF_SET_LOCAL (symbolP); 2042 symbol_table_insert (symbolP); 2043 } 2044} 2045 2046/* .loop [count] 2047 Count defaults to 1024. */ 2048 2049static void 2050tic54x_loop (int count) 2051{ 2052 ILLEGAL_WITHIN_STRUCT (); 2053 2054 SKIP_WHITESPACE (); 2055 if (!is_end_of_line[(int) *input_line_pointer]) 2056 count = get_absolute_expression (); 2057 2058 do_repeat (count, "LOOP", "ENDLOOP"); 2059} 2060 2061/* Normally, endloop gets eaten by the preceding loop. */ 2062 2063static void 2064tic54x_endloop (int ignore ATTRIBUTE_UNUSED) 2065{ 2066 as_bad (_("ENDLOOP without corresponding LOOP")); 2067 ignore_rest_of_line (); 2068} 2069 2070/* .break [condition]. */ 2071 2072static void 2073tic54x_break (int ignore ATTRIBUTE_UNUSED) 2074{ 2075 int cond = 1; 2076 2077 ILLEGAL_WITHIN_STRUCT (); 2078 2079 SKIP_WHITESPACE (); 2080 if (!is_end_of_line[(int) *input_line_pointer]) 2081 cond = get_absolute_expression (); 2082 2083 if (cond) 2084 end_repeat (substitution_line ? 1 : 0); 2085} 2086 2087static void 2088set_address_mode (int mode) 2089{ 2090 amode = mode; 2091 if (mode == far_mode) 2092 { 2093 symbolS *symbolP = symbol_new ("__allow_far", absolute_section, 2094 (valueT) 1, &zero_address_frag); 2095 SF_SET_LOCAL (symbolP); 2096 symbol_table_insert (symbolP); 2097 } 2098} 2099 2100static int address_mode_needs_set = 1; 2101 2102static void 2103tic54x_address_mode (int mode) 2104{ 2105 if (assembly_begun && amode != (unsigned) mode) 2106 { 2107 as_bad (_("Mixing of normal and extended addressing not supported")); 2108 ignore_rest_of_line (); 2109 return; 2110 } 2111 if (mode == far_mode && cpu != VNONE && cpu != V548 && cpu != V549) 2112 { 2113 as_bad (_("Extended addressing not supported on the specified CPU")); 2114 ignore_rest_of_line (); 2115 return; 2116 } 2117 2118 set_address_mode (mode); 2119 demand_empty_rest_of_line (); 2120} 2121 2122/* .sblock "section"|section [,...,"section"|section] 2123 Designate initialized sections for blocking. */ 2124 2125static void 2126tic54x_sblock (int ignore ATTRIBUTE_UNUSED) 2127{ 2128 int c = ','; 2129 2130 ILLEGAL_WITHIN_STRUCT (); 2131 2132 while (c == ',') 2133 { 2134 segT seg; 2135 char *name; 2136 2137 if (*input_line_pointer == '"') 2138 { 2139 int len; 2140 2141 name = demand_copy_C_string (&len); 2142 } 2143 else 2144 { 2145 char *section_name = input_line_pointer; 2146 2147 c = get_symbol_end (); 2148 name = xmalloc (strlen (section_name) + 1); 2149 strcpy (name, section_name); 2150 *input_line_pointer = c; 2151 } 2152 2153 seg = bfd_get_section_by_name (stdoutput, name); 2154 if (seg == NULL) 2155 { 2156 as_bad (_("Unrecognized section '%s'"), name); 2157 ignore_rest_of_line (); 2158 return; 2159 } 2160 else if (!tic54x_initialized_section (seg)) 2161 { 2162 as_bad (_(".sblock may be used for initialized sections only")); 2163 ignore_rest_of_line (); 2164 return; 2165 } 2166 seg->flags |= SEC_TIC54X_BLOCK; 2167 2168 c = *input_line_pointer; 2169 if (!is_end_of_line[(int) c]) 2170 ++input_line_pointer; 2171 } 2172 2173 demand_empty_rest_of_line (); 2174} 2175 2176/* symbol .set value 2177 symbol .equ value 2178 2179 value must be defined externals; no forward-referencing allowed 2180 symbols assigned with .set/.equ may not be redefined. */ 2181 2182static void 2183tic54x_set (int ignore ATTRIBUTE_UNUSED) 2184{ 2185 symbolS *symbolP; 2186 char *name; 2187 2188 ILLEGAL_WITHIN_STRUCT (); 2189 2190 if (!line_label) 2191 { 2192 as_bad (_("Symbol missing for .set/.equ")); 2193 ignore_rest_of_line (); 2194 return; 2195 } 2196 name = xstrdup (S_GET_NAME (line_label)); 2197 line_label = NULL; 2198 if ((symbolP = symbol_find (name)) == NULL 2199 && (symbolP = md_undefined_symbol (name)) == NULL) 2200 { 2201 symbolP = symbol_new (name, absolute_section, 0, &zero_address_frag); 2202 S_SET_STORAGE_CLASS (symbolP, C_STAT); 2203 } 2204 free (name); 2205 S_SET_DATA_TYPE (symbolP, T_INT); 2206 S_SET_SEGMENT (symbolP, absolute_section); 2207 symbol_table_insert (symbolP); 2208 pseudo_set (symbolP); 2209 demand_empty_rest_of_line (); 2210} 2211 2212/* .fclist 2213 .fcnolist 2214 List false conditional blocks. */ 2215 2216static void 2217tic54x_fclist (int show) 2218{ 2219 if (show) 2220 listing &= ~LISTING_NOCOND; 2221 else 2222 listing |= LISTING_NOCOND; 2223 demand_empty_rest_of_line (); 2224} 2225 2226static void 2227tic54x_sslist (int show) 2228{ 2229 ILLEGAL_WITHIN_STRUCT (); 2230 2231 listing_sslist = show; 2232} 2233 2234/* .var SYM[,...,SYMN] 2235 Define a substitution string to be local to a macro. */ 2236 2237static void 2238tic54x_var (int ignore ATTRIBUTE_UNUSED) 2239{ 2240 static char empty[] = ""; 2241 char *name; 2242 int c; 2243 2244 ILLEGAL_WITHIN_STRUCT (); 2245 2246 if (macro_level == 0) 2247 { 2248 as_bad (_(".var may only be used within a macro definition")); 2249 ignore_rest_of_line (); 2250 return; 2251 } 2252 do 2253 { 2254 if (!ISALPHA (*input_line_pointer)) 2255 { 2256 as_bad (_("Substitution symbols must begin with a letter")); 2257 ignore_rest_of_line (); 2258 return; 2259 } 2260 name = input_line_pointer; 2261 c = get_symbol_end (); 2262 /* .var symbols start out with a null string. */ 2263 name = strcpy (xmalloc (strlen (name) + 1), name); 2264 hash_insert (subsym_hash[macro_level], name, empty); 2265 *input_line_pointer = c; 2266 if (c == ',') 2267 { 2268 ++input_line_pointer; 2269 if (is_end_of_line[(int) *input_line_pointer]) 2270 c = *input_line_pointer; 2271 } 2272 } 2273 while (c == ','); 2274 2275 demand_empty_rest_of_line (); 2276} 2277 2278/* .mlib <macro library filename> 2279 2280 Macro libraries are archived (standard AR-format) text macro definitions 2281 Expand the file and include it. 2282 2283 FIXME need to try the source file directory as well. */ 2284 2285static void 2286tic54x_mlib (int ignore ATTRIBUTE_UNUSED) 2287{ 2288 char *filename; 2289 char *path; 2290 int len, i; 2291 bfd *abfd, *mbfd; 2292 2293 ILLEGAL_WITHIN_STRUCT (); 2294 2295 /* Parse the filename. */ 2296 if (*input_line_pointer == '"') 2297 { 2298 if ((filename = demand_copy_C_string (&len)) == NULL) 2299 return; 2300 } 2301 else 2302 { 2303 SKIP_WHITESPACE (); 2304 len = 0; 2305 while (!is_end_of_line[(int) *input_line_pointer] 2306 && !ISSPACE (*input_line_pointer)) 2307 { 2308 obstack_1grow (¬es, *input_line_pointer); 2309 ++input_line_pointer; 2310 ++len; 2311 } 2312 obstack_1grow (¬es, '\0'); 2313 filename = obstack_finish (¬es); 2314 } 2315 demand_empty_rest_of_line (); 2316 2317 tic54x_set_default_include (0); 2318 path = xmalloc ((unsigned long) len + include_dir_maxlen + 5); 2319 2320 for (i = 0; i < include_dir_count; i++) 2321 { 2322 FILE *try; 2323 2324 strcpy (path, include_dirs[i]); 2325 strcat (path, "/"); 2326 strcat (path, filename); 2327 if ((try = fopen (path, "r")) != NULL) 2328 { 2329 fclose (try); 2330 break; 2331 } 2332 } 2333 2334 if (i >= include_dir_count) 2335 { 2336 free (path); 2337 path = filename; 2338 } 2339 2340 /* FIXME: if path is found, malloc'd storage is not freed. Of course, this 2341 happens all over the place, and since the assembler doesn't usually keep 2342 running for a very long time, it really doesn't matter. */ 2343 register_dependency (path); 2344 2345 /* Expand all archive entries to temporary files and include them. */ 2346 abfd = bfd_openr (path, NULL); 2347 if (!abfd) 2348 { 2349 as_bad (_("can't open macro library file '%s' for reading: %s"), 2350 path, bfd_errmsg (bfd_get_error ())); 2351 ignore_rest_of_line (); 2352 return; 2353 } 2354 if (!bfd_check_format (abfd, bfd_archive)) 2355 { 2356 as_bad (_("File '%s' not in macro archive format"), path); 2357 ignore_rest_of_line (); 2358 return; 2359 } 2360 2361 /* Open each BFD as binary (it should be straight ASCII text). */ 2362 for (mbfd = bfd_openr_next_archived_file (abfd, NULL); 2363 mbfd != NULL; mbfd = bfd_openr_next_archived_file (abfd, mbfd)) 2364 { 2365 /* Get a size at least as big as the archive member. */ 2366 bfd_size_type size = bfd_get_size (mbfd); 2367 char *buf = xmalloc (size); 2368 char *fname = tmpnam (NULL); 2369 FILE *ftmp; 2370 2371 /* We're not sure how big it is, but it will be smaller than "size". */ 2372 bfd_bread (buf, size, mbfd); 2373 2374 /* Write to a temporary file, then use s_include to include it 2375 a bit of a hack. */ 2376 ftmp = fopen (fname, "w+b"); 2377 fwrite ((void *) buf, size, 1, ftmp); 2378 if (buf[size - 1] != '\n') 2379 fwrite ("\n", 1, 1, ftmp); 2380 fclose (ftmp); 2381 free (buf); 2382 input_scrub_insert_file (fname); 2383 unlink (fname); 2384 } 2385} 2386 2387const pseudo_typeS md_pseudo_table[] = 2388{ 2389 { "algebraic", s_ignore , 0 }, 2390 { "align" , tic54x_align_words , 128 }, 2391 { "ascii" , tic54x_stringer , 'p' }, 2392 { "asciz" , tic54x_stringer , 'P' }, 2393 { "even" , tic54x_align_words , 2 }, 2394 { "asg" , tic54x_asg , 0 }, 2395 { "eval" , tic54x_eval , 0 }, 2396 { "bss" , tic54x_bss , 0 }, 2397 { "byte" , tic54x_cons , 'b' }, 2398 { "ubyte" , tic54x_cons , 'B' }, 2399 { "char" , tic54x_cons , 'c' }, 2400 { "uchar" , tic54x_cons , 'C' }, 2401 { "clink" , tic54x_clink , 0 }, 2402 { "c_mode" , tic54x_address_mode , c_mode }, 2403 { "copy" , tic54x_include , 'c' }, 2404 { "include" , tic54x_include , 'i' }, 2405 { "data" , tic54x_sect , 'd' }, 2406 { "double" , tic54x_float_cons , 'd' }, 2407 { "ldouble" , tic54x_float_cons , 'l' }, 2408 { "drlist" , s_ignore , 0 }, 2409 { "drnolist" , s_ignore , 0 }, 2410 { "emsg" , tic54x_message , 'e' }, 2411 { "mmsg" , tic54x_message , 'm' }, 2412 { "wmsg" , tic54x_message , 'w' }, 2413 { "far_mode" , tic54x_address_mode , far_mode }, 2414 { "fclist" , tic54x_fclist , 1 }, 2415 { "fcnolist" , tic54x_fclist , 0 }, 2416 { "field" , tic54x_field , -1 }, 2417 { "float" , tic54x_float_cons , 'f' }, 2418 { "xfloat" , tic54x_float_cons , 'x' }, 2419 { "global" , tic54x_global , 'g' }, 2420 { "def" , tic54x_global , 'd' }, 2421 { "ref" , tic54x_global , 'r' }, 2422 { "half" , tic54x_cons , 'h' }, 2423 { "uhalf" , tic54x_cons , 'H' }, 2424 { "short" , tic54x_cons , 's' }, 2425 { "ushort" , tic54x_cons , 'S' }, 2426 { "if" , s_if , (int) O_ne }, 2427 { "elseif" , s_elseif , (int) O_ne }, 2428 { "else" , s_else , 0 }, 2429 { "endif" , s_endif , 0 }, 2430 { "int" , tic54x_cons , 'i' }, 2431 { "uint" , tic54x_cons , 'I' }, 2432 { "word" , tic54x_cons , 'w' }, 2433 { "uword" , tic54x_cons , 'W' }, 2434 { "label" , tic54x_label , 0 }, /* Loadtime 2435 address. */ 2436 { "length" , s_ignore , 0 }, 2437 { "width" , s_ignore , 0 }, 2438 { "long" , tic54x_cons , 'l' }, 2439 { "ulong" , tic54x_cons , 'L' }, 2440 { "xlong" , tic54x_cons , 'x' }, 2441 { "loop" , tic54x_loop , 1024 }, 2442 { "break" , tic54x_break , 0 }, 2443 { "endloop" , tic54x_endloop , 0 }, 2444 { "mlib" , tic54x_mlib , 0 }, 2445 { "mlist" , s_ignore , 0 }, 2446 { "mnolist" , s_ignore , 0 }, 2447 { "mmregs" , tic54x_mmregs , 0 }, 2448 { "newblock" , tic54x_clear_local_labels, 0 }, 2449 { "option" , s_ignore , 0 }, 2450 { "p2align" , tic54x_p2align , 0 }, 2451 { "sblock" , tic54x_sblock , 0 }, 2452 { "sect" , tic54x_sect , '*' }, 2453 { "set" , tic54x_set , 0 }, 2454 { "equ" , tic54x_set , 0 }, 2455 { "space" , tic54x_space , 0 }, 2456 { "bes" , tic54x_space , 1 }, 2457 { "sslist" , tic54x_sslist , 1 }, 2458 { "ssnolist" , tic54x_sslist , 0 }, 2459 { "string" , tic54x_stringer , 's' }, 2460 { "pstring" , tic54x_stringer , 'p' }, 2461 { "struct" , tic54x_struct , 0 }, 2462 { "tag" , tic54x_tag , 0 }, 2463 { "endstruct", tic54x_endstruct , 0 }, 2464 { "tab" , s_ignore , 0 }, 2465 { "text" , tic54x_sect , 't' }, 2466 { "union" , tic54x_struct , 1 }, 2467 { "endunion" , tic54x_endstruct , 1 }, 2468 { "usect" , tic54x_usect , 0 }, 2469 { "var" , tic54x_var , 0 }, 2470 { "version" , tic54x_version , 0 }, 2471 {0 , 0 , 0 } 2472}; 2473 2474int 2475md_parse_option (int c, char *arg) 2476{ 2477 switch (c) 2478 { 2479 default: 2480 return 0; 2481 case OPTION_COFF_VERSION: 2482 { 2483 int version = atoi (arg); 2484 2485 if (version != 0 && version != 1 && version != 2) 2486 as_fatal (_("Bad COFF version '%s'"), arg); 2487 /* FIXME -- not yet implemented. */ 2488 break; 2489 } 2490 case OPTION_CPU_VERSION: 2491 { 2492 cpu = lookup_version (arg); 2493 cpu_needs_set = 1; 2494 if (cpu == VNONE) 2495 as_fatal (_("Bad CPU version '%s'"), arg); 2496 break; 2497 } 2498 case OPTION_ADDRESS_MODE: 2499 amode = far_mode; 2500 address_mode_needs_set = 1; 2501 break; 2502 case OPTION_STDERR_TO_FILE: 2503 { 2504 char *filename = arg; 2505 FILE *fp = fopen (filename, "w+"); 2506 2507 if (fp == NULL) 2508 as_fatal (_("Can't redirect stderr to the file '%s'"), filename); 2509 fclose (fp); 2510 if ((fp = freopen (filename, "w+", stderr)) == NULL) 2511 as_fatal (_("Can't redirect stderr to the file '%s'"), filename); 2512 break; 2513 } 2514 } 2515 2516 return 1; 2517} 2518 2519/* Create a "local" substitution string hash table for a new macro level 2520 Some docs imply that macros have to use .newblock in order to be able 2521 to re-use a local label. We effectively do an automatic .newblock by 2522 deleting the local label hash between macro invocations. */ 2523 2524void 2525tic54x_macro_start (void) 2526{ 2527 ++macro_level; 2528 subsym_hash[macro_level] = hash_new (); 2529 local_label_hash[macro_level] = hash_new (); 2530} 2531 2532void 2533tic54x_macro_info (const macro_entry *macro) 2534{ 2535 const formal_entry *entry; 2536 2537 /* Put the formal args into the substitution symbol table. */ 2538 for (entry = macro->formals; entry; entry = entry->next) 2539 { 2540 char *name = strncpy (xmalloc (entry->name.len + 1), 2541 entry->name.ptr, entry->name.len); 2542 char *value = strncpy (xmalloc (entry->actual.len + 1), 2543 entry->actual.ptr, entry->actual.len); 2544 2545 name[entry->name.len] = '\0'; 2546 value[entry->actual.len] = '\0'; 2547 hash_insert (subsym_hash[macro_level], name, value); 2548 } 2549} 2550 2551/* Get rid of this macro's .var's, arguments, and local labels. */ 2552 2553void 2554tic54x_macro_end (void) 2555{ 2556 hash_die (subsym_hash[macro_level]); 2557 subsym_hash[macro_level] = NULL; 2558 hash_die (local_label_hash[macro_level]); 2559 local_label_hash[macro_level] = NULL; 2560 --macro_level; 2561} 2562 2563static int 2564subsym_symlen (char *a, char *ignore ATTRIBUTE_UNUSED) 2565{ 2566 return strlen (a); 2567} 2568 2569/* Compare symbol A to string B. */ 2570 2571static int 2572subsym_symcmp (char *a, char *b) 2573{ 2574 return strcmp (a, b); 2575} 2576 2577/* Return the index of the first occurrence of B in A, or zero if none 2578 assumes b is an integer char value as a string. Index is one-based. */ 2579 2580static int 2581subsym_firstch (char *a, char *b) 2582{ 2583 int val = atoi (b); 2584 char *tmp = strchr (a, val); 2585 2586 return tmp ? tmp - a + 1 : 0; 2587} 2588 2589/* Similar to firstch, but returns index of last occurrence of B in A. */ 2590 2591static int 2592subsym_lastch (char *a, char *b) 2593{ 2594 int val = atoi (b); 2595 char *tmp = strrchr (a, val); 2596 2597 return tmp ? tmp - a + 1 : 0; 2598} 2599 2600/* Returns 1 if string A is defined in the symbol table (NOT the substitution 2601 symbol table). */ 2602 2603static int 2604subsym_isdefed (char *a, char *ignore ATTRIBUTE_UNUSED) 2605{ 2606 symbolS *symbolP = symbol_find (a); 2607 2608 return symbolP != NULL; 2609} 2610 2611/* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol 2612 A, or zero if B is a null string. Both arguments *must* be substitution 2613 symbols, unsubstituted. */ 2614 2615static int 2616subsym_ismember (char *sym, char *list) 2617{ 2618 char *elem, *ptr, *listv; 2619 2620 if (!list) 2621 return 0; 2622 2623 listv = subsym_lookup (list, macro_level); 2624 if (!listv) 2625 { 2626 as_bad (_("Undefined substitution symbol '%s'"), list); 2627 ignore_rest_of_line (); 2628 return 0; 2629 } 2630 2631 ptr = elem = xmalloc (strlen (listv) + 1); 2632 strcpy (elem, listv); 2633 while (*ptr && *ptr != ',') 2634 ++ptr; 2635 *ptr++ = 0; 2636 2637 subsym_create_or_replace (sym, elem); 2638 2639 /* Reassign the list. */ 2640 subsym_create_or_replace (list, ptr); 2641 2642 /* Assume this value, docs aren't clear. */ 2643 return *list != 0; 2644} 2645 2646/* Return zero if not a constant; otherwise: 2647 1 if binary 2648 2 if octal 2649 3 if hexadecimal 2650 4 if character 2651 5 if decimal. */ 2652 2653static int 2654subsym_iscons (char *a, char *ignore ATTRIBUTE_UNUSED) 2655{ 2656 expressionS expn; 2657 2658 parse_expression (a, &expn); 2659 2660 if (expn.X_op == O_constant) 2661 { 2662 int len = strlen (a); 2663 2664 switch (TOUPPER (a[len - 1])) 2665 { 2666 case 'B': 2667 return 1; 2668 case 'Q': 2669 return 2; 2670 case 'H': 2671 return 3; 2672 case '\'': 2673 return 4; 2674 default: 2675 break; 2676 } 2677 /* No suffix; either octal, hex, or decimal. */ 2678 if (*a == '0' && len > 1) 2679 { 2680 if (TOUPPER (a[1]) == 'X') 2681 return 3; 2682 return 2; 2683 } 2684 return 5; 2685 } 2686 2687 return 0; 2688} 2689 2690/* Return 1 if A is a valid symbol name. Expects string input. */ 2691 2692static int 2693subsym_isname (char *a, char *ignore ATTRIBUTE_UNUSED) 2694{ 2695 if (!is_name_beginner (*a)) 2696 return 0; 2697 while (*a) 2698 { 2699 if (!is_part_of_name (*a)) 2700 return 0; 2701 ++a; 2702 } 2703 return 1; 2704} 2705 2706/* Return whether the string is a register; accepts ar0-7, unless .mmregs has 2707 been seen; if so, recognize any memory-mapped register. 2708 Note this does not recognize "A" or "B" accumulators. */ 2709 2710static int 2711subsym_isreg (char *a, char *ignore ATTRIBUTE_UNUSED) 2712{ 2713 if (hash_find (reg_hash, a)) 2714 return 1; 2715 if (hash_find (mmreg_hash, a)) 2716 return 1; 2717 return 0; 2718} 2719 2720/* Return the structure size, given the stag. */ 2721 2722static int 2723subsym_structsz (char *name, char *ignore ATTRIBUTE_UNUSED) 2724{ 2725 struct stag *stag = (struct stag *) hash_find (stag_hash, name); 2726 2727 if (stag) 2728 return stag->size; 2729 2730 return 0; 2731} 2732 2733/* If anybody actually uses this, they can fix it :) 2734 FIXME I'm not sure what the "reference point" of a structure is. It might 2735 be either the initial offset given .struct, or it may be the offset of the 2736 structure within another structure, or it might be something else 2737 altogether. since the TI assembler doesn't seem to ever do anything but 2738 return zero, we punt and return zero. */ 2739 2740static int 2741subsym_structacc (char *stag_name ATTRIBUTE_UNUSED, 2742 char *ignore ATTRIBUTE_UNUSED) 2743{ 2744 return 0; 2745} 2746 2747static float 2748math_ceil (float arg1, float ignore ATTRIBUTE_UNUSED) 2749{ 2750 return (float) ceil (arg1); 2751} 2752 2753static float 2754math_cvi (float arg1, float ignore ATTRIBUTE_UNUSED) 2755{ 2756 return (int) arg1; 2757} 2758 2759static float 2760math_floor (float arg1, float ignore ATTRIBUTE_UNUSED) 2761{ 2762 return (float) floor (arg1); 2763} 2764 2765static float 2766math_fmod (float arg1, float arg2) 2767{ 2768 return (int) arg1 % (int) arg2; 2769} 2770 2771static float 2772math_int (float arg1, float ignore ATTRIBUTE_UNUSED) 2773{ 2774 return ((float) ((int) arg1)) == arg1; 2775} 2776 2777static float 2778math_round (float arg1, float ignore ATTRIBUTE_UNUSED) 2779{ 2780 return arg1 > 0 ? (int) (arg1 + 0.5) : (int) (arg1 - 0.5); 2781} 2782 2783static float 2784math_sgn (float arg1, float ignore ATTRIBUTE_UNUSED) 2785{ 2786 return (arg1 < 0) ? -1 : (arg1 ? 1 : 0); 2787} 2788 2789static float 2790math_trunc (float arg1, float ignore ATTRIBUTE_UNUSED) 2791{ 2792 return (int) arg1; 2793} 2794 2795static float 2796math_acos (float arg1, float ignore ATTRIBUTE_UNUSED) 2797{ 2798 return (float) acos (arg1); 2799} 2800 2801static float 2802math_asin (float arg1, float ignore ATTRIBUTE_UNUSED) 2803{ 2804 return (float) asin (arg1); 2805} 2806 2807static float 2808math_atan (float arg1, float ignore ATTRIBUTE_UNUSED) 2809{ 2810 return (float) atan (arg1); 2811} 2812 2813static float 2814math_atan2 (float arg1, float arg2) 2815{ 2816 return (float) atan2 (arg1, arg2); 2817} 2818 2819static float 2820math_cosh (float arg1, float ignore ATTRIBUTE_UNUSED) 2821{ 2822 return (float) cosh (arg1); 2823} 2824 2825static float 2826math_cos (float arg1, float ignore ATTRIBUTE_UNUSED) 2827{ 2828 return (float) cos (arg1); 2829} 2830 2831static float 2832math_cvf (float arg1, float ignore ATTRIBUTE_UNUSED) 2833{ 2834 return (float) arg1; 2835} 2836 2837static float 2838math_exp (float arg1, float ignore ATTRIBUTE_UNUSED) 2839{ 2840 return (float) exp (arg1); 2841} 2842 2843static float 2844math_fabs (float arg1, float ignore ATTRIBUTE_UNUSED) 2845{ 2846 return (float) fabs (arg1); 2847} 2848 2849/* expr1 * 2^expr2. */ 2850 2851static float 2852math_ldexp (float arg1, float arg2) 2853{ 2854 return arg1 * (float) pow (2.0, arg2); 2855} 2856 2857static float 2858math_log10 (float arg1, float ignore ATTRIBUTE_UNUSED) 2859{ 2860 return (float) log10 (arg1); 2861} 2862 2863static float 2864math_log (float arg1, float ignore ATTRIBUTE_UNUSED) 2865{ 2866 return (float) log (arg1); 2867} 2868 2869static float 2870math_max (float arg1, float arg2) 2871{ 2872 return (arg1 > arg2) ? arg1 : arg2; 2873} 2874 2875static float 2876math_min (float arg1, float arg2) 2877{ 2878 return (arg1 < arg2) ? arg1 : arg2; 2879} 2880 2881static float 2882math_pow (float arg1, float arg2) 2883{ 2884 return (float) pow (arg1, arg2); 2885} 2886 2887static float 2888math_sin (float arg1, float ignore ATTRIBUTE_UNUSED) 2889{ 2890 return (float) sin (arg1); 2891} 2892 2893static float 2894math_sinh (float arg1, float ignore ATTRIBUTE_UNUSED) 2895{ 2896 return (float) sinh (arg1); 2897} 2898 2899static float 2900math_sqrt (float arg1, float ignore ATTRIBUTE_UNUSED) 2901{ 2902 return (float) sqrt (arg1); 2903} 2904 2905static float 2906math_tan (float arg1, float ignore ATTRIBUTE_UNUSED) 2907{ 2908 return (float) tan (arg1); 2909} 2910 2911static float 2912math_tanh (float arg1, float ignore ATTRIBUTE_UNUSED) 2913{ 2914 return (float) tanh (arg1); 2915} 2916 2917/* Built-in substitution symbol functions and math functions. */ 2918typedef struct 2919{ 2920 char *name; 2921 int (*proc) (char *, char *); 2922 int nargs; 2923} subsym_proc_entry; 2924 2925static const subsym_proc_entry subsym_procs[] = 2926{ 2927 /* Assembler built-in string substitution functions. */ 2928 { "$symlen", subsym_symlen, 1, }, 2929 { "$symcmp", subsym_symcmp, 2, }, 2930 { "$firstch", subsym_firstch, 2, }, 2931 { "$lastch", subsym_lastch, 2, }, 2932 { "$isdefed", subsym_isdefed, 1, }, 2933 { "$ismember", subsym_ismember, 2, }, 2934 { "$iscons", subsym_iscons, 1, }, 2935 { "$isname", subsym_isname, 1, }, 2936 { "$isreg", subsym_isreg, 1, }, 2937 { "$structsz", subsym_structsz, 1, }, 2938 { "$structacc", subsym_structacc, 1, }, 2939 { NULL, NULL, 0 }, 2940}; 2941 2942typedef struct 2943{ 2944 char *name; 2945 float (*proc) (float, float); 2946 int nargs; 2947 int int_return; 2948} math_proc_entry; 2949 2950static const math_proc_entry math_procs[] = 2951{ 2952 /* Integer-returning built-in math functions. */ 2953 { "$cvi", math_cvi, 1, 1 }, 2954 { "$int", math_int, 1, 1 }, 2955 { "$sgn", math_sgn, 1, 1 }, 2956 2957 /* Float-returning built-in math functions. */ 2958 { "$acos", math_acos, 1, 0 }, 2959 { "$asin", math_asin, 1, 0 }, 2960 { "$atan", math_atan, 1, 0 }, 2961 { "$atan2", math_atan2, 2, 0 }, 2962 { "$ceil", math_ceil, 1, 0 }, 2963 { "$cosh", math_cosh, 1, 0 }, 2964 { "$cos", math_cos, 1, 0 }, 2965 { "$cvf", math_cvf, 1, 0 }, 2966 { "$exp", math_exp, 1, 0 }, 2967 { "$fabs", math_fabs, 1, 0 }, 2968 { "$floor", math_floor, 1, 0 }, 2969 { "$fmod", math_fmod, 2, 0 }, 2970 { "$ldexp", math_ldexp, 2, 0 }, 2971 { "$log10", math_log10, 1, 0 }, 2972 { "$log", math_log, 1, 0 }, 2973 { "$max", math_max, 2, 0 }, 2974 { "$min", math_min, 2, 0 }, 2975 { "$pow", math_pow, 2, 0 }, 2976 { "$round", math_round, 1, 0 }, 2977 { "$sin", math_sin, 1, 0 }, 2978 { "$sinh", math_sinh, 1, 0 }, 2979 { "$sqrt", math_sqrt, 1, 0 }, 2980 { "$tan", math_tan, 1, 0 }, 2981 { "$tanh", math_tanh, 1, 0 }, 2982 { "$trunc", math_trunc, 1, 0 }, 2983 { NULL, NULL, 0, 0 }, 2984}; 2985 2986void 2987md_begin (void) 2988{ 2989 insn_template *tm; 2990 symbol *sym; 2991 const subsym_proc_entry *subsym_proc; 2992 const math_proc_entry *math_proc; 2993 const char *hash_err; 2994 char **symname; 2995 char *TIC54X_DIR = getenv ("TIC54X_DIR"); 2996 char *A_DIR = TIC54X_DIR ? TIC54X_DIR : getenv ("A_DIR"); 2997 2998 local_label_id = 0; 2999 3000 /* Look for A_DIR and add it to the include list. */ 3001 if (A_DIR != NULL) 3002 { 3003 char *tmp = xstrdup (A_DIR); 3004 3005 do 3006 { 3007 char *next = strchr (tmp, ';'); 3008 3009 if (next) 3010 *next++ = '\0'; 3011 add_include_dir (tmp); 3012 tmp = next; 3013 } 3014 while (tmp != NULL); 3015 } 3016 3017 op_hash = hash_new (); 3018 for (tm = (insn_template *) tic54x_optab; tm->name; tm++) 3019 { 3020 if (hash_find (op_hash, tm->name)) 3021 continue; 3022 hash_err = hash_insert (op_hash, tm->name, (char *) tm); 3023 if (hash_err) 3024 as_fatal ("Internal Error: Can't hash %s: %s", 3025 tm->name, hash_err); 3026 } 3027 parop_hash = hash_new (); 3028 for (tm = (insn_template *) tic54x_paroptab; tm->name; tm++) 3029 { 3030 if (hash_find (parop_hash, tm->name)) 3031 continue; 3032 hash_err = hash_insert (parop_hash, tm->name, (char *) tm); 3033 if (hash_err) 3034 as_fatal ("Internal Error: Can't hash %s: %s", 3035 tm->name, hash_err); 3036 } 3037 reg_hash = hash_new (); 3038 for (sym = (symbol *) regs; sym->name; sym++) 3039 { 3040 /* Add basic registers to the symbol table. */ 3041 symbolS *symbolP = symbol_new (sym->name, absolute_section, 3042 (valueT) sym->value, &zero_address_frag); 3043 SF_SET_LOCAL (symbolP); 3044 symbol_table_insert (symbolP); 3045 hash_err = hash_insert (reg_hash, sym->name, (char *) sym); 3046 } 3047 for (sym = (symbol *) mmregs; sym->name; sym++) 3048 hash_err = hash_insert (reg_hash, sym->name, (char *) sym); 3049 mmreg_hash = hash_new (); 3050 for (sym = (symbol *) mmregs; sym->name; sym++) 3051 hash_err = hash_insert (mmreg_hash, sym->name, (char *) sym); 3052 3053 cc_hash = hash_new (); 3054 for (sym = (symbol *) condition_codes; sym->name; sym++) 3055 hash_err = hash_insert (cc_hash, sym->name, (char *) sym); 3056 3057 cc2_hash = hash_new (); 3058 for (sym = (symbol *) cc2_codes; sym->name; sym++) 3059 hash_err = hash_insert (cc2_hash, sym->name, (char *) sym); 3060 3061 cc3_hash = hash_new (); 3062 for (sym = (symbol *) cc3_codes; sym->name; sym++) 3063 hash_err = hash_insert (cc3_hash, sym->name, (char *) sym); 3064 3065 sbit_hash = hash_new (); 3066 for (sym = (symbol *) status_bits; sym->name; sym++) 3067 hash_err = hash_insert (sbit_hash, sym->name, (char *) sym); 3068 3069 misc_symbol_hash = hash_new (); 3070 for (symname = (char **) misc_symbols; *symname; symname++) 3071 hash_err = hash_insert (misc_symbol_hash, *symname, *symname); 3072 3073 /* Only the base substitution table and local label table are initialized; 3074 the others (for local macro substitution) get instantiated as needed. */ 3075 local_label_hash[0] = hash_new (); 3076 subsym_hash[0] = hash_new (); 3077 for (subsym_proc = subsym_procs; subsym_proc->name; subsym_proc++) 3078 hash_err = hash_insert (subsym_hash[0], subsym_proc->name, 3079 (char *) subsym_proc); 3080 3081 math_hash = hash_new (); 3082 for (math_proc = math_procs; math_proc->name; math_proc++) 3083 { 3084 /* Insert into the main subsym hash for recognition; insert into 3085 the math hash to actually store information. */ 3086 hash_err = hash_insert (subsym_hash[0], math_proc->name, 3087 (char *) math_proc); 3088 hash_err = hash_insert (math_hash, math_proc->name, 3089 (char *) math_proc); 3090 } 3091 subsym_recurse_hash = hash_new (); 3092 stag_hash = hash_new (); 3093} 3094 3095static int 3096is_accumulator (struct opstruct *operand) 3097{ 3098 return strcasecmp (operand->buf, "a") == 0 3099 || strcasecmp (operand->buf, "b") == 0; 3100} 3101 3102/* Return the number of operands found, or -1 on error, copying the 3103 operands into the given array and the accompanying expressions into 3104 the next array. */ 3105 3106static int 3107get_operands (struct opstruct operands[], char *line) 3108{ 3109 char *lptr = line; 3110 int numexp = 0; 3111 int expecting_operand = 0; 3112 int i; 3113 3114 while (numexp < MAX_OPERANDS && !is_end_of_line[(int) *lptr]) 3115 { 3116 int paren_not_balanced = 0; 3117 char *op_start, *op_end; 3118 3119 while (*lptr && ISSPACE (*lptr)) 3120 ++lptr; 3121 op_start = lptr; 3122 while (paren_not_balanced || *lptr != ',') 3123 { 3124 if (*lptr == '\0') 3125 { 3126 if (paren_not_balanced) 3127 { 3128 as_bad (_("Unbalanced parenthesis in operand %d"), numexp); 3129 return -1; 3130 } 3131 else 3132 break; 3133 } 3134 if (*lptr == '(') 3135 ++paren_not_balanced; 3136 else if (*lptr == ')') 3137 --paren_not_balanced; 3138 ++lptr; 3139 } 3140 op_end = lptr; 3141 if (op_end != op_start) 3142 { 3143 int len = op_end - op_start; 3144 3145 strncpy (operands[numexp].buf, op_start, len); 3146 operands[numexp].buf[len] = 0; 3147 /* Trim trailing spaces; while the preprocessor gets rid of most, 3148 there are weird usage patterns that can introduce them 3149 (i.e. using strings for macro args). */ 3150 while (len > 0 && ISSPACE (operands[numexp].buf[len - 1])) 3151 operands[numexp].buf[--len] = 0; 3152 lptr = op_end; 3153 ++numexp; 3154 } 3155 else 3156 { 3157 if (expecting_operand || *lptr == ',') 3158 { 3159 as_bad (_("Expecting operand after ','")); 3160 return -1; 3161 } 3162 } 3163 if (*lptr == ',') 3164 { 3165 if (*++lptr == '\0') 3166 { 3167 as_bad (_("Expecting operand after ','")); 3168 return -1; 3169 } 3170 expecting_operand = 1; 3171 } 3172 } 3173 3174 while (*lptr && ISSPACE (*lptr++)) 3175 ; 3176 if (!is_end_of_line[(int) *lptr]) 3177 { 3178 as_bad (_("Extra junk on line")); 3179 return -1; 3180 } 3181 3182 /* OK, now parse them into expressions. */ 3183 for (i = 0; i < numexp; i++) 3184 { 3185 memset (&operands[i].exp, 0, sizeof (operands[i].exp)); 3186 if (operands[i].buf[0] == '#') 3187 { 3188 /* Immediate. */ 3189 parse_expression (operands[i].buf + 1, &operands[i].exp); 3190 } 3191 else if (operands[i].buf[0] == '@') 3192 { 3193 /* Direct notation. */ 3194 parse_expression (operands[i].buf + 1, &operands[i].exp); 3195 } 3196 else if (operands[i].buf[0] == '*') 3197 { 3198 /* Indirect. */ 3199 char *paren = strchr (operands[i].buf, '('); 3200 3201 /* Allow immediate syntax in the inner expression. */ 3202 if (paren && paren[1] == '#') 3203 *++paren = '('; 3204 3205 /* Pull out the lk expression or SP offset, if present. */ 3206 if (paren != NULL) 3207 { 3208 int len = strlen (paren); 3209 char *end = paren + len; 3210 int c; 3211 3212 while (end[-1] != ')') 3213 if (--end <= paren) 3214 { 3215 as_bad (_("Badly formed address expression")); 3216 return -1; 3217 } 3218 c = *end; 3219 *end = '\0'; 3220 parse_expression (paren, &operands[i].exp); 3221 *end = c; 3222 } 3223 else 3224 operands[i].exp.X_op = O_absent; 3225 } 3226 else 3227 parse_expression (operands[i].buf, &operands[i].exp); 3228 } 3229 3230 return numexp; 3231} 3232 3233/* Predicates for different operand types. */ 3234 3235static int 3236is_immediate (struct opstruct *operand) 3237{ 3238 return *operand->buf == '#'; 3239} 3240 3241/* This is distinguished from immediate because some numbers must be constants 3242 and must *not* have the '#' prefix. */ 3243 3244static int 3245is_absolute (struct opstruct *operand) 3246{ 3247 return operand->exp.X_op == O_constant && !is_immediate (operand); 3248} 3249 3250/* Is this an indirect operand? */ 3251 3252static int 3253is_indirect (struct opstruct *operand) 3254{ 3255 return operand->buf[0] == '*'; 3256} 3257 3258/* Is this a valid dual-memory operand? */ 3259 3260static int 3261is_dual (struct opstruct *operand) 3262{ 3263 if (is_indirect (operand) && strncasecmp (operand->buf, "*ar", 3) == 0) 3264 { 3265 char *tmp = operand->buf + 3; 3266 int arf; 3267 int valid_mod; 3268 3269 arf = *tmp++ - '0'; 3270 /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%. */ 3271 valid_mod = *tmp == '\0' || 3272 strcasecmp (tmp, "-") == 0 || 3273 strcasecmp (tmp, "+") == 0 || 3274 strcasecmp (tmp, "+0%") == 0; 3275 return arf >= 2 && arf <= 5 && valid_mod; 3276 } 3277 return 0; 3278} 3279 3280static int 3281is_mmreg (struct opstruct *operand) 3282{ 3283 return (is_absolute (operand) 3284 || is_immediate (operand) 3285 || hash_find (mmreg_hash, operand->buf) != 0); 3286} 3287 3288static int 3289is_type (struct opstruct *operand, enum optype type) 3290{ 3291 switch (type) 3292 { 3293 case OP_None: 3294 return operand->buf[0] == 0; 3295 case OP_Xmem: 3296 case OP_Ymem: 3297 return is_dual (operand); 3298 case OP_Sind: 3299 return is_indirect (operand); 3300 case OP_xpmad_ms7: 3301 /* This one *must* be immediate. */ 3302 return is_immediate (operand); 3303 case OP_xpmad: 3304 case OP_pmad: 3305 case OP_PA: 3306 case OP_dmad: 3307 case OP_Lmem: 3308 case OP_MMR: 3309 return 1; 3310 case OP_Smem: 3311 /* Address may be a numeric, indirect, or an expression. */ 3312 return !is_immediate (operand); 3313 case OP_MMRY: 3314 case OP_MMRX: 3315 return is_mmreg (operand); 3316 case OP_SRC: 3317 case OP_SRC1: 3318 case OP_RND: 3319 case OP_DST: 3320 return is_accumulator (operand); 3321 case OP_B: 3322 return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'B'; 3323 case OP_A: 3324 return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'A'; 3325 case OP_ARX: 3326 return strncasecmp ("ar", operand->buf, 2) == 0 3327 && ISDIGIT (operand->buf[2]); 3328 case OP_SBIT: 3329 return hash_find (sbit_hash, operand->buf) != 0 || is_absolute (operand); 3330 case OP_CC: 3331 return hash_find (cc_hash, operand->buf) != 0; 3332 case OP_CC2: 3333 return hash_find (cc2_hash, operand->buf) != 0; 3334 case OP_CC3: 3335 return hash_find (cc3_hash, operand->buf) != 0 3336 || is_immediate (operand) || is_absolute (operand); 3337 case OP_16: 3338 return (is_immediate (operand) || is_absolute (operand)) 3339 && operand->exp.X_add_number == 16; 3340 case OP_N: 3341 /* Allow st0 or st1 instead of a numeric. */ 3342 return is_absolute (operand) || is_immediate (operand) || 3343 strcasecmp ("st0", operand->buf) == 0 || 3344 strcasecmp ("st1", operand->buf) == 0; 3345 case OP_12: 3346 case OP_123: 3347 return is_absolute (operand) || is_immediate (operand); 3348 case OP_SHFT: 3349 return (is_immediate (operand) || is_absolute (operand)) 3350 && operand->exp.X_add_number >= 0 && operand->exp.X_add_number < 16; 3351 case OP_SHIFT: 3352 /* Let this one catch out-of-range values. */ 3353 return (is_immediate (operand) || is_absolute (operand)) 3354 && operand->exp.X_add_number != 16; 3355 case OP_BITC: 3356 case OP_031: 3357 case OP_k8: 3358 return is_absolute (operand) || is_immediate (operand); 3359 case OP_k8u: 3360 return is_immediate (operand) 3361 && operand->exp.X_op == O_constant 3362 && operand->exp.X_add_number >= 0 3363 && operand->exp.X_add_number < 256; 3364 case OP_lk: 3365 case OP_lku: 3366 /* Allow anything; assumes opcodes are ordered with Smem operands 3367 versions first. */ 3368 return 1; 3369 case OP_k5: 3370 case OP_k3: 3371 case OP_k9: 3372 /* Just make sure it's an integer; check range later. */ 3373 return is_immediate (operand); 3374 case OP_T: 3375 return strcasecmp ("t", operand->buf) == 0 || 3376 strcasecmp ("treg", operand->buf) == 0; 3377 case OP_TS: 3378 return strcasecmp ("ts", operand->buf) == 0; 3379 case OP_ASM: 3380 return strcasecmp ("asm", operand->buf) == 0; 3381 case OP_TRN: 3382 return strcasecmp ("trn", operand->buf) == 0; 3383 case OP_DP: 3384 return strcasecmp ("dp", operand->buf) == 0; 3385 case OP_ARP: 3386 return strcasecmp ("arp", operand->buf) == 0; 3387 default: 3388 return 0; 3389 } 3390} 3391 3392static int 3393operands_match (tic54x_insn *insn, 3394 struct opstruct *operands, 3395 int opcount, 3396 const enum optype *refoptype, 3397 int minops, 3398 int maxops) 3399{ 3400 int op = 0, refop = 0; 3401 3402 if (opcount == 0 && minops == 0) 3403 return 1; 3404 3405 while (op <= maxops && refop <= maxops) 3406 { 3407 while (!is_type (&operands[op], OPTYPE (refoptype[refop]))) 3408 { 3409 /* Skip an optional template operand if it doesn't agree 3410 with the current operand. */ 3411 if (refoptype[refop] & OPT) 3412 { 3413 ++refop; 3414 --maxops; 3415 if (refop > maxops) 3416 return 0; 3417 } 3418 else 3419 return 0; 3420 } 3421 3422 /* Save the actual operand type for later use. */ 3423 operands[op].type = OPTYPE (refoptype[refop]); 3424 ++refop; 3425 ++op; 3426 /* Have we matched them all yet? */ 3427 if (op == opcount) 3428 { 3429 while (op < maxops) 3430 { 3431 /* If a later operand is *not* optional, no match. */ 3432 if ((refoptype[refop] & OPT) == 0) 3433 return 0; 3434 /* Flag any implicit default OP_DST operands so we know to add 3435 them explicitly when encoding the operand later. */ 3436 if (OPTYPE (refoptype[refop]) == OP_DST) 3437 insn->using_default_dst = 1; 3438 ++refop; 3439 ++op; 3440 } 3441 3442 return 1; 3443 } 3444 } 3445 3446 return 0; 3447} 3448 3449/* 16-bit direct memory address 3450 Explicit dmad operands are always in last word of insn (usually second 3451 word, but bumped to third if lk addressing is used) 3452 3453 We allow *(dmad) notation because the TI assembler allows it. 3454 3455 XPC_CODE: 3456 0 for 16-bit addresses 3457 1 for full 23-bit addresses 3458 2 for the upper 7 bits of a 23-bit address (LDX). */ 3459 3460static int 3461encode_dmad (tic54x_insn *insn, struct opstruct *operand, int xpc_code) 3462{ 3463 int op = 1 + insn->is_lkaddr; 3464 3465 /* Only allow *(dmad) expressions; all others are invalid. */ 3466 if (is_indirect (operand) && operand->buf[strlen (operand->buf) - 1] != ')') 3467 { 3468 as_bad (_("Invalid dmad syntax '%s'"), operand->buf); 3469 return 0; 3470 } 3471 3472 insn->opcode[op].addr_expr = operand->exp; 3473 3474 if (insn->opcode[op].addr_expr.X_op == O_constant) 3475 { 3476 valueT value = insn->opcode[op].addr_expr.X_add_number; 3477 3478 if (xpc_code == 1) 3479 { 3480 insn->opcode[0].word &= 0xFF80; 3481 insn->opcode[0].word |= (value >> 16) & 0x7F; 3482 insn->opcode[1].word = value & 0xFFFF; 3483 } 3484 else if (xpc_code == 2) 3485 insn->opcode[op].word = (value >> 16) & 0xFFFF; 3486 else 3487 insn->opcode[op].word = value; 3488 } 3489 else 3490 { 3491 /* Do the fixup later; just store the expression. */ 3492 insn->opcode[op].word = 0; 3493 insn->opcode[op].r_nchars = 2; 3494 3495 if (amode == c_mode) 3496 insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23; 3497 else if (xpc_code == 1) 3498 { 3499 /* This relocation spans two words, so adjust accordingly. */ 3500 insn->opcode[0].addr_expr = operand->exp; 3501 insn->opcode[0].r_type = BFD_RELOC_TIC54X_23; 3502 insn->opcode[0].r_nchars = 4; 3503 insn->opcode[0].unresolved = 1; 3504 /* It's really 2 words, but we want to stop encoding after the 3505 first, since we must encode both words at once. */ 3506 insn->words = 1; 3507 } 3508 else if (xpc_code == 2) 3509 insn->opcode[op].r_type = BFD_RELOC_TIC54X_MS7_OF_23; 3510 else 3511 insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23; 3512 3513 insn->opcode[op].unresolved = 1; 3514 } 3515 3516 return 1; 3517} 3518 3519/* 7-bit direct address encoding. */ 3520 3521static int 3522encode_address (tic54x_insn *insn, struct opstruct *operand) 3523{ 3524 /* Assumes that dma addresses are *always* in word 0 of the opcode. */ 3525 insn->opcode[0].addr_expr = operand->exp; 3526 3527 if (operand->exp.X_op == O_constant) 3528 insn->opcode[0].word |= (operand->exp.X_add_number & 0x7F); 3529 else 3530 { 3531 if (operand->exp.X_op == O_register) 3532 as_bad (_("Use the .mmregs directive to use memory-mapped register names such as '%s'"), operand->buf); 3533 /* Do the fixup later; just store the expression. */ 3534 insn->opcode[0].r_nchars = 1; 3535 insn->opcode[0].r_type = BFD_RELOC_TIC54X_PARTLS7; 3536 insn->opcode[0].unresolved = 1; 3537 } 3538 3539 return 1; 3540} 3541 3542static int 3543encode_indirect (tic54x_insn *insn, struct opstruct *operand) 3544{ 3545 int arf; 3546 int mod; 3547 3548 if (insn->is_lkaddr) 3549 { 3550 /* lk addresses always go in the second insn word. */ 3551 mod = ((TOUPPER (operand->buf[1]) == 'A') ? 12 : 3552 (operand->buf[1] == '(') ? 15 : 3553 (strchr (operand->buf, '%') != NULL) ? 14 : 13); 3554 arf = ((mod == 12) ? operand->buf[3] - '0' : 3555 (mod == 15) ? 0 : operand->buf[4] - '0'); 3556 3557 insn->opcode[1].addr_expr = operand->exp; 3558 3559 if (operand->exp.X_op == O_constant) 3560 insn->opcode[1].word = operand->exp.X_add_number; 3561 else 3562 { 3563 insn->opcode[1].word = 0; 3564 insn->opcode[1].r_nchars = 2; 3565 insn->opcode[1].r_type = BFD_RELOC_TIC54X_16_OF_23; 3566 insn->opcode[1].unresolved = 1; 3567 } 3568 } 3569 else if (strncasecmp (operand->buf, "*sp (", 4) == 0) 3570 { 3571 /* Stack offsets look the same as 7-bit direct addressing. */ 3572 return encode_address (insn, operand); 3573 } 3574 else 3575 { 3576 arf = (TOUPPER (operand->buf[1]) == 'A' ? 3577 operand->buf[3] : operand->buf[4]) - '0'; 3578 3579 if (operand->buf[1] == '+') 3580 { 3581 mod = 3; /* *+ARx */ 3582 if (insn->tm->flags & FL_SMR) 3583 as_warn (_("Address mode *+ARx is write-only. " 3584 "Results of reading are undefined.")); 3585 } 3586 else if (operand->buf[4] == '\0') 3587 mod = 0; /* *ARx */ 3588 else if (operand->buf[5] == '\0') 3589 mod = (operand->buf[4] == '-' ? 1 : 2); /* *ARx+ / *ARx- */ 3590 else if (operand->buf[6] == '\0') 3591 { 3592 if (operand->buf[5] == '0') 3593 mod = (operand->buf[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0 */ 3594 else 3595 mod = (operand->buf[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-% */ 3596 } 3597 else if (TOUPPER (operand->buf[6]) == 'B') 3598 mod = (operand->buf[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B */ 3599 else if (TOUPPER (operand->buf[6]) == '%') 3600 mod = (operand->buf[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0% */ 3601 else 3602 { 3603 as_bad (_("Unrecognized indirect address format \"%s\""), 3604 operand->buf); 3605 return 0; 3606 } 3607 } 3608 3609 insn->opcode[0].word |= 0x80 | (mod << 3) | arf; 3610 3611 return 1; 3612} 3613 3614static int 3615encode_integer (tic54x_insn *insn, 3616 struct opstruct *operand, 3617 int which, 3618 int min, 3619 int max, 3620 unsigned short mask) 3621{ 3622 long parse, integer; 3623 3624 insn->opcode[which].addr_expr = operand->exp; 3625 3626 if (operand->exp.X_op == O_constant) 3627 { 3628 parse = operand->exp.X_add_number; 3629 /* Hack -- fixup for 16-bit hex quantities that get converted positive 3630 instead of negative. */ 3631 if ((parse & 0x8000) && min == -32768 && max == 32767) 3632 integer = (short) parse; 3633 else 3634 integer = parse; 3635 3636 if (integer >= min && integer <= max) 3637 { 3638 insn->opcode[which].word |= (integer & mask); 3639 return 1; 3640 } 3641 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"), 3642 operand->buf, min, max); 3643 } 3644 else 3645 { 3646 if (insn->opcode[which].addr_expr.X_op == O_constant) 3647 { 3648 insn->opcode[which].word |= 3649 insn->opcode[which].addr_expr.X_add_number & mask; 3650 } 3651 else 3652 { 3653 /* Do the fixup later; just store the expression. */ 3654 bfd_reloc_code_real_type rtype = 3655 (mask == 0x1FF ? BFD_RELOC_TIC54X_PARTMS9 : 3656 mask == 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23 : 3657 mask == 0x7F ? BFD_RELOC_TIC54X_PARTLS7 : BFD_RELOC_8); 3658 int size = (mask == 0x1FF || mask == 0xFFFF) ? 2 : 1; 3659 3660 if (rtype == BFD_RELOC_8) 3661 as_bad (_("Error in relocation handling")); 3662 3663 insn->opcode[which].r_nchars = size; 3664 insn->opcode[which].r_type = rtype; 3665 insn->opcode[which].unresolved = 1; 3666 } 3667 3668 return 1; 3669 } 3670 3671 return 0; 3672} 3673 3674static int 3675encode_condition (tic54x_insn *insn, struct opstruct *operand) 3676{ 3677 symbol *cc = (symbol *) hash_find (cc_hash, operand->buf); 3678 if (!cc) 3679 { 3680 as_bad (_("Unrecognized condition code \"%s\""), operand->buf); 3681 return 0; 3682 } 3683#define CC_GROUP 0x40 3684#define CC_ACC 0x08 3685#define CATG_A1 0x07 3686#define CATG_B1 0x30 3687#define CATG_A2 0x30 3688#define CATG_B2 0x0C 3689#define CATG_C2 0x03 3690 /* Disallow group 1 conditions mixed with group 2 conditions 3691 if group 1, allow only one category A and one category B 3692 if group 2, allow only one each of category A, B, and C. */ 3693 if (((insn->opcode[0].word & 0xFF) != 0)) 3694 { 3695 if ((insn->opcode[0].word & CC_GROUP) != (cc->value & CC_GROUP)) 3696 { 3697 as_bad (_("Condition \"%s\" does not match preceding group"), 3698 operand->buf); 3699 return 0; 3700 } 3701 if (insn->opcode[0].word & CC_GROUP) 3702 { 3703 if ((insn->opcode[0].word & CC_ACC) != (cc->value & CC_ACC)) 3704 { 3705 as_bad (_("Condition \"%s\" uses a different accumulator from " 3706 "a preceding condition"), 3707 operand->buf); 3708 return 0; 3709 } 3710 if ((insn->opcode[0].word & CATG_A1) && (cc->value & CATG_A1)) 3711 { 3712 as_bad (_("Only one comparison conditional allowed")); 3713 return 0; 3714 } 3715 if ((insn->opcode[0].word & CATG_B1) && (cc->value & CATG_B1)) 3716 { 3717 as_bad (_("Only one overflow conditional allowed")); 3718 return 0; 3719 } 3720 } 3721 else if ( ((insn->opcode[0].word & CATG_A2) && (cc->value & CATG_A2)) 3722 || ((insn->opcode[0].word & CATG_B2) && (cc->value & CATG_B2)) 3723 || ((insn->opcode[0].word & CATG_C2) && (cc->value & CATG_C2))) 3724 { 3725 as_bad (_("Duplicate %s conditional"), operand->buf); 3726 return 0; 3727 } 3728 } 3729 3730 insn->opcode[0].word |= cc->value; 3731 return 1; 3732} 3733 3734static int 3735encode_cc3 (tic54x_insn *insn, struct opstruct *operand) 3736{ 3737 symbol *cc3 = (symbol *) hash_find (cc3_hash, operand->buf); 3738 int value = cc3 ? cc3->value : operand->exp.X_add_number << 8; 3739 3740 if ((value & 0x0300) != value) 3741 { 3742 as_bad (_("Unrecognized condition code \"%s\""), operand->buf); 3743 return 0; 3744 } 3745 insn->opcode[0].word |= value; 3746 return 1; 3747} 3748 3749static int 3750encode_arx (tic54x_insn *insn, struct opstruct *operand) 3751{ 3752 int arf = strlen (operand->buf) >= 3 ? operand->buf[2] - '0' : -1; 3753 3754 if (strncasecmp ("ar", operand->buf, 2) || arf < 0 || arf > 7) 3755 { 3756 as_bad (_("Invalid auxiliary register (use AR0-AR7)")); 3757 return 0; 3758 } 3759 insn->opcode[0].word |= arf; 3760 return 1; 3761} 3762 3763static int 3764encode_cc2 (tic54x_insn *insn, struct opstruct *operand) 3765{ 3766 symbol *cc2 = (symbol *) hash_find (cc2_hash, operand->buf); 3767 3768 if (!cc2) 3769 { 3770 as_bad (_("Unrecognized condition code \"%s\""), operand->buf); 3771 return 0; 3772 } 3773 insn->opcode[0].word |= cc2->value; 3774 return 1; 3775} 3776 3777static int 3778encode_operand (tic54x_insn *insn, enum optype type, struct opstruct *operand) 3779{ 3780 int ext = (insn->tm->flags & FL_EXT) != 0; 3781 3782 if (type == OP_MMR && operand->exp.X_op != O_constant) 3783 { 3784 /* Disallow long-constant addressing for memory-mapped addressing. */ 3785 if (insn->is_lkaddr) 3786 { 3787 as_bad (_("lk addressing modes are invalid for memory-mapped " 3788 "register addressing")); 3789 return 0; 3790 } 3791 type = OP_Smem; 3792 /* Warn about *+ARx when used with MMR operands. */ 3793 if (strncasecmp (operand->buf, "*+ar", 4) == 0) 3794 { 3795 as_warn (_("Address mode *+ARx is not allowed in memory-mapped " 3796 "register addressing. Resulting behavior is " 3797 "undefined.")); 3798 } 3799 } 3800 3801 switch (type) 3802 { 3803 case OP_None: 3804 return 1; 3805 case OP_dmad: 3806 /* 16-bit immediate value. */ 3807 return encode_dmad (insn, operand, 0); 3808 case OP_SRC: 3809 if (TOUPPER (*operand->buf) == 'B') 3810 { 3811 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 9); 3812 if (insn->using_default_dst) 3813 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8); 3814 } 3815 return 1; 3816 case OP_RND: 3817 /* Make sure this agrees with the OP_DST operand. */ 3818 if (!((TOUPPER (operand->buf[0]) == 'B') ^ 3819 ((insn->opcode[0].word & (1 << 8)) != 0))) 3820 { 3821 as_bad (_("Destination accumulator for each part of this parallel " 3822 "instruction must be different")); 3823 return 0; 3824 } 3825 return 1; 3826 case OP_SRC1: 3827 case OP_DST: 3828 if (TOUPPER (operand->buf[0]) == 'B') 3829 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8); 3830 return 1; 3831 case OP_Xmem: 3832 case OP_Ymem: 3833 { 3834 int mod = (operand->buf[4] == '\0' ? 0 : /* *arx */ 3835 operand->buf[4] == '-' ? 1 : /* *arx- */ 3836 operand->buf[5] == '\0' ? 2 : 3); /* *arx+, *arx+0% */ 3837 int arf = operand->buf[3] - '0' - 2; 3838 int code = (mod << 2) | arf; 3839 insn->opcode[0].word |= (code << (type == OP_Xmem ? 4 : 0)); 3840 return 1; 3841 } 3842 case OP_Lmem: 3843 case OP_Smem: 3844 if (!is_indirect (operand)) 3845 return encode_address (insn, operand); 3846 /* Fall through. */ 3847 case OP_Sind: 3848 return encode_indirect (insn, operand); 3849 case OP_xpmad_ms7: 3850 return encode_dmad (insn, operand, 2); 3851 case OP_xpmad: 3852 return encode_dmad (insn, operand, 1); 3853 case OP_PA: 3854 case OP_pmad: 3855 return encode_dmad (insn, operand, 0); 3856 case OP_ARX: 3857 return encode_arx (insn, operand); 3858 case OP_MMRX: 3859 case OP_MMRY: 3860 case OP_MMR: 3861 { 3862 int value = operand->exp.X_add_number; 3863 3864 if (type == OP_MMR) 3865 insn->opcode[0].word |= value; 3866 else 3867 { 3868 if (value < 16 || value > 24) 3869 { 3870 as_bad (_("Memory mapped register \"%s\" out of range"), 3871 operand->buf); 3872 return 0; 3873 } 3874 if (type == OP_MMRX) 3875 insn->opcode[0].word |= (value - 16) << 4; 3876 else 3877 insn->opcode[0].word |= (value - 16); 3878 } 3879 return 1; 3880 } 3881 case OP_B: 3882 case OP_A: 3883 return 1; 3884 case OP_SHFT: 3885 return encode_integer (insn, operand, ext + insn->is_lkaddr, 3886 0, 15, 0xF); 3887 case OP_SHIFT: 3888 return encode_integer (insn, operand, ext + insn->is_lkaddr, 3889 -16, 15, 0x1F); 3890 case OP_lk: 3891 return encode_integer (insn, operand, 1 + insn->is_lkaddr, 3892 -32768, 32767, 0xFFFF); 3893 case OP_CC: 3894 return encode_condition (insn, operand); 3895 case OP_CC2: 3896 return encode_cc2 (insn, operand); 3897 case OP_CC3: 3898 return encode_cc3 (insn, operand); 3899 case OP_BITC: 3900 return encode_integer (insn, operand, 0, 0, 15, 0xF); 3901 case OP_k8: 3902 return encode_integer (insn, operand, 0, -128, 127, 0xFF); 3903 case OP_123: 3904 { 3905 int value = operand->exp.X_add_number; 3906 int code; 3907 if (value < 1 || value > 3) 3908 { 3909 as_bad (_("Invalid operand (use 1, 2, or 3)")); 3910 return 0; 3911 } 3912 code = value == 1 ? 0 : value == 2 ? 0x2 : 0x1; 3913 insn->opcode[0].word |= (code << 8); 3914 return 1; 3915 } 3916 case OP_031: 3917 return encode_integer (insn, operand, 0, 0, 31, 0x1F); 3918 case OP_k8u: 3919 return encode_integer (insn, operand, 0, 0, 255, 0xFF); 3920 case OP_lku: 3921 return encode_integer (insn, operand, 1 + insn->is_lkaddr, 3922 0, 65535, 0xFFFF); 3923 case OP_SBIT: 3924 { 3925 symbol *sbit = (symbol *) hash_find (sbit_hash, operand->buf); 3926 int value = is_absolute (operand) ? 3927 operand->exp.X_add_number : (sbit ? sbit->value : -1); 3928 int reg = 0; 3929 3930 if (insn->opcount == 1) 3931 { 3932 if (!sbit) 3933 { 3934 as_bad (_("A status register or status bit name is required")); 3935 return 0; 3936 } 3937 /* Guess the register based on the status bit; "ovb" is the last 3938 status bit defined for st0. */ 3939 if (sbit > (symbol *) hash_find (sbit_hash, "ovb")) 3940 reg = 1; 3941 } 3942 if (value == -1) 3943 { 3944 as_bad (_("Unrecognized status bit \"%s\""), operand->buf); 3945 return 0; 3946 } 3947 insn->opcode[0].word |= value; 3948 insn->opcode[0].word |= (reg << 9); 3949 return 1; 3950 } 3951 case OP_N: 3952 if (strcasecmp (operand->buf, "st0") == 0 3953 || strcasecmp (operand->buf, "st1") == 0) 3954 { 3955 insn->opcode[0].word |= 3956 ((unsigned short) (operand->buf[2] - '0')) << 9; 3957 return 1; 3958 } 3959 else if (operand->exp.X_op == O_constant 3960 && (operand->exp.X_add_number == 0 3961 || operand->exp.X_add_number == 1)) 3962 { 3963 insn->opcode[0].word |= 3964 ((unsigned short) (operand->exp.X_add_number)) << 9; 3965 return 1; 3966 } 3967 as_bad (_("Invalid status register \"%s\""), operand->buf); 3968 return 0; 3969 case OP_k5: 3970 return encode_integer (insn, operand, 0, -16, 15, 0x1F); 3971 case OP_k3: 3972 return encode_integer (insn, operand, 0, 0, 7, 0x7); 3973 case OP_k9: 3974 return encode_integer (insn, operand, 0, 0, 0x1FF, 0x1FF); 3975 case OP_12: 3976 if (operand->exp.X_add_number != 1 3977 && operand->exp.X_add_number != 2) 3978 { 3979 as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand->buf); 3980 return 0; 3981 } 3982 insn->opcode[0].word |= (operand->exp.X_add_number - 1) << 9; 3983 return 1; 3984 case OP_16: 3985 case OP_T: 3986 case OP_TS: 3987 case OP_ASM: 3988 case OP_TRN: 3989 case OP_DP: 3990 case OP_ARP: 3991 /* No encoding necessary. */ 3992 return 1; 3993 default: 3994 return 0; 3995 } 3996 3997 return 1; 3998} 3999 4000static void 4001emit_insn (tic54x_insn *insn) 4002{ 4003 int i; 4004 flagword oldflags = bfd_get_section_flags (stdoutput, now_seg); 4005 flagword flags = oldflags | SEC_CODE; 4006 4007 if (! bfd_set_section_flags (stdoutput, now_seg, flags)) 4008 as_warn (_("error setting flags for \"%s\": %s"), 4009 bfd_section_name (stdoutput, now_seg), 4010 bfd_errmsg (bfd_get_error ())); 4011 4012 for (i = 0; i < insn->words; i++) 4013 { 4014 int size = (insn->opcode[i].unresolved 4015 && insn->opcode[i].r_type == BFD_RELOC_TIC54X_23) ? 4 : 2; 4016 char *p = frag_more (size); 4017 4018 if (size == 2) 4019 md_number_to_chars (p, (valueT) insn->opcode[i].word, 2); 4020 else 4021 md_number_to_chars (p, (valueT) insn->opcode[i].word << 16, 4); 4022 4023 if (insn->opcode[i].unresolved) 4024 fix_new_exp (frag_now, p - frag_now->fr_literal, 4025 insn->opcode[i].r_nchars, &insn->opcode[i].addr_expr, 4026 FALSE, insn->opcode[i].r_type); 4027 } 4028} 4029 4030/* Convert the operand strings into appropriate opcode values 4031 return the total number of words used by the instruction. */ 4032 4033static int 4034build_insn (tic54x_insn *insn) 4035{ 4036 int i; 4037 4038 /* Only non-parallel instructions support lk addressing. */ 4039 if (!(insn->tm->flags & FL_PAR)) 4040 { 4041 for (i = 0; i < insn->opcount; i++) 4042 { 4043 if ((OPTYPE (insn->operands[i].type) == OP_Smem 4044 || OPTYPE (insn->operands[i].type) == OP_Lmem 4045 || OPTYPE (insn->operands[i].type) == OP_Sind) 4046 && strchr (insn->operands[i].buf, '(') 4047 /* Don't mistake stack-relative addressing for lk addressing. */ 4048 && strncasecmp (insn->operands[i].buf, "*sp (", 4) != 0) 4049 { 4050 insn->is_lkaddr = 1; 4051 insn->lkoperand = i; 4052 break; 4053 } 4054 } 4055 } 4056 insn->words = insn->tm->words + insn->is_lkaddr; 4057 4058 insn->opcode[0].word = insn->tm->opcode; 4059 if (insn->tm->flags & FL_EXT) 4060 insn->opcode[1 + insn->is_lkaddr].word = insn->tm->opcode2; 4061 4062 for (i = 0; i < insn->opcount; i++) 4063 { 4064 enum optype type = insn->operands[i].type; 4065 4066 if (!encode_operand (insn, type, &insn->operands[i])) 4067 return 0; 4068 } 4069 if (insn->tm->flags & FL_PAR) 4070 for (i = 0; i < insn->paropcount; i++) 4071 { 4072 enum optype partype = insn->paroperands[i].type; 4073 4074 if (!encode_operand (insn, partype, &insn->paroperands[i])) 4075 return 0; 4076 } 4077 4078 emit_insn (insn); 4079 4080 return insn->words; 4081} 4082 4083static int 4084optimize_insn (tic54x_insn *insn) 4085{ 4086 /* Optimize some instructions, helping out the brain-dead programmer. */ 4087#define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0) 4088 if (strcasecmp (insn->tm->name, "add") == 0) 4089 { 4090 if (insn->opcount > 1 4091 && is_accumulator (&insn->operands[insn->opcount - 2]) 4092 && is_accumulator (&insn->operands[insn->opcount - 1]) 4093 && strcasecmp (insn->operands[insn->opcount - 2].buf, 4094 insn->operands[insn->opcount - 1].buf) == 0) 4095 { 4096 --insn->opcount; 4097 insn->using_default_dst = 1; 4098 return 1; 4099 } 4100 4101 /* Try to collapse if Xmem and shift count is zero. */ 4102 if ((OPTYPE (insn->tm->operand_types[0]) == OP_Xmem 4103 && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT 4104 && is_zero (insn->operands[1])) 4105 /* Or if Smem, shift is zero or absent, and SRC == DST. */ 4106 || (OPTYPE (insn->tm->operand_types[0]) == OP_Smem 4107 && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT 4108 && is_type (&insn->operands[1], OP_SHIFT) 4109 && is_zero (insn->operands[1]) && insn->opcount == 3)) 4110 { 4111 insn->operands[1] = insn->operands[2]; 4112 insn->opcount = 2; 4113 return 1; 4114 } 4115 } 4116 else if (strcasecmp (insn->tm->name, "ld") == 0) 4117 { 4118 if (insn->opcount == 3 && insn->operands[0].type != OP_SRC) 4119 { 4120 if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT 4121 || OPTYPE (insn->tm->operand_types[1]) == OP_SHFT) 4122 && is_zero (insn->operands[1]) 4123 && (OPTYPE (insn->tm->operand_types[0]) != OP_lk 4124 || (insn->operands[0].exp.X_op == O_constant 4125 && insn->operands[0].exp.X_add_number <= 255 4126 && insn->operands[0].exp.X_add_number >= 0))) 4127 { 4128 insn->operands[1] = insn->operands[2]; 4129 insn->opcount = 2; 4130 return 1; 4131 } 4132 } 4133 } 4134 else if (strcasecmp (insn->tm->name, "sth") == 0 4135 || strcasecmp (insn->tm->name, "stl") == 0) 4136 { 4137 if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT 4138 || OPTYPE (insn->tm->operand_types[1]) == OP_SHFT) 4139 && is_zero (insn->operands[1])) 4140 { 4141 insn->operands[1] = insn->operands[2]; 4142 insn->opcount = 2; 4143 return 1; 4144 } 4145 } 4146 else if (strcasecmp (insn->tm->name, "sub") == 0) 4147 { 4148 if (insn->opcount > 1 4149 && is_accumulator (&insn->operands[insn->opcount - 2]) 4150 && is_accumulator (&insn->operands[insn->opcount - 1]) 4151 && strcasecmp (insn->operands[insn->opcount - 2].buf, 4152 insn->operands[insn->opcount - 1].buf) == 0) 4153 { 4154 --insn->opcount; 4155 insn->using_default_dst = 1; 4156 return 1; 4157 } 4158 4159 if ( ((OPTYPE (insn->tm->operand_types[0]) == OP_Smem 4160 && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT) 4161 || (OPTYPE (insn->tm->operand_types[0]) == OP_Xmem 4162 && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT)) 4163 && is_zero (insn->operands[1]) 4164 && insn->opcount == 3) 4165 { 4166 insn->operands[1] = insn->operands[2]; 4167 insn->opcount = 2; 4168 return 1; 4169 } 4170 } 4171 return 0; 4172} 4173 4174/* Find a matching template if possible, and get the operand strings. */ 4175 4176static int 4177tic54x_parse_insn (tic54x_insn *insn, char *line) 4178{ 4179 insn->tm = (insn_template *) hash_find (op_hash, insn->mnemonic); 4180 if (!insn->tm) 4181 { 4182 as_bad (_("Unrecognized instruction \"%s\""), insn->mnemonic); 4183 return 0; 4184 } 4185 4186 insn->opcount = get_operands (insn->operands, line); 4187 if (insn->opcount < 0) 4188 return 0; 4189 4190 /* Check each variation of operands for this mnemonic. */ 4191 while (insn->tm->name && strcasecmp (insn->tm->name, insn->mnemonic) == 0) 4192 { 4193 if (insn->opcount >= insn->tm->minops 4194 && insn->opcount <= insn->tm->maxops 4195 && operands_match (insn, &insn->operands[0], insn->opcount, 4196 insn->tm->operand_types, 4197 insn->tm->minops, insn->tm->maxops)) 4198 { 4199 /* SUCCESS! now try some optimizations. */ 4200 if (optimize_insn (insn)) 4201 { 4202 insn->tm = (insn_template *) hash_find (op_hash, 4203 insn->mnemonic); 4204 continue; 4205 } 4206 4207 return 1; 4208 } 4209 ++(insn->tm); 4210 } 4211 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"), 4212 line, insn->mnemonic); 4213 return 0; 4214} 4215 4216/* We set this in start_line_hook, 'cause if we do a line replacement, we 4217 won't be able to see the next line. */ 4218static int parallel_on_next_line_hint = 0; 4219 4220/* See if this is part of a parallel instruction 4221 Look for a subsequent line starting with "||". */ 4222 4223static int 4224next_line_shows_parallel (char *next_line) 4225{ 4226 /* Look for the second half. */ 4227 while (ISSPACE (*next_line)) 4228 ++next_line; 4229 4230 return (next_line[0] == PARALLEL_SEPARATOR 4231 && next_line[1] == PARALLEL_SEPARATOR); 4232} 4233 4234static int 4235tic54x_parse_parallel_insn_firstline (tic54x_insn *insn, char *line) 4236{ 4237 insn->tm = (insn_template *) hash_find (parop_hash, insn->mnemonic); 4238 if (!insn->tm) 4239 { 4240 as_bad (_("Unrecognized parallel instruction \"%s\""), 4241 insn->mnemonic); 4242 return 0; 4243 } 4244 4245 while (insn->tm->name && strcasecmp (insn->tm->name, 4246 insn->mnemonic) == 0) 4247 { 4248 insn->opcount = get_operands (insn->operands, line); 4249 if (insn->opcount < 0) 4250 return 0; 4251 if (insn->opcount == 2 4252 && operands_match (insn, &insn->operands[0], insn->opcount, 4253 insn->tm->operand_types, 2, 2)) 4254 { 4255 return 1; 4256 } 4257 ++(insn->tm); 4258 } 4259 /* Didn't find a matching parallel; try for a normal insn. */ 4260 return 0; 4261} 4262 4263/* Parse the second line of a two-line parallel instruction. */ 4264 4265static int 4266tic54x_parse_parallel_insn_lastline (tic54x_insn *insn, char *line) 4267{ 4268 int valid_mnemonic = 0; 4269 4270 insn->paropcount = get_operands (insn->paroperands, line); 4271 while (insn->tm->name && strcasecmp (insn->tm->name, 4272 insn->mnemonic) == 0) 4273 { 4274 if (strcasecmp (insn->tm->parname, insn->parmnemonic) == 0) 4275 { 4276 valid_mnemonic = 1; 4277 4278 if (insn->paropcount >= insn->tm->minops 4279 && insn->paropcount <= insn->tm->maxops 4280 && operands_match (insn, insn->paroperands, 4281 insn->paropcount, 4282 insn->tm->paroperand_types, 4283 insn->tm->minops, insn->tm->maxops)) 4284 return 1; 4285 } 4286 ++(insn->tm); 4287 } 4288 if (valid_mnemonic) 4289 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""), 4290 insn->parmnemonic); 4291 else 4292 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""), 4293 insn->mnemonic, insn->parmnemonic); 4294 4295 return 0; 4296} 4297 4298/* If quotes found, return copy of line up to closing quote; 4299 otherwise up until terminator. 4300 If it's a string, pass as-is; otherwise attempt substitution symbol 4301 replacement on the value. */ 4302 4303static char * 4304subsym_get_arg (char *line, char *terminators, char **str, int nosub) 4305{ 4306 char *ptr = line; 4307 char *endp; 4308 int is_string = *line == '"'; 4309 int is_char = ISDIGIT (*line); 4310 4311 if (is_char) 4312 { 4313 while (ISDIGIT (*ptr)) 4314 ++ptr; 4315 endp = ptr; 4316 *str = xmalloc (ptr - line + 1); 4317 strncpy (*str, line, ptr - line); 4318 (*str)[ptr - line] = 0; 4319 } 4320 else if (is_string) 4321 { 4322 char *savedp = input_line_pointer; 4323 int len; 4324 4325 input_line_pointer = ptr; 4326 *str = demand_copy_C_string (&len); 4327 endp = input_line_pointer; 4328 input_line_pointer = savedp; 4329 4330 /* Do forced substitutions if requested. */ 4331 if (!nosub && **str == ':') 4332 *str = subsym_substitute (*str, 1); 4333 } 4334 else 4335 { 4336 char *term = terminators; 4337 char *value = NULL; 4338 4339 while (*ptr && *ptr != *term) 4340 { 4341 if (!*term) 4342 { 4343 term = terminators; 4344 ++ptr; 4345 } 4346 else 4347 ++term; 4348 } 4349 endp = ptr; 4350 *str = xmalloc (ptr - line + 1); 4351 strncpy (*str, line, ptr - line); 4352 (*str)[ptr - line] = 0; 4353 /* Do simple substitution, if available. */ 4354 if (!nosub && (value = subsym_lookup (*str, macro_level)) != NULL) 4355 *str = value; 4356 } 4357 4358 return endp; 4359} 4360 4361/* Replace the given substitution string. 4362 We start at the innermost macro level, so that existing locals remain local 4363 Note: we're treating macro args identically to .var's; I don't know if 4364 that's compatible w/TI's assembler. */ 4365 4366static void 4367subsym_create_or_replace (char *name, char *value) 4368{ 4369 int i; 4370 4371 for (i = macro_level; i > 0; i--) 4372 { 4373 if (hash_find (subsym_hash[i], name)) 4374 { 4375 hash_replace (subsym_hash[i], name, value); 4376 return; 4377 } 4378 } 4379 if (hash_find (subsym_hash[0], name)) 4380 hash_replace (subsym_hash[0], name, value); 4381 else 4382 hash_insert (subsym_hash[0], name, value); 4383} 4384 4385/* Look up the substitution string replacement for the given symbol. 4386 Start with the innermost macro substitution table given and work 4387 outwards. */ 4388 4389static char * 4390subsym_lookup (char *name, int nest_level) 4391{ 4392 char *value = hash_find (subsym_hash[nest_level], name); 4393 4394 if (value || nest_level == 0) 4395 return value; 4396 4397 return subsym_lookup (name, nest_level - 1); 4398} 4399 4400/* Do substitution-symbol replacement on the given line (recursively). 4401 return the argument if no substitution was done 4402 4403 Also look for built-in functions ($func (arg)) and local labels. 4404 4405 If FORCED is set, look for forced substitutions of the form ':SYMBOL:'. */ 4406 4407static char * 4408subsym_substitute (char *line, int forced) 4409{ 4410 /* For each apparent symbol, see if it's a substitution symbol, and if so, 4411 replace it in the input. */ 4412 char *replacement; /* current replacement for LINE. */ 4413 char *head; /* Start of line. */ 4414 char *ptr; /* Current examination point. */ 4415 int changed = 0; /* Did we make a substitution? */ 4416 int eval_line = 0; /* Is this line a .eval/.asg statement? */ 4417 int eval_symbol = 0; /* Are we in the middle of the symbol for 4418 .eval/.asg? */ 4419 char *eval_end = NULL; 4420 int recurse = 1; 4421 int line_conditional = 0; 4422 char *tmp; 4423 4424 /* Work with a copy of the input line. */ 4425 replacement = xmalloc (strlen (line) + 1); 4426 strcpy (replacement, line); 4427 4428 ptr = head = replacement; 4429 4430 /* Flag lines where we might need to replace a single '=' with two; 4431 GAS uses single '=' to assign macro args values, and possibly other 4432 places, so limit what we replace. */ 4433 if (strstr (line, ".if") 4434 || strstr (line, ".elseif") 4435 || strstr (line, ".break")) 4436 line_conditional = 1; 4437 4438 /* Watch out for .eval, so that we avoid doing substitution on the 4439 symbol being assigned a value. */ 4440 if (strstr (line, ".eval") || strstr (line, ".asg")) 4441 eval_line = 1; 4442 4443 /* If it's a macro definition, don't do substitution on the argument 4444 names. */ 4445 if (strstr (line, ".macro")) 4446 return line; 4447 4448 while (!is_end_of_line[(int) *ptr]) 4449 { 4450 int current_char = *ptr; 4451 4452 /* Need to update this since LINE may have been modified. */ 4453 if (eval_line) 4454 eval_end = strrchr (ptr, ','); 4455 4456 /* Replace triple double quotes with bounding quote/escapes. */ 4457 if (current_char == '"' && ptr[1] == '"' && ptr[2] == '"') 4458 { 4459 ptr[1] = '\\'; 4460 tmp = strstr (ptr + 2, "\"\"\""); 4461 if (tmp) 4462 tmp[0] = '\\'; 4463 changed = 1; 4464 } 4465 4466 /* Replace a single '=' with a '=='; 4467 for compatibility with older code only. */ 4468 if (line_conditional && current_char == '=') 4469 { 4470 if (ptr[1] == '=') 4471 { 4472 ptr += 2; 4473 continue; 4474 } 4475 *ptr++ = '\0'; 4476 tmp = xmalloc (strlen (head) + 2 + strlen (ptr) + 1); 4477 sprintf (tmp, "%s==%s", head, ptr); 4478 /* Continue examining after the '=='. */ 4479 ptr = tmp + strlen (head) + 2; 4480 free (replacement); 4481 head = replacement = tmp; 4482 changed = 1; 4483 } 4484 4485 /* Flag when we've reached the symbol part of .eval/.asg. */ 4486 if (eval_line && ptr >= eval_end) 4487 eval_symbol = 1; 4488 4489 /* For each apparent symbol, see if it's a substitution symbol, and if 4490 so, replace it in the input. */ 4491 if ((forced && current_char == ':') 4492 || (!forced && is_name_beginner (current_char))) 4493 { 4494 char *name; /* Symbol to be replaced. */ 4495 char *savedp = input_line_pointer; 4496 int c; 4497 char *value = NULL; 4498 char *tail; /* Rest of line after symbol. */ 4499 4500 /* Skip the colon. */ 4501 if (forced) 4502 ++ptr; 4503 4504 name = input_line_pointer = ptr; 4505 c = get_symbol_end (); 4506 /* '?' is not normally part of a symbol, but it IS part of a local 4507 label. */ 4508 if (c == '?') 4509 { 4510 *input_line_pointer++ = c; 4511 c = *input_line_pointer; 4512 *input_line_pointer = '\0'; 4513 } 4514 /* Avoid infinite recursion; if a symbol shows up a second time for 4515 substitution, leave it as is. */ 4516 if (hash_find (subsym_recurse_hash, name) == NULL) 4517 value = subsym_lookup (name, macro_level); 4518 else 4519 as_warn (_("%s symbol recursion stopped at " 4520 "second appearance of '%s'"), 4521 forced ? "Forced substitution" : "Substitution", name); 4522 ptr = tail = input_line_pointer; 4523 input_line_pointer = savedp; 4524 4525 /* Check for local labels; replace them with the appropriate 4526 substitution. */ 4527 if ((*name == '$' && ISDIGIT (name[1]) && name[2] == '\0') 4528 || name[strlen (name) - 1] == '?') 4529 { 4530 /* Use an existing identifier for that label if, available, or 4531 create a new, unique identifier. */ 4532 value = hash_find (local_label_hash[macro_level], name); 4533 if (value == NULL) 4534 { 4535 char digit[11]; 4536 char *namecopy = strcpy (xmalloc (strlen (name) + 1), name); 4537 4538 value = strcpy (xmalloc (strlen (name) + sizeof (digit) + 1), 4539 name); 4540 if (*value != '$') 4541 value[strlen (value) - 1] = '\0'; 4542 sprintf (digit, ".%d", local_label_id++); 4543 strcat (value, digit); 4544 hash_insert (local_label_hash[macro_level], namecopy, value); 4545 } 4546 /* Indicate where to continue looking for substitutions. */ 4547 ptr = tail; 4548 } 4549 /* Check for built-in subsym and math functions. */ 4550 else if (value != NULL && *name == '$') 4551 { 4552 subsym_proc_entry *entry = (subsym_proc_entry *) value; 4553 math_proc_entry *math_entry = hash_find (math_hash, name); 4554 char *arg1, *arg2 = NULL; 4555 4556 *ptr = c; 4557 if (entry == NULL) 4558 { 4559 as_bad (_("Unrecognized substitution symbol function")); 4560 break; 4561 } 4562 else if (*ptr != '(') 4563 { 4564 as_bad (_("Missing '(' after substitution symbol function")); 4565 break; 4566 } 4567 ++ptr; 4568 if (math_entry != NULL) 4569 { 4570 float farg1, farg2 = 0; 4571 volatile float fresult; 4572 4573 farg1 = (float) strtod (ptr, &ptr); 4574 if (math_entry->nargs == 2) 4575 { 4576 if (*ptr++ != ',') 4577 { 4578 as_bad (_("Expecting second argument")); 4579 break; 4580 } 4581 farg2 = (float) strtod (ptr, &ptr); 4582 } 4583 fresult = (*math_entry->proc) (farg1, farg2); 4584 value = xmalloc (128); 4585 if (math_entry->int_return) 4586 sprintf (value, "%d", (int) fresult); 4587 else 4588 sprintf (value, "%f", fresult); 4589 if (*ptr++ != ')') 4590 { 4591 as_bad (_("Extra junk in function call, expecting ')'")); 4592 break; 4593 } 4594 /* Don't bother recursing; the replacement isn't a 4595 symbol. */ 4596 recurse = 0; 4597 } 4598 else 4599 { 4600 int val; 4601 int arg_type[2] = { *ptr == '"' , 0 }; 4602 int ismember = !strcmp (entry->name, "$ismember"); 4603 4604 /* Parse one or two args, which must be a substitution 4605 symbol, string or a character-string constant. */ 4606 /* For all functions, a string or substitution symbol may be 4607 used, with the following exceptions: 4608 firstch/lastch: 2nd arg must be character constant 4609 ismember: both args must be substitution symbols. */ 4610 ptr = subsym_get_arg (ptr, ",)", &arg1, ismember); 4611 if (!arg1) 4612 break; 4613 if (entry->nargs == 2) 4614 { 4615 if (*ptr++ != ',') 4616 { 4617 as_bad (_("Function expects two arguments")); 4618 break; 4619 } 4620 /* Character constants are converted to numerics 4621 by the preprocessor. */ 4622 arg_type[1] = (ISDIGIT (*ptr)) ? 2 : (*ptr == '"'); 4623 ptr = subsym_get_arg (ptr, ")", &arg2, ismember); 4624 } 4625 /* Args checking. */ 4626 if ((!strcmp (entry->name, "$firstch") 4627 || !strcmp (entry->name, "$lastch")) 4628 && arg_type[1] != 2) 4629 { 4630 as_bad (_("Expecting character constant argument")); 4631 break; 4632 } 4633 if (ismember 4634 && (arg_type[0] != 0 || arg_type[1] != 0)) 4635 { 4636 as_bad (_("Both arguments must be substitution symbols")); 4637 break; 4638 } 4639 if (*ptr++ != ')') 4640 { 4641 as_bad (_("Extra junk in function call, expecting ')'")); 4642 break; 4643 } 4644 val = (*entry->proc) (arg1, arg2); 4645 value = xmalloc (64); 4646 sprintf (value, "%d", val); 4647 } 4648 /* Fix things up to replace the entire expression, not just the 4649 function name. */ 4650 tail = ptr; 4651 c = *tail; 4652 } 4653 4654 if (value != NULL && !eval_symbol) 4655 { 4656 /* Replace the symbol with its string replacement and 4657 continue. Recursively replace VALUE until either no 4658 substitutions are performed, or a substitution that has been 4659 previously made is encountered again. 4660 4661 put the symbol into the recursion hash table so we only 4662 try to replace a symbol once. */ 4663 if (recurse) 4664 { 4665 hash_insert (subsym_recurse_hash, name, name); 4666 value = subsym_substitute (value, macro_level > 0); 4667 hash_delete (subsym_recurse_hash, name, FALSE); 4668 } 4669 4670 /* Temporarily zero-terminate where the symbol started. */ 4671 *name = 0; 4672 if (forced) 4673 { 4674 if (c == '(') 4675 { 4676 /* Subscripted substitution symbol -- use just the 4677 indicated portion of the string; the description 4678 kinda indicates that forced substitution is not 4679 supposed to be recursive, but I'm not sure. */ 4680 unsigned beg, len = 1; /* default to a single char */ 4681 char *newval = strcpy (xmalloc (strlen (value) + 1), 4682 value); 4683 4684 savedp = input_line_pointer; 4685 input_line_pointer = tail + 1; 4686 beg = get_absolute_expression (); 4687 if (beg < 1) 4688 { 4689 as_bad (_("Invalid subscript (use 1 to %d)"), 4690 (int) strlen (value)); 4691 break; 4692 } 4693 if (*input_line_pointer == ',') 4694 { 4695 ++input_line_pointer; 4696 len = get_absolute_expression (); 4697 if (beg + len > strlen (value)) 4698 { 4699 as_bad (_("Invalid length (use 0 to %d"), 4700 (int) strlen (value) - beg); 4701 break; 4702 } 4703 } 4704 newval += beg - 1; 4705 newval[len] = 0; 4706 tail = input_line_pointer; 4707 if (*tail++ != ')') 4708 { 4709 as_bad (_("Missing ')' in subscripted substitution " 4710 "symbol expression")); 4711 break; 4712 } 4713 c = *tail; 4714 input_line_pointer = savedp; 4715 4716 value = newval; 4717 } 4718 name[-1] = 0; 4719 } 4720 tmp = xmalloc (strlen (head) + strlen (value) + 4721 strlen (tail + 1) + 2); 4722 strcpy (tmp, head); 4723 strcat (tmp, value); 4724 /* Make sure forced substitutions are properly terminated. */ 4725 if (forced) 4726 { 4727 if (c != ':') 4728 { 4729 as_bad (_("Missing forced substitution terminator ':'")); 4730 break; 4731 } 4732 ++tail; 4733 } 4734 else 4735 /* Restore the character after the symbol end. */ 4736 *tail = c; 4737 strcat (tmp, tail); 4738 /* Continue examining after the replacement value. */ 4739 ptr = tmp + strlen (head) + strlen (value); 4740 free (replacement); 4741 head = replacement = tmp; 4742 changed = 1; 4743 } 4744 else 4745 *ptr = c; 4746 } 4747 else 4748 { 4749 ++ptr; 4750 } 4751 } 4752 4753 if (changed) 4754 return replacement; 4755 else 4756 return line; 4757} 4758 4759/* We use this to handle substitution symbols 4760 hijack input_line_pointer, replacing it with our substituted string. 4761 4762 .sslist should enable listing the line after replacements are made... 4763 4764 returns the new buffer limit. */ 4765 4766void 4767tic54x_start_line_hook (void) 4768{ 4769 char *line, *endp; 4770 char *replacement = NULL; 4771 4772 /* Work with a copy of the input line, including EOL char. */ 4773 endp = input_line_pointer; 4774 while (!is_end_of_line[(int) *endp++]) 4775 ; 4776 line = xmalloc (endp - input_line_pointer + 1); 4777 strncpy (line, input_line_pointer, endp - input_line_pointer + 1); 4778 line[endp - input_line_pointer] = 0; 4779 4780 /* Scan ahead for parallel insns. */ 4781 parallel_on_next_line_hint = next_line_shows_parallel (endp + 1); 4782 4783 /* If within a macro, first process forced replacements. */ 4784 if (macro_level > 0) 4785 replacement = subsym_substitute (line, 1); 4786 else 4787 replacement = line; 4788 replacement = subsym_substitute (replacement, 0); 4789 4790 if (replacement != line) 4791 { 4792 char *tmp = replacement; 4793 char *comment = strchr (replacement, ';'); 4794 char endc = replacement[strlen (replacement) - 1]; 4795 4796 /* Clean up the replacement; we'd prefer to have this done by the 4797 standard preprocessing equipment (maybe do_scrub_chars?) 4798 but for now, do a quick-and-dirty. */ 4799 if (comment != NULL) 4800 { 4801 comment[0] = endc; 4802 comment[1] = 0; 4803 --comment; 4804 } 4805 else 4806 comment = replacement + strlen (replacement) - 1; 4807 4808 /* Trim trailing whitespace. */ 4809 while (ISSPACE (*comment)) 4810 { 4811 comment[0] = endc; 4812 comment[1] = 0; 4813 --comment; 4814 } 4815 4816 /* Compact leading whitespace. */ 4817 while (ISSPACE (tmp[0]) && ISSPACE (tmp[1])) 4818 ++tmp; 4819 4820 input_line_pointer = endp; 4821 input_scrub_insert_line (tmp); 4822 free (replacement); 4823 free (line); 4824 /* Keep track of whether we've done a substitution. */ 4825 substitution_line = 1; 4826 } 4827 else 4828 { 4829 /* No change. */ 4830 free (line); 4831 substitution_line = 0; 4832 } 4833} 4834 4835/* This is the guts of the machine-dependent assembler. STR points to a 4836 machine dependent instruction. This function is supposed to emit 4837 the frags/bytes it assembles to. */ 4838void 4839md_assemble (char *line) 4840{ 4841 static int repeat_slot = 0; 4842 static int delay_slots = 0; /* How many delay slots left to fill? */ 4843 static int is_parallel = 0; 4844 static tic54x_insn insn; 4845 char *lptr; 4846 char *savedp = input_line_pointer; 4847 int c; 4848 4849 input_line_pointer = line; 4850 c = get_symbol_end (); 4851 4852 if (cpu == VNONE) 4853 cpu = V542; 4854 if (address_mode_needs_set) 4855 { 4856 set_address_mode (amode); 4857 address_mode_needs_set = 0; 4858 } 4859 if (cpu_needs_set) 4860 { 4861 set_cpu (cpu); 4862 cpu_needs_set = 0; 4863 } 4864 assembly_begun = 1; 4865 4866 if (is_parallel) 4867 { 4868 is_parallel = 0; 4869 4870 strcpy (insn.parmnemonic, line); 4871 lptr = input_line_pointer; 4872 *lptr = c; 4873 input_line_pointer = savedp; 4874 4875 if (tic54x_parse_parallel_insn_lastline (&insn, lptr)) 4876 { 4877 int words = build_insn (&insn); 4878 4879 if (delay_slots != 0) 4880 { 4881 if (words > delay_slots) 4882 { 4883 as_bad (_("Instruction does not fit in available delay " 4884 "slots (%d-word insn, %d slots left)"), 4885 words, delay_slots); 4886 delay_slots = 0; 4887 return; 4888 } 4889 delay_slots -= words; 4890 } 4891 } 4892 return; 4893 } 4894 4895 memset (&insn, 0, sizeof (insn)); 4896 strcpy (insn.mnemonic, line); 4897 lptr = input_line_pointer; 4898 *lptr = c; 4899 input_line_pointer = savedp; 4900 4901 /* See if this line is part of a parallel instruction; if so, either this 4902 line or the next line will have the "||" specifier preceding the 4903 mnemonic, and we look for it in the parallel insn hash table. */ 4904 if (strstr (line, "||") != NULL || parallel_on_next_line_hint) 4905 { 4906 char *tmp = strstr (line, "||"); 4907 if (tmp != NULL) 4908 *tmp = '\0'; 4909 4910 if (tic54x_parse_parallel_insn_firstline (&insn, lptr)) 4911 { 4912 is_parallel = 1; 4913 /* If the parallel part is on the same line, process it now, 4914 otherwise let the assembler pick up the next line for us. */ 4915 if (tmp != NULL) 4916 { 4917 while (ISSPACE (tmp[2])) 4918 ++tmp; 4919 md_assemble (tmp + 2); 4920 } 4921 } 4922 else 4923 { 4924 as_bad (_("Unrecognized parallel instruction '%s'"), line); 4925 } 4926 return; 4927 } 4928 4929 if (tic54x_parse_insn (&insn, lptr)) 4930 { 4931 int words; 4932 4933 if ((insn.tm->flags & FL_LP) 4934 && cpu != V545LP && cpu != V546LP) 4935 { 4936 as_bad (_("Instruction '%s' requires an LP cpu version"), 4937 insn.tm->name); 4938 return; 4939 } 4940 if ((insn.tm->flags & FL_FAR) 4941 && amode != far_mode) 4942 { 4943 as_bad (_("Instruction '%s' requires far mode addressing"), 4944 insn.tm->name); 4945 return; 4946 } 4947 4948 words = build_insn (&insn); 4949 4950 /* Is this instruction in a delay slot? */ 4951 if (delay_slots) 4952 { 4953 if (words > delay_slots) 4954 { 4955 as_warn (_("Instruction does not fit in available delay " 4956 "slots (%d-word insn, %d slots left). " 4957 "Resulting behavior is undefined."), 4958 words, delay_slots); 4959 delay_slots = 0; 4960 return; 4961 } 4962 /* Branches in delay slots are not allowed. */ 4963 if (insn.tm->flags & FL_BMASK) 4964 { 4965 as_warn (_("Instructions which cause PC discontinuity are not " 4966 "allowed in a delay slot. " 4967 "Resulting behavior is undefined.")); 4968 } 4969 delay_slots -= words; 4970 } 4971 4972 /* Is this instruction the target of a repeat? */ 4973 if (repeat_slot) 4974 { 4975 if (insn.tm->flags & FL_NR) 4976 as_warn (_("'%s' is not repeatable. " 4977 "Resulting behavior is undefined."), 4978 insn.tm->name); 4979 else if (insn.is_lkaddr) 4980 as_warn (_("Instructions using long offset modifiers or absolute " 4981 "addresses are not repeatable. " 4982 "Resulting behavior is undefined.")); 4983 repeat_slot = 0; 4984 } 4985 4986 /* Make sure we check the target of a repeat instruction. */ 4987 if (insn.tm->flags & B_REPEAT) 4988 { 4989 repeat_slot = 1; 4990 /* FIXME -- warn if repeat_slot == 1 at EOF. */ 4991 } 4992 /* Make sure we check our delay slots for validity. */ 4993 if (insn.tm->flags & FL_DELAY) 4994 { 4995 delay_slots = 2; 4996 /* FIXME -- warn if delay_slots != 0 at EOF. */ 4997 } 4998 } 4999} 5000 5001/* Do a final adjustment on the symbol table; in this case, make sure we have 5002 a ".file" symbol. */ 5003 5004void 5005tic54x_adjust_symtab (void) 5006{ 5007 if (symbol_rootP == NULL 5008 || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) 5009 { 5010 char *filename; 5011 unsigned lineno; 5012 as_where (&filename, &lineno); 5013 c_dot_file_symbol (filename, 0); 5014 } 5015} 5016 5017/* In order to get gas to ignore any | chars at the start of a line, 5018 this function returns true if a | is found in a line. 5019 This lets us process parallel instructions, which span two lines. */ 5020 5021int 5022tic54x_unrecognized_line (int c) 5023{ 5024 return c == PARALLEL_SEPARATOR; 5025} 5026 5027/* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*? 5028 Encode their names so that only we see them and can map them to the 5029 appropriate places. 5030 FIXME -- obviously this isn't done yet. These locals still show up in the 5031 symbol table. */ 5032void 5033tic54x_define_label (symbolS *sym) 5034{ 5035 /* Just in case we need this later; note that this is not necessarily the 5036 same thing as line_label... 5037 When aligning or assigning labels to fields, sometimes the label is 5038 assigned other than the address at which the label appears. 5039 FIXME -- is this really needed? I think all the proper label assignment 5040 is done in tic54x_cons. */ 5041 last_label_seen = sym; 5042} 5043 5044/* Try to parse something that normal parsing failed at. */ 5045 5046symbolS * 5047tic54x_undefined_symbol (char *name) 5048{ 5049 symbol *sym; 5050 5051 /* Not sure how to handle predefined symbols. */ 5052 if ((sym = (symbol *) hash_find (cc_hash, name)) != NULL || 5053 (sym = (symbol *) hash_find (cc2_hash, name)) != NULL || 5054 (sym = (symbol *) hash_find (cc3_hash, name)) != NULL || 5055 (sym = (symbol *) hash_find (misc_symbol_hash, name)) != NULL || 5056 (sym = (symbol *) hash_find (sbit_hash, name)) != NULL) 5057 { 5058 return symbol_new (name, reg_section, 5059 (valueT) sym->value, 5060 &zero_address_frag); 5061 } 5062 5063 if ((sym = (symbol *) hash_find (reg_hash, name)) != NULL || 5064 (sym = (symbol *) hash_find (mmreg_hash, name)) != NULL || 5065 !strcasecmp (name, "a") || !strcasecmp (name, "b")) 5066 { 5067 return symbol_new (name, reg_section, 5068 (valueT) sym ? sym->value : 0, 5069 &zero_address_frag); 5070 } 5071 5072 return NULL; 5073} 5074 5075/* Parse a name in an expression before the expression parser takes a stab at 5076 it. */ 5077 5078int 5079tic54x_parse_name (char *name ATTRIBUTE_UNUSED, 5080 expressionS *expn ATTRIBUTE_UNUSED) 5081{ 5082 return 0; 5083} 5084 5085char * 5086md_atof (int type, char *literalP, int *sizeP) 5087{ 5088 /* Target data is little-endian, but floats are stored 5089 big-"word"ian. ugh. */ 5090 return ieee_md_atof (type, literalP, sizeP, TRUE); 5091} 5092 5093arelent * 5094tc_gen_reloc (asection *section, fixS *fixP) 5095{ 5096 arelent *rel; 5097 bfd_reloc_code_real_type code = fixP->fx_r_type; 5098 asymbol *sym = symbol_get_bfdsym (fixP->fx_addsy); 5099 5100 rel = (arelent *) xmalloc (sizeof (arelent)); 5101 rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 5102 *rel->sym_ptr_ptr = sym; 5103 /* We assume that all rel->address are host byte offsets. */ 5104 rel->address = fixP->fx_frag->fr_address + fixP->fx_where; 5105 rel->address /= OCTETS_PER_BYTE; 5106 rel->howto = bfd_reloc_type_lookup (stdoutput, code); 5107 if (!strcmp (sym->name, section->name)) 5108 rel->howto += HOWTO_BANK; 5109 5110 if (!rel->howto) 5111 { 5112 const char *name = S_GET_NAME (fixP->fx_addsy); 5113 if (name == NULL) 5114 name = "<unknown>"; 5115 as_fatal ("Cannot generate relocation type for symbol %s, code %s", 5116 name, bfd_get_reloc_code_name (code)); 5117 return NULL; 5118 } 5119 return rel; 5120} 5121 5122/* Handle cons expressions. */ 5123 5124void 5125tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *expn) 5126{ 5127 bfd_reloc_code_real_type r; 5128 5129 switch (octets) 5130 { 5131 default: 5132 as_bad (_("Unsupported relocation size %d"), octets); 5133 r = BFD_RELOC_TIC54X_16_OF_23; 5134 break; 5135 case 2: 5136 r = BFD_RELOC_TIC54X_16_OF_23; 5137 break; 5138 case 4: 5139 /* TI assembler always uses this, regardless of addressing mode. */ 5140 if (emitting_long) 5141 r = BFD_RELOC_TIC54X_23; 5142 else 5143 /* We never want to directly generate this; this is provided for 5144 stabs support only. */ 5145 r = BFD_RELOC_32; 5146 break; 5147 } 5148 fix_new_exp (frag, where, octets, expn, 0, r); 5149} 5150 5151/* Attempt to simplify or even eliminate a fixup. 5152 To indicate that a fixup has been eliminated, set fixP->fx_done. 5153 5154 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry. */ 5155 5156void 5157md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) 5158{ 5159 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 5160 valueT val = * valP; 5161 5162 switch (fixP->fx_r_type) 5163 { 5164 default: 5165 as_fatal ("Bad relocation type: 0x%02x", fixP->fx_r_type); 5166 return; 5167 case BFD_RELOC_TIC54X_MS7_OF_23: 5168 val = (val >> 16) & 0x7F; 5169 /* Fall through. */ 5170 case BFD_RELOC_TIC54X_16_OF_23: 5171 case BFD_RELOC_16: 5172 bfd_put_16 (stdoutput, val, buf); 5173 /* Indicate what we're actually writing, so that we don't get warnings 5174 about exceeding available space. */ 5175 *valP = val & 0xFFFF; 5176 break; 5177 case BFD_RELOC_TIC54X_PARTLS7: 5178 bfd_put_16 (stdoutput, 5179 (bfd_get_16 (stdoutput, buf) & 0xFF80) | (val & 0x7F), 5180 buf); 5181 /* Indicate what we're actually writing, so that we don't get warnings 5182 about exceeding available space. */ 5183 *valP = val & 0x7F; 5184 break; 5185 case BFD_RELOC_TIC54X_PARTMS9: 5186 /* TI assembler doesn't shift its encoding for relocatable files, and is 5187 thus incompatible with this implementation's relocatable files. */ 5188 bfd_put_16 (stdoutput, 5189 (bfd_get_16 (stdoutput, buf) & 0xFE00) | (val >> 7), 5190 buf); 5191 break; 5192 case BFD_RELOC_32: 5193 case BFD_RELOC_TIC54X_23: 5194 bfd_put_32 (stdoutput, 5195 (bfd_get_32 (stdoutput, buf) & 0xFF800000) | val, 5196 buf); 5197 break; 5198 } 5199 5200 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) 5201 fixP->fx_done = 1; 5202} 5203 5204/* This is our chance to record section alignment 5205 don't need to do anything here, since BFD does the proper encoding. */ 5206 5207valueT 5208md_section_align (segT segment ATTRIBUTE_UNUSED, valueT section_size) 5209{ 5210 return section_size; 5211} 5212 5213long 5214md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED) 5215{ 5216 return 0; 5217} 5218 5219/* Mostly little-endian, but longwords (4 octets) get MS word stored 5220 first. */ 5221 5222void 5223tic54x_number_to_chars (char *buf, valueT val, int n) 5224{ 5225 if (n != 4) 5226 number_to_chars_littleendian (buf, val, n); 5227 else 5228 { 5229 number_to_chars_littleendian (buf , val >> 16 , 2); 5230 number_to_chars_littleendian (buf + 2, val & 0xFFFF, 2); 5231 } 5232} 5233 5234int 5235tic54x_estimate_size_before_relax (fragS *frag ATTRIBUTE_UNUSED, 5236 segT seg ATTRIBUTE_UNUSED) 5237{ 5238 return 0; 5239} 5240 5241/* We use this to handle bit allocations which we couldn't handle before due 5242 to symbols being in different frags. return number of octets added. */ 5243 5244int 5245tic54x_relax_frag (fragS *frag, long stretch ATTRIBUTE_UNUSED) 5246{ 5247 symbolS *sym = frag->fr_symbol; 5248 int growth = 0; 5249 int i; 5250 5251 if (sym != NULL) 5252 { 5253 struct bit_info *bi = (struct bit_info *) frag->fr_opcode; 5254 int bit_offset = frag_bit_offset (frag_prev (frag, bi->seg), bi->seg); 5255 int size = S_GET_VALUE (sym); 5256 fragS *prev_frag = bit_offset_frag (frag_prev (frag, bi->seg), bi->seg); 5257 int available = 16 - bit_offset; 5258 5259 if (symbol_get_frag (sym) != &zero_address_frag 5260 || S_IS_COMMON (sym) 5261 || !S_IS_DEFINED (sym)) 5262 as_bad_where (frag->fr_file, frag->fr_line, 5263 _("non-absolute value used with .space/.bes")); 5264 5265 if (size < 0) 5266 { 5267 as_warn (_("negative value ignored in %s"), 5268 bi->type == TYPE_SPACE ? ".space" : 5269 bi->type == TYPE_BES ? ".bes" : ".field"); 5270 growth = 0; 5271 frag->tc_frag_data = frag->fr_fix = 0; 5272 return 0; 5273 } 5274 5275 if (bi->type == TYPE_FIELD) 5276 { 5277 /* Bit fields of 16 or larger will have already been handled. */ 5278 if (bit_offset != 0 && available >= size) 5279 { 5280 char *p = prev_frag->fr_literal; 5281 5282 valueT value = bi->value; 5283 value <<= available - size; 5284 value |= ((unsigned short) p[1] << 8) | p[0]; 5285 md_number_to_chars (p, value, 2); 5286 if ((prev_frag->tc_frag_data += size) == 16) 5287 prev_frag->tc_frag_data = 0; 5288 if (bi->sym) 5289 symbol_set_frag (bi->sym, prev_frag); 5290 /* This frag is no longer used. */ 5291 growth = -frag->fr_fix; 5292 frag->fr_fix = 0; 5293 frag->tc_frag_data = 0; 5294 } 5295 else 5296 { 5297 char *p = frag->fr_literal; 5298 5299 valueT value = bi->value << (16 - size); 5300 md_number_to_chars (p, value, 2); 5301 if ((frag->tc_frag_data = size) == 16) 5302 frag->tc_frag_data = 0; 5303 growth = 0; 5304 } 5305 } 5306 else 5307 { 5308 if (bit_offset != 0 && bit_offset < 16) 5309 { 5310 if (available >= size) 5311 { 5312 if ((prev_frag->tc_frag_data += size) == 16) 5313 prev_frag->tc_frag_data = 0; 5314 if (bi->sym) 5315 symbol_set_frag (bi->sym, prev_frag); 5316 /* This frag is no longer used. */ 5317 growth = -frag->fr_fix; 5318 frag->fr_fix = 0; 5319 frag->tc_frag_data = 0; 5320 goto getout; 5321 } 5322 if (bi->type == TYPE_SPACE && bi->sym) 5323 symbol_set_frag (bi->sym, prev_frag); 5324 size -= available; 5325 } 5326 growth = (size + 15) / 16 * OCTETS_PER_BYTE - frag->fr_fix; 5327 for (i = 0; i < growth; i++) 5328 frag->fr_literal[i] = 0; 5329 frag->fr_fix = growth; 5330 frag->tc_frag_data = size % 16; 5331 /* Make sure any BES label points to the LAST word allocated. */ 5332 if (bi->type == TYPE_BES && bi->sym) 5333 S_SET_VALUE (bi->sym, frag->fr_fix / OCTETS_PER_BYTE - 1); 5334 } 5335 getout: 5336 frag->fr_symbol = 0; 5337 frag->fr_opcode = 0; 5338 free ((void *) bi); 5339 } 5340 return growth; 5341} 5342 5343void 5344tic54x_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, 5345 segT seg ATTRIBUTE_UNUSED, 5346 fragS *frag) 5347{ 5348 /* Offset is in bytes. */ 5349 frag->fr_offset = (frag->fr_next->fr_address 5350 - frag->fr_address 5351 - frag->fr_fix) / frag->fr_var; 5352 if (frag->fr_offset < 0) 5353 { 5354 as_bad_where (frag->fr_file, frag->fr_line, 5355 _("attempt to .space/.bes backwards? (%ld)"), 5356 (long) frag->fr_offset); 5357 } 5358 frag->fr_type = rs_space; 5359} 5360 5361/* We need to avoid having labels defined for certain directives/pseudo-ops 5362 since once the label is defined, it's in the symbol table for good. TI 5363 syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax, 5364 I guess, except I've never seen a definition of MRI syntax). 5365 5366 C is the character that used to be at *REST, which points to the end of the 5367 label. 5368 5369 Don't allow labels to start with '.' */ 5370 5371int 5372tic54x_start_label (int c, char *rest) 5373{ 5374 /* If within .struct/.union, no auto line labels, please. */ 5375 if (current_stag != NULL) 5376 return 0; 5377 5378 /* Disallow labels starting with "." */ 5379 if (c != ':') 5380 { 5381 char *label = rest; 5382 5383 while (!is_end_of_line[(int) label[-1]]) 5384 --label; 5385 if (*label == '.') 5386 { 5387 as_bad (_("Invalid label '%s'"), label); 5388 return 0; 5389 } 5390 } 5391 5392 if (is_end_of_line[(int) c]) 5393 return 1; 5394 5395 if (ISSPACE (c)) 5396 while (ISSPACE (c = *++rest)) 5397 ; 5398 if (c == '.') 5399 { 5400 /* Don't let colon () define a label for any of these... */ 5401 return (strncasecmp (rest, ".tag", 4) != 0 || !ISSPACE (rest[4])) 5402 && (strncasecmp (rest, ".struct", 7) != 0 || !ISSPACE (rest[7])) 5403 && (strncasecmp (rest, ".union", 6) != 0 || !ISSPACE (rest[6])) 5404 && (strncasecmp (rest, ".macro", 6) != 0 || !ISSPACE (rest[6])) 5405 && (strncasecmp (rest, ".set", 4) != 0 || !ISSPACE (rest[4])) 5406 && (strncasecmp (rest, ".equ", 4) != 0 || !ISSPACE (rest[4])); 5407 } 5408 5409 return 1; 5410} 5411