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