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