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