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