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