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