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