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