1 1.1 christos /* tc-tic4x.c -- Assemble for the Texas Instruments TMS320C[34]x. 2 1.10 christos Copyright (C) 1997-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos Contributed by Michael P. Hayes (m.hayes (at) elec.canterbury.ac.nz) 5 1.1 christos 6 1.1 christos This file is part of GAS, the GNU Assembler. 7 1.1 christos 8 1.1 christos GAS is free software; you can redistribute it and/or modify 9 1.1 christos it under the terms of the GNU General Public License as published by 10 1.1 christos the Free Software Foundation; either version 3, or (at your option) 11 1.1 christos any later version. 12 1.1 christos 13 1.1 christos GAS is distributed in the hope that it will be useful, 14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 1.1 christos GNU General Public License for more details. 17 1.1 christos 18 1.1 christos You should have received a copy of the GNU General Public License 19 1.1 christos along with GAS; see the file COPYING. If not, write to 20 1.3 christos the Free Software Foundation, 51 Franklin Street - Fifth Floor, 21 1.1 christos Boston, MA 02110-1301, USA. */ 22 1.1 christos /* 23 1.1 christos TODOs: 24 1.1 christos ------ 25 1.3 christos 26 1.1 christos o .align cannot handle fill-data-width larger than 0xFF/8-bits. It 27 1.1 christos should be possible to define a 32-bits pattern. 28 1.1 christos 29 1.1 christos o .align: Implement a 'bu' insn if the number of nop's exceeds 4 30 1.1 christos within the align frag. if(fragsize>4words) insert bu fragend+1 31 1.1 christos first. 32 1.1 christos 33 1.1 christos o .usect if has symbol on previous line not implemented 34 1.1 christos 35 1.1 christos o .sym, .eos, .stag, .etag, .member not implemented 36 1.1 christos 37 1.1 christos o Evaluation of constant floating point expressions (expr.c needs 38 1.1 christos work!) 39 1.1 christos 40 1.1 christos o Support 'abc' constants (that is 0x616263). */ 41 1.1 christos 42 1.1 christos #include "as.h" 43 1.1 christos #include "safe-ctype.h" 44 1.1 christos #include "opcode/tic4x.h" 45 1.1 christos #include "subsegs.h" 46 1.1 christos 47 1.1 christos /* OK, we accept a syntax similar to the other well known C30 48 1.1 christos assembly tools. With TIC4X_ALT_SYNTAX defined we are more 49 1.1 christos flexible, allowing a more Unix-like syntax: `%' in front of 50 1.1 christos register names, `#' in front of immediate constants, and 51 1.1 christos not requiring `@' in front of direct addresses. */ 52 1.1 christos 53 1.1 christos #define TIC4X_ALT_SYNTAX 54 1.1 christos 55 1.1 christos /* Handle of the inst mnemonic hash table. */ 56 1.8 christos static htab_t tic4x_op_hash = NULL; 57 1.1 christos 58 1.1 christos /* Handle asg pseudo. */ 59 1.8 christos static htab_t tic4x_asg_hash = NULL; 60 1.1 christos 61 1.1 christos static unsigned int tic4x_cpu = 0; /* Default to TMS320C40. */ 62 1.1 christos static unsigned int tic4x_revision = 0; /* CPU revision */ 63 1.1 christos static unsigned int tic4x_idle2 = 0; /* Idle2 support */ 64 1.1 christos static unsigned int tic4x_lowpower = 0; /* Lowpower support */ 65 1.1 christos static unsigned int tic4x_enhanced = 0; /* Enhanced opcode support */ 66 1.1 christos static unsigned int tic4x_big_model = 0; /* Default to small memory model. */ 67 1.1 christos static unsigned int tic4x_reg_args = 0; /* Default to args passed on stack. */ 68 1.1 christos static unsigned long tic4x_oplevel = 0; /* Opcode level */ 69 1.1 christos 70 1.1 christos #define OPTION_CPU 'm' 71 1.1 christos #define OPTION_BIG (OPTION_MD_BASE + 1) 72 1.1 christos #define OPTION_SMALL (OPTION_MD_BASE + 2) 73 1.1 christos #define OPTION_MEMPARM (OPTION_MD_BASE + 3) 74 1.1 christos #define OPTION_REGPARM (OPTION_MD_BASE + 4) 75 1.1 christos #define OPTION_IDLE2 (OPTION_MD_BASE + 5) 76 1.1 christos #define OPTION_LOWPOWER (OPTION_MD_BASE + 6) 77 1.1 christos #define OPTION_ENHANCED (OPTION_MD_BASE + 7) 78 1.1 christos #define OPTION_REV (OPTION_MD_BASE + 8) 79 1.1 christos 80 1.10 christos const char md_shortopts[] = "bm:prs"; 81 1.10 christos const struct option md_longopts[] = 82 1.1 christos { 83 1.1 christos { "mcpu", required_argument, NULL, OPTION_CPU }, 84 1.1 christos { "mdsp", required_argument, NULL, OPTION_CPU }, 85 1.1 christos { "mbig", no_argument, NULL, OPTION_BIG }, 86 1.1 christos { "msmall", no_argument, NULL, OPTION_SMALL }, 87 1.1 christos { "mmemparm", no_argument, NULL, OPTION_MEMPARM }, 88 1.1 christos { "mregparm", no_argument, NULL, OPTION_REGPARM }, 89 1.1 christos { "midle2", no_argument, NULL, OPTION_IDLE2 }, 90 1.1 christos { "mlowpower", no_argument, NULL, OPTION_LOWPOWER }, 91 1.1 christos { "menhanced", no_argument, NULL, OPTION_ENHANCED }, 92 1.1 christos { "mrev", required_argument, NULL, OPTION_REV }, 93 1.1 christos { NULL, no_argument, NULL, 0 } 94 1.1 christos }; 95 1.1 christos 96 1.10 christos const size_t md_longopts_size = sizeof (md_longopts); 97 1.1 christos 98 1.1 christos typedef enum 99 1.1 christos { 100 1.1 christos M_UNKNOWN, M_IMMED, M_DIRECT, M_REGISTER, M_INDIRECT, 101 1.1 christos M_IMMED_F, M_PARALLEL, M_HI 102 1.1 christos } 103 1.1 christos tic4x_addr_mode_t; 104 1.1 christos 105 1.1 christos typedef struct tic4x_operand 106 1.1 christos { 107 1.1 christos tic4x_addr_mode_t mode; /* Addressing mode. */ 108 1.1 christos expressionS expr; /* Expression. */ 109 1.1 christos int disp; /* Displacement for indirect addressing. */ 110 1.1 christos int aregno; /* Aux. register number. */ 111 1.1 christos LITTLENUM_TYPE fwords[MAX_LITTLENUMS]; /* Float immed. number. */ 112 1.1 christos } 113 1.1 christos tic4x_operand_t; 114 1.1 christos 115 1.1 christos typedef struct tic4x_insn 116 1.1 christos { 117 1.1 christos char name[TIC4X_NAME_MAX]; /* Mnemonic of instruction. */ 118 1.1 christos unsigned int in_use; /* True if in_use. */ 119 1.1 christos unsigned int parallel; /* True if parallel instruction. */ 120 1.1 christos unsigned int nchars; /* This is always 4 for the C30. */ 121 1.1 christos unsigned long opcode; /* Opcode number. */ 122 1.1 christos expressionS exp; /* Expression required for relocation. */ 123 1.5 christos /* Relocation type required. */ 124 1.5 christos bfd_reloc_code_real_type reloc; 125 1.1 christos int pcrel; /* True if relocation PC relative. */ 126 1.1 christos char *pname; /* Name of instruction in parallel. */ 127 1.1 christos unsigned int num_operands; /* Number of operands in total. */ 128 1.1 christos tic4x_inst_t *inst; /* Pointer to first template. */ 129 1.1 christos tic4x_operand_t operands[TIC4X_OPERANDS_MAX]; 130 1.1 christos } 131 1.1 christos tic4x_insn_t; 132 1.1 christos 133 1.1 christos static tic4x_insn_t the_insn; /* Info about our instruction. */ 134 1.1 christos static tic4x_insn_t *insn = &the_insn; 135 1.1 christos 136 1.1 christos static void tic4x_asg (int); 137 1.1 christos static void tic4x_bss (int); 138 1.1 christos static void tic4x_globl (int); 139 1.1 christos static void tic4x_cons (int); 140 1.1 christos static void tic4x_stringer (int); 141 1.1 christos static void tic4x_eval (int); 142 1.1 christos static void tic4x_newblock (int); 143 1.1 christos static void tic4x_sect (int); 144 1.1 christos static void tic4x_set (int); 145 1.1 christos static void tic4x_usect (int); 146 1.1 christos static void tic4x_version (int); 147 1.1 christos 148 1.1 christos 149 1.1 christos const pseudo_typeS 150 1.1 christos md_pseudo_table[] = 151 1.1 christos { 152 1.1 christos {"align", s_align_bytes, 32}, 153 1.1 christos {"ascii", tic4x_stringer, 1}, 154 1.1 christos {"asciz", tic4x_stringer, 0}, 155 1.1 christos {"asg", tic4x_asg, 0}, 156 1.1 christos {"block", s_space, 4}, 157 1.1 christos {"byte", tic4x_cons, 1}, 158 1.1 christos {"bss", tic4x_bss, 0}, 159 1.1 christos {"copy", s_include, 0}, 160 1.1 christos {"def", tic4x_globl, 0}, 161 1.1 christos {"equ", tic4x_set, 0}, 162 1.1 christos {"eval", tic4x_eval, 0}, 163 1.1 christos {"global", tic4x_globl, 0}, 164 1.1 christos {"globl", tic4x_globl, 0}, 165 1.1 christos {"hword", tic4x_cons, 2}, 166 1.1 christos {"ieee", float_cons, 'i'}, 167 1.1 christos {"int", tic4x_cons, 4}, /* .int allocates 4 bytes. */ 168 1.1 christos {"ldouble", float_cons, 'e'}, 169 1.1 christos {"newblock", tic4x_newblock, 0}, 170 1.1 christos {"ref", s_ignore, 0}, /* All undefined treated as external. */ 171 1.1 christos {"set", tic4x_set, 0}, 172 1.1 christos {"sect", tic4x_sect, 1}, /* Define named section. */ 173 1.1 christos {"space", s_space, 4}, 174 1.1 christos {"string", tic4x_stringer, 0}, 175 1.1 christos {"usect", tic4x_usect, 0}, /* Reserve space in uninit. named sect. */ 176 1.1 christos {"version", tic4x_version, 0}, 177 1.1 christos {"word", tic4x_cons, 4}, /* .word allocates 4 bytes. */ 178 1.1 christos {"xdef", tic4x_globl, 0}, 179 1.1 christos {NULL, 0, 0}, 180 1.1 christos }; 181 1.1 christos 182 1.1 christos int md_short_jump_size = 4; 183 1.1 christos int md_long_jump_size = 4; 184 1.1 christos 185 1.1 christos /* This array holds the chars that always start a comment. If the 186 1.1 christos pre-processor is disabled, these aren't very useful. */ 187 1.1 christos #ifdef TIC4X_ALT_SYNTAX 188 1.1 christos const char comment_chars[] = ";!"; 189 1.1 christos #else 190 1.1 christos const char comment_chars[] = ";"; 191 1.1 christos #endif 192 1.1 christos 193 1.1 christos /* This array holds the chars that only start a comment at the beginning of 194 1.1 christos a line. If the line seems to have the form '# 123 filename' 195 1.3 christos .line and .file directives will appear in the pre-processed output. 196 1.1 christos Note that input_file.c hand checks for '#' at the beginning of the 197 1.1 christos first line of the input file. This is because the compiler outputs 198 1.3 christos #NO_APP at the beginning of its output. 199 1.1 christos Also note that comments like this one will always work. */ 200 1.1 christos const char line_comment_chars[] = "#*"; 201 1.1 christos 202 1.1 christos /* We needed an unused char for line separation to work around the 203 1.1 christos lack of macros, using sed and such. */ 204 1.1 christos const char line_separator_chars[] = "&"; 205 1.1 christos 206 1.1 christos /* Chars that can be used to separate mant from exp in floating point nums. */ 207 1.1 christos const char EXP_CHARS[] = "eE"; 208 1.1 christos 209 1.1 christos /* Chars that mean this number is a floating point constant. */ 210 1.1 christos /* As in 0f12.456 */ 211 1.1 christos /* or 0d1.2345e12 */ 212 1.1 christos const char FLT_CHARS[] = "fFilsS"; 213 1.1 christos 214 1.1 christos /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be 215 1.1 christos changed in read.c. Ideally it shouldn't have to know about it at 216 1.1 christos all, but nothing is ideal around here. */ 217 1.1 christos 218 1.1 christos /* Flonums returned here. */ 219 1.1 christos extern FLONUM_TYPE generic_floating_point_number; 220 1.1 christos 221 1.1 christos /* Precision in LittleNums. */ 222 1.6 christos #define MAX_PRECISION (4) /* It's a bit overkill for us, but the code 223 1.1 christos requires it... */ 224 1.1 christos #define S_PRECISION (1) /* Short float constants 16-bit. */ 225 1.1 christos #define F_PRECISION (2) /* Float and double types 32-bit. */ 226 1.1 christos #define E_PRECISION (4) /* Extended precision, 64-bit (real 40-bit). */ 227 1.1 christos #define GUARD (2) 228 1.1 christos 229 1.1 christos /* Turn generic_floating_point_number into a real short/float/double. */ 230 1.1 christos static int 231 1.1 christos tic4x_gen_to_words (FLONUM_TYPE flonum, LITTLENUM_TYPE *words, int precision) 232 1.1 christos { 233 1.1 christos int return_value = 0; 234 1.1 christos LITTLENUM_TYPE *p; /* Littlenum pointer. */ 235 1.1 christos int mantissa_bits; /* Bits in mantissa field. */ 236 1.1 christos int exponent_bits; /* Bits in exponent field. */ 237 1.1 christos int exponent; 238 1.1 christos unsigned int sone; /* Scaled one. */ 239 1.1 christos unsigned int sfract; /* Scaled fraction. */ 240 1.1 christos unsigned int smant; /* Scaled mantissa. */ 241 1.1 christos unsigned int tmp; 242 1.1 christos unsigned int mover; /* Mantissa overflow bits */ 243 1.1 christos unsigned int rbit; /* Round bit. */ 244 1.1 christos int shift; /* Shift count. */ 245 1.1 christos 246 1.1 christos /* NOTE: Svein Seldal <Svein (at) dev.seldal.com> 247 1.1 christos The code in this function is altered slightly to support floats 248 1.1 christos with 31-bits mantissas, thus the documentation below may be a 249 1.1 christos little bit inaccurate. 250 1.3 christos 251 1.1 christos By Michael P. Hayes <m.hayes (at) elec.canterbury.ac.nz> 252 1.1 christos Here is how a generic floating point number is stored using 253 1.1 christos flonums (an extension of bignums) where p is a pointer to an 254 1.1 christos array of LITTLENUMs. 255 1.1 christos 256 1.1 christos For example 2e-3 is stored with exp = -4 and 257 1.1 christos bits[0] = 0x0000 258 1.1 christos bits[1] = 0x0000 259 1.1 christos bits[2] = 0x4fde 260 1.1 christos bits[3] = 0x978d 261 1.1 christos bits[4] = 0x126e 262 1.1 christos bits[5] = 0x0083 263 1.1 christos with low = &bits[2], high = &bits[5], and leader = &bits[5]. 264 1.1 christos 265 1.1 christos This number can be written as 266 1.1 christos 0x0083126e978d4fde.00000000 * 65536**-4 or 267 1.1 christos 0x0.0083126e978d4fde * 65536**0 or 268 1.1 christos 0x0.83126e978d4fde * 2**-8 = 2e-3 269 1.1 christos 270 1.1 christos Note that low points to the 65536**0 littlenum (bits[2]) and 271 1.1 christos leader points to the most significant non-zero littlenum 272 1.1 christos (bits[5]). 273 1.1 christos 274 1.1 christos TMS320C3X floating point numbers are a bit of a strange beast. 275 1.1 christos The 32-bit flavour has the 8 MSBs representing the exponent in 276 1.1 christos twos complement format (-128 to +127). There is then a sign bit 277 1.1 christos followed by 23 bits of mantissa. The mantissa is expressed in 278 1.1 christos twos complement format with the binary point after the most 279 1.1 christos significant non sign bit. The bit after the binary point is 280 1.1 christos suppressed since it is the complement of the sign bit. The 281 1.1 christos effective mantissa is thus 24 bits. Zero is represented by an 282 1.1 christos exponent of -128. 283 1.1 christos 284 1.1 christos The 16-bit flavour has the 4 MSBs representing the exponent in 285 1.1 christos twos complement format (-8 to +7). There is then a sign bit 286 1.1 christos followed by 11 bits of mantissa. The mantissa is expressed in 287 1.1 christos twos complement format with the binary point after the most 288 1.1 christos significant non sign bit. The bit after the binary point is 289 1.1 christos suppressed since it is the complement of the sign bit. The 290 1.1 christos effective mantissa is thus 12 bits. Zero is represented by an 291 1.1 christos exponent of -8. For example, 292 1.1 christos 293 1.1 christos number norm mant m x e s i fraction f 294 1.1 christos +0.500 => 1.00000000000 -1 -1 0 1 .00000000000 (1 + 0) * 2^(-1) 295 1.1 christos +0.999 => 1.11111111111 -1 -1 0 1 .11111111111 (1 + 0.99) * 2^(-1) 296 1.1 christos +1.000 => 1.00000000000 0 0 0 1 .00000000000 (1 + 0) * 2^(0) 297 1.1 christos +1.500 => 1.10000000000 0 0 0 1 .10000000000 (1 + 0.5) * 2^(0) 298 1.1 christos +1.999 => 1.11111111111 0 0 0 1 .11111111111 (1 + 0.9) * 2^(0) 299 1.1 christos +2.000 => 1.00000000000 1 1 0 1 .00000000000 (1 + 0) * 2^(1) 300 1.1 christos +4.000 => 1.00000000000 2 2 0 1 .00000000000 (1 + 0) * 2^(2) 301 1.1 christos -0.500 => 1.00000000000 -1 -1 1 0 .10000000000 (-2 + 0) * 2^(-2) 302 1.1 christos -1.000 => 1.00000000000 0 -1 1 0 .00000000000 (-2 + 0) * 2^(-1) 303 1.1 christos -1.500 => 1.10000000000 0 0 1 0 .10000000000 (-2 + 0.5) * 2^(0) 304 1.1 christos -1.999 => 1.11111111111 0 0 1 0 .00000000001 (-2 + 0.11) * 2^(0) 305 1.1 christos -2.000 => 1.00000000000 1 1 1 0 .00000000000 (-2 + 0) * 2^(0) 306 1.1 christos -4.000 => 1.00000000000 2 1 1 0 .00000000000 (-2 + 0) * 2^(1) 307 1.1 christos 308 1.1 christos where e is the exponent, s is the sign bit, i is the implied bit, 309 1.1 christos and f is the fraction stored in the mantissa field. 310 1.1 christos 311 1.1 christos num = (1 + f) * 2^x = m * 2^e if s = 0 312 1.1 christos num = (-2 + f) * 2^x = -m * 2^e if s = 1 313 1.1 christos where 0 <= f < 1.0 and 1.0 <= m < 2.0 314 1.1 christos 315 1.1 christos The fraction (f) and exponent (e) fields for the TMS320C3X format 316 1.1 christos can be derived from the normalised mantissa (m) and exponent (x) using: 317 1.1 christos 318 1.1 christos f = m - 1, e = x if s = 0 319 1.1 christos f = 2 - m, e = x if s = 1 and m != 1.0 320 1.1 christos f = 0, e = x - 1 if s = 1 and m = 1.0 321 1.1 christos f = 0, e = -8 if m = 0 322 1.1 christos 323 1.1 christos 324 1.1 christos OK, the other issue we have to consider is rounding since the 325 1.1 christos mantissa has a much higher potential precision than what we can 326 1.1 christos represent. To do this we add half the smallest storable fraction. 327 1.1 christos We then have to renormalise the number to allow for overflow. 328 1.1 christos 329 1.1 christos To convert a generic flonum into a TMS320C3X floating point 330 1.1 christos number, here's what we try to do.... 331 1.1 christos 332 1.1 christos The first thing is to generate a normalised mantissa (m) where 333 1.1 christos 1.0 <= m < 2 and to convert the exponent from base 16 to base 2. 334 1.1 christos We desire the binary point to be placed after the most significant 335 1.1 christos non zero bit. This process is done in two steps: firstly, the 336 1.1 christos littlenum with the most significant non zero bit is located (this 337 1.1 christos is done for us since leader points to this littlenum) and the 338 1.1 christos binary point (which is currently after the LSB of the littlenum 339 1.1 christos pointed to by low) is moved to before the MSB of the littlenum 340 1.1 christos pointed to by leader. This requires the exponent to be adjusted 341 1.1 christos by leader - low + 1. In the earlier example, the new exponent is 342 1.1 christos thus -4 + (5 - 2 + 1) = 0 (base 65536). We now need to convert 343 1.1 christos the exponent to base 2 by multiplying the exponent by 16 (log2 344 1.1 christos 65536). The exponent base 2 is thus also zero. 345 1.1 christos 346 1.1 christos The second step is to hunt for the most significant non zero bit 347 1.1 christos in the leader littlenum. We do this by left shifting a copy of 348 1.1 christos the leader littlenum until bit 16 is set (0x10000) and counting 349 1.1 christos the number of shifts, S, required. The number of shifts then has to 350 1.1 christos be added to correct the exponent (base 2). For our example, this 351 1.1 christos will require 9 shifts and thus our normalised exponent (base 2) is 352 1.1 christos 0 + 9 = 9. Note that the worst case scenario is when the leader 353 1.1 christos littlenum is 1, thus requiring 16 shifts. 354 1.1 christos 355 1.1 christos We now have to left shift the other littlenums by the same amount, 356 1.1 christos propagating the shifted bits into the more significant littlenums. 357 1.1 christos To save a lot of unnecessary shifting we only have to consider 358 1.1 christos two or three littlenums, since the greatest number of mantissa 359 1.1 christos bits required is 24 + 1 rounding bit. While two littlenums 360 1.1 christos provide 32 bits of precision, the most significant littlenum 361 1.1 christos may only contain a single significant bit and thus an extra 362 1.1 christos littlenum is required. 363 1.1 christos 364 1.1 christos Denoting the number of bits in the fraction field as F, we require 365 1.1 christos G = F + 2 bits (one extra bit is for rounding, the other gets 366 1.1 christos suppressed). Say we required S shifts to find the most 367 1.1 christos significant bit in the leader littlenum, the number of left shifts 368 1.1 christos required to move this bit into bit position G - 1 is L = G + S - 17. 369 1.1 christos Note that this shift count may be negative for the short floating 370 1.1 christos point flavour (where F = 11 and thus G = 13 and potentially S < 3). 371 1.1 christos If L > 0 we have to shunt the next littlenum into position. Bit 372 1.1 christos 15 (the MSB) of the next littlenum needs to get moved into position 373 1.1 christos L - 1 (If L > 15 we need all the bits of this littlenum and 374 1.1 christos some more from the next one.). We subtract 16 from L and use this 375 1.1 christos as the left shift count; the resultant value we or with the 376 1.1 christos previous result. If L > 0, we repeat this operation. */ 377 1.1 christos 378 1.1 christos if (precision != S_PRECISION) 379 1.1 christos words[1] = 0x0000; 380 1.1 christos if (precision == E_PRECISION) 381 1.1 christos words[2] = words[3] = 0x0000; 382 1.1 christos 383 1.1 christos /* 0.0e0 or NaN seen. */ 384 1.1 christos if (flonum.low > flonum.leader /* = 0.0e0 */ 385 1.8 christos || flonum.sign == 0 /* = NaN */ 386 1.8 christos || flonum.sign == 'Q' || flonum.sign == 'q' /* = QNaN */ 387 1.8 christos || flonum.sign == 'S' || flonum.sign == 's') /* = SNaN */ 388 1.1 christos { 389 1.8 christos if (flonum.sign != '+' && flonum.sign != '-') 390 1.1 christos as_bad (_("Nan, using zero.")); 391 1.1 christos words[0] = 0x8000; 392 1.1 christos return return_value; 393 1.1 christos } 394 1.1 christos 395 1.1 christos if (flonum.sign == 'P') 396 1.1 christos { 397 1.1 christos /* +INF: Replace with maximum float. */ 398 1.1 christos if (precision == S_PRECISION) 399 1.1 christos words[0] = 0x77ff; 400 1.3 christos else 401 1.1 christos { 402 1.1 christos words[0] = 0x7f7f; 403 1.1 christos words[1] = 0xffff; 404 1.1 christos } 405 1.1 christos if (precision == E_PRECISION) 406 1.1 christos { 407 1.1 christos words[2] = 0x7fff; 408 1.1 christos words[3] = 0xffff; 409 1.1 christos } 410 1.1 christos return return_value; 411 1.1 christos } 412 1.1 christos else if (flonum.sign == 'N') 413 1.1 christos { 414 1.1 christos /* -INF: Replace with maximum float. */ 415 1.1 christos if (precision == S_PRECISION) 416 1.1 christos words[0] = 0x7800; 417 1.3 christos else 418 1.1 christos words[0] = 0x7f80; 419 1.1 christos if (precision == E_PRECISION) 420 1.1 christos words[2] = 0x8000; 421 1.1 christos return return_value; 422 1.1 christos } 423 1.1 christos 424 1.1 christos exponent = (flonum.exponent + flonum.leader - flonum.low + 1) * 16; 425 1.1 christos 426 1.1 christos if (!(tmp = *flonum.leader)) 427 1.1 christos abort (); /* Hmmm. */ 428 1.1 christos shift = 0; /* Find position of first sig. bit. */ 429 1.1 christos while (tmp >>= 1) 430 1.1 christos shift++; 431 1.1 christos exponent -= (16 - shift); /* Adjust exponent. */ 432 1.1 christos 433 1.1 christos if (precision == S_PRECISION) /* Allow 1 rounding bit. */ 434 1.1 christos { 435 1.1 christos exponent_bits = 4; 436 1.1 christos mantissa_bits = 11; 437 1.1 christos } 438 1.1 christos else if(precision == F_PRECISION) 439 1.1 christos { 440 1.1 christos exponent_bits = 8; 441 1.1 christos mantissa_bits = 23; 442 1.1 christos } 443 1.1 christos else /* E_PRECISION */ 444 1.1 christos { 445 1.1 christos exponent_bits = 8; 446 1.1 christos mantissa_bits = 31; 447 1.1 christos } 448 1.1 christos 449 1.1 christos shift = mantissa_bits - shift; 450 1.1 christos 451 1.1 christos smant = 0; 452 1.1 christos mover = 0; 453 1.1 christos rbit = 0; 454 1.1 christos /* Store the mantissa data into smant and the roundbit into rbit */ 455 1.1 christos for (p = flonum.leader; p >= flonum.low && shift > -16; p--) 456 1.1 christos { 457 1.8 christos tmp = shift >= 0 ? (unsigned) *p << shift : (unsigned) *p >> -shift; 458 1.8 christos rbit = shift < 0 ? (((unsigned) *p >> (-shift-1)) & 0x1) : 0; 459 1.1 christos smant |= tmp; 460 1.1 christos shift -= 16; 461 1.1 christos } 462 1.1 christos 463 1.1 christos /* OK, we've got our scaled mantissa so let's round it up */ 464 1.1 christos if(rbit) 465 1.1 christos { 466 1.1 christos /* If the mantissa is going to overflow when added, lets store 467 1.8 christos the extra bit in mover. */ 468 1.8 christos if (smant == (1u << mantissa_bits << 1) - 1) 469 1.1 christos mover=1; 470 1.1 christos smant++; 471 1.1 christos } 472 1.1 christos 473 1.1 christos /* Get the scaled one value */ 474 1.8 christos sone = 1u << mantissa_bits; 475 1.1 christos 476 1.1 christos /* The number may be unnormalised so renormalise it... */ 477 1.1 christos if(mover) 478 1.1 christos { 479 1.1 christos smant >>= 1; 480 1.1 christos smant |= sone; /* Insert the bit from mover into smant */ 481 1.1 christos exponent++; 482 1.1 christos } 483 1.1 christos 484 1.1 christos /* The binary point is now between bit positions 11 and 10 or 23 and 22, 485 1.1 christos i.e., between mantissa_bits - 1 and mantissa_bits - 2 and the 486 1.1 christos bit at mantissa_bits - 1 should be set. */ 487 1.1 christos if (!(sone&smant)) 488 1.1 christos abort (); /* Ooops. */ 489 1.1 christos 490 1.1 christos if (flonum.sign == '+') 491 1.1 christos sfract = smant - sone; /* smant - 1.0. */ 492 1.1 christos else 493 1.1 christos { 494 1.1 christos /* This seems to work. */ 495 1.1 christos if (smant == sone) 496 1.1 christos { 497 1.1 christos exponent--; 498 1.1 christos sfract = 0; 499 1.1 christos } 500 1.1 christos else 501 1.1 christos { 502 1.1 christos sfract = -smant & (sone-1); /* 2.0 - smant. */ 503 1.1 christos } 504 1.1 christos sfract |= sone; /* Insert sign bit. */ 505 1.1 christos } 506 1.1 christos 507 1.1 christos if (abs (exponent) >= (1 << (exponent_bits - 1))) 508 1.1 christos as_bad (_("Cannot represent exponent in %d bits"), exponent_bits); 509 1.1 christos 510 1.1 christos /* Force exponent to fit in desired field width. */ 511 1.1 christos exponent &= (1 << (exponent_bits)) - 1; 512 1.1 christos 513 1.1 christos if (precision == E_PRECISION) 514 1.1 christos { 515 1.1 christos /* Map the float part first (100% equal format as F_PRECISION) */ 516 1.1 christos words[0] = exponent << (mantissa_bits+1-24); 517 1.1 christos words[0] |= sfract >> 24; 518 1.1 christos words[1] = sfract >> 8; 519 1.1 christos 520 1.1 christos /* Map the mantissa in the next */ 521 1.1 christos words[2] = sfract >> 16; 522 1.1 christos words[3] = sfract & 0xffff; 523 1.1 christos } 524 1.1 christos else 525 1.1 christos { 526 1.1 christos /* Insert the exponent data into the word */ 527 1.8 christos sfract |= (unsigned) exponent << (mantissa_bits + 1); 528 1.1 christos 529 1.1 christos if (precision == S_PRECISION) 530 1.1 christos words[0] = sfract; 531 1.1 christos else 532 1.1 christos { 533 1.1 christos words[0] = sfract >> 16; 534 1.1 christos words[1] = sfract & 0xffff; 535 1.1 christos } 536 1.1 christos } 537 1.1 christos 538 1.1 christos return return_value; 539 1.1 christos } 540 1.1 christos 541 1.1 christos /* Returns pointer past text consumed. */ 542 1.1 christos static char * 543 1.1 christos tic4x_atof (char *str, char what_kind, LITTLENUM_TYPE *words) 544 1.1 christos { 545 1.1 christos /* Extra bits for zeroed low-order bits. The 1st MAX_PRECISION are 546 1.1 christos zeroed, the last contain flonum bits. */ 547 1.1 christos static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; 548 1.1 christos char *return_value; 549 1.1 christos /* Number of 16-bit words in the format. */ 550 1.1 christos int precision; 551 1.1 christos FLONUM_TYPE save_gen_flonum; 552 1.1 christos 553 1.1 christos /* We have to save the generic_floating_point_number because it 554 1.1 christos contains storage allocation about the array of LITTLENUMs where 555 1.1 christos the value is actually stored. We will allocate our own array of 556 1.1 christos littlenums below, but have to restore the global one on exit. */ 557 1.1 christos save_gen_flonum = generic_floating_point_number; 558 1.1 christos 559 1.1 christos return_value = str; 560 1.1 christos generic_floating_point_number.low = bits + MAX_PRECISION; 561 1.1 christos generic_floating_point_number.high = NULL; 562 1.1 christos generic_floating_point_number.leader = NULL; 563 1.1 christos generic_floating_point_number.exponent = 0; 564 1.1 christos generic_floating_point_number.sign = '\0'; 565 1.1 christos 566 1.1 christos /* Use more LittleNums than seems necessary: the highest flonum may 567 1.1 christos have 15 leading 0 bits, so could be useless. */ 568 1.1 christos 569 1.1 christos memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); 570 1.1 christos 571 1.1 christos switch (what_kind) 572 1.1 christos { 573 1.1 christos case 's': 574 1.1 christos case 'S': 575 1.1 christos precision = S_PRECISION; 576 1.1 christos break; 577 1.1 christos 578 1.1 christos case 'd': 579 1.1 christos case 'D': 580 1.1 christos case 'f': 581 1.1 christos case 'F': 582 1.1 christos precision = F_PRECISION; 583 1.1 christos break; 584 1.1 christos 585 1.1 christos case 'E': 586 1.1 christos case 'e': 587 1.1 christos precision = E_PRECISION; 588 1.1 christos break; 589 1.1 christos 590 1.1 christos default: 591 1.1 christos as_bad (_("Invalid floating point number")); 592 1.1 christos return (NULL); 593 1.1 christos } 594 1.1 christos 595 1.1 christos generic_floating_point_number.high 596 1.1 christos = generic_floating_point_number.low + precision - 1 + GUARD; 597 1.1 christos 598 1.1 christos if (atof_generic (&return_value, ".", EXP_CHARS, 599 1.1 christos &generic_floating_point_number)) 600 1.1 christos { 601 1.1 christos as_bad (_("Invalid floating point number")); 602 1.1 christos return (NULL); 603 1.1 christos } 604 1.1 christos 605 1.1 christos tic4x_gen_to_words (generic_floating_point_number, 606 1.1 christos words, precision); 607 1.1 christos 608 1.1 christos /* Restore the generic_floating_point_number's storage alloc (and 609 1.1 christos everything else). */ 610 1.1 christos generic_floating_point_number = save_gen_flonum; 611 1.1 christos 612 1.1 christos return return_value; 613 1.1 christos } 614 1.1 christos 615 1.3 christos static void 616 1.5 christos tic4x_insert_reg (const char *regname, int regnum) 617 1.1 christos { 618 1.1 christos char buf[32]; 619 1.1 christos int i; 620 1.1 christos 621 1.8 christos symbol_table_insert (symbol_new (regname, reg_section, 622 1.8 christos &zero_address_frag, regnum)); 623 1.1 christos for (i = 0; regname[i]; i++) 624 1.1 christos buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i]; 625 1.1 christos buf[i] = '\0'; 626 1.1 christos 627 1.8 christos symbol_table_insert (symbol_new (buf, reg_section, 628 1.8 christos &zero_address_frag, regnum)); 629 1.1 christos } 630 1.1 christos 631 1.3 christos static void 632 1.5 christos tic4x_insert_sym (const char *symname, int value) 633 1.1 christos { 634 1.1 christos symbolS *symbolP; 635 1.1 christos 636 1.1 christos symbolP = symbol_new (symname, absolute_section, 637 1.8 christos &zero_address_frag, value); 638 1.1 christos SF_SET_LOCAL (symbolP); 639 1.1 christos symbol_table_insert (symbolP); 640 1.1 christos } 641 1.1 christos 642 1.1 christos static char * 643 1.1 christos tic4x_expression (char *str, expressionS *exp) 644 1.1 christos { 645 1.1 christos char *s; 646 1.1 christos char *t; 647 1.1 christos 648 1.1 christos t = input_line_pointer; /* Save line pointer. */ 649 1.1 christos input_line_pointer = str; 650 1.1 christos expression (exp); 651 1.9 christos resolve_register (exp); 652 1.1 christos s = input_line_pointer; 653 1.1 christos input_line_pointer = t; /* Restore line pointer. */ 654 1.1 christos return s; /* Return pointer to where parsing stopped. */ 655 1.1 christos } 656 1.1 christos 657 1.1 christos static char * 658 1.1 christos tic4x_expression_abs (char *str, offsetT *value) 659 1.1 christos { 660 1.1 christos char *s; 661 1.1 christos char *t; 662 1.1 christos 663 1.1 christos t = input_line_pointer; /* Save line pointer. */ 664 1.1 christos input_line_pointer = str; 665 1.1 christos *value = get_absolute_expression (); 666 1.1 christos s = input_line_pointer; 667 1.1 christos input_line_pointer = t; /* Restore line pointer. */ 668 1.1 christos return s; 669 1.1 christos } 670 1.1 christos 671 1.3 christos static void 672 1.1 christos tic4x_emit_char (char c, int b) 673 1.1 christos { 674 1.1 christos expressionS exp; 675 1.1 christos 676 1.1 christos exp.X_op = O_constant; 677 1.1 christos exp.X_add_number = c; 678 1.1 christos emit_expr (&exp, b); 679 1.1 christos } 680 1.1 christos 681 1.3 christos static void 682 1.1 christos tic4x_seg_alloc (char *name ATTRIBUTE_UNUSED, 683 1.1 christos segT seg ATTRIBUTE_UNUSED, 684 1.1 christos int size, 685 1.1 christos symbolS *symbolP) 686 1.1 christos { 687 1.1 christos /* Note that the size is in words 688 1.1 christos so we multiply it by 4 to get the number of bytes to allocate. */ 689 1.1 christos 690 1.1 christos /* If we have symbol: .usect ".fred", size etc., 691 1.1 christos the symbol needs to point to the first location reserved 692 1.1 christos by the pseudo op. */ 693 1.1 christos 694 1.1 christos if (size) 695 1.1 christos { 696 1.1 christos char *p; 697 1.1 christos 698 1.10 christos p = frag_var (rs_fill, 1, 1, 0, symbolP, size * OCTETS_PER_BYTE, NULL); 699 1.1 christos *p = 0; 700 1.1 christos } 701 1.1 christos } 702 1.1 christos 703 1.1 christos /* .asg ["]character-string["], symbol */ 704 1.3 christos static void 705 1.1 christos tic4x_asg (int x ATTRIBUTE_UNUSED) 706 1.1 christos { 707 1.1 christos char c; 708 1.1 christos char *name; 709 1.1 christos char *str; 710 1.9 christos size_t len; 711 1.1 christos 712 1.1 christos SKIP_WHITESPACE (); 713 1.1 christos str = input_line_pointer; 714 1.1 christos 715 1.1 christos /* Skip string expression. */ 716 1.1 christos while (*input_line_pointer != ',' && *input_line_pointer) 717 1.1 christos input_line_pointer++; 718 1.1 christos if (*input_line_pointer != ',') 719 1.1 christos { 720 1.1 christos as_bad (_("Comma expected\n")); 721 1.1 christos return; 722 1.1 christos } 723 1.9 christos len = input_line_pointer - str; 724 1.9 christos str = notes_memdup (str, len, len + 1); 725 1.9 christos input_line_pointer++; 726 1.3 christos c = get_symbol_name (&name); /* Get terminator. */ 727 1.9 christos name = notes_strdup (name); 728 1.8 christos str_hash_insert (tic4x_asg_hash, name, str, 1); 729 1.3 christos (void) restore_line_pointer (c); 730 1.1 christos demand_empty_rest_of_line (); 731 1.1 christos } 732 1.1 christos 733 1.1 christos /* .bss symbol, size */ 734 1.3 christos static void 735 1.1 christos tic4x_bss (int x ATTRIBUTE_UNUSED) 736 1.1 christos { 737 1.1 christos char c; 738 1.1 christos char *name; 739 1.1 christos char *p; 740 1.1 christos offsetT size; 741 1.1 christos segT current_seg; 742 1.1 christos subsegT current_subseg; 743 1.1 christos symbolS *symbolP; 744 1.1 christos 745 1.1 christos current_seg = now_seg; /* Save current seg. */ 746 1.1 christos current_subseg = now_subseg; /* Save current subseg. */ 747 1.1 christos 748 1.1 christos SKIP_WHITESPACE (); 749 1.3 christos c = get_symbol_name (&name); /* Get terminator. */ 750 1.3 christos if (c == '"') 751 1.3 christos c = * ++ input_line_pointer; 752 1.1 christos if (c != ',') 753 1.1 christos { 754 1.1 christos as_bad (_(".bss size argument missing\n")); 755 1.1 christos return; 756 1.1 christos } 757 1.1 christos 758 1.1 christos input_line_pointer = 759 1.1 christos tic4x_expression_abs (++input_line_pointer, &size); 760 1.1 christos if (size < 0) 761 1.1 christos { 762 1.1 christos as_bad (_(".bss size %ld < 0!"), (long) size); 763 1.1 christos return; 764 1.1 christos } 765 1.1 christos subseg_set (bss_section, 0); 766 1.1 christos symbolP = symbol_find_or_make (name); 767 1.1 christos 768 1.1 christos if (S_GET_SEGMENT (symbolP) == bss_section) 769 1.1 christos symbol_get_frag (symbolP)->fr_symbol = 0; 770 1.1 christos 771 1.1 christos symbol_set_frag (symbolP, frag_now); 772 1.1 christos 773 1.10 christos p = frag_var (rs_org, 1, 1, 0, symbolP, size * OCTETS_PER_BYTE, NULL); 774 1.1 christos *p = 0; /* Fill char. */ 775 1.1 christos 776 1.1 christos S_SET_SEGMENT (symbolP, bss_section); 777 1.1 christos 778 1.1 christos /* The symbol may already have been created with a preceding 779 1.1 christos ".globl" directive -- be careful not to step on storage class 780 1.1 christos in that case. Otherwise, set it to static. */ 781 1.1 christos if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) 782 1.1 christos S_SET_STORAGE_CLASS (symbolP, C_STAT); 783 1.1 christos 784 1.1 christos subseg_set (current_seg, current_subseg); /* Restore current seg. */ 785 1.1 christos demand_empty_rest_of_line (); 786 1.1 christos } 787 1.1 christos 788 1.1 christos static void 789 1.1 christos tic4x_globl (int ignore ATTRIBUTE_UNUSED) 790 1.1 christos { 791 1.1 christos char *name; 792 1.1 christos int c; 793 1.1 christos symbolS *symbolP; 794 1.1 christos 795 1.1 christos do 796 1.1 christos { 797 1.3 christos c = get_symbol_name (&name); 798 1.1 christos symbolP = symbol_find_or_make (name); 799 1.10 christos restore_line_pointer (c); 800 1.10 christos SKIP_WHITESPACE (); 801 1.1 christos S_SET_STORAGE_CLASS (symbolP, C_EXT); 802 1.1 christos S_SET_EXTERNAL (symbolP); 803 1.1 christos if (c == ',') 804 1.1 christos { 805 1.1 christos input_line_pointer++; 806 1.1 christos SKIP_WHITESPACE (); 807 1.1 christos if (*input_line_pointer == '\n') 808 1.1 christos c = '\n'; 809 1.1 christos } 810 1.1 christos } 811 1.1 christos while (c == ','); 812 1.1 christos 813 1.1 christos demand_empty_rest_of_line (); 814 1.1 christos } 815 1.1 christos 816 1.1 christos /* Handle .byte, .word. .int, .long */ 817 1.3 christos static void 818 1.1 christos tic4x_cons (int bytes) 819 1.1 christos { 820 1.3 christos unsigned int c; 821 1.1 christos do 822 1.1 christos { 823 1.1 christos SKIP_WHITESPACE (); 824 1.1 christos if (*input_line_pointer == '"') 825 1.1 christos { 826 1.1 christos input_line_pointer++; 827 1.1 christos while (is_a_char (c = next_char_of_string ())) 828 1.1 christos tic4x_emit_char (c, 4); 829 1.1 christos know (input_line_pointer[-1] == '\"'); 830 1.1 christos } 831 1.1 christos else 832 1.1 christos { 833 1.1 christos expressionS exp; 834 1.1 christos 835 1.1 christos input_line_pointer = tic4x_expression (input_line_pointer, &exp); 836 1.1 christos if (exp.X_op == O_constant) 837 1.1 christos { 838 1.1 christos switch (bytes) 839 1.1 christos { 840 1.1 christos case 1: 841 1.1 christos exp.X_add_number &= 255; 842 1.1 christos break; 843 1.1 christos case 2: 844 1.1 christos exp.X_add_number &= 65535; 845 1.1 christos break; 846 1.1 christos } 847 1.1 christos } 848 1.1 christos /* Perhaps we should disallow .byte and .hword with 849 1.1 christos a non constant expression that will require relocation. */ 850 1.1 christos emit_expr (&exp, 4); 851 1.1 christos } 852 1.1 christos } 853 1.1 christos while (*input_line_pointer++ == ','); 854 1.1 christos 855 1.1 christos input_line_pointer--; /* Put terminator back into stream. */ 856 1.1 christos demand_empty_rest_of_line (); 857 1.1 christos } 858 1.1 christos 859 1.1 christos /* Handle .ascii, .asciz, .string */ 860 1.3 christos static void 861 1.1 christos tic4x_stringer (int append_zero) 862 1.1 christos { 863 1.1 christos int bytes; 864 1.3 christos unsigned int c; 865 1.1 christos 866 1.1 christos bytes = 0; 867 1.1 christos do 868 1.1 christos { 869 1.1 christos SKIP_WHITESPACE (); 870 1.1 christos if (*input_line_pointer == '"') 871 1.1 christos { 872 1.1 christos input_line_pointer++; 873 1.1 christos while (is_a_char (c = next_char_of_string ())) 874 1.1 christos { 875 1.1 christos tic4x_emit_char (c, 1); 876 1.1 christos bytes++; 877 1.1 christos } 878 1.1 christos 879 1.1 christos if (append_zero) 880 1.1 christos { 881 1.1 christos tic4x_emit_char (c, 1); 882 1.1 christos bytes++; 883 1.1 christos } 884 1.1 christos 885 1.1 christos know (input_line_pointer[-1] == '\"'); 886 1.1 christos } 887 1.1 christos else 888 1.1 christos { 889 1.1 christos expressionS exp; 890 1.1 christos 891 1.1 christos input_line_pointer = tic4x_expression (input_line_pointer, &exp); 892 1.1 christos if (exp.X_op != O_constant) 893 1.1 christos { 894 1.1 christos as_bad (_("Non-constant symbols not allowed\n")); 895 1.1 christos return; 896 1.1 christos } 897 1.6 christos exp.X_add_number &= 255; /* Limit number to 8-bit */ 898 1.1 christos emit_expr (&exp, 1); 899 1.1 christos bytes++; 900 1.1 christos } 901 1.1 christos } 902 1.1 christos while (*input_line_pointer++ == ','); 903 1.1 christos 904 1.1 christos /* Fill out the rest of the expression with 0's to fill up a full word */ 905 1.1 christos if ( bytes&0x3 ) 906 1.1 christos tic4x_emit_char (0, 4-(bytes&0x3)); 907 1.1 christos 908 1.1 christos input_line_pointer--; /* Put terminator back into stream. */ 909 1.1 christos demand_empty_rest_of_line (); 910 1.1 christos } 911 1.1 christos 912 1.1 christos /* .eval expression, symbol */ 913 1.3 christos static void 914 1.1 christos tic4x_eval (int x ATTRIBUTE_UNUSED) 915 1.1 christos { 916 1.1 christos char c; 917 1.1 christos offsetT value; 918 1.1 christos char *name; 919 1.1 christos 920 1.1 christos SKIP_WHITESPACE (); 921 1.1 christos input_line_pointer = 922 1.1 christos tic4x_expression_abs (input_line_pointer, &value); 923 1.1 christos if (*input_line_pointer++ != ',') 924 1.1 christos { 925 1.1 christos as_bad (_("Symbol missing\n")); 926 1.1 christos return; 927 1.1 christos } 928 1.3 christos c = get_symbol_name (&name); /* Get terminator. */ 929 1.1 christos tic4x_insert_sym (name, value); 930 1.3 christos (void) restore_line_pointer (c); 931 1.1 christos demand_empty_rest_of_line (); 932 1.1 christos } 933 1.1 christos 934 1.1 christos /* Reset local labels. */ 935 1.3 christos static void 936 1.1 christos tic4x_newblock (int x ATTRIBUTE_UNUSED) 937 1.1 christos { 938 1.1 christos dollar_label_clear (); 939 1.1 christos } 940 1.1 christos 941 1.1 christos /* .sect "section-name" [, value] */ 942 1.1 christos /* .sect ["]section-name[:subsection-name]["] [, value] */ 943 1.3 christos static void 944 1.1 christos tic4x_sect (int x ATTRIBUTE_UNUSED) 945 1.1 christos { 946 1.1 christos char c; 947 1.1 christos char *section_name; 948 1.1 christos char *name; 949 1.1 christos segT seg; 950 1.1 christos offsetT num; 951 1.1 christos 952 1.1 christos SKIP_WHITESPACE (); 953 1.1 christos if (*input_line_pointer == '"') 954 1.1 christos input_line_pointer++; 955 1.3 christos c = get_symbol_name (§ion_name); /* Get terminator. */ 956 1.3 christos if (c == '"') 957 1.3 christos c = * ++ input_line_pointer; 958 1.1 christos input_line_pointer++; /* Skip null symbol terminator. */ 959 1.5 christos name = xstrdup (section_name); 960 1.1 christos 961 1.1 christos /* TI C from version 5.0 allows a section name to contain a 962 1.1 christos subsection name as well. The subsection name is separated by a 963 1.1 christos ':' from the section name. Currently we scan the subsection 964 1.1 christos name and discard it. 965 1.1 christos Volker Kuhlmann <v.kuhlmann (at) elec.canterbury.ac.nz>. */ 966 1.1 christos if (c == ':') 967 1.1 christos { 968 1.3 christos char *subname; 969 1.3 christos c = get_symbol_name (&subname); /* Get terminator. */ 970 1.3 christos if (c == '"') 971 1.3 christos c = * ++ input_line_pointer; 972 1.1 christos input_line_pointer++; /* Skip null symbol terminator. */ 973 1.1 christos as_warn (_(".sect: subsection name ignored")); 974 1.1 christos } 975 1.1 christos 976 1.1 christos /* We might still have a '"' to discard, but the character after a 977 1.3 christos symbol name will be overwritten with a \0 by get_symbol_name() 978 1.1 christos [VK]. */ 979 1.1 christos 980 1.1 christos if (c == ',') 981 1.1 christos input_line_pointer = 982 1.1 christos tic4x_expression_abs (input_line_pointer, &num); 983 1.1 christos else if (*input_line_pointer == ',') 984 1.1 christos { 985 1.1 christos input_line_pointer = 986 1.1 christos tic4x_expression_abs (++input_line_pointer, &num); 987 1.1 christos } 988 1.1 christos else 989 1.1 christos num = 0; 990 1.1 christos 991 1.1 christos seg = subseg_new (name, num); 992 1.1 christos if (line_label != NULL) 993 1.1 christos { 994 1.1 christos S_SET_SEGMENT (line_label, seg); 995 1.1 christos symbol_set_frag (line_label, frag_now); 996 1.1 christos } 997 1.1 christos 998 1.7 christos if (bfd_section_flags (seg) == SEC_NO_FLAGS) 999 1.1 christos { 1000 1.7 christos if (!bfd_set_section_flags (seg, SEC_DATA)) 1001 1.1 christos as_warn (_("Error setting flags for \"%s\": %s"), name, 1002 1.1 christos bfd_errmsg (bfd_get_error ())); 1003 1.1 christos } 1004 1.1 christos 1005 1.3 christos /* If the last character overwritten by get_symbol_name() was an 1006 1.1 christos end-of-line, we must restore it or the end of the line will not be 1007 1.1 christos recognised and scanning extends into the next line, stopping with 1008 1.1 christos an error (blame Volker Kuhlmann <v.kuhlmann (at) elec.canterbury.ac.nz> 1009 1.1 christos if this is not true). */ 1010 1.10 christos if (is_end_of_stmt (c)) 1011 1.1 christos *(--input_line_pointer) = c; 1012 1.1 christos 1013 1.1 christos demand_empty_rest_of_line (); 1014 1.1 christos } 1015 1.1 christos 1016 1.1 christos /* symbol[:] .set value or .set symbol, value */ 1017 1.3 christos static void 1018 1.1 christos tic4x_set (int x ATTRIBUTE_UNUSED) 1019 1.1 christos { 1020 1.1 christos symbolS *symbolP; 1021 1.1 christos 1022 1.1 christos SKIP_WHITESPACE (); 1023 1.1 christos if ((symbolP = line_label) == NULL) 1024 1.1 christos { 1025 1.1 christos char c; 1026 1.1 christos char *name; 1027 1.1 christos 1028 1.3 christos c = get_symbol_name (&name); /* Get terminator. */ 1029 1.3 christos if (c == '"') 1030 1.3 christos c = * ++ input_line_pointer; 1031 1.1 christos if (c != ',') 1032 1.1 christos { 1033 1.1 christos as_bad (_(".set syntax invalid\n")); 1034 1.1 christos ignore_rest_of_line (); 1035 1.1 christos return; 1036 1.1 christos } 1037 1.1 christos ++input_line_pointer; 1038 1.1 christos symbolP = symbol_find_or_make (name); 1039 1.1 christos } 1040 1.1 christos else 1041 1.1 christos symbol_table_insert (symbolP); 1042 1.1 christos 1043 1.1 christos pseudo_set (symbolP); 1044 1.1 christos demand_empty_rest_of_line (); 1045 1.1 christos } 1046 1.1 christos 1047 1.1 christos /* [symbol] .usect ["]section-name["], size-in-words [, alignment-flag] */ 1048 1.3 christos static void 1049 1.1 christos tic4x_usect (int x ATTRIBUTE_UNUSED) 1050 1.1 christos { 1051 1.1 christos char c; 1052 1.1 christos char *name; 1053 1.1 christos char *section_name; 1054 1.1 christos segT seg; 1055 1.1 christos offsetT size, alignment_flag; 1056 1.1 christos segT current_seg; 1057 1.1 christos subsegT current_subseg; 1058 1.1 christos 1059 1.1 christos current_seg = now_seg; /* save current seg. */ 1060 1.1 christos current_subseg = now_subseg; /* save current subseg. */ 1061 1.1 christos 1062 1.1 christos SKIP_WHITESPACE (); 1063 1.1 christos if (*input_line_pointer == '"') 1064 1.1 christos input_line_pointer++; 1065 1.3 christos c = get_symbol_name (§ion_name); /* Get terminator. */ 1066 1.3 christos if (c == '"') 1067 1.3 christos c = * ++ input_line_pointer; 1068 1.1 christos input_line_pointer++; /* Skip null symbol terminator. */ 1069 1.5 christos name = xstrdup (section_name); 1070 1.1 christos 1071 1.1 christos if (c == ',') 1072 1.1 christos input_line_pointer = 1073 1.1 christos tic4x_expression_abs (input_line_pointer, &size); 1074 1.1 christos else if (*input_line_pointer == ',') 1075 1.1 christos { 1076 1.1 christos input_line_pointer = 1077 1.1 christos tic4x_expression_abs (++input_line_pointer, &size); 1078 1.1 christos } 1079 1.1 christos else 1080 1.1 christos size = 0; 1081 1.1 christos 1082 1.1 christos /* Read a possibly present third argument (alignment flag) [VK]. */ 1083 1.1 christos if (*input_line_pointer == ',') 1084 1.1 christos { 1085 1.1 christos input_line_pointer = 1086 1.1 christos tic4x_expression_abs (++input_line_pointer, &alignment_flag); 1087 1.1 christos } 1088 1.1 christos else 1089 1.1 christos alignment_flag = 0; 1090 1.1 christos if (alignment_flag) 1091 1.1 christos as_warn (_(".usect: non-zero alignment flag ignored")); 1092 1.1 christos 1093 1.1 christos seg = subseg_new (name, 0); 1094 1.1 christos if (line_label != NULL) 1095 1.1 christos { 1096 1.1 christos S_SET_SEGMENT (line_label, seg); 1097 1.1 christos symbol_set_frag (line_label, frag_now); 1098 1.1 christos S_SET_VALUE (line_label, frag_now_fix ()); 1099 1.1 christos } 1100 1.1 christos seg_info (seg)->bss = 1; /* Uninitialised data. */ 1101 1.7 christos if (!bfd_set_section_flags (seg, SEC_ALLOC)) 1102 1.1 christos as_warn (_("Error setting flags for \"%s\": %s"), name, 1103 1.1 christos bfd_errmsg (bfd_get_error ())); 1104 1.1 christos tic4x_seg_alloc (name, seg, size, line_label); 1105 1.1 christos 1106 1.1 christos if (S_GET_STORAGE_CLASS (line_label) != C_EXT) 1107 1.1 christos S_SET_STORAGE_CLASS (line_label, C_STAT); 1108 1.1 christos 1109 1.1 christos subseg_set (current_seg, current_subseg); /* Restore current seg. */ 1110 1.1 christos demand_empty_rest_of_line (); 1111 1.1 christos } 1112 1.1 christos 1113 1.1 christos /* .version cpu-version. */ 1114 1.3 christos static void 1115 1.1 christos tic4x_version (int x ATTRIBUTE_UNUSED) 1116 1.1 christos { 1117 1.1 christos offsetT temp; 1118 1.1 christos 1119 1.1 christos input_line_pointer = 1120 1.1 christos tic4x_expression_abs (input_line_pointer, &temp); 1121 1.1 christos if (!IS_CPU_TIC3X (temp) && !IS_CPU_TIC4X (temp)) 1122 1.1 christos as_bad (_("This assembler does not support processor generation %ld"), 1123 1.1 christos (long) temp); 1124 1.1 christos 1125 1.1 christos if (tic4x_cpu && temp != (offsetT) tic4x_cpu) 1126 1.1 christos as_warn (_("Changing processor generation on fly not supported...")); 1127 1.1 christos tic4x_cpu = temp; 1128 1.1 christos demand_empty_rest_of_line (); 1129 1.1 christos } 1130 1.1 christos 1131 1.3 christos static void 1132 1.1 christos tic4x_init_regtable (void) 1133 1.1 christos { 1134 1.1 christos unsigned int i; 1135 1.1 christos 1136 1.1 christos for (i = 0; i < tic3x_num_registers; i++) 1137 1.1 christos tic4x_insert_reg (tic3x_registers[i].name, 1138 1.1 christos tic3x_registers[i].regno); 1139 1.1 christos 1140 1.1 christos if (IS_CPU_TIC4X (tic4x_cpu)) 1141 1.1 christos { 1142 1.1 christos /* Add additional Tic4x registers, overriding some C3x ones. */ 1143 1.1 christos for (i = 0; i < tic4x_num_registers; i++) 1144 1.1 christos tic4x_insert_reg (tic4x_registers[i].name, 1145 1.1 christos tic4x_registers[i].regno); 1146 1.1 christos } 1147 1.1 christos } 1148 1.1 christos 1149 1.3 christos static void 1150 1.1 christos tic4x_init_symbols (void) 1151 1.1 christos { 1152 1.1 christos /* The TI tools accept case insensitive versions of these symbols, 1153 1.1 christos we don't ! 1154 1.1 christos 1155 1.1 christos For TI C/Asm 5.0 1156 1.1 christos 1157 1.1 christos .TMS320xx 30,31,32,40,or 44 set according to -v flag 1158 1.1 christos .C3X or .C3x 1 or 0 1 if -v30,-v31,or -v32 1159 1.1 christos .C30 1 or 0 1 if -v30 1160 1.1 christos .C31 1 or 0 1 if -v31 1161 1.1 christos .C32 1 or 0 1 if -v32 1162 1.1 christos .C4X or .C4x 1 or 0 1 if -v40, or -v44 1163 1.1 christos .C40 1 or 0 1 if -v40 1164 1.1 christos .C44 1 or 0 1 if -v44 1165 1.1 christos 1166 1.1 christos .REGPARM 1 or 0 1 if -mr option used 1167 1.1 christos .BIGMODEL 1 or 0 1 if -mb option used 1168 1.1 christos 1169 1.1 christos These symbols are currently supported but will be removed in a 1170 1.1 christos later version: 1171 1.1 christos .TMS320C30 1 or 0 1 if -v30,-v31,or -v32 1172 1.1 christos .TMS320C31 1 or 0 1 if -v31 1173 1.1 christos .TMS320C32 1 or 0 1 if -v32 1174 1.1 christos .TMS320C40 1 or 0 1 if -v40, or -v44 1175 1.1 christos .TMS320C44 1 or 0 1 if -v44 1176 1.1 christos 1177 1.1 christos Source: TI: TMS320C3x/C4x Assembly Language Tools User's Guide, 1178 1.1 christos 1997, SPRU035C, p. 3-17/3-18. */ 1179 1.1 christos tic4x_insert_sym (".REGPARM", tic4x_reg_args); 1180 1.3 christos tic4x_insert_sym (".MEMPARM", !tic4x_reg_args); 1181 1.1 christos tic4x_insert_sym (".BIGMODEL", tic4x_big_model); 1182 1.1 christos tic4x_insert_sym (".C30INTERRUPT", 0); 1183 1.1 christos tic4x_insert_sym (".TMS320xx", tic4x_cpu == 0 ? 40 : tic4x_cpu); 1184 1.1 christos tic4x_insert_sym (".C3X", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33); 1185 1.1 christos tic4x_insert_sym (".C3x", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33); 1186 1.1 christos tic4x_insert_sym (".C4X", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44); 1187 1.1 christos tic4x_insert_sym (".C4x", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44); 1188 1.1 christos /* Do we need to have the following symbols also in lower case? */ 1189 1.1 christos tic4x_insert_sym (".TMS320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33); 1190 1.1 christos tic4x_insert_sym (".tms320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33); 1191 1.1 christos tic4x_insert_sym (".TMS320C31", tic4x_cpu == 31); 1192 1.1 christos tic4x_insert_sym (".tms320C31", tic4x_cpu == 31); 1193 1.1 christos tic4x_insert_sym (".TMS320C32", tic4x_cpu == 32); 1194 1.1 christos tic4x_insert_sym (".tms320C32", tic4x_cpu == 32); 1195 1.1 christos tic4x_insert_sym (".TMS320C33", tic4x_cpu == 33); 1196 1.1 christos tic4x_insert_sym (".tms320C33", tic4x_cpu == 33); 1197 1.1 christos tic4x_insert_sym (".TMS320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0); 1198 1.1 christos tic4x_insert_sym (".tms320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0); 1199 1.1 christos tic4x_insert_sym (".TMS320C44", tic4x_cpu == 44); 1200 1.1 christos tic4x_insert_sym (".tms320C44", tic4x_cpu == 44); 1201 1.1 christos tic4x_insert_sym (".TMX320C40", 0); /* C40 first pass silicon ? */ 1202 1.1 christos tic4x_insert_sym (".tmx320C40", 0); 1203 1.1 christos } 1204 1.1 christos 1205 1.1 christos /* Insert a new instruction template into hash table. */ 1206 1.8 christos static void 1207 1.1 christos tic4x_inst_insert (const tic4x_inst_t *inst) 1208 1.1 christos { 1209 1.1 christos static char prev_name[16]; 1210 1.1 christos 1211 1.1 christos /* Only insert the first name if have several similar entries. */ 1212 1.1 christos if (!strcmp (inst->name, prev_name) || inst->name[0] == '\0') 1213 1.8 christos return; 1214 1.8 christos 1215 1.8 christos if (str_hash_insert (tic4x_op_hash, inst->name, inst, 0) != NULL) 1216 1.8 christos as_fatal (_("duplicate %s"), inst->name); 1217 1.1 christos 1218 1.8 christos strcpy (prev_name, inst->name); 1219 1.1 christos } 1220 1.1 christos 1221 1.1 christos /* Make a new instruction template. */ 1222 1.1 christos static tic4x_inst_t * 1223 1.5 christos tic4x_inst_make (const char *name, unsigned long opcode, const char *args) 1224 1.1 christos { 1225 1.1 christos static tic4x_inst_t *insts = NULL; 1226 1.1 christos static char *names = NULL; 1227 1.1 christos static int iindex = 0; 1228 1.1 christos 1229 1.1 christos if (insts == NULL) 1230 1.1 christos { 1231 1.1 christos /* Allocate memory to store name strings. */ 1232 1.5 christos names = XNEWVEC (char, 8192); 1233 1.1 christos /* Allocate memory for additional insts. */ 1234 1.5 christos insts = XNEWVEC (tic4x_inst_t, 1024); 1235 1.1 christos } 1236 1.1 christos insts[iindex].name = names; 1237 1.1 christos insts[iindex].opcode = opcode; 1238 1.1 christos insts[iindex].opmask = 0xffffffff; 1239 1.1 christos insts[iindex].args = args; 1240 1.1 christos iindex++; 1241 1.1 christos 1242 1.8 christos while (*name) 1243 1.1 christos *names++ = *name++; 1244 1.1 christos *names++ = '\0'; 1245 1.1 christos 1246 1.1 christos return &insts[iindex - 1]; 1247 1.1 christos } 1248 1.1 christos 1249 1.1 christos /* Add instruction template, creating dynamic templates as required. */ 1250 1.8 christos static void 1251 1.1 christos tic4x_inst_add (const tic4x_inst_t *insts) 1252 1.1 christos { 1253 1.5 christos const char *s = insts->name; 1254 1.1 christos char *d; 1255 1.1 christos unsigned int i; 1256 1.1 christos char name[16]; 1257 1.1 christos 1258 1.1 christos d = name; 1259 1.1 christos 1260 1.1 christos /* We do not care about INSNs that is not a part of our 1261 1.1 christos oplevel setting. */ 1262 1.1 christos if ((insts->oplevel & tic4x_oplevel) == 0) 1263 1.8 christos return; 1264 1.1 christos 1265 1.1 christos while (1) 1266 1.1 christos { 1267 1.1 christos switch (*s) 1268 1.1 christos { 1269 1.1 christos case 'B': 1270 1.1 christos case 'C': 1271 1.1 christos /* Dynamically create all the conditional insts. */ 1272 1.1 christos for (i = 0; i < tic4x_num_conds; i++) 1273 1.1 christos { 1274 1.1 christos tic4x_inst_t *inst; 1275 1.1 christos int k = 0; 1276 1.5 christos const char *c = tic4x_conds[i].name; 1277 1.1 christos char *e = d; 1278 1.1 christos 1279 1.1 christos while (*c) 1280 1.1 christos *e++ = *c++; 1281 1.1 christos c = s + 1; 1282 1.1 christos while (*c) 1283 1.1 christos *e++ = *c++; 1284 1.1 christos *e = '\0'; 1285 1.1 christos 1286 1.1 christos /* If instruction found then have already processed it. */ 1287 1.8 christos if (str_hash_find (tic4x_op_hash, name)) 1288 1.8 christos return; 1289 1.1 christos 1290 1.1 christos do 1291 1.1 christos { 1292 1.1 christos inst = tic4x_inst_make (name, insts[k].opcode + 1293 1.1 christos (tic4x_conds[i].cond << 1294 1.1 christos (*s == 'B' ? 16 : 23)), 1295 1.1 christos insts[k].args); 1296 1.1 christos if (k == 0) /* Save strcmp() with following func. */ 1297 1.8 christos tic4x_inst_insert (inst); 1298 1.1 christos k++; 1299 1.1 christos } 1300 1.1 christos while (!strcmp (insts->name, 1301 1.1 christos insts[k].name)); 1302 1.1 christos } 1303 1.8 christos return; 1304 1.1 christos 1305 1.1 christos case '\0': 1306 1.8 christos tic4x_inst_insert (insts); 1307 1.8 christos return; 1308 1.1 christos 1309 1.1 christos default: 1310 1.1 christos *d++ = *s++; 1311 1.1 christos break; 1312 1.1 christos } 1313 1.1 christos } 1314 1.1 christos } 1315 1.1 christos 1316 1.1 christos /* This function is called once, at assembler startup time. It should 1317 1.1 christos set up all the tables, etc., that the MD part of the assembler will 1318 1.1 christos need. */ 1319 1.3 christos void 1320 1.1 christos md_begin (void) 1321 1.1 christos { 1322 1.1 christos unsigned int i; 1323 1.1 christos 1324 1.1 christos /* Setup the proper opcode level according to the 1325 1.1 christos commandline parameters */ 1326 1.1 christos tic4x_oplevel = OP_C3X; 1327 1.1 christos 1328 1.1 christos if ( IS_CPU_TIC4X(tic4x_cpu) ) 1329 1.1 christos tic4x_oplevel |= OP_C4X; 1330 1.1 christos 1331 1.1 christos if ( ( tic4x_cpu == 31 && tic4x_revision >= 6) 1332 1.1 christos || (tic4x_cpu == 32 && tic4x_revision >= 2) 1333 1.1 christos || (tic4x_cpu == 33) 1334 1.1 christos || tic4x_enhanced ) 1335 1.1 christos tic4x_oplevel |= OP_ENH; 1336 1.1 christos 1337 1.1 christos if ( ( tic4x_cpu == 30 && tic4x_revision >= 7) 1338 1.1 christos || (tic4x_cpu == 31 && tic4x_revision >= 5) 1339 1.1 christos || (tic4x_cpu == 32) 1340 1.1 christos || tic4x_lowpower ) 1341 1.1 christos tic4x_oplevel |= OP_LPWR; 1342 1.1 christos 1343 1.1 christos if ( ( tic4x_cpu == 30 && tic4x_revision >= 7) 1344 1.1 christos || (tic4x_cpu == 31 && tic4x_revision >= 5) 1345 1.1 christos || (tic4x_cpu == 32) 1346 1.1 christos || (tic4x_cpu == 33) 1347 1.1 christos || (tic4x_cpu == 40 && tic4x_revision >= 5) 1348 1.1 christos || (tic4x_cpu == 44) 1349 1.1 christos || tic4x_idle2 ) 1350 1.1 christos tic4x_oplevel |= OP_IDLE2; 1351 1.1 christos 1352 1.1 christos /* Create hash table for mnemonics. */ 1353 1.8 christos tic4x_op_hash = str_htab_create (); 1354 1.1 christos 1355 1.1 christos /* Create hash table for asg pseudo. */ 1356 1.8 christos tic4x_asg_hash = str_htab_create (); 1357 1.1 christos 1358 1.1 christos /* Add mnemonics to hash table, expanding conditional mnemonics on fly. */ 1359 1.1 christos for (i = 0; i < tic4x_num_insts; i++) 1360 1.8 christos tic4x_inst_add (tic4x_insts + i); 1361 1.1 christos 1362 1.1 christos /* Create dummy inst to avoid errors accessing end of table. */ 1363 1.1 christos tic4x_inst_make ("", 0, ""); 1364 1.1 christos 1365 1.1 christos /* Add registers to symbol table. */ 1366 1.1 christos tic4x_init_regtable (); 1367 1.1 christos 1368 1.1 christos /* Add predefined symbols to symbol table. */ 1369 1.1 christos tic4x_init_symbols (); 1370 1.1 christos } 1371 1.1 christos 1372 1.3 christos void 1373 1.9 christos tic4x_md_finish (void) 1374 1.1 christos { 1375 1.3 christos bfd_set_arch_mach (stdoutput, bfd_arch_tic4x, 1376 1.1 christos IS_CPU_TIC4X (tic4x_cpu) ? bfd_mach_tic4x : bfd_mach_tic3x); 1377 1.1 christos } 1378 1.1 christos 1379 1.3 christos static int 1380 1.1 christos tic4x_indirect_parse (tic4x_operand_t *operand, 1381 1.1 christos const tic4x_indirect_t *indirect) 1382 1.1 christos { 1383 1.5 christos const char *n = indirect->name; 1384 1.1 christos char *s = input_line_pointer; 1385 1.1 christos char *b; 1386 1.1 christos symbolS *symbolP; 1387 1.1 christos char name[32]; 1388 1.1 christos 1389 1.1 christos operand->disp = 0; 1390 1.1 christos for (; *n; n++) 1391 1.1 christos { 1392 1.1 christos switch (*n) 1393 1.1 christos { 1394 1.1 christos case 'a': /* Need to match aux register. */ 1395 1.1 christos b = name; 1396 1.1 christos #ifdef TIC4X_ALT_SYNTAX 1397 1.1 christos if (*s == '%') 1398 1.1 christos s++; 1399 1.1 christos #endif 1400 1.1 christos while (ISALNUM (*s)) 1401 1.1 christos *b++ = *s++; 1402 1.1 christos *b++ = '\0'; 1403 1.1 christos if (!(symbolP = symbol_find (name))) 1404 1.1 christos return 0; 1405 1.1 christos 1406 1.1 christos if (S_GET_SEGMENT (symbolP) != reg_section) 1407 1.1 christos return 0; 1408 1.1 christos 1409 1.1 christos operand->aregno = S_GET_VALUE (symbolP); 1410 1.1 christos if (operand->aregno >= REG_AR0 && operand->aregno <= REG_AR7) 1411 1.1 christos break; 1412 1.1 christos 1413 1.1 christos as_bad (_("Auxiliary register AR0--AR7 required for indirect")); 1414 1.1 christos return -1; 1415 1.1 christos 1416 1.1 christos case 'd': /* Need to match constant for disp. */ 1417 1.1 christos #ifdef TIC4X_ALT_SYNTAX 1418 1.1 christos if (*s == '%') /* expr() will die if we don't skip this. */ 1419 1.1 christos s++; 1420 1.1 christos #endif 1421 1.1 christos s = tic4x_expression (s, &operand->expr); 1422 1.1 christos if (operand->expr.X_op != O_constant) 1423 1.1 christos return 0; 1424 1.1 christos operand->disp = operand->expr.X_add_number; 1425 1.1 christos if (operand->disp < 0 || operand->disp > 255) 1426 1.1 christos { 1427 1.1 christos as_bad (_("Bad displacement %d (require 0--255)\n"), 1428 1.1 christos operand->disp); 1429 1.1 christos return -1; 1430 1.1 christos } 1431 1.1 christos break; 1432 1.1 christos 1433 1.1 christos case 'y': /* Need to match IR0. */ 1434 1.1 christos case 'z': /* Need to match IR1. */ 1435 1.1 christos #ifdef TIC4X_ALT_SYNTAX 1436 1.1 christos if (*s == '%') 1437 1.1 christos s++; 1438 1.1 christos #endif 1439 1.1 christos s = tic4x_expression (s, &operand->expr); 1440 1.1 christos if (operand->expr.X_op != O_register) 1441 1.1 christos return 0; 1442 1.1 christos if (operand->expr.X_add_number != REG_IR0 1443 1.1 christos && operand->expr.X_add_number != REG_IR1) 1444 1.1 christos { 1445 1.1 christos as_bad (_("Index register IR0,IR1 required for displacement")); 1446 1.1 christos return -1; 1447 1.1 christos } 1448 1.1 christos 1449 1.1 christos if (*n == 'y' && operand->expr.X_add_number == REG_IR0) 1450 1.1 christos break; 1451 1.1 christos if (*n == 'z' && operand->expr.X_add_number == REG_IR1) 1452 1.1 christos break; 1453 1.1 christos return 0; 1454 1.1 christos 1455 1.1 christos case '(': 1456 1.1 christos if (*s != '(') /* No displacement, assume to be 1. */ 1457 1.1 christos { 1458 1.1 christos operand->disp = 1; 1459 1.1 christos while (*n != ')') 1460 1.1 christos n++; 1461 1.1 christos } 1462 1.1 christos else 1463 1.1 christos s++; 1464 1.1 christos break; 1465 1.1 christos 1466 1.1 christos default: 1467 1.1 christos if (TOLOWER (*s) != *n) 1468 1.1 christos return 0; 1469 1.1 christos s++; 1470 1.1 christos } 1471 1.1 christos } 1472 1.10 christos if (!is_whitespace (*s) && *s != ',' && !is_end_of_stmt (*s)) 1473 1.1 christos return 0; 1474 1.1 christos input_line_pointer = s; 1475 1.1 christos return 1; 1476 1.1 christos } 1477 1.1 christos 1478 1.1 christos static char * 1479 1.1 christos tic4x_operand_parse (char *s, tic4x_operand_t *operand) 1480 1.1 christos { 1481 1.1 christos unsigned int i; 1482 1.1 christos char c; 1483 1.1 christos int ret; 1484 1.1 christos expressionS *exp = &operand->expr; 1485 1.1 christos char *save = input_line_pointer; 1486 1.1 christos char *str; 1487 1.1 christos char *new_pointer; 1488 1.1 christos struct hash_entry *entry = NULL; 1489 1.1 christos 1490 1.1 christos input_line_pointer = s; 1491 1.1 christos SKIP_WHITESPACE (); 1492 1.1 christos 1493 1.3 christos c = get_symbol_name (&str); /* Get terminator. */ 1494 1.1 christos new_pointer = input_line_pointer; 1495 1.8 christos if (strlen (str) && (entry = str_hash_find (tic4x_asg_hash, str)) != NULL) 1496 1.1 christos { 1497 1.3 christos (void) restore_line_pointer (c); 1498 1.1 christos input_line_pointer = (char *) entry; 1499 1.1 christos } 1500 1.1 christos else 1501 1.1 christos { 1502 1.3 christos (void) restore_line_pointer (c); 1503 1.1 christos input_line_pointer = str; 1504 1.1 christos } 1505 1.1 christos 1506 1.1 christos operand->mode = M_UNKNOWN; 1507 1.1 christos switch (*input_line_pointer) 1508 1.1 christos { 1509 1.1 christos #ifdef TIC4X_ALT_SYNTAX 1510 1.1 christos case '%': 1511 1.1 christos input_line_pointer = tic4x_expression (++input_line_pointer, exp); 1512 1.1 christos if (exp->X_op != O_register) 1513 1.1 christos as_bad (_("Expecting a register name")); 1514 1.1 christos operand->mode = M_REGISTER; 1515 1.1 christos break; 1516 1.1 christos 1517 1.1 christos case '^': 1518 1.1 christos /* Denotes high 16 bits. */ 1519 1.1 christos input_line_pointer = tic4x_expression (++input_line_pointer, exp); 1520 1.1 christos if (exp->X_op == O_constant) 1521 1.1 christos operand->mode = M_IMMED; 1522 1.1 christos else if (exp->X_op == O_big) 1523 1.1 christos { 1524 1.1 christos if (exp->X_add_number) 1525 1.1 christos as_bad (_("Number too large")); /* bignum required */ 1526 1.1 christos else 1527 1.1 christos { 1528 1.1 christos tic4x_gen_to_words (generic_floating_point_number, 1529 1.1 christos operand->fwords, S_PRECISION); 1530 1.1 christos operand->mode = M_IMMED_F; 1531 1.1 christos } 1532 1.1 christos } 1533 1.1 christos /* Allow ori ^foo, ar0 to be equivalent to ldi .hi.foo, ar0 */ 1534 1.1 christos /* WARNING : The TI C40 assembler cannot do this. */ 1535 1.1 christos else if (exp->X_op == O_symbol) 1536 1.6 christos operand->mode = M_HI; 1537 1.6 christos else 1538 1.6 christos as_bad (_("Expecting a constant value")); 1539 1.6 christos break; 1540 1.1 christos 1541 1.1 christos case '#': 1542 1.1 christos input_line_pointer = tic4x_expression (++input_line_pointer, exp); 1543 1.1 christos if (exp->X_op == O_constant) 1544 1.1 christos operand->mode = M_IMMED; 1545 1.1 christos else if (exp->X_op == O_big) 1546 1.1 christos { 1547 1.1 christos if (exp->X_add_number > 0) 1548 1.1 christos as_bad (_("Number too large")); /* bignum required. */ 1549 1.1 christos else 1550 1.1 christos { 1551 1.1 christos tic4x_gen_to_words (generic_floating_point_number, 1552 1.1 christos operand->fwords, S_PRECISION); 1553 1.1 christos operand->mode = M_IMMED_F; 1554 1.1 christos } 1555 1.1 christos } 1556 1.1 christos /* Allow ori foo, ar0 to be equivalent to ldi .lo.foo, ar0 */ 1557 1.1 christos /* WARNING : The TI C40 assembler cannot do this. */ 1558 1.1 christos else if (exp->X_op == O_symbol) 1559 1.6 christos operand->mode = M_IMMED; 1560 1.1 christos else 1561 1.1 christos as_bad (_("Expecting a constant value")); 1562 1.1 christos break; 1563 1.6 christos 1564 1.1 christos case '\\': 1565 1.1 christos #endif 1566 1.1 christos case '@': 1567 1.1 christos input_line_pointer = tic4x_expression (++input_line_pointer, exp); 1568 1.1 christos if (exp->X_op != O_constant && exp->X_op != O_symbol) 1569 1.1 christos as_bad (_("Bad direct addressing construct %s"), s); 1570 1.1 christos if (exp->X_op == O_constant) 1571 1.1 christos { 1572 1.1 christos if (exp->X_add_number < 0) 1573 1.1 christos as_bad (_("Direct value of %ld is not suitable"), 1574 1.1 christos (long) exp->X_add_number); 1575 1.1 christos } 1576 1.1 christos operand->mode = M_DIRECT; 1577 1.1 christos break; 1578 1.1 christos 1579 1.1 christos case '*': 1580 1.1 christos ret = -1; 1581 1.1 christos for (i = 0; i < tic4x_num_indirects; i++) 1582 1.1 christos if ((ret = tic4x_indirect_parse (operand, &tic4x_indirects[i]))) 1583 1.1 christos break; 1584 1.1 christos if (ret < 0) 1585 1.1 christos break; 1586 1.1 christos if (i < tic4x_num_indirects) 1587 1.1 christos { 1588 1.1 christos operand->mode = M_INDIRECT; 1589 1.1 christos /* Indirect addressing mode number. */ 1590 1.1 christos operand->expr.X_add_number = tic4x_indirects[i].modn; 1591 1.1 christos /* Convert *+ARn(0) to *ARn etc. Maybe we should 1592 1.1 christos squeal about silly ones? */ 1593 1.1 christos if (operand->expr.X_add_number < 0x08 && !operand->disp) 1594 1.1 christos operand->expr.X_add_number = 0x18; 1595 1.1 christos } 1596 1.1 christos else 1597 1.1 christos as_bad (_("Unknown indirect addressing mode")); 1598 1.1 christos break; 1599 1.1 christos 1600 1.1 christos default: 1601 1.1 christos operand->mode = M_IMMED; /* Assume immediate. */ 1602 1.1 christos str = input_line_pointer; 1603 1.1 christos input_line_pointer = tic4x_expression (input_line_pointer, exp); 1604 1.1 christos if (exp->X_op == O_register) 1605 1.1 christos { 1606 1.1 christos know (exp->X_add_symbol == 0); 1607 1.1 christos know (exp->X_op_symbol == 0); 1608 1.1 christos operand->mode = M_REGISTER; 1609 1.1 christos break; 1610 1.1 christos } 1611 1.1 christos else if (exp->X_op == O_big) 1612 1.1 christos { 1613 1.1 christos if (exp->X_add_number > 0) 1614 1.1 christos as_bad (_("Number too large")); /* bignum required. */ 1615 1.1 christos else 1616 1.1 christos { 1617 1.1 christos tic4x_gen_to_words (generic_floating_point_number, 1618 1.1 christos operand->fwords, S_PRECISION); 1619 1.1 christos operand->mode = M_IMMED_F; 1620 1.1 christos } 1621 1.1 christos break; 1622 1.1 christos } 1623 1.1 christos #ifdef TIC4X_ALT_SYNTAX 1624 1.1 christos /* Allow ldi foo, ar0 to be equivalent to ldi @foo, ar0. */ 1625 1.1 christos else if (exp->X_op == O_symbol) 1626 1.1 christos { 1627 1.1 christos operand->mode = M_DIRECT; 1628 1.1 christos break; 1629 1.1 christos } 1630 1.1 christos #endif 1631 1.1 christos } 1632 1.1 christos if (entry == NULL) 1633 1.1 christos new_pointer = input_line_pointer; 1634 1.1 christos input_line_pointer = save; 1635 1.1 christos return new_pointer; 1636 1.1 christos } 1637 1.1 christos 1638 1.3 christos static int 1639 1.1 christos tic4x_operands_match (tic4x_inst_t *inst, tic4x_insn_t *tinsn, int check) 1640 1.1 christos { 1641 1.1 christos const char *args = inst->args; 1642 1.1 christos unsigned long opcode = inst->opcode; 1643 1.1 christos int num_operands = tinsn->num_operands; 1644 1.1 christos tic4x_operand_t *operand = tinsn->operands; 1645 1.1 christos expressionS *exp = &operand->expr; 1646 1.1 christos int ret = 1; 1647 1.1 christos int reg; 1648 1.1 christos 1649 1.1 christos /* Build the opcode, checking as we go to make sure that the 1650 1.1 christos operands match. 1651 1.1 christos 1652 1.1 christos If an operand matches, we modify insn or opcode appropriately, 1653 1.1 christos and do a "continue". If an operand fails to match, we "break". */ 1654 1.1 christos 1655 1.1 christos tinsn->nchars = 4; /* Instructions always 4 bytes. */ 1656 1.1 christos tinsn->reloc = NO_RELOC; 1657 1.1 christos tinsn->pcrel = 0; 1658 1.1 christos 1659 1.1 christos if (*args == '\0') 1660 1.1 christos { 1661 1.1 christos tinsn->opcode = opcode; 1662 1.1 christos return num_operands == 0; 1663 1.1 christos } 1664 1.1 christos 1665 1.1 christos for (;; ++args) 1666 1.1 christos { 1667 1.1 christos switch (*args) 1668 1.1 christos { 1669 1.1 christos 1670 1.1 christos case '\0': /* End of args. */ 1671 1.1 christos if (num_operands == 1) 1672 1.1 christos { 1673 1.1 christos tinsn->opcode = opcode; 1674 1.1 christos return ret; 1675 1.1 christos } 1676 1.1 christos break; /* Too many operands. */ 1677 1.1 christos 1678 1.1 christos case '#': /* This is only used for ldp. */ 1679 1.1 christos if (operand->mode != M_DIRECT && operand->mode != M_IMMED) 1680 1.1 christos break; 1681 1.1 christos /* While this looks like a direct addressing mode, we actually 1682 1.1 christos use an immediate mode form of ldiu or ldpk instruction. */ 1683 1.1 christos if (exp->X_op == O_constant) 1684 1.1 christos { 1685 1.1 christos if( ( IS_CPU_TIC4X (tic4x_cpu) && exp->X_add_number <= 65535 ) 1686 1.1 christos || ( IS_CPU_TIC3X (tic4x_cpu) && exp->X_add_number <= 255 ) ) 1687 1.1 christos { 1688 1.1 christos INSERTS (opcode, exp->X_add_number, 15, 0); 1689 1.1 christos continue; 1690 1.1 christos } 1691 1.1 christos else 1692 1.1 christos { 1693 1.1 christos if (!check) 1694 1.1 christos as_bad (_("Immediate value of %ld is too large for ldf"), 1695 1.1 christos (long) exp->X_add_number); 1696 1.1 christos ret = -1; 1697 1.1 christos continue; 1698 1.1 christos } 1699 1.1 christos } 1700 1.1 christos else if (exp->X_op == O_symbol) 1701 1.1 christos { 1702 1.1 christos tinsn->reloc = BFD_RELOC_HI16; 1703 1.1 christos tinsn->exp = *exp; 1704 1.1 christos continue; 1705 1.1 christos } 1706 1.1 christos break; /* Not direct (dp) addressing. */ 1707 1.1 christos 1708 1.1 christos case '@': /* direct. */ 1709 1.1 christos if (operand->mode != M_DIRECT) 1710 1.1 christos break; 1711 1.1 christos if (exp->X_op == O_constant) 1712 1.1 christos { 1713 1.1 christos /* Store only the 16 LSBs of the number. */ 1714 1.1 christos INSERTS (opcode, exp->X_add_number, 15, 0); 1715 1.1 christos continue; 1716 1.1 christos } 1717 1.1 christos else if (exp->X_op == O_symbol) 1718 1.1 christos { 1719 1.1 christos tinsn->reloc = BFD_RELOC_LO16; 1720 1.1 christos tinsn->exp = *exp; 1721 1.1 christos continue; 1722 1.1 christos } 1723 1.1 christos break; /* Not direct addressing. */ 1724 1.1 christos 1725 1.1 christos case 'A': 1726 1.1 christos if (operand->mode != M_REGISTER) 1727 1.1 christos break; 1728 1.1 christos reg = exp->X_add_number; 1729 1.1 christos if (reg >= REG_AR0 && reg <= REG_AR7) 1730 1.1 christos INSERTU (opcode, reg - REG_AR0, 24, 22); 1731 1.1 christos else 1732 1.1 christos { 1733 1.1 christos if (!check) 1734 1.1 christos as_bad (_("Destination register must be ARn")); 1735 1.1 christos ret = -1; 1736 1.1 christos } 1737 1.1 christos continue; 1738 1.1 christos 1739 1.1 christos case 'B': /* Unsigned integer immediate. */ 1740 1.1 christos /* Allow br label or br @label. */ 1741 1.1 christos if (operand->mode != M_IMMED && operand->mode != M_DIRECT) 1742 1.1 christos break; 1743 1.1 christos if (exp->X_op == O_constant) 1744 1.1 christos { 1745 1.1 christos if (exp->X_add_number < (1 << 24)) 1746 1.1 christos { 1747 1.1 christos INSERTU (opcode, exp->X_add_number, 23, 0); 1748 1.1 christos continue; 1749 1.1 christos } 1750 1.1 christos else 1751 1.1 christos { 1752 1.1 christos if (!check) 1753 1.1 christos as_bad (_("Immediate value of %ld is too large"), 1754 1.1 christos (long) exp->X_add_number); 1755 1.1 christos ret = -1; 1756 1.1 christos continue; 1757 1.1 christos } 1758 1.1 christos } 1759 1.1 christos if (IS_CPU_TIC4X (tic4x_cpu)) 1760 1.1 christos { 1761 1.1 christos tinsn->reloc = BFD_RELOC_24_PCREL; 1762 1.1 christos tinsn->pcrel = 1; 1763 1.1 christos } 1764 1.1 christos else 1765 1.1 christos { 1766 1.1 christos tinsn->reloc = BFD_RELOC_24; 1767 1.1 christos tinsn->pcrel = 0; 1768 1.1 christos } 1769 1.1 christos tinsn->exp = *exp; 1770 1.1 christos continue; 1771 1.1 christos 1772 1.1 christos case 'C': 1773 1.1 christos if (!IS_CPU_TIC4X (tic4x_cpu)) 1774 1.1 christos break; 1775 1.1 christos if (operand->mode != M_INDIRECT) 1776 1.1 christos break; 1777 1.1 christos /* Require either *+ARn(disp) or *ARn. */ 1778 1.1 christos if (operand->expr.X_add_number != 0 1779 1.1 christos && operand->expr.X_add_number != 0x18) 1780 1.1 christos { 1781 1.1 christos if (!check) 1782 1.1 christos as_bad (_("Invalid indirect addressing mode")); 1783 1.1 christos ret = -1; 1784 1.1 christos continue; 1785 1.1 christos } 1786 1.1 christos INSERTU (opcode, operand->aregno - REG_AR0, 2, 0); 1787 1.1 christos INSERTU (opcode, operand->disp, 7, 3); 1788 1.1 christos continue; 1789 1.1 christos 1790 1.1 christos case 'E': 1791 1.1 christos if (!(operand->mode == M_REGISTER)) 1792 1.1 christos break; 1793 1.1 christos INSERTU (opcode, exp->X_add_number, 7, 0); 1794 1.1 christos continue; 1795 1.1 christos 1796 1.1 christos case 'e': 1797 1.1 christos if (!(operand->mode == M_REGISTER)) 1798 1.1 christos break; 1799 1.1 christos reg = exp->X_add_number; 1800 1.3 christos if ( (reg >= REG_R0 && reg <= REG_R7) 1801 1.1 christos || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) ) 1802 1.1 christos INSERTU (opcode, reg, 7, 0); 1803 1.1 christos else 1804 1.1 christos { 1805 1.1 christos if (!check) 1806 1.1 christos as_bad (_("Register must be Rn")); 1807 1.1 christos ret = -1; 1808 1.1 christos } 1809 1.1 christos continue; 1810 1.1 christos 1811 1.1 christos case 'F': 1812 1.1 christos if (operand->mode != M_IMMED_F 1813 1.1 christos && !(operand->mode == M_IMMED && exp->X_op == O_constant)) 1814 1.1 christos break; 1815 1.1 christos 1816 1.1 christos if (operand->mode != M_IMMED_F) 1817 1.1 christos { 1818 1.1 christos /* OK, we 've got something like cmpf 0, r0 1819 1.1 christos Why can't they stick in a bloody decimal point ?! */ 1820 1.1 christos char string[16]; 1821 1.1 christos 1822 1.1 christos /* Create floating point number string. */ 1823 1.1 christos sprintf (string, "%d.0", (int) exp->X_add_number); 1824 1.1 christos tic4x_atof (string, 's', operand->fwords); 1825 1.1 christos } 1826 1.1 christos 1827 1.1 christos INSERTU (opcode, operand->fwords[0], 15, 0); 1828 1.1 christos continue; 1829 1.1 christos 1830 1.1 christos case 'G': 1831 1.1 christos if (operand->mode != M_REGISTER) 1832 1.1 christos break; 1833 1.1 christos INSERTU (opcode, exp->X_add_number, 15, 8); 1834 1.1 christos continue; 1835 1.1 christos 1836 1.1 christos case 'g': 1837 1.1 christos if (operand->mode != M_REGISTER) 1838 1.1 christos break; 1839 1.1 christos reg = exp->X_add_number; 1840 1.3 christos if ( (reg >= REG_R0 && reg <= REG_R7) 1841 1.1 christos || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) ) 1842 1.1 christos INSERTU (opcode, reg, 15, 8); 1843 1.1 christos else 1844 1.1 christos { 1845 1.1 christos if (!check) 1846 1.1 christos as_bad (_("Register must be Rn")); 1847 1.1 christos ret = -1; 1848 1.1 christos } 1849 1.1 christos continue; 1850 1.1 christos 1851 1.1 christos case 'H': 1852 1.1 christos if (operand->mode != M_REGISTER) 1853 1.1 christos break; 1854 1.1 christos reg = exp->X_add_number; 1855 1.1 christos if (reg >= REG_R0 && reg <= REG_R7) 1856 1.1 christos INSERTU (opcode, reg - REG_R0, 18, 16); 1857 1.1 christos else 1858 1.1 christos { 1859 1.1 christos if (!check) 1860 1.1 christos as_bad (_("Register must be R0--R7")); 1861 1.1 christos ret = -1; 1862 1.1 christos } 1863 1.1 christos continue; 1864 1.1 christos 1865 1.1 christos case 'i': 1866 1.1 christos if ( operand->mode == M_REGISTER 1867 1.1 christos && tic4x_oplevel & OP_ENH ) 1868 1.1 christos { 1869 1.1 christos reg = exp->X_add_number; 1870 1.1 christos INSERTU (opcode, reg, 4, 0); 1871 1.1 christos INSERTU (opcode, 7, 7, 5); 1872 1.1 christos continue; 1873 1.1 christos } 1874 1.1 christos /* Fallthrough */ 1875 1.1 christos 1876 1.1 christos case 'I': 1877 1.1 christos if (operand->mode != M_INDIRECT) 1878 1.1 christos break; 1879 1.1 christos if (operand->disp != 0 && operand->disp != 1) 1880 1.1 christos { 1881 1.1 christos if (IS_CPU_TIC4X (tic4x_cpu)) 1882 1.1 christos break; 1883 1.1 christos if (!check) 1884 1.1 christos as_bad (_("Invalid indirect addressing mode displacement %d"), 1885 1.1 christos operand->disp); 1886 1.1 christos ret = -1; 1887 1.1 christos continue; 1888 1.1 christos } 1889 1.1 christos INSERTU (opcode, operand->aregno - REG_AR0, 2, 0); 1890 1.1 christos INSERTU (opcode, operand->expr.X_add_number, 7, 3); 1891 1.1 christos continue; 1892 1.1 christos 1893 1.1 christos case 'j': 1894 1.1 christos if ( operand->mode == M_REGISTER 1895 1.1 christos && tic4x_oplevel & OP_ENH ) 1896 1.1 christos { 1897 1.1 christos reg = exp->X_add_number; 1898 1.1 christos INSERTU (opcode, reg, 12, 8); 1899 1.1 christos INSERTU (opcode, 7, 15, 13); 1900 1.1 christos continue; 1901 1.1 christos } 1902 1.1 christos /* Fallthrough */ 1903 1.1 christos 1904 1.1 christos case 'J': 1905 1.1 christos if (operand->mode != M_INDIRECT) 1906 1.1 christos break; 1907 1.1 christos if (operand->disp != 0 && operand->disp != 1) 1908 1.1 christos { 1909 1.1 christos if (IS_CPU_TIC4X (tic4x_cpu)) 1910 1.1 christos break; 1911 1.1 christos if (!check) 1912 1.1 christos as_bad (_("Invalid indirect addressing mode displacement %d"), 1913 1.1 christos operand->disp); 1914 1.1 christos ret = -1; 1915 1.1 christos continue; 1916 1.1 christos } 1917 1.1 christos INSERTU (opcode, operand->aregno - REG_AR0, 10, 8); 1918 1.1 christos INSERTU (opcode, operand->expr.X_add_number, 15, 11); 1919 1.1 christos continue; 1920 1.1 christos 1921 1.1 christos case 'K': 1922 1.1 christos if (operand->mode != M_REGISTER) 1923 1.1 christos break; 1924 1.1 christos reg = exp->X_add_number; 1925 1.1 christos if (reg >= REG_R0 && reg <= REG_R7) 1926 1.1 christos INSERTU (opcode, reg - REG_R0, 21, 19); 1927 1.1 christos else 1928 1.1 christos { 1929 1.1 christos if (!check) 1930 1.1 christos as_bad (_("Register must be R0--R7")); 1931 1.1 christos ret = -1; 1932 1.1 christos } 1933 1.1 christos continue; 1934 1.1 christos 1935 1.1 christos case 'L': 1936 1.1 christos if (operand->mode != M_REGISTER) 1937 1.1 christos break; 1938 1.1 christos reg = exp->X_add_number; 1939 1.1 christos if (reg >= REG_R0 && reg <= REG_R7) 1940 1.1 christos INSERTU (opcode, reg - REG_R0, 24, 22); 1941 1.1 christos else 1942 1.1 christos { 1943 1.1 christos if (!check) 1944 1.1 christos as_bad (_("Register must be R0--R7")); 1945 1.1 christos ret = -1; 1946 1.1 christos } 1947 1.1 christos continue; 1948 1.1 christos 1949 1.1 christos case 'M': 1950 1.1 christos if (operand->mode != M_REGISTER) 1951 1.1 christos break; 1952 1.1 christos reg = exp->X_add_number; 1953 1.1 christos if (reg == REG_R2 || reg == REG_R3) 1954 1.1 christos INSERTU (opcode, reg - REG_R2, 22, 22); 1955 1.1 christos else 1956 1.1 christos { 1957 1.1 christos if (!check) 1958 1.1 christos as_bad (_("Destination register must be R2 or R3")); 1959 1.1 christos ret = -1; 1960 1.1 christos } 1961 1.1 christos continue; 1962 1.1 christos 1963 1.1 christos case 'N': 1964 1.1 christos if (operand->mode != M_REGISTER) 1965 1.1 christos break; 1966 1.1 christos reg = exp->X_add_number; 1967 1.1 christos if (reg == REG_R0 || reg == REG_R1) 1968 1.1 christos INSERTU (opcode, reg - REG_R0, 23, 23); 1969 1.1 christos else 1970 1.1 christos { 1971 1.1 christos if (!check) 1972 1.1 christos as_bad (_("Destination register must be R0 or R1")); 1973 1.1 christos ret = -1; 1974 1.1 christos } 1975 1.1 christos continue; 1976 1.1 christos 1977 1.1 christos case 'O': 1978 1.1 christos if (!IS_CPU_TIC4X (tic4x_cpu)) 1979 1.1 christos break; 1980 1.1 christos if (operand->mode != M_INDIRECT) 1981 1.1 christos break; 1982 1.1 christos /* Require either *+ARn(disp) or *ARn. */ 1983 1.1 christos if (operand->expr.X_add_number != 0 1984 1.1 christos && operand->expr.X_add_number != 0x18) 1985 1.1 christos { 1986 1.1 christos if (!check) 1987 1.1 christos as_bad (_("Invalid indirect addressing mode")); 1988 1.1 christos ret = -1; 1989 1.1 christos continue; 1990 1.1 christos } 1991 1.1 christos INSERTU (opcode, operand->aregno - REG_AR0, 10, 8); 1992 1.1 christos INSERTU (opcode, operand->disp, 15, 11); 1993 1.1 christos continue; 1994 1.1 christos 1995 1.1 christos case 'P': /* PC relative displacement. */ 1996 1.1 christos /* Allow br label or br @label. */ 1997 1.1 christos if (operand->mode != M_IMMED && operand->mode != M_DIRECT) 1998 1.1 christos break; 1999 1.1 christos if (exp->X_op == O_constant) 2000 1.1 christos { 2001 1.1 christos if (exp->X_add_number >= -32768 && exp->X_add_number <= 32767) 2002 1.1 christos { 2003 1.1 christos INSERTS (opcode, exp->X_add_number, 15, 0); 2004 1.1 christos continue; 2005 1.1 christos } 2006 1.1 christos else 2007 1.1 christos { 2008 1.1 christos if (!check) 2009 1.1 christos as_bad (_("Displacement value of %ld is too large"), 2010 1.1 christos (long) exp->X_add_number); 2011 1.1 christos ret = -1; 2012 1.1 christos continue; 2013 1.1 christos } 2014 1.1 christos } 2015 1.1 christos tinsn->reloc = BFD_RELOC_16_PCREL; 2016 1.1 christos tinsn->pcrel = 1; 2017 1.1 christos tinsn->exp = *exp; 2018 1.1 christos continue; 2019 1.1 christos 2020 1.1 christos case 'Q': 2021 1.1 christos if (operand->mode != M_REGISTER) 2022 1.1 christos break; 2023 1.1 christos reg = exp->X_add_number; 2024 1.1 christos INSERTU (opcode, reg, 15, 0); 2025 1.1 christos continue; 2026 1.1 christos 2027 1.1 christos case 'q': 2028 1.1 christos if (operand->mode != M_REGISTER) 2029 1.1 christos break; 2030 1.1 christos reg = exp->X_add_number; 2031 1.3 christos if ( (reg >= REG_R0 && reg <= REG_R7) 2032 1.1 christos || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) ) 2033 1.1 christos INSERTU (opcode, reg, 15, 0); 2034 1.1 christos else 2035 1.1 christos { 2036 1.1 christos if (!check) 2037 1.1 christos as_bad (_("Register must be Rn")); 2038 1.1 christos ret = -1; 2039 1.1 christos } 2040 1.1 christos continue; 2041 1.1 christos 2042 1.1 christos case 'R': 2043 1.1 christos if (operand->mode != M_REGISTER) 2044 1.1 christos break; 2045 1.1 christos reg = exp->X_add_number; 2046 1.1 christos INSERTU (opcode, reg, 20, 16); 2047 1.1 christos continue; 2048 1.1 christos 2049 1.1 christos case 'r': 2050 1.1 christos if (operand->mode != M_REGISTER) 2051 1.1 christos break; 2052 1.1 christos reg = exp->X_add_number; 2053 1.3 christos if ( (reg >= REG_R0 && reg <= REG_R7) 2054 1.1 christos || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) ) 2055 1.1 christos INSERTU (opcode, reg, 20, 16); 2056 1.1 christos else 2057 1.1 christos { 2058 1.1 christos if (!check) 2059 1.1 christos as_bad (_("Register must be Rn")); 2060 1.1 christos ret = -1; 2061 1.1 christos } 2062 1.1 christos continue; 2063 1.1 christos 2064 1.1 christos case 'S': /* Short immediate int. */ 2065 1.1 christos if (operand->mode != M_IMMED && operand->mode != M_HI) 2066 1.1 christos break; 2067 1.1 christos if (exp->X_op == O_big) 2068 1.1 christos { 2069 1.1 christos if (!check) 2070 1.1 christos as_bad (_("Floating point number not valid in expression")); 2071 1.1 christos ret = -1; 2072 1.1 christos continue; 2073 1.1 christos } 2074 1.1 christos if (exp->X_op == O_constant) 2075 1.1 christos { 2076 1.1 christos if (exp->X_add_number >= -32768 && exp->X_add_number <= 65535) 2077 1.1 christos { 2078 1.1 christos INSERTS (opcode, exp->X_add_number, 15, 0); 2079 1.1 christos continue; 2080 1.1 christos } 2081 1.1 christos else 2082 1.1 christos { 2083 1.1 christos if (!check) 2084 1.1 christos as_bad (_("Signed immediate value %ld too large"), 2085 1.1 christos (long) exp->X_add_number); 2086 1.1 christos ret = -1; 2087 1.1 christos continue; 2088 1.1 christos } 2089 1.1 christos } 2090 1.1 christos else if (exp->X_op == O_symbol) 2091 1.1 christos { 2092 1.1 christos if (operand->mode == M_HI) 2093 1.1 christos { 2094 1.1 christos tinsn->reloc = BFD_RELOC_HI16; 2095 1.1 christos } 2096 1.1 christos else 2097 1.1 christos { 2098 1.1 christos tinsn->reloc = BFD_RELOC_LO16; 2099 1.1 christos } 2100 1.1 christos tinsn->exp = *exp; 2101 1.1 christos continue; 2102 1.1 christos } 2103 1.1 christos /* Handle cases like ldi foo - $, ar0 where foo 2104 1.1 christos is a forward reference. Perhaps we should check 2105 1.1 christos for X_op == O_symbol and disallow things like 2106 1.1 christos ldi foo, ar0. */ 2107 1.1 christos tinsn->reloc = BFD_RELOC_16; 2108 1.1 christos tinsn->exp = *exp; 2109 1.1 christos continue; 2110 1.1 christos 2111 1.1 christos case 'T': /* 5-bit immediate value for tic4x stik. */ 2112 1.1 christos if (!IS_CPU_TIC4X (tic4x_cpu)) 2113 1.1 christos break; 2114 1.1 christos if (operand->mode != M_IMMED) 2115 1.1 christos break; 2116 1.1 christos if (exp->X_op == O_constant) 2117 1.1 christos { 2118 1.1 christos if (exp->X_add_number < 16 && exp->X_add_number >= -16) 2119 1.1 christos { 2120 1.1 christos INSERTS (opcode, exp->X_add_number, 20, 16); 2121 1.1 christos continue; 2122 1.1 christos } 2123 1.1 christos else 2124 1.1 christos { 2125 1.1 christos if (!check) 2126 1.1 christos as_bad (_("Immediate value of %ld is too large"), 2127 1.1 christos (long) exp->X_add_number); 2128 1.1 christos ret = -1; 2129 1.1 christos continue; 2130 1.1 christos } 2131 1.1 christos } 2132 1.1 christos break; /* No relocations allowed. */ 2133 1.1 christos 2134 1.1 christos case 'U': /* Unsigned integer immediate. */ 2135 1.1 christos if (operand->mode != M_IMMED && operand->mode != M_HI) 2136 1.1 christos break; 2137 1.1 christos if (exp->X_op == O_constant) 2138 1.1 christos { 2139 1.1 christos if (exp->X_add_number < (1 << 16) && exp->X_add_number >= 0) 2140 1.1 christos { 2141 1.1 christos INSERTU (opcode, exp->X_add_number, 15, 0); 2142 1.1 christos continue; 2143 1.1 christos } 2144 1.1 christos else 2145 1.1 christos { 2146 1.1 christos if (!check) 2147 1.1 christos as_bad (_("Unsigned immediate value %ld too large"), 2148 1.1 christos (long) exp->X_add_number); 2149 1.1 christos ret = -1; 2150 1.1 christos continue; 2151 1.1 christos } 2152 1.1 christos } 2153 1.1 christos else if (exp->X_op == O_symbol) 2154 1.1 christos { 2155 1.1 christos if (operand->mode == M_HI) 2156 1.1 christos tinsn->reloc = BFD_RELOC_HI16; 2157 1.1 christos else 2158 1.1 christos tinsn->reloc = BFD_RELOC_LO16; 2159 1.1 christos 2160 1.1 christos tinsn->exp = *exp; 2161 1.1 christos continue; 2162 1.1 christos } 2163 1.1 christos tinsn->reloc = BFD_RELOC_16; 2164 1.1 christos tinsn->exp = *exp; 2165 1.1 christos continue; 2166 1.1 christos 2167 1.1 christos case 'V': /* Trap numbers (immediate field). */ 2168 1.1 christos if (operand->mode != M_IMMED) 2169 1.1 christos break; 2170 1.1 christos if (exp->X_op == O_constant) 2171 1.1 christos { 2172 1.1 christos if (exp->X_add_number < 512 && IS_CPU_TIC4X (tic4x_cpu)) 2173 1.1 christos { 2174 1.1 christos INSERTU (opcode, exp->X_add_number, 8, 0); 2175 1.1 christos continue; 2176 1.1 christos } 2177 1.1 christos else if (exp->X_add_number < 32 && IS_CPU_TIC3X (tic4x_cpu)) 2178 1.1 christos { 2179 1.7 christos INSERTU (opcode, exp->X_add_number | 0x20, 5, 0); 2180 1.1 christos continue; 2181 1.1 christos } 2182 1.1 christos else 2183 1.1 christos { 2184 1.1 christos if (!check) 2185 1.1 christos as_bad (_("Immediate value of %ld is too large"), 2186 1.1 christos (long) exp->X_add_number); 2187 1.1 christos ret = -1; 2188 1.1 christos continue; 2189 1.1 christos } 2190 1.1 christos } 2191 1.1 christos break; /* No relocations allowed. */ 2192 1.1 christos 2193 1.1 christos case 'W': /* Short immediate int (0--7). */ 2194 1.1 christos if (!IS_CPU_TIC4X (tic4x_cpu)) 2195 1.1 christos break; 2196 1.1 christos if (operand->mode != M_IMMED) 2197 1.1 christos break; 2198 1.1 christos if (exp->X_op == O_big) 2199 1.1 christos { 2200 1.1 christos if (!check) 2201 1.1 christos as_bad (_("Floating point number not valid in expression")); 2202 1.1 christos ret = -1; 2203 1.1 christos continue; 2204 1.1 christos } 2205 1.1 christos if (exp->X_op == O_constant) 2206 1.1 christos { 2207 1.1 christos if (exp->X_add_number >= -256 && exp->X_add_number <= 127) 2208 1.1 christos { 2209 1.1 christos INSERTS (opcode, exp->X_add_number, 7, 0); 2210 1.1 christos continue; 2211 1.1 christos } 2212 1.1 christos else 2213 1.1 christos { 2214 1.1 christos if (!check) 2215 1.1 christos as_bad (_("Immediate value %ld too large"), 2216 1.1 christos (long) exp->X_add_number); 2217 1.1 christos ret = -1; 2218 1.1 christos continue; 2219 1.1 christos } 2220 1.1 christos } 2221 1.1 christos tinsn->reloc = BFD_RELOC_16; 2222 1.1 christos tinsn->exp = *exp; 2223 1.1 christos continue; 2224 1.1 christos 2225 1.1 christos case 'X': /* Expansion register for tic4x. */ 2226 1.1 christos if (operand->mode != M_REGISTER) 2227 1.1 christos break; 2228 1.1 christos reg = exp->X_add_number; 2229 1.1 christos if (reg >= REG_IVTP && reg <= REG_TVTP) 2230 1.1 christos INSERTU (opcode, reg - REG_IVTP, 4, 0); 2231 1.1 christos else 2232 1.1 christos { 2233 1.1 christos if (!check) 2234 1.1 christos as_bad (_("Register must be ivtp or tvtp")); 2235 1.1 christos ret = -1; 2236 1.1 christos } 2237 1.1 christos continue; 2238 1.1 christos 2239 1.1 christos case 'Y': /* Address register for tic4x lda. */ 2240 1.1 christos if (operand->mode != M_REGISTER) 2241 1.1 christos break; 2242 1.1 christos reg = exp->X_add_number; 2243 1.1 christos if (reg >= REG_AR0 && reg <= REG_SP) 2244 1.1 christos INSERTU (opcode, reg, 20, 16); 2245 1.1 christos else 2246 1.1 christos { 2247 1.1 christos if (!check) 2248 1.1 christos as_bad (_("Register must be address register")); 2249 1.1 christos ret = -1; 2250 1.1 christos } 2251 1.1 christos continue; 2252 1.1 christos 2253 1.1 christos case 'Z': /* Expansion register for tic4x. */ 2254 1.1 christos if (operand->mode != M_REGISTER) 2255 1.1 christos break; 2256 1.1 christos reg = exp->X_add_number; 2257 1.1 christos if (reg >= REG_IVTP && reg <= REG_TVTP) 2258 1.1 christos INSERTU (opcode, reg - REG_IVTP, 20, 16); 2259 1.1 christos else 2260 1.1 christos { 2261 1.1 christos if (!check) 2262 1.1 christos as_bad (_("Register must be ivtp or tvtp")); 2263 1.1 christos ret = -1; 2264 1.1 christos } 2265 1.1 christos continue; 2266 1.1 christos 2267 1.1 christos case '*': 2268 1.1 christos if (operand->mode != M_INDIRECT) 2269 1.1 christos break; 2270 1.1 christos INSERTS (opcode, operand->disp, 7, 0); 2271 1.1 christos INSERTU (opcode, operand->aregno - REG_AR0, 10, 8); 2272 1.1 christos INSERTU (opcode, operand->expr.X_add_number, 15, 11); 2273 1.1 christos continue; 2274 1.1 christos 2275 1.1 christos case '|': /* treat as `,' if have ldi_ldi form. */ 2276 1.1 christos if (tinsn->parallel) 2277 1.1 christos { 2278 1.1 christos if (--num_operands < 0) 2279 1.1 christos break; /* Too few operands. */ 2280 1.1 christos operand++; 2281 1.1 christos if (operand->mode != M_PARALLEL) 2282 1.1 christos break; 2283 1.1 christos } 2284 1.1 christos /* Fall through. */ 2285 1.1 christos 2286 1.1 christos case ',': /* Another operand. */ 2287 1.1 christos if (--num_operands < 0) 2288 1.1 christos break; /* Too few operands. */ 2289 1.1 christos operand++; 2290 1.1 christos exp = &operand->expr; 2291 1.1 christos continue; 2292 1.1 christos 2293 1.1 christos case ';': /* Another optional operand. */ 2294 1.1 christos if (num_operands == 1 || operand[1].mode == M_PARALLEL) 2295 1.1 christos continue; 2296 1.1 christos if (--num_operands < 0) 2297 1.1 christos break; /* Too few operands. */ 2298 1.1 christos operand++; 2299 1.1 christos exp = &operand->expr; 2300 1.1 christos continue; 2301 1.1 christos 2302 1.1 christos default: 2303 1.1 christos BAD_CASE (*args); 2304 1.1 christos } 2305 1.1 christos return 0; 2306 1.1 christos } 2307 1.1 christos } 2308 1.1 christos 2309 1.1 christos static void 2310 1.1 christos tic4x_insn_check (tic4x_insn_t *tinsn) 2311 1.1 christos { 2312 1.3 christos 2313 1.1 christos if (!strcmp (tinsn->name, "lda")) 2314 1.1 christos { 2315 1.1 christos if (tinsn->num_operands < 2 || tinsn->num_operands > 2) 2316 1.1 christos as_fatal ("Illegal internal LDA insn definition"); 2317 1.1 christos 2318 1.1 christos if (tinsn->operands[0].mode == M_REGISTER 2319 1.1 christos && tinsn->operands[1].mode == M_REGISTER 2320 1.1 christos && tinsn->operands[0].expr.X_add_number == tinsn->operands[1].expr.X_add_number ) 2321 1.1 christos as_bad (_("Source and destination register should not be equal")); 2322 1.1 christos } 2323 1.1 christos else if (!strcmp (tinsn->name, "ldi_ldi") 2324 1.1 christos || !strcmp (tinsn->name, "ldi1_ldi2") 2325 1.1 christos || !strcmp (tinsn->name, "ldi2_ldi1") 2326 1.1 christos || !strcmp (tinsn->name, "ldf_ldf") 2327 1.1 christos || !strcmp (tinsn->name, "ldf1_ldf2") 2328 1.1 christos || !strcmp (tinsn->name, "ldf2_ldf1") ) 2329 1.1 christos { 2330 1.3 christos if (tinsn->num_operands < 4 || tinsn->num_operands > 5) 2331 1.1 christos as_fatal ("Illegal internal %s insn definition", tinsn->name); 2332 1.3 christos 2333 1.1 christos if (tinsn->operands[1].mode == M_REGISTER 2334 1.1 christos && tinsn->operands[tinsn->num_operands-1].mode == M_REGISTER 2335 1.1 christos && tinsn->operands[1].expr.X_add_number == tinsn->operands[tinsn->num_operands-1].expr.X_add_number ) 2336 1.6 christos as_warn (_("Equal parallel destination registers, one result will be discarded")); 2337 1.1 christos } 2338 1.1 christos } 2339 1.1 christos 2340 1.3 christos static void 2341 1.1 christos tic4x_insn_output (tic4x_insn_t *tinsn) 2342 1.1 christos { 2343 1.1 christos char *dst; 2344 1.1 christos 2345 1.1 christos /* Grab another fragment for opcode. */ 2346 1.1 christos dst = frag_more (tinsn->nchars); 2347 1.1 christos 2348 1.1 christos /* Put out opcode word as a series of bytes in little endian order. */ 2349 1.1 christos md_number_to_chars (dst, tinsn->opcode, tinsn->nchars); 2350 1.1 christos 2351 1.1 christos /* Put out the symbol-dependent stuff. */ 2352 1.1 christos if (tinsn->reloc != NO_RELOC) 2353 1.1 christos { 2354 1.1 christos /* Where is the offset into the fragment for this instruction. */ 2355 1.1 christos fix_new_exp (frag_now, 2356 1.1 christos dst - frag_now->fr_literal, /* where */ 2357 1.1 christos tinsn->nchars, /* size */ 2358 1.1 christos &tinsn->exp, 2359 1.1 christos tinsn->pcrel, 2360 1.1 christos tinsn->reloc); 2361 1.1 christos } 2362 1.1 christos } 2363 1.1 christos 2364 1.1 christos /* Parse the operands. */ 2365 1.3 christos static int 2366 1.1 christos tic4x_operands_parse (char *s, tic4x_operand_t *operands, int num_operands) 2367 1.1 christos { 2368 1.1 christos if (!*s) 2369 1.1 christos return num_operands; 2370 1.1 christos 2371 1.1 christos do 2372 1.1 christos s = tic4x_operand_parse (s, &operands[num_operands++]); 2373 1.1 christos while (num_operands < TIC4X_OPERANDS_MAX && *s++ == ','); 2374 1.1 christos 2375 1.1 christos if (num_operands > TIC4X_OPERANDS_MAX) 2376 1.1 christos { 2377 1.1 christos as_bad (_("Too many operands scanned")); 2378 1.1 christos return -1; 2379 1.1 christos } 2380 1.1 christos return num_operands; 2381 1.1 christos } 2382 1.1 christos 2383 1.1 christos /* Assemble a single instruction. Its label has already been handled 2384 1.1 christos by the generic front end. We just parse mnemonic and operands, and 2385 1.1 christos produce the bytes of data and relocation. */ 2386 1.3 christos void 2387 1.1 christos md_assemble (char *str) 2388 1.1 christos { 2389 1.1 christos int ok = 0; 2390 1.1 christos char *s; 2391 1.1 christos int i; 2392 1.1 christos int parsed = 0; 2393 1.3 christos size_t len; 2394 1.1 christos tic4x_inst_t *inst; /* Instruction template. */ 2395 1.1 christos tic4x_inst_t *first_inst; 2396 1.1 christos 2397 1.1 christos /* Scan for parallel operators */ 2398 1.1 christos if (str) 2399 1.1 christos { 2400 1.1 christos s = str; 2401 1.1 christos while (*s && *s != '|') 2402 1.1 christos s++; 2403 1.3 christos 2404 1.1 christos if (*s && s[1]=='|') 2405 1.1 christos { 2406 1.1 christos if(insn->parallel) 2407 1.1 christos { 2408 1.1 christos as_bad (_("Parallel opcode cannot contain more than two instructions")); 2409 1.1 christos insn->parallel = 0; 2410 1.1 christos insn->in_use = 0; 2411 1.1 christos return; 2412 1.1 christos } 2413 1.3 christos 2414 1.1 christos /* Lets take care of the first part of the parallel insn */ 2415 1.1 christos *s++ = 0; 2416 1.1 christos md_assemble(str); 2417 1.1 christos insn->parallel = 1; 2418 1.1 christos str = ++s; 2419 1.1 christos /* .. and let the second run though here */ 2420 1.1 christos } 2421 1.1 christos } 2422 1.3 christos 2423 1.1 christos if (str && insn->parallel) 2424 1.1 christos { 2425 1.1 christos /* Find mnemonic (second part of parallel instruction). */ 2426 1.1 christos s = str; 2427 1.1 christos /* Skip past instruction mnemonic. */ 2428 1.10 christos while (!is_end_of_stmt (*s) && !is_whitespace (*s)) 2429 1.1 christos s++; 2430 1.8 christos if (*s) /* Null terminate for str_hash_find. */ 2431 1.1 christos *s++ = '\0'; /* and skip past null. */ 2432 1.3 christos len = strlen (insn->name); 2433 1.3 christos snprintf (insn->name + len, TIC4X_NAME_MAX - len, "_%s", str); 2434 1.1 christos 2435 1.1 christos insn->operands[insn->num_operands++].mode = M_PARALLEL; 2436 1.1 christos 2437 1.1 christos if ((i = tic4x_operands_parse 2438 1.1 christos (s, insn->operands, insn->num_operands)) < 0) 2439 1.1 christos { 2440 1.1 christos insn->parallel = 0; 2441 1.1 christos insn->in_use = 0; 2442 1.1 christos return; 2443 1.1 christos } 2444 1.1 christos insn->num_operands = i; 2445 1.1 christos parsed = 1; 2446 1.1 christos } 2447 1.1 christos 2448 1.1 christos if (insn->in_use) 2449 1.1 christos { 2450 1.10 christos if ((insn->inst = str_hash_find (tic4x_op_hash, insn->name)) == NULL) 2451 1.1 christos { 2452 1.1 christos as_bad (_("Unknown opcode `%s'."), insn->name); 2453 1.1 christos insn->parallel = 0; 2454 1.1 christos insn->in_use = 0; 2455 1.1 christos return; 2456 1.1 christos } 2457 1.1 christos 2458 1.1 christos inst = insn->inst; 2459 1.1 christos first_inst = NULL; 2460 1.1 christos do 2461 1.1 christos { 2462 1.1 christos ok = tic4x_operands_match (inst, insn, 1); 2463 1.1 christos if (ok < 0) 2464 1.1 christos { 2465 1.1 christos if (!first_inst) 2466 1.1 christos first_inst = inst; 2467 1.1 christos ok = 0; 2468 1.1 christos } 2469 1.7 christos } 2470 1.7 christos while (!ok && !strcmp (inst->name, inst[1].name) && inst++); 2471 1.1 christos 2472 1.1 christos if (ok > 0) 2473 1.1 christos { 2474 1.1 christos tic4x_insn_check (insn); 2475 1.1 christos tic4x_insn_output (insn); 2476 1.1 christos } 2477 1.1 christos else if (!ok) 2478 1.1 christos { 2479 1.1 christos if (first_inst) 2480 1.1 christos tic4x_operands_match (first_inst, insn, 0); 2481 1.1 christos as_bad (_("Invalid operands for %s"), insn->name); 2482 1.1 christos } 2483 1.1 christos else 2484 1.1 christos as_bad (_("Invalid instruction %s"), insn->name); 2485 1.1 christos } 2486 1.1 christos 2487 1.1 christos if (str && !parsed) 2488 1.1 christos { 2489 1.1 christos /* Find mnemonic. */ 2490 1.1 christos s = str; 2491 1.10 christos while (!is_end_of_stmt (*s) && !is_whitespace (*s)) /* Skip past instruction mnemonic. */ 2492 1.1 christos s++; 2493 1.8 christos if (*s) /* Null terminate for str_hash_find. */ 2494 1.1 christos *s++ = '\0'; /* and skip past null. */ 2495 1.3 christos strncpy (insn->name, str, TIC4X_NAME_MAX - 1); 2496 1.3 christos insn->name[TIC4X_NAME_MAX - 1] = '\0'; 2497 1.1 christos 2498 1.1 christos if ((i = tic4x_operands_parse (s, insn->operands, 0)) < 0) 2499 1.1 christos { 2500 1.1 christos insn->inst = NULL; /* Flag that error occurred. */ 2501 1.1 christos insn->parallel = 0; 2502 1.1 christos insn->in_use = 0; 2503 1.1 christos return; 2504 1.1 christos } 2505 1.1 christos insn->num_operands = i; 2506 1.1 christos insn->in_use = 1; 2507 1.1 christos } 2508 1.1 christos else 2509 1.1 christos insn->in_use = 0; 2510 1.1 christos insn->parallel = 0; 2511 1.1 christos } 2512 1.1 christos 2513 1.1 christos void 2514 1.1 christos tic4x_cleanup (void) 2515 1.1 christos { 2516 1.1 christos if (insn->in_use) 2517 1.1 christos md_assemble (NULL); 2518 1.1 christos } 2519 1.1 christos 2520 1.1 christos /* Turn a string in input_line_pointer into a floating point constant 2521 1.1 christos of type type, and store the appropriate bytes in *litP. The number 2522 1.1 christos of chars emitted is stored in *sizeP. An error message is 2523 1.1 christos returned, or NULL on OK. */ 2524 1.1 christos 2525 1.5 christos const char * 2526 1.1 christos md_atof (int type, char *litP, int *sizeP) 2527 1.1 christos { 2528 1.1 christos int prec; 2529 1.1 christos int ieee; 2530 1.1 christos LITTLENUM_TYPE words[MAX_LITTLENUMS]; 2531 1.1 christos LITTLENUM_TYPE *wordP; 2532 1.1 christos char *t; 2533 1.1 christos 2534 1.1 christos switch (type) 2535 1.1 christos { 2536 1.1 christos case 's': /* .single */ 2537 1.1 christos case 'S': 2538 1.1 christos ieee = 0; 2539 1.1 christos prec = 1; 2540 1.1 christos break; 2541 1.1 christos 2542 1.1 christos case 'd': /* .double */ 2543 1.1 christos case 'D': 2544 1.1 christos case 'f': /* .float */ 2545 1.1 christos case 'F': 2546 1.1 christos ieee = 0; 2547 1.1 christos prec = 2; /* 1 32-bit word */ 2548 1.1 christos break; 2549 1.1 christos 2550 1.1 christos case 'i': /* .ieee */ 2551 1.1 christos case 'I': 2552 1.1 christos prec = 2; 2553 1.1 christos ieee = 1; 2554 1.1 christos type = 'f'; /* Rewrite type to be usable by atof_ieee(). */ 2555 1.1 christos break; 2556 1.1 christos 2557 1.1 christos case 'e': /* .ldouble */ 2558 1.1 christos case 'E': 2559 1.1 christos prec = 4; /* 2 32-bit words */ 2560 1.1 christos ieee = 0; 2561 1.1 christos break; 2562 1.1 christos 2563 1.1 christos default: 2564 1.1 christos *sizeP = 0; 2565 1.1 christos return _("Unrecognized or unsupported floating point constant"); 2566 1.1 christos } 2567 1.1 christos 2568 1.1 christos if (ieee) 2569 1.1 christos t = atof_ieee (input_line_pointer, type, words); 2570 1.1 christos else 2571 1.1 christos t = tic4x_atof (input_line_pointer, type, words); 2572 1.1 christos if (t) 2573 1.1 christos input_line_pointer = t; 2574 1.1 christos *sizeP = prec * sizeof (LITTLENUM_TYPE); 2575 1.1 christos 2576 1.1 christos /* This loops outputs the LITTLENUMs in REVERSE order; in accord with 2577 1.1 christos little endian byte order. */ 2578 1.1 christos /* SES: However it is required to put the words (32-bits) out in the 2579 1.1 christos correct order, hence we write 2 and 2 littlenums in little endian 2580 1.1 christos order, while we keep the original order on successive words. */ 2581 1.1 christos for (wordP = words; wordP<(words+prec) ; wordP+=2) 2582 1.1 christos { 2583 1.1 christos if (wordP < (words + prec - 1)) /* Dump wordP[1] (if we have one). */ 2584 1.10 christos { 2585 1.10 christos md_number_to_chars (litP, wordP[1], sizeof (LITTLENUM_TYPE)); 2586 1.10 christos litP += sizeof (LITTLENUM_TYPE); 2587 1.10 christos } 2588 1.1 christos 2589 1.1 christos /* Dump wordP[0] */ 2590 1.10 christos md_number_to_chars (litP, wordP[0], sizeof (LITTLENUM_TYPE)); 2591 1.1 christos litP += sizeof (LITTLENUM_TYPE); 2592 1.1 christos } 2593 1.1 christos return NULL; 2594 1.1 christos } 2595 1.1 christos 2596 1.3 christos void 2597 1.1 christos md_apply_fix (fixS *fixP, valueT *value, segT seg ATTRIBUTE_UNUSED) 2598 1.1 christos { 2599 1.1 christos char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 2600 1.1 christos valueT val = *value; 2601 1.1 christos 2602 1.1 christos switch (fixP->fx_r_type) 2603 1.1 christos { 2604 1.1 christos case BFD_RELOC_HI16: 2605 1.1 christos val >>= 16; 2606 1.1 christos break; 2607 1.1 christos 2608 1.1 christos case BFD_RELOC_LO16: 2609 1.1 christos val &= 0xffff; 2610 1.1 christos break; 2611 1.1 christos default: 2612 1.1 christos break; 2613 1.1 christos } 2614 1.1 christos 2615 1.1 christos switch (fixP->fx_r_type) 2616 1.1 christos { 2617 1.1 christos case BFD_RELOC_32: 2618 1.1 christos buf[3] = val >> 24; 2619 1.6 christos /* Fall through. */ 2620 1.1 christos case BFD_RELOC_24: 2621 1.1 christos case BFD_RELOC_24_PCREL: 2622 1.1 christos buf[2] = val >> 16; 2623 1.6 christos /* Fall through. */ 2624 1.1 christos case BFD_RELOC_16: 2625 1.1 christos case BFD_RELOC_16_PCREL: 2626 1.1 christos case BFD_RELOC_LO16: 2627 1.1 christos case BFD_RELOC_HI16: 2628 1.1 christos buf[1] = val >> 8; 2629 1.1 christos buf[0] = val; 2630 1.1 christos break; 2631 1.1 christos 2632 1.1 christos case NO_RELOC: 2633 1.1 christos default: 2634 1.1 christos as_bad (_("Bad relocation type: 0x%02x"), fixP->fx_r_type); 2635 1.1 christos break; 2636 1.1 christos } 2637 1.1 christos 2638 1.1 christos if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1; 2639 1.1 christos } 2640 1.1 christos 2641 1.1 christos /* Should never be called for tic4x. */ 2642 1.3 christos void 2643 1.1 christos md_convert_frag (bfd *headers ATTRIBUTE_UNUSED, 2644 1.1 christos segT sec ATTRIBUTE_UNUSED, 2645 1.1 christos fragS *fragP ATTRIBUTE_UNUSED) 2646 1.1 christos { 2647 1.1 christos as_fatal ("md_convert_frag"); 2648 1.1 christos } 2649 1.1 christos 2650 1.1 christos /* Should never be called for tic4x. */ 2651 1.1 christos void 2652 1.1 christos md_create_short_jump (char *ptr ATTRIBUTE_UNUSED, 2653 1.1 christos addressT from_addr ATTRIBUTE_UNUSED, 2654 1.1 christos addressT to_addr ATTRIBUTE_UNUSED, 2655 1.1 christos fragS *frag ATTRIBUTE_UNUSED, 2656 1.1 christos symbolS *to_symbol ATTRIBUTE_UNUSED) 2657 1.1 christos { 2658 1.1 christos as_fatal ("md_create_short_jmp\n"); 2659 1.1 christos } 2660 1.1 christos 2661 1.1 christos /* Should never be called for tic4x. */ 2662 1.1 christos void 2663 1.1 christos md_create_long_jump (char *ptr ATTRIBUTE_UNUSED, 2664 1.1 christos addressT from_addr ATTRIBUTE_UNUSED, 2665 1.1 christos addressT to_addr ATTRIBUTE_UNUSED, 2666 1.1 christos fragS *frag ATTRIBUTE_UNUSED, 2667 1.1 christos symbolS *to_symbol ATTRIBUTE_UNUSED) 2668 1.1 christos { 2669 1.1 christos as_fatal ("md_create_long_jump\n"); 2670 1.1 christos } 2671 1.1 christos 2672 1.1 christos /* Should never be called for tic4x. */ 2673 1.1 christos int 2674 1.1 christos md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, 2675 1.1 christos segT segtype ATTRIBUTE_UNUSED) 2676 1.1 christos { 2677 1.1 christos as_fatal ("md_estimate_size_before_relax\n"); 2678 1.1 christos return 0; 2679 1.1 christos } 2680 1.1 christos 2681 1.1 christos 2682 1.1 christos int 2683 1.5 christos md_parse_option (int c, const char *arg) 2684 1.1 christos { 2685 1.1 christos switch (c) 2686 1.1 christos { 2687 1.1 christos case OPTION_CPU: /* cpu brand */ 2688 1.1 christos if (TOLOWER (*arg) == 'c') 2689 1.1 christos arg++; 2690 1.1 christos tic4x_cpu = atoi (arg); 2691 1.1 christos if (!IS_CPU_TIC3X (tic4x_cpu) && !IS_CPU_TIC4X (tic4x_cpu)) 2692 1.1 christos as_warn (_("Unsupported processor generation %d"), tic4x_cpu); 2693 1.1 christos break; 2694 1.1 christos 2695 1.1 christos case OPTION_REV: /* cpu revision */ 2696 1.1 christos tic4x_revision = atoi (arg); 2697 1.1 christos break; 2698 1.1 christos 2699 1.1 christos case 'b': 2700 1.1 christos as_warn (_("Option -b is depreciated, please use -mbig")); 2701 1.6 christos /* Fall through. */ 2702 1.1 christos case OPTION_BIG: /* big model */ 2703 1.1 christos tic4x_big_model = 1; 2704 1.1 christos break; 2705 1.1 christos 2706 1.1 christos case 'p': 2707 1.1 christos as_warn (_("Option -p is depreciated, please use -mmemparm")); 2708 1.6 christos /* Fall through. */ 2709 1.1 christos case OPTION_MEMPARM: /* push args */ 2710 1.1 christos tic4x_reg_args = 0; 2711 1.1 christos break; 2712 1.1 christos 2713 1.3 christos case 'r': 2714 1.1 christos as_warn (_("Option -r is depreciated, please use -mregparm")); 2715 1.6 christos /* Fall through. */ 2716 1.1 christos case OPTION_REGPARM: /* register args */ 2717 1.1 christos tic4x_reg_args = 1; 2718 1.1 christos break; 2719 1.1 christos 2720 1.1 christos case 's': 2721 1.1 christos as_warn (_("Option -s is depreciated, please use -msmall")); 2722 1.6 christos /* Fall through. */ 2723 1.1 christos case OPTION_SMALL: /* small model */ 2724 1.1 christos tic4x_big_model = 0; 2725 1.1 christos break; 2726 1.1 christos 2727 1.1 christos case OPTION_IDLE2: 2728 1.1 christos tic4x_idle2 = 1; 2729 1.1 christos break; 2730 1.1 christos 2731 1.1 christos case OPTION_LOWPOWER: 2732 1.1 christos tic4x_lowpower = 1; 2733 1.1 christos break; 2734 1.1 christos 2735 1.1 christos case OPTION_ENHANCED: 2736 1.1 christos tic4x_enhanced = 1; 2737 1.1 christos break; 2738 1.1 christos 2739 1.1 christos default: 2740 1.1 christos return 0; 2741 1.1 christos } 2742 1.1 christos 2743 1.1 christos return 1; 2744 1.1 christos } 2745 1.1 christos 2746 1.1 christos void 2747 1.1 christos md_show_usage (FILE *stream) 2748 1.1 christos { 2749 1.1 christos fprintf (stream, 2750 1.1 christos _("\nTIC4X options:\n" 2751 1.1 christos " -mcpu=CPU -mCPU select architecture variant. CPU can be:\n" 2752 1.1 christos " 30 - TMS320C30\n" 2753 1.1 christos " 31 - TMS320C31, TMS320LC31\n" 2754 1.1 christos " 32 - TMS320C32\n" 2755 1.1 christos " 33 - TMS320VC33\n" 2756 1.1 christos " 40 - TMS320C40\n" 2757 1.1 christos " 44 - TMS320C44\n" 2758 1.1 christos " -mrev=REV set cpu hardware revision (integer numbers).\n" 2759 1.1 christos " Combinations of -mcpu and -mrev will enable/disable\n" 2760 1.1 christos " the appropriate options (-midle2, -mlowpower and\n" 2761 1.1 christos " -menhanced) according to the selected type\n" 2762 1.1 christos " -mbig select big memory model\n" 2763 1.1 christos " -msmall select small memory model (default)\n" 2764 1.1 christos " -mregparm select register parameters (default)\n" 2765 1.1 christos " -mmemparm select memory parameters\n" 2766 1.1 christos " -midle2 enable IDLE2 support\n" 2767 1.1 christos " -mlowpower enable LOPOWER and MAXSPEED support\n" 2768 1.1 christos " -menhanced enable enhanced opcode support\n")); 2769 1.1 christos } 2770 1.1 christos 2771 1.1 christos /* This is called when a line is unrecognized. This is used to handle 2772 1.1 christos definitions of TI C3x tools style local labels $n where n is a single 2773 1.1 christos decimal digit. */ 2774 1.3 christos int 2775 1.1 christos tic4x_unrecognized_line (int c) 2776 1.1 christos { 2777 1.1 christos int lab; 2778 1.1 christos char *s; 2779 1.1 christos 2780 1.1 christos if (c != '$' || ! ISDIGIT (input_line_pointer[0])) 2781 1.1 christos return 0; 2782 1.1 christos 2783 1.1 christos s = input_line_pointer; 2784 1.1 christos 2785 1.1 christos /* Let's allow multiple digit local labels. */ 2786 1.1 christos lab = 0; 2787 1.1 christos while (ISDIGIT (*s)) 2788 1.1 christos { 2789 1.1 christos lab = lab * 10 + *s - '0'; 2790 1.1 christos s++; 2791 1.1 christos } 2792 1.1 christos 2793 1.1 christos if (dollar_label_defined (lab)) 2794 1.1 christos { 2795 1.1 christos as_bad (_("Label \"$%d\" redefined"), lab); 2796 1.1 christos return 0; 2797 1.1 christos } 2798 1.1 christos 2799 1.1 christos define_dollar_label (lab); 2800 1.1 christos colon (dollar_label_name (lab, 0)); 2801 1.1 christos input_line_pointer = s + 1; 2802 1.1 christos 2803 1.1 christos return 1; 2804 1.1 christos } 2805 1.1 christos 2806 1.1 christos /* Handle local labels peculiar to us referred to in an expression. */ 2807 1.1 christos symbolS * 2808 1.1 christos md_undefined_symbol (char *name) 2809 1.1 christos { 2810 1.1 christos /* Look for local labels of the form $n. */ 2811 1.1 christos if (name[0] == '$' && ISDIGIT (name[1])) 2812 1.1 christos { 2813 1.1 christos symbolS *symbolP; 2814 1.1 christos char *s = name + 1; 2815 1.1 christos int lab = 0; 2816 1.1 christos 2817 1.10 christos while (ISDIGIT (*s)) 2818 1.1 christos { 2819 1.1 christos lab = lab * 10 + *s - '0'; 2820 1.1 christos s++; 2821 1.1 christos } 2822 1.1 christos if (dollar_label_defined (lab)) 2823 1.1 christos { 2824 1.1 christos name = dollar_label_name (lab, 0); 2825 1.1 christos symbolP = symbol_find (name); 2826 1.1 christos } 2827 1.1 christos else 2828 1.1 christos { 2829 1.1 christos name = dollar_label_name (lab, 1); 2830 1.1 christos symbolP = symbol_find_or_make (name); 2831 1.1 christos } 2832 1.1 christos 2833 1.1 christos return symbolP; 2834 1.1 christos } 2835 1.1 christos return NULL; 2836 1.1 christos } 2837 1.1 christos 2838 1.1 christos /* Parse an operand that is machine-specific. */ 2839 1.1 christos void 2840 1.1 christos md_operand (expressionS *expressionP ATTRIBUTE_UNUSED) 2841 1.1 christos { 2842 1.1 christos } 2843 1.1 christos 2844 1.1 christos /* Round up a section size to the appropriate boundary---do we need this? */ 2845 1.1 christos valueT 2846 1.1 christos md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 2847 1.1 christos { 2848 1.1 christos return size; /* Byte (i.e., 32-bit) alignment is fine? */ 2849 1.1 christos } 2850 1.1 christos 2851 1.3 christos static int 2852 1.1 christos tic4x_pc_offset (unsigned int op) 2853 1.1 christos { 2854 1.1 christos /* Determine the PC offset for a C[34]x instruction. 2855 1.1 christos This could be simplified using some boolean algebra 2856 1.1 christos but at the expense of readability. */ 2857 1.1 christos switch (op >> 24) 2858 1.1 christos { 2859 1.1 christos case 0x60: /* br */ 2860 1.1 christos case 0x62: /* call (C4x) */ 2861 1.1 christos case 0x64: /* rptb (C4x) */ 2862 1.1 christos return 1; 2863 1.1 christos case 0x61: /* brd */ 2864 1.1 christos case 0x63: /* laj */ 2865 1.1 christos case 0x65: /* rptbd (C4x) */ 2866 1.1 christos return 3; 2867 1.1 christos case 0x66: /* swi */ 2868 1.1 christos case 0x67: 2869 1.1 christos return 0; 2870 1.1 christos default: 2871 1.1 christos break; 2872 1.1 christos } 2873 1.1 christos 2874 1.1 christos switch ((op & 0xffe00000) >> 20) 2875 1.1 christos { 2876 1.1 christos case 0x6a0: /* bB */ 2877 1.1 christos case 0x720: /* callB */ 2878 1.1 christos case 0x740: /* trapB */ 2879 1.1 christos return 1; 2880 1.1 christos 2881 1.1 christos case 0x6a2: /* bBd */ 2882 1.1 christos case 0x6a6: /* bBat */ 2883 1.1 christos case 0x6aa: /* bBaf */ 2884 1.1 christos case 0x722: /* lajB */ 2885 1.1 christos case 0x748: /* latB */ 2886 1.1 christos case 0x798: /* rptbd */ 2887 1.1 christos return 3; 2888 1.1 christos 2889 1.1 christos default: 2890 1.1 christos break; 2891 1.1 christos } 2892 1.1 christos 2893 1.1 christos switch ((op & 0xfe200000) >> 20) 2894 1.1 christos { 2895 1.1 christos case 0x6e0: /* dbB */ 2896 1.1 christos return 1; 2897 1.1 christos 2898 1.1 christos case 0x6e2: /* dbBd */ 2899 1.1 christos return 3; 2900 1.1 christos 2901 1.1 christos default: 2902 1.1 christos break; 2903 1.1 christos } 2904 1.1 christos 2905 1.1 christos return 0; 2906 1.1 christos } 2907 1.1 christos 2908 1.1 christos /* Exactly what point is a PC-relative offset relative TO? 2909 1.1 christos With the C3x we have the following: 2910 1.1 christos DBcond, Bcond disp + PC + 1 => PC 2911 1.1 christos DBcondD, BcondD disp + PC + 3 => PC 2912 1.1 christos */ 2913 1.1 christos long 2914 1.1 christos md_pcrel_from (fixS *fixP) 2915 1.1 christos { 2916 1.1 christos unsigned char *buf; 2917 1.1 christos unsigned int op; 2918 1.1 christos 2919 1.1 christos buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where; 2920 1.7 christos op = ((unsigned) buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; 2921 1.1 christos 2922 1.1 christos return ((fixP->fx_where + fixP->fx_frag->fr_address) >> 2) + 2923 1.1 christos tic4x_pc_offset (op); 2924 1.1 christos } 2925 1.1 christos 2926 1.1 christos /* Fill the alignment area with NOP's on .text, unless fill-data 2927 1.1 christos was specified. */ 2928 1.3 christos int 2929 1.1 christos tic4x_do_align (int alignment, 2930 1.1 christos const char *fill, 2931 1.1 christos int len, 2932 1.1 christos int max) 2933 1.1 christos { 2934 1.1 christos /* Because we are talking lwords, not bytes, adjust alignment to do words */ 2935 1.1 christos alignment += 2; 2936 1.3 christos 2937 1.1 christos if (alignment != 0 && !need_pass_2) 2938 1.1 christos { 2939 1.1 christos if (fill == NULL) 2940 1.1 christos { 2941 1.3 christos if (subseg_text_p (now_seg)) 2942 1.1 christos { 2943 1.1 christos char nop[4]; 2944 1.1 christos 2945 1.1 christos md_number_to_chars (nop, TIC_NOP_OPCODE, 4); 2946 1.1 christos frag_align_pattern (alignment, nop, sizeof (nop), max); 2947 1.1 christos } 2948 1.1 christos else 2949 1.1 christos frag_align (alignment, 0, max); 2950 1.1 christos } 2951 1.1 christos else if (len <= 1) 2952 1.1 christos frag_align (alignment, *fill, max); 2953 1.1 christos else 2954 1.1 christos frag_align_pattern (alignment, fill, len, max); 2955 1.1 christos } 2956 1.3 christos 2957 1.1 christos /* Return 1 to skip the default alignment function */ 2958 1.1 christos return 1; 2959 1.1 christos } 2960 1.1 christos 2961 1.1 christos /* Look for and remove parallel instruction operator ||. */ 2962 1.3 christos void 2963 1.1 christos tic4x_start_line (void) 2964 1.1 christos { 2965 1.1 christos char *s = input_line_pointer; 2966 1.1 christos 2967 1.1 christos SKIP_WHITESPACE (); 2968 1.1 christos 2969 1.1 christos /* If parallel instruction prefix found at start of line, skip it. */ 2970 1.1 christos if (*input_line_pointer == '|' && input_line_pointer[1] == '|') 2971 1.1 christos { 2972 1.1 christos if (insn->in_use) 2973 1.1 christos { 2974 1.1 christos insn->parallel = 1; 2975 1.1 christos input_line_pointer ++; 2976 1.1 christos *input_line_pointer = ' '; 2977 1.1 christos /* So line counters get bumped. */ 2978 1.1 christos input_line_pointer[-1] = '\n'; 2979 1.1 christos } 2980 1.1 christos } 2981 1.1 christos else 2982 1.1 christos { 2983 1.1 christos /* Write out the previous insn here */ 2984 1.1 christos if (insn->in_use) 2985 1.1 christos md_assemble (NULL); 2986 1.1 christos input_line_pointer = s; 2987 1.1 christos } 2988 1.1 christos } 2989 1.1 christos 2990 1.1 christos arelent * 2991 1.1 christos tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixP) 2992 1.1 christos { 2993 1.1 christos arelent *reloc; 2994 1.1 christos 2995 1.10 christos reloc = notes_alloc (sizeof (arelent)); 2996 1.10 christos reloc->sym_ptr_ptr = notes_alloc (sizeof (asymbol *)); 2997 1.1 christos *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); 2998 1.1 christos reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; 2999 1.1 christos reloc->address /= OCTETS_PER_BYTE; 3000 1.1 christos reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); 3001 1.10 christos if (reloc->howto == NULL) 3002 1.1 christos { 3003 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line, 3004 1.1 christos _("Reloc %d not supported by object file format"), 3005 1.1 christos (int) fixP->fx_r_type); 3006 1.1 christos return NULL; 3007 1.1 christos } 3008 1.1 christos 3009 1.1 christos if (fixP->fx_r_type == BFD_RELOC_HI16) 3010 1.1 christos reloc->addend = fixP->fx_offset; 3011 1.1 christos else 3012 1.1 christos reloc->addend = fixP->fx_addnumber; 3013 1.1 christos 3014 1.1 christos return reloc; 3015 1.1 christos } 3016