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