cleanup FLT_CHARS and EXP_CHARS
[deliverable/binutils-gdb.git] / gas / config / tc-tic4x.c
CommitLineData
be33c5dd 1/* tc-tic4x.c -- Assemble for the Texas Instruments TMS320C[34]x.
6f2750fe 2 Copyright (C) 1997-2016 Free Software Foundation, Inc.
026df7c5
NC
3
4 Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
5
6 This file is part of GAS, the GNU Assembler.
7
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
ec2655a6 10 the Free Software Foundation; either version 3, or (at your option)
026df7c5
NC
11 any later version.
12
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GAS; see the file COPYING. If not, write to
3739860c 20 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
4b4da160 21 Boston, MA 02110-1301, USA. */
247b1fe6
SS
22/*
23 TODOs:
24 ------
3739860c 25
44287f60
SS
26 o .align cannot handle fill-data-width larger than 0xFF/8-bits. It
27 should be possible to define a 32-bits pattern.
026df7c5 28
33b7f697 29 o .align: Implement a 'bu' insn if the number of nop's exceeds 4
44287f60
SS
30 within the align frag. if(fragsize>4words) insert bu fragend+1
31 first.
026df7c5 32
247b1fe6 33 o .usect if has symbol on previous line not implemented
026df7c5 34
247b1fe6 35 o .sym, .eos, .stag, .etag, .member not implemented
026df7c5 36
44287f60
SS
37 o Evaluation of constant floating point expressions (expr.c needs
38 work!)
026df7c5 39
df7b86aa 40 o Support 'abc' constants (that is 0x616263). */
026df7c5 41
026df7c5 42#include "as.h"
df7b86aa 43#include "safe-ctype.h"
026df7c5
NC
44#include "opcode/tic4x.h"
45#include "subsegs.h"
026df7c5
NC
46
47/* OK, we accept a syntax similar to the other well known C30
be33c5dd 48 assembly tools. With TIC4X_ALT_SYNTAX defined we are more
026df7c5
NC
49 flexible, allowing a more Unix-like syntax: `%' in front of
50 register names, `#' in front of immediate constants, and
51 not requiring `@' in front of direct addresses. */
52
be33c5dd 53#define TIC4X_ALT_SYNTAX
026df7c5
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'
3739860c 198 .line and .file directives will appear in the pre-processed output.
026df7c5
NC
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
3739860c 201 #NO_APP at the beginning of its output.
026df7c5
NC
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.
3739860c 253
247b1fe6
SS
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;
3739860c 401 else
026df7c5
NC
402 {
403 words[0] = 0x7f7f;
404 words[1] = 0xffff;
405 }
247b1fe6
SS
406 if (precision == E_PRECISION)
407 {
408 words[2] = 0x7fff;
409 words[3] = 0xffff;
410 }
026df7c5
NC
411 return return_value;
412 }
413 else if (flonum.sign == 'N')
414 {
415 /* -INF: Replace with maximum float. */
416 if (precision == S_PRECISION)
417 words[0] = 0x7800;
3739860c 418 else
247b1fe6
SS
419 words[0] = 0x7f80;
420 if (precision == E_PRECISION)
421 words[2] = 0x8000;
026df7c5
NC
422 return return_value;
423 }
424
425 exponent = (flonum.exponent + flonum.leader - flonum.low + 1) * 16;
426
427 if (!(tmp = *flonum.leader))
428 abort (); /* Hmmm. */
429 shift = 0; /* Find position of first sig. bit. */
430 while (tmp >>= 1)
431 shift++;
432 exponent -= (16 - shift); /* Adjust exponent. */
433
434 if (precision == S_PRECISION) /* Allow 1 rounding bit. */
435 {
436 exponent_bits = 4;
247b1fe6 437 mantissa_bits = 11;
026df7c5 438 }
247b1fe6
SS
439 else if(precision == F_PRECISION)
440 {
441 exponent_bits = 8;
442 mantissa_bits = 23;
443 }
444 else /* E_PRECISION */
026df7c5
NC
445 {
446 exponent_bits = 8;
247b1fe6 447 mantissa_bits = 31;
026df7c5
NC
448 }
449
450 shift = mantissa_bits - shift;
451
452 smant = 0;
247b1fe6
SS
453 mover = 0;
454 rbit = 0;
455 /* Store the mantissa data into smant and the roundbit into rbit */
026df7c5
NC
456 for (p = flonum.leader; p >= flonum.low && shift > -16; p--)
457 {
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
3739860c 620static void
f86f5863 621tic4x_insert_reg (const 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
3739860c 636static void
f86f5863 637tic4x_insert_sym (const 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
3739860c 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
3739860c 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 */
3739860c 710static void
5a49b8ac 711tic4x_asg (int x ATTRIBUTE_UNUSED)
026df7c5
NC
712{
713 char c;
714 char *name;
715 char *str;
026df7c5
NC
716
717 SKIP_WHITESPACE ();
718 str = input_line_pointer;
719
720 /* Skip string expression. */
721 while (*input_line_pointer != ',' && *input_line_pointer)
722 input_line_pointer++;
723 if (*input_line_pointer != ',')
724 {
20203fb9 725 as_bad (_("Comma expected\n"));
026df7c5
NC
726 return;
727 }
728 *input_line_pointer++ = '\0';
d02603dc 729 c = get_symbol_name (&name); /* Get terminator. */
4ec9d7d5
TS
730 str = xstrdup (str);
731 name = xstrdup (name);
be33c5dd 732 if (hash_find (tic4x_asg_hash, name))
5a49b8ac 733 hash_replace (tic4x_asg_hash, name, (void *) str);
026df7c5 734 else
5a49b8ac 735 hash_insert (tic4x_asg_hash, name, (void *) str);
d02603dc 736 (void) restore_line_pointer (c);
026df7c5
NC
737 demand_empty_rest_of_line ();
738}
739
740/* .bss symbol, size */
3739860c 741static void
5a49b8ac 742tic4x_bss (int x ATTRIBUTE_UNUSED)
026df7c5
NC
743{
744 char c;
745 char *name;
746 char *p;
2132e3a3 747 offsetT size;
026df7c5
NC
748 segT current_seg;
749 subsegT current_subseg;
750 symbolS *symbolP;
751
752 current_seg = now_seg; /* Save current seg. */
753 current_subseg = now_subseg; /* Save current subseg. */
754
755 SKIP_WHITESPACE ();
d02603dc
NC
756 c = get_symbol_name (&name); /* Get terminator. */
757 if (c == '"')
758 c = * ++ input_line_pointer;
026df7c5
NC
759 if (c != ',')
760 {
20203fb9 761 as_bad (_(".bss size argument missing\n"));
026df7c5
NC
762 return;
763 }
764
765 input_line_pointer =
be33c5dd 766 tic4x_expression_abs (++input_line_pointer, &size);
026df7c5
NC
767 if (size < 0)
768 {
20203fb9 769 as_bad (_(".bss size %ld < 0!"), (long) size);
026df7c5
NC
770 return;
771 }
772 subseg_set (bss_section, 0);
773 symbolP = symbol_find_or_make (name);
774
775 if (S_GET_SEGMENT (symbolP) == bss_section)
776 symbol_get_frag (symbolP)->fr_symbol = 0;
777
778 symbol_set_frag (symbolP, frag_now);
779
780 p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
781 size * OCTETS_PER_BYTE, (char *) 0);
782 *p = 0; /* Fill char. */
783
784 S_SET_SEGMENT (symbolP, bss_section);
785
786 /* The symbol may already have been created with a preceding
787 ".globl" directive -- be careful not to step on storage class
788 in that case. Otherwise, set it to static. */
789 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
790 S_SET_STORAGE_CLASS (symbolP, C_STAT);
791
792 subseg_set (current_seg, current_subseg); /* Restore current seg. */
793 demand_empty_rest_of_line ();
794}
795
247b1fe6 796static void
5a49b8ac 797tic4x_globl (int ignore ATTRIBUTE_UNUSED)
026df7c5
NC
798{
799 char *name;
800 int c;
801 symbolS *symbolP;
802
803 do
804 {
d02603dc 805 c = get_symbol_name (&name);
026df7c5
NC
806 symbolP = symbol_find_or_make (name);
807 *input_line_pointer = c;
d02603dc 808 SKIP_WHITESPACE_AFTER_NAME ();
026df7c5 809 S_SET_STORAGE_CLASS (symbolP, C_EXT);
e144674a 810 S_SET_EXTERNAL (symbolP);
026df7c5
NC
811 if (c == ',')
812 {
813 input_line_pointer++;
814 SKIP_WHITESPACE ();
815 if (*input_line_pointer == '\n')
816 c = '\n';
817 }
818 }
819 while (c == ',');
820
821 demand_empty_rest_of_line ();
822}
823
824/* Handle .byte, .word. .int, .long */
3739860c 825static void
5a49b8ac 826tic4x_cons (int bytes)
026df7c5 827{
ed9e98c2 828 unsigned int c;
026df7c5
NC
829 do
830 {
831 SKIP_WHITESPACE ();
832 if (*input_line_pointer == '"')
833 {
834 input_line_pointer++;
835 while (is_a_char (c = next_char_of_string ()))
be33c5dd 836 tic4x_emit_char (c, 4);
026df7c5
NC
837 know (input_line_pointer[-1] == '\"');
838 }
839 else
840 {
841 expressionS exp;
842
be33c5dd 843 input_line_pointer = tic4x_expression (input_line_pointer, &exp);
026df7c5
NC
844 if (exp.X_op == O_constant)
845 {
846 switch (bytes)
847 {
848 case 1:
849 exp.X_add_number &= 255;
850 break;
851 case 2:
852 exp.X_add_number &= 65535;
853 break;
854 }
855 }
856 /* Perhaps we should disallow .byte and .hword with
857 a non constant expression that will require relocation. */
858 emit_expr (&exp, 4);
859 }
860 }
861 while (*input_line_pointer++ == ',');
862
863 input_line_pointer--; /* Put terminator back into stream. */
864 demand_empty_rest_of_line ();
865}
866
247b1fe6 867/* Handle .ascii, .asciz, .string */
3739860c 868static void
5a49b8ac 869tic4x_stringer (int append_zero)
247b1fe6
SS
870{
871 int bytes;
ed9e98c2 872 unsigned int c;
247b1fe6
SS
873
874 bytes = 0;
875 do
876 {
877 SKIP_WHITESPACE ();
878 if (*input_line_pointer == '"')
879 {
880 input_line_pointer++;
881 while (is_a_char (c = next_char_of_string ()))
882 {
be33c5dd 883 tic4x_emit_char (c, 1);
247b1fe6
SS
884 bytes++;
885 }
886
887 if (append_zero)
888 {
be33c5dd 889 tic4x_emit_char (c, 1);
247b1fe6
SS
890 bytes++;
891 }
892
893 know (input_line_pointer[-1] == '\"');
894 }
895 else
896 {
897 expressionS exp;
898
be33c5dd 899 input_line_pointer = tic4x_expression (input_line_pointer, &exp);
247b1fe6
SS
900 if (exp.X_op != O_constant)
901 {
20203fb9 902 as_bad (_("Non-constant symbols not allowed\n"));
247b1fe6
SS
903 return;
904 }
905 exp.X_add_number &= 255; /* Limit numeber to 8-bit */
906 emit_expr (&exp, 1);
907 bytes++;
908 }
909 }
910 while (*input_line_pointer++ == ',');
911
912 /* Fill out the rest of the expression with 0's to fill up a full word */
913 if ( bytes&0x3 )
be33c5dd 914 tic4x_emit_char (0, 4-(bytes&0x3));
247b1fe6
SS
915
916 input_line_pointer--; /* Put terminator back into stream. */
917 demand_empty_rest_of_line ();
918}
919
026df7c5 920/* .eval expression, symbol */
3739860c 921static void
5a49b8ac 922tic4x_eval (int x ATTRIBUTE_UNUSED)
026df7c5
NC
923{
924 char c;
2132e3a3 925 offsetT value;
026df7c5
NC
926 char *name;
927
928 SKIP_WHITESPACE ();
929 input_line_pointer =
be33c5dd 930 tic4x_expression_abs (input_line_pointer, &value);
026df7c5
NC
931 if (*input_line_pointer++ != ',')
932 {
20203fb9 933 as_bad (_("Symbol missing\n"));
026df7c5
NC
934 return;
935 }
d02603dc 936 c = get_symbol_name (&name); /* Get terminator. */
be33c5dd 937 tic4x_insert_sym (name, value);
d02603dc 938 (void) restore_line_pointer (c);
87975d2a 939 demand_empty_rest_of_line ();
026df7c5
NC
940}
941
942/* Reset local labels. */
3739860c 943static void
5a49b8ac 944tic4x_newblock (int x ATTRIBUTE_UNUSED)
026df7c5
NC
945{
946 dollar_label_clear ();
947}
948
949/* .sect "section-name" [, value] */
950/* .sect ["]section-name[:subsection-name]["] [, value] */
3739860c 951static void
5a49b8ac 952tic4x_sect (int x ATTRIBUTE_UNUSED)
026df7c5
NC
953{
954 char c;
955 char *section_name;
026df7c5
NC
956 char *name;
957 segT seg;
2132e3a3 958 offsetT num;
026df7c5
NC
959
960 SKIP_WHITESPACE ();
961 if (*input_line_pointer == '"')
962 input_line_pointer++;
d02603dc
NC
963 c = get_symbol_name (&section_name); /* Get terminator. */
964 if (c == '"')
965 c = * ++ input_line_pointer;
026df7c5
NC
966 input_line_pointer++; /* Skip null symbol terminator. */
967 name = xmalloc (input_line_pointer - section_name + 1);
968 strcpy (name, section_name);
969
970 /* TI C from version 5.0 allows a section name to contain a
971 subsection name as well. The subsection name is separated by a
972 ':' from the section name. Currently we scan the subsection
973 name and discard it.
974 Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>. */
975 if (c == ':')
976 {
d02603dc
NC
977 char *subname;
978 c = get_symbol_name (&subname); /* Get terminator. */
979 if (c == '"')
980 c = * ++ input_line_pointer;
026df7c5 981 input_line_pointer++; /* Skip null symbol terminator. */
20203fb9 982 as_warn (_(".sect: subsection name ignored"));
026df7c5
NC
983 }
984
985 /* We might still have a '"' to discard, but the character after a
d02603dc 986 symbol name will be overwritten with a \0 by get_symbol_name()
026df7c5
NC
987 [VK]. */
988
989 if (c == ',')
990 input_line_pointer =
be33c5dd 991 tic4x_expression_abs (input_line_pointer, &num);
026df7c5
NC
992 else if (*input_line_pointer == ',')
993 {
994 input_line_pointer =
be33c5dd 995 tic4x_expression_abs (++input_line_pointer, &num);
026df7c5
NC
996 }
997 else
998 num = 0;
999
1000 seg = subseg_new (name, num);
1001 if (line_label != NULL)
1002 {
1003 S_SET_SEGMENT (line_label, seg);
1004 symbol_set_frag (line_label, frag_now);
1005 }
1006
1007 if (bfd_get_section_flags (stdoutput, seg) == SEC_NO_FLAGS)
1008 {
1009 if (!bfd_set_section_flags (stdoutput, seg, SEC_DATA))
20203fb9 1010 as_warn (_("Error setting flags for \"%s\": %s"), name,
026df7c5
NC
1011 bfd_errmsg (bfd_get_error ()));
1012 }
1013
d02603dc 1014 /* If the last character overwritten by get_symbol_name() was an
026df7c5
NC
1015 end-of-line, we must restore it or the end of the line will not be
1016 recognised and scanning extends into the next line, stopping with
1017 an error (blame Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>
1018 if this is not true). */
1019 if (is_end_of_line[(unsigned char) c])
1020 *(--input_line_pointer) = c;
1021
1022 demand_empty_rest_of_line ();
1023}
1024
1025/* symbol[:] .set value or .set symbol, value */
3739860c 1026static void
5a49b8ac 1027tic4x_set (int x ATTRIBUTE_UNUSED)
026df7c5
NC
1028{
1029 symbolS *symbolP;
1030
1031 SKIP_WHITESPACE ();
1032 if ((symbolP = line_label) == NULL)
1033 {
1034 char c;
1035 char *name;
1036
d02603dc
NC
1037 c = get_symbol_name (&name); /* Get terminator. */
1038 if (c == '"')
1039 c = * ++ input_line_pointer;
026df7c5
NC
1040 if (c != ',')
1041 {
20203fb9 1042 as_bad (_(".set syntax invalid\n"));
026df7c5
NC
1043 ignore_rest_of_line ();
1044 return;
1045 }
90e3ad06 1046 ++input_line_pointer;
026df7c5
NC
1047 symbolP = symbol_find_or_make (name);
1048 }
1049 else
1050 symbol_table_insert (symbolP);
1051
1052 pseudo_set (symbolP);
1053 demand_empty_rest_of_line ();
1054}
1055
1056/* [symbol] .usect ["]section-name["], size-in-words [, alignment-flag] */
3739860c 1057static void
5a49b8ac 1058tic4x_usect (int x ATTRIBUTE_UNUSED)
026df7c5
NC
1059{
1060 char c;
1061 char *name;
1062 char *section_name;
1063 segT seg;
2132e3a3 1064 offsetT size, alignment_flag;
026df7c5
NC
1065 segT current_seg;
1066 subsegT current_subseg;
1067
1068 current_seg = now_seg; /* save current seg. */
1069 current_subseg = now_subseg; /* save current subseg. */
1070
1071 SKIP_WHITESPACE ();
1072 if (*input_line_pointer == '"')
1073 input_line_pointer++;
d02603dc
NC
1074 c = get_symbol_name (&section_name); /* Get terminator. */
1075 if (c == '"')
1076 c = * ++ input_line_pointer;
026df7c5
NC
1077 input_line_pointer++; /* Skip null symbol terminator. */
1078 name = xmalloc (input_line_pointer - section_name + 1);
1079 strcpy (name, section_name);
1080
1081 if (c == ',')
1082 input_line_pointer =
be33c5dd 1083 tic4x_expression_abs (input_line_pointer, &size);
026df7c5
NC
1084 else if (*input_line_pointer == ',')
1085 {
1086 input_line_pointer =
be33c5dd 1087 tic4x_expression_abs (++input_line_pointer, &size);
026df7c5
NC
1088 }
1089 else
1090 size = 0;
1091
1092 /* Read a possibly present third argument (alignment flag) [VK]. */
1093 if (*input_line_pointer == ',')
1094 {
1095 input_line_pointer =
be33c5dd 1096 tic4x_expression_abs (++input_line_pointer, &alignment_flag);
026df7c5
NC
1097 }
1098 else
1099 alignment_flag = 0;
1100 if (alignment_flag)
20203fb9 1101 as_warn (_(".usect: non-zero alignment flag ignored"));
026df7c5
NC
1102
1103 seg = subseg_new (name, 0);
1104 if (line_label != NULL)
1105 {
1106 S_SET_SEGMENT (line_label, seg);
1107 symbol_set_frag (line_label, frag_now);
1108 S_SET_VALUE (line_label, frag_now_fix ());
1109 }
1110 seg_info (seg)->bss = 1; /* Uninitialised data. */
1111 if (!bfd_set_section_flags (stdoutput, seg, SEC_ALLOC))
20203fb9 1112 as_warn (_("Error setting flags for \"%s\": %s"), name,
026df7c5 1113 bfd_errmsg (bfd_get_error ()));
be33c5dd 1114 tic4x_seg_alloc (name, seg, size, line_label);
026df7c5
NC
1115
1116 if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1117 S_SET_STORAGE_CLASS (line_label, C_STAT);
1118
1119 subseg_set (current_seg, current_subseg); /* Restore current seg. */
1120 demand_empty_rest_of_line ();
1121}
1122
1123/* .version cpu-version. */
3739860c 1124static void
5a49b8ac 1125tic4x_version (int x ATTRIBUTE_UNUSED)
026df7c5 1126{
2132e3a3 1127 offsetT temp;
026df7c5
NC
1128
1129 input_line_pointer =
be33c5dd
SS
1130 tic4x_expression_abs (input_line_pointer, &temp);
1131 if (!IS_CPU_TIC3X (temp) && !IS_CPU_TIC4X (temp))
20203fb9 1132 as_bad (_("This assembler does not support processor generation %ld"),
2132e3a3 1133 (long) temp);
026df7c5 1134
2132e3a3 1135 if (tic4x_cpu && temp != (offsetT) tic4x_cpu)
20203fb9 1136 as_warn (_("Changing processor generation on fly not supported..."));
be33c5dd 1137 tic4x_cpu = temp;
026df7c5
NC
1138 demand_empty_rest_of_line ();
1139}
1140
3739860c 1141static void
5a49b8ac 1142tic4x_init_regtable (void)
026df7c5
NC
1143{
1144 unsigned int i;
1145
be33c5dd
SS
1146 for (i = 0; i < tic3x_num_registers; i++)
1147 tic4x_insert_reg (tic3x_registers[i].name,
1148 tic3x_registers[i].regno);
026df7c5 1149
be33c5dd 1150 if (IS_CPU_TIC4X (tic4x_cpu))
026df7c5 1151 {
be33c5dd
SS
1152 /* Add additional Tic4x registers, overriding some C3x ones. */
1153 for (i = 0; i < tic4x_num_registers; i++)
1154 tic4x_insert_reg (tic4x_registers[i].name,
1155 tic4x_registers[i].regno);
026df7c5
NC
1156 }
1157}
1158
3739860c 1159static void
5a49b8ac 1160tic4x_init_symbols (void)
026df7c5
NC
1161{
1162 /* The TI tools accept case insensitive versions of these symbols,
1163 we don't !
1164
1165 For TI C/Asm 5.0
1166
1167 .TMS320xx 30,31,32,40,or 44 set according to -v flag
1168 .C3X or .C3x 1 or 0 1 if -v30,-v31,or -v32
1169 .C30 1 or 0 1 if -v30
1170 .C31 1 or 0 1 if -v31
1171 .C32 1 or 0 1 if -v32
1172 .C4X or .C4x 1 or 0 1 if -v40, or -v44
1173 .C40 1 or 0 1 if -v40
1174 .C44 1 or 0 1 if -v44
1175
1176 .REGPARM 1 or 0 1 if -mr option used
1177 .BIGMODEL 1 or 0 1 if -mb option used
1178
1179 These symbols are currently supported but will be removed in a
1180 later version:
1181 .TMS320C30 1 or 0 1 if -v30,-v31,or -v32
1182 .TMS320C31 1 or 0 1 if -v31
1183 .TMS320C32 1 or 0 1 if -v32
1184 .TMS320C40 1 or 0 1 if -v40, or -v44
1185 .TMS320C44 1 or 0 1 if -v44
1186
1187 Source: TI: TMS320C3x/C4x Assembly Language Tools User's Guide,
1188 1997, SPRU035C, p. 3-17/3-18. */
be33c5dd 1189 tic4x_insert_sym (".REGPARM", tic4x_reg_args);
3739860c 1190 tic4x_insert_sym (".MEMPARM", !tic4x_reg_args);
be33c5dd
SS
1191 tic4x_insert_sym (".BIGMODEL", tic4x_big_model);
1192 tic4x_insert_sym (".C30INTERRUPT", 0);
1193 tic4x_insert_sym (".TMS320xx", tic4x_cpu == 0 ? 40 : tic4x_cpu);
1194 tic4x_insert_sym (".C3X", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1195 tic4x_insert_sym (".C3x", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1196 tic4x_insert_sym (".C4X", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
1197 tic4x_insert_sym (".C4x", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
026df7c5 1198 /* Do we need to have the following symbols also in lower case? */
be33c5dd
SS
1199 tic4x_insert_sym (".TMS320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1200 tic4x_insert_sym (".tms320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1201 tic4x_insert_sym (".TMS320C31", tic4x_cpu == 31);
1202 tic4x_insert_sym (".tms320C31", tic4x_cpu == 31);
1203 tic4x_insert_sym (".TMS320C32", tic4x_cpu == 32);
1204 tic4x_insert_sym (".tms320C32", tic4x_cpu == 32);
1205 tic4x_insert_sym (".TMS320C33", tic4x_cpu == 33);
1206 tic4x_insert_sym (".tms320C33", tic4x_cpu == 33);
1207 tic4x_insert_sym (".TMS320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
1208 tic4x_insert_sym (".tms320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
1209 tic4x_insert_sym (".TMS320C44", tic4x_cpu == 44);
1210 tic4x_insert_sym (".tms320C44", tic4x_cpu == 44);
1211 tic4x_insert_sym (".TMX320C40", 0); /* C40 first pass silicon ? */
1212 tic4x_insert_sym (".tmx320C40", 0);
026df7c5
NC
1213}
1214
1215/* Insert a new instruction template into hash table. */
3739860c 1216static int
9c95b521 1217tic4x_inst_insert (const tic4x_inst_t *inst)
026df7c5
NC
1218{
1219 static char prev_name[16];
1220 const char *retval = NULL;
1221
1222 /* Only insert the first name if have several similar entries. */
1223 if (!strcmp (inst->name, prev_name) || inst->name[0] == '\0')
1224 return 1;
1225
5a49b8ac 1226 retval = hash_insert (tic4x_op_hash, inst->name, (void *) inst);
026df7c5
NC
1227 if (retval != NULL)
1228 fprintf (stderr, "internal error: can't hash `%s': %s\n",
1229 inst->name, retval);
1230 else
1231 strcpy (prev_name, inst->name);
1232 return retval == NULL;
1233}
1234
1235/* Make a new instruction template. */
be33c5dd 1236static tic4x_inst_t *
b9bb4a93 1237tic4x_inst_make (const char *name, unsigned long opcode, const char *args)
026df7c5 1238{
be33c5dd 1239 static tic4x_inst_t *insts = NULL;
026df7c5 1240 static char *names = NULL;
91d6fa6a 1241 static int iindex = 0;
026df7c5
NC
1242
1243 if (insts == NULL)
1244 {
1245 /* Allocate memory to store name strings. */
1246 names = (char *) xmalloc (sizeof (char) * 8192);
1247 /* Allocate memory for additional insts. */
be33c5dd
SS
1248 insts = (tic4x_inst_t *)
1249 xmalloc (sizeof (tic4x_inst_t) * 1024);
026df7c5 1250 }
91d6fa6a
NC
1251 insts[iindex].name = names;
1252 insts[iindex].opcode = opcode;
1253 insts[iindex].opmask = 0xffffffff;
1254 insts[iindex].args = args;
1255 iindex++;
026df7c5
NC
1256
1257 do
1258 *names++ = *name++;
1259 while (*name);
1260 *names++ = '\0';
1261
91d6fa6a 1262 return &insts[iindex - 1];
026df7c5
NC
1263}
1264
1265/* Add instruction template, creating dynamic templates as required. */
3739860c 1266static int
9c95b521 1267tic4x_inst_add (const tic4x_inst_t *insts)
026df7c5 1268{
f86f5863 1269 const char *s = insts->name;
026df7c5
NC
1270 char *d;
1271 unsigned int i;
1272 int ok = 1;
1273 char name[16];
1274
1275 d = name;
1276
9c87d6c7 1277 /* We do not care about INSNs that is not a part of our
7ba29e2a
NC
1278 oplevel setting. */
1279 if ((insts->oplevel & tic4x_oplevel) == 0)
9c87d6c7
SS
1280 return ok;
1281
026df7c5
NC
1282 while (1)
1283 {
1284 switch (*s)
1285 {
1286 case 'B':
1287 case 'C':
1288 /* Dynamically create all the conditional insts. */
be33c5dd 1289 for (i = 0; i < tic4x_num_conds; i++)
026df7c5 1290 {
be33c5dd 1291 tic4x_inst_t *inst;
026df7c5 1292 int k = 0;
f86f5863 1293 const char *c = tic4x_conds[i].name;
026df7c5
NC
1294 char *e = d;
1295
1296 while (*c)
1297 *e++ = *c++;
1298 c = s + 1;
1299 while (*c)
1300 *e++ = *c++;
1301 *e = '\0';
1302
1303 /* If instruction found then have already processed it. */
be33c5dd 1304 if (hash_find (tic4x_op_hash, name))
026df7c5
NC
1305 return 1;
1306
1307 do
1308 {
be33c5dd
SS
1309 inst = tic4x_inst_make (name, insts[k].opcode +
1310 (tic4x_conds[i].cond <<
026df7c5
NC
1311 (*s == 'B' ? 16 : 23)),
1312 insts[k].args);
1313 if (k == 0) /* Save strcmp() with following func. */
be33c5dd 1314 ok &= tic4x_inst_insert (inst);
026df7c5
NC
1315 k++;
1316 }
1317 while (!strcmp (insts->name,
1318 insts[k].name));
1319 }
1320 return ok;
1321 break;
1322
1323 case '\0':
be33c5dd 1324 return tic4x_inst_insert (insts);
026df7c5
NC
1325 break;
1326
1327 default:
1328 *d++ = *s++;
1329 break;
1330 }
1331 }
1332}
1333
1334/* This function is called once, at assembler startup time. It should
1335 set up all the tables, etc., that the MD part of the assembler will
1336 need. */
3739860c 1337void
5a49b8ac 1338md_begin (void)
026df7c5
NC
1339{
1340 int ok = 1;
1341 unsigned int i;
1342
9c87d6c7
SS
1343 /* Setup the proper opcode level according to the
1344 commandline parameters */
be33c5dd
SS
1345 tic4x_oplevel = OP_C3X;
1346
1347 if ( IS_CPU_TIC4X(tic4x_cpu) )
1348 tic4x_oplevel |= OP_C4X;
1349
1350 if ( ( tic4x_cpu == 31 && tic4x_revision >= 6)
1351 || (tic4x_cpu == 32 && tic4x_revision >= 2)
1352 || (tic4x_cpu == 33)
1353 || tic4x_enhanced )
1354 tic4x_oplevel |= OP_ENH;
1355
1356 if ( ( tic4x_cpu == 30 && tic4x_revision >= 7)
1357 || (tic4x_cpu == 31 && tic4x_revision >= 5)
1358 || (tic4x_cpu == 32)
1359 || tic4x_lowpower )
1360 tic4x_oplevel |= OP_LPWR;
1361
1362 if ( ( tic4x_cpu == 30 && tic4x_revision >= 7)
1363 || (tic4x_cpu == 31 && tic4x_revision >= 5)
1364 || (tic4x_cpu == 32)
1365 || (tic4x_cpu == 33)
1366 || (tic4x_cpu == 40 && tic4x_revision >= 5)
1367 || (tic4x_cpu == 44)
1368 || tic4x_idle2 )
1369 tic4x_oplevel |= OP_IDLE2;
9c87d6c7 1370
026df7c5 1371 /* Create hash table for mnemonics. */
be33c5dd 1372 tic4x_op_hash = hash_new ();
026df7c5
NC
1373
1374 /* Create hash table for asg pseudo. */
be33c5dd 1375 tic4x_asg_hash = hash_new ();
026df7c5
NC
1376
1377 /* Add mnemonics to hash table, expanding conditional mnemonics on fly. */
be33c5dd 1378 for (i = 0; i < tic4x_num_insts; i++)
9c95b521 1379 ok &= tic4x_inst_add (tic4x_insts + i);
026df7c5
NC
1380
1381 /* Create dummy inst to avoid errors accessing end of table. */
be33c5dd 1382 tic4x_inst_make ("", 0, "");
026df7c5
NC
1383
1384 if (!ok)
1385 as_fatal ("Broken assembler. No assembly attempted.");
1386
1387 /* Add registers to symbol table. */
be33c5dd 1388 tic4x_init_regtable ();
026df7c5
NC
1389
1390 /* Add predefined symbols to symbol table. */
be33c5dd 1391 tic4x_init_symbols ();
026df7c5
NC
1392}
1393
3739860c 1394void
5a49b8ac 1395tic4x_end (void)
026df7c5 1396{
3739860c 1397 bfd_set_arch_mach (stdoutput, bfd_arch_tic4x,
be33c5dd 1398 IS_CPU_TIC4X (tic4x_cpu) ? bfd_mach_tic4x : bfd_mach_tic3x);
026df7c5
NC
1399}
1400
3739860c 1401static int
5a49b8ac
AM
1402tic4x_indirect_parse (tic4x_operand_t *operand,
1403 const tic4x_indirect_t *indirect)
026df7c5 1404{
f86f5863 1405 const char *n = indirect->name;
026df7c5
NC
1406 char *s = input_line_pointer;
1407 char *b;
1408 symbolS *symbolP;
1409 char name[32];
1410
1411 operand->disp = 0;
1412 for (; *n; n++)
1413 {
1414 switch (*n)
1415 {
1416 case 'a': /* Need to match aux register. */
1417 b = name;
be33c5dd 1418#ifdef TIC4X_ALT_SYNTAX
026df7c5
NC
1419 if (*s == '%')
1420 s++;
1421#endif
278ed128 1422 while (ISALNUM (*s))
026df7c5
NC
1423 *b++ = *s++;
1424 *b++ = '\0';
1425 if (!(symbolP = symbol_find (name)))
1426 return 0;
1427
1428 if (S_GET_SEGMENT (symbolP) != reg_section)
1429 return 0;
1430
1431 operand->aregno = S_GET_VALUE (symbolP);
1432 if (operand->aregno >= REG_AR0 && operand->aregno <= REG_AR7)
1433 break;
1434
20203fb9 1435 as_bad (_("Auxiliary register AR0--AR7 required for indirect"));
026df7c5
NC
1436 return -1;
1437
1438 case 'd': /* Need to match constant for disp. */
be33c5dd 1439#ifdef TIC4X_ALT_SYNTAX
026df7c5
NC
1440 if (*s == '%') /* expr() will die if we don't skip this. */
1441 s++;
1442#endif
be33c5dd 1443 s = tic4x_expression (s, &operand->expr);
026df7c5
NC
1444 if (operand->expr.X_op != O_constant)
1445 return 0;
1446 operand->disp = operand->expr.X_add_number;
1447 if (operand->disp < 0 || operand->disp > 255)
1448 {
20203fb9 1449 as_bad (_("Bad displacement %d (require 0--255)\n"),
026df7c5
NC
1450 operand->disp);
1451 return -1;
1452 }
1453 break;
1454
1455 case 'y': /* Need to match IR0. */
1456 case 'z': /* Need to match IR1. */
be33c5dd 1457#ifdef TIC4X_ALT_SYNTAX
026df7c5
NC
1458 if (*s == '%')
1459 s++;
1460#endif
be33c5dd 1461 s = tic4x_expression (s, &operand->expr);
026df7c5
NC
1462 if (operand->expr.X_op != O_register)
1463 return 0;
1464 if (operand->expr.X_add_number != REG_IR0
1465 && operand->expr.X_add_number != REG_IR1)
1466 {
20203fb9 1467 as_bad (_("Index register IR0,IR1 required for displacement"));
026df7c5
NC
1468 return -1;
1469 }
1470
1471 if (*n == 'y' && operand->expr.X_add_number == REG_IR0)
1472 break;
1473 if (*n == 'z' && operand->expr.X_add_number == REG_IR1)
1474 break;
1475 return 0;
1476
1477 case '(':
1478 if (*s != '(') /* No displacement, assume to be 1. */
1479 {
1480 operand->disp = 1;
1481 while (*n != ')')
1482 n++;
1483 }
1484 else
1485 s++;
1486 break;
1487
1488 default:
278ed128 1489 if (TOLOWER (*s) != *n)
026df7c5
NC
1490 return 0;
1491 s++;
1492 }
1493 }
1494 if (*s != ' ' && *s != ',' && *s != '\0')
1495 return 0;
1496 input_line_pointer = s;
1497 return 1;
1498}
1499
247b1fe6 1500static char *
5a49b8ac 1501tic4x_operand_parse (char *s, tic4x_operand_t *operand)
026df7c5
NC
1502{
1503 unsigned int i;
1504 char c;
1505 int ret;
1506 expressionS *exp = &operand->expr;
1507 char *save = input_line_pointer;
1508 char *str;
d3ce72d0 1509 char *new_pointer;
026df7c5
NC
1510 struct hash_entry *entry = NULL;
1511
1512 input_line_pointer = s;
1513 SKIP_WHITESPACE ();
1514
d02603dc 1515 c = get_symbol_name (&str); /* Get terminator. */
d3ce72d0 1516 new_pointer = input_line_pointer;
be33c5dd 1517 if (strlen (str) && (entry = hash_find (tic4x_asg_hash, str)) != NULL)
026df7c5 1518 {
d02603dc 1519 (void) restore_line_pointer (c);
026df7c5
NC
1520 input_line_pointer = (char *) entry;
1521 }
1522 else
1523 {
d02603dc 1524 (void) restore_line_pointer (c);
026df7c5
NC
1525 input_line_pointer = str;
1526 }
1527
1528 operand->mode = M_UNKNOWN;
1529 switch (*input_line_pointer)
1530 {
be33c5dd 1531#ifdef TIC4X_ALT_SYNTAX
026df7c5 1532 case '%':
be33c5dd 1533 input_line_pointer = tic4x_expression (++input_line_pointer, exp);
026df7c5 1534 if (exp->X_op != O_register)
20203fb9 1535 as_bad (_("Expecting a register name"));
026df7c5
NC
1536 operand->mode = M_REGISTER;
1537 break;
1538
1539 case '^':
1540 /* Denotes high 16 bits. */
be33c5dd 1541 input_line_pointer = tic4x_expression (++input_line_pointer, exp);
026df7c5
NC
1542 if (exp->X_op == O_constant)
1543 operand->mode = M_IMMED;
1544 else if (exp->X_op == O_big)
1545 {
1546 if (exp->X_add_number)
20203fb9 1547 as_bad (_("Number too large")); /* bignum required */
026df7c5
NC
1548 else
1549 {
be33c5dd 1550 tic4x_gen_to_words (generic_floating_point_number,
026df7c5
NC
1551 operand->fwords, S_PRECISION);
1552 operand->mode = M_IMMED_F;
1553 }
1554 }
1555 /* Allow ori ^foo, ar0 to be equivalent to ldi .hi.foo, ar0 */
1556 /* WARNING : The TI C40 assembler cannot do this. */
1557 else if (exp->X_op == O_symbol)
1558 {
1559 operand->mode = M_HI;
1560 break;
1561 }
1562
1563 case '#':
be33c5dd 1564 input_line_pointer = tic4x_expression (++input_line_pointer, exp);
026df7c5
NC
1565 if (exp->X_op == O_constant)
1566 operand->mode = M_IMMED;
1567 else if (exp->X_op == O_big)
1568 {
1569 if (exp->X_add_number > 0)
20203fb9 1570 as_bad (_("Number too large")); /* bignum required. */
026df7c5
NC
1571 else
1572 {
be33c5dd 1573 tic4x_gen_to_words (generic_floating_point_number,
026df7c5
NC
1574 operand->fwords, S_PRECISION);
1575 operand->mode = M_IMMED_F;
1576 }
1577 }
1578 /* Allow ori foo, ar0 to be equivalent to ldi .lo.foo, ar0 */
1579 /* WARNING : The TI C40 assembler cannot do this. */
1580 else if (exp->X_op == O_symbol)
1581 {
1582 operand->mode = M_IMMED;
1583 break;
1584 }
1585
1586 else
20203fb9 1587 as_bad (_("Expecting a constant value"));
026df7c5
NC
1588 break;
1589 case '\\':
1590#endif
1591 case '@':
be33c5dd 1592 input_line_pointer = tic4x_expression (++input_line_pointer, exp);
026df7c5 1593 if (exp->X_op != O_constant && exp->X_op != O_symbol)
20203fb9 1594 as_bad (_("Bad direct addressing construct %s"), s);
026df7c5
NC
1595 if (exp->X_op == O_constant)
1596 {
1597 if (exp->X_add_number < 0)
20203fb9 1598 as_bad (_("Direct value of %ld is not suitable"),
026df7c5
NC
1599 (long) exp->X_add_number);
1600 }
1601 operand->mode = M_DIRECT;
1602 break;
1603
1604 case '*':
1605 ret = -1;
be33c5dd
SS
1606 for (i = 0; i < tic4x_num_indirects; i++)
1607 if ((ret = tic4x_indirect_parse (operand, &tic4x_indirects[i])))
026df7c5
NC
1608 break;
1609 if (ret < 0)
1610 break;
be33c5dd 1611 if (i < tic4x_num_indirects)
026df7c5
NC
1612 {
1613 operand->mode = M_INDIRECT;
1614 /* Indirect addressing mode number. */
be33c5dd 1615 operand->expr.X_add_number = tic4x_indirects[i].modn;
026df7c5
NC
1616 /* Convert *+ARn(0) to *ARn etc. Maybe we should
1617 squeal about silly ones? */
1618 if (operand->expr.X_add_number < 0x08 && !operand->disp)
1619 operand->expr.X_add_number = 0x18;
1620 }
1621 else
20203fb9 1622 as_bad (_("Unknown indirect addressing mode"));
026df7c5
NC
1623 break;
1624
1625 default:
1626 operand->mode = M_IMMED; /* Assume immediate. */
1627 str = input_line_pointer;
be33c5dd 1628 input_line_pointer = tic4x_expression (input_line_pointer, exp);
026df7c5
NC
1629 if (exp->X_op == O_register)
1630 {
1631 know (exp->X_add_symbol == 0);
1632 know (exp->X_op_symbol == 0);
1633 operand->mode = M_REGISTER;
1634 break;
1635 }
1636 else if (exp->X_op == O_big)
1637 {
1638 if (exp->X_add_number > 0)
20203fb9 1639 as_bad (_("Number too large")); /* bignum required. */
026df7c5
NC
1640 else
1641 {
be33c5dd 1642 tic4x_gen_to_words (generic_floating_point_number,
026df7c5
NC
1643 operand->fwords, S_PRECISION);
1644 operand->mode = M_IMMED_F;
1645 }
1646 break;
1647 }
be33c5dd 1648#ifdef TIC4X_ALT_SYNTAX
026df7c5
NC
1649 /* Allow ldi foo, ar0 to be equivalent to ldi @foo, ar0. */
1650 else if (exp->X_op == O_symbol)
1651 {
1652 operand->mode = M_DIRECT;
1653 break;
1654 }
1655#endif
1656 }
1657 if (entry == NULL)
d3ce72d0 1658 new_pointer = input_line_pointer;
026df7c5 1659 input_line_pointer = save;
d3ce72d0 1660 return new_pointer;
026df7c5
NC
1661}
1662
3739860c 1663static int
91d6fa6a 1664tic4x_operands_match (tic4x_inst_t *inst, tic4x_insn_t *tinsn, int check)
026df7c5
NC
1665{
1666 const char *args = inst->args;
1667 unsigned long opcode = inst->opcode;
91d6fa6a
NC
1668 int num_operands = tinsn->num_operands;
1669 tic4x_operand_t *operand = tinsn->operands;
026df7c5
NC
1670 expressionS *exp = &operand->expr;
1671 int ret = 1;
1672 int reg;
1673
1674 /* Build the opcode, checking as we go to make sure that the
1675 operands match.
1676
1677 If an operand matches, we modify insn or opcode appropriately,
1678 and do a "continue". If an operand fails to match, we "break". */
1679
91d6fa6a
NC
1680 tinsn->nchars = 4; /* Instructions always 4 bytes. */
1681 tinsn->reloc = NO_RELOC;
1682 tinsn->pcrel = 0;
026df7c5
NC
1683
1684 if (*args == '\0')
1685 {
91d6fa6a 1686 tinsn->opcode = opcode;
026df7c5
NC
1687 return num_operands == 0;
1688 }
1689
1690 for (;; ++args)
1691 {
1692 switch (*args)
1693 {
1694
1695 case '\0': /* End of args. */
1696 if (num_operands == 1)
1697 {
91d6fa6a 1698 tinsn->opcode = opcode;
026df7c5
NC
1699 return ret;
1700 }
1701 break; /* Too many operands. */
1702
1703 case '#': /* This is only used for ldp. */
1704 if (operand->mode != M_DIRECT && operand->mode != M_IMMED)
1705 break;
1706 /* While this looks like a direct addressing mode, we actually
1707 use an immediate mode form of ldiu or ldpk instruction. */
1708 if (exp->X_op == O_constant)
1709 {
be33c5dd
SS
1710 if( ( IS_CPU_TIC4X (tic4x_cpu) && exp->X_add_number <= 65535 )
1711 || ( IS_CPU_TIC3X (tic4x_cpu) && exp->X_add_number <= 255 ) )
44287f60
SS
1712 {
1713 INSERTS (opcode, exp->X_add_number, 15, 0);
1714 continue;
1715 }
1716 else
1717 {
9c87d6c7 1718 if (!check)
20203fb9 1719 as_bad (_("Immediate value of %ld is too large for ldf"),
9c87d6c7 1720 (long) exp->X_add_number);
44287f60
SS
1721 ret = -1;
1722 continue;
1723 }
026df7c5
NC
1724 }
1725 else if (exp->X_op == O_symbol)
1726 {
91d6fa6a
NC
1727 tinsn->reloc = BFD_RELOC_HI16;
1728 tinsn->exp = *exp;
026df7c5
NC
1729 continue;
1730 }
1731 break; /* Not direct (dp) addressing. */
1732
1733 case '@': /* direct. */
1734 if (operand->mode != M_DIRECT)
1735 break;
1736 if (exp->X_op == O_constant)
da91385d
SS
1737 {
1738 /* Store only the 16 LSBs of the number. */
1739 INSERTS (opcode, exp->X_add_number, 15, 0);
1740 continue;
026df7c5
NC
1741 }
1742 else if (exp->X_op == O_symbol)
1743 {
91d6fa6a
NC
1744 tinsn->reloc = BFD_RELOC_LO16;
1745 tinsn->exp = *exp;
026df7c5
NC
1746 continue;
1747 }
1748 break; /* Not direct addressing. */
1749
1750 case 'A':
1751 if (operand->mode != M_REGISTER)
1752 break;
1753 reg = exp->X_add_number;
1754 if (reg >= REG_AR0 && reg <= REG_AR7)
1755 INSERTU (opcode, reg - REG_AR0, 24, 22);
1756 else
1757 {
9c87d6c7 1758 if (!check)
20203fb9 1759 as_bad (_("Destination register must be ARn"));
026df7c5
NC
1760 ret = -1;
1761 }
1762 continue;
1763
1764 case 'B': /* Unsigned integer immediate. */
1765 /* Allow br label or br @label. */
1766 if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
1767 break;
1768 if (exp->X_op == O_constant)
1769 {
1770 if (exp->X_add_number < (1 << 24))
1771 {
1772 INSERTU (opcode, exp->X_add_number, 23, 0);
1773 continue;
1774 }
1775 else
1776 {
9c87d6c7 1777 if (!check)
20203fb9 1778 as_bad (_("Immediate value of %ld is too large"),
9c87d6c7 1779 (long) exp->X_add_number);
026df7c5
NC
1780 ret = -1;
1781 continue;
1782 }
1783 }
be33c5dd 1784 if (IS_CPU_TIC4X (tic4x_cpu))
026df7c5 1785 {
91d6fa6a
NC
1786 tinsn->reloc = BFD_RELOC_24_PCREL;
1787 tinsn->pcrel = 1;
026df7c5
NC
1788 }
1789 else
1790 {
91d6fa6a
NC
1791 tinsn->reloc = BFD_RELOC_24;
1792 tinsn->pcrel = 0;
026df7c5 1793 }
91d6fa6a 1794 tinsn->exp = *exp;
026df7c5
NC
1795 continue;
1796
1797 case 'C':
be33c5dd 1798 if (!IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
1799 break;
1800 if (operand->mode != M_INDIRECT)
1801 break;
44287f60 1802 /* Require either *+ARn(disp) or *ARn. */
026df7c5
NC
1803 if (operand->expr.X_add_number != 0
1804 && operand->expr.X_add_number != 0x18)
1805 {
9c87d6c7 1806 if (!check)
20203fb9 1807 as_bad (_("Invalid indirect addressing mode"));
9c87d6c7 1808 ret = -1;
026df7c5
NC
1809 continue;
1810 }
1811 INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
1812 INSERTU (opcode, operand->disp, 7, 3);
1813 continue;
1814
1815 case 'E':
1816 if (!(operand->mode == M_REGISTER))
1817 break;
1818 INSERTU (opcode, exp->X_add_number, 7, 0);
1819 continue;
1820
44287f60
SS
1821 case 'e':
1822 if (!(operand->mode == M_REGISTER))
1823 break;
1824 reg = exp->X_add_number;
3739860c 1825 if ( (reg >= REG_R0 && reg <= REG_R7)
be33c5dd 1826 || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
44287f60
SS
1827 INSERTU (opcode, reg, 7, 0);
1828 else
1829 {
9c87d6c7 1830 if (!check)
20203fb9 1831 as_bad (_("Register must be Rn"));
44287f60
SS
1832 ret = -1;
1833 }
1834 continue;
1835
026df7c5
NC
1836 case 'F':
1837 if (operand->mode != M_IMMED_F
1838 && !(operand->mode == M_IMMED && exp->X_op == O_constant))
1839 break;
1840
1841 if (operand->mode != M_IMMED_F)
1842 {
1843 /* OK, we 've got something like cmpf 0, r0
1844 Why can't they stick in a bloody decimal point ?! */
1845 char string[16];
1846
1847 /* Create floating point number string. */
1848 sprintf (string, "%d.0", (int) exp->X_add_number);
be33c5dd 1849 tic4x_atof (string, 's', operand->fwords);
026df7c5
NC
1850 }
1851
1852 INSERTU (opcode, operand->fwords[0], 15, 0);
1853 continue;
1854
1855 case 'G':
1856 if (operand->mode != M_REGISTER)
1857 break;
1858 INSERTU (opcode, exp->X_add_number, 15, 8);
1859 continue;
1860
44287f60
SS
1861 case 'g':
1862 if (operand->mode != M_REGISTER)
1863 break;
1864 reg = exp->X_add_number;
3739860c 1865 if ( (reg >= REG_R0 && reg <= REG_R7)
be33c5dd 1866 || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
44287f60
SS
1867 INSERTU (opcode, reg, 15, 8);
1868 else
1869 {
9c87d6c7 1870 if (!check)
20203fb9 1871 as_bad (_("Register must be Rn"));
44287f60
SS
1872 ret = -1;
1873 }
1874 continue;
1875
026df7c5
NC
1876 case 'H':
1877 if (operand->mode != M_REGISTER)
1878 break;
1879 reg = exp->X_add_number;
1880 if (reg >= REG_R0 && reg <= REG_R7)
1881 INSERTU (opcode, reg - REG_R0, 18, 16);
1882 else
1883 {
9c87d6c7 1884 if (!check)
20203fb9 1885 as_bad (_("Register must be R0--R7"));
026df7c5
NC
1886 ret = -1;
1887 }
1888 continue;
1889
9c87d6c7
SS
1890 case 'i':
1891 if ( operand->mode == M_REGISTER
be33c5dd 1892 && tic4x_oplevel & OP_ENH )
9c87d6c7
SS
1893 {
1894 reg = exp->X_add_number;
1895 INSERTU (opcode, reg, 4, 0);
1896 INSERTU (opcode, 7, 7, 5);
1897 continue;
1898 }
1899 /* Fallthrough */
1900
026df7c5
NC
1901 case 'I':
1902 if (operand->mode != M_INDIRECT)
1903 break;
1904 if (operand->disp != 0 && operand->disp != 1)
1905 {
be33c5dd 1906 if (IS_CPU_TIC4X (tic4x_cpu))
026df7c5 1907 break;
9c87d6c7 1908 if (!check)
20203fb9 1909 as_bad (_("Invalid indirect addressing mode displacement %d"),
9c87d6c7 1910 operand->disp);
026df7c5
NC
1911 ret = -1;
1912 continue;
1913 }
1914 INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
1915 INSERTU (opcode, operand->expr.X_add_number, 7, 3);
1916 continue;
1917
9c87d6c7
SS
1918 case 'j':
1919 if ( operand->mode == M_REGISTER
be33c5dd 1920 && tic4x_oplevel & OP_ENH )
9c87d6c7
SS
1921 {
1922 reg = exp->X_add_number;
1923 INSERTU (opcode, reg, 12, 8);
1924 INSERTU (opcode, 7, 15, 13);
1925 continue;
1926 }
1927 /* Fallthrough */
1928
026df7c5
NC
1929 case 'J':
1930 if (operand->mode != M_INDIRECT)
1931 break;
1932 if (operand->disp != 0 && operand->disp != 1)
1933 {
be33c5dd 1934 if (IS_CPU_TIC4X (tic4x_cpu))
026df7c5 1935 break;
9c87d6c7 1936 if (!check)
20203fb9 1937 as_bad (_("Invalid indirect addressing mode displacement %d"),
9c87d6c7 1938 operand->disp);
026df7c5
NC
1939 ret = -1;
1940 continue;
1941 }
1942 INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
1943 INSERTU (opcode, operand->expr.X_add_number, 15, 11);
1944 continue;
1945
1946 case 'K':
1947 if (operand->mode != M_REGISTER)
1948 break;
1949 reg = exp->X_add_number;
1950 if (reg >= REG_R0 && reg <= REG_R7)
1951 INSERTU (opcode, reg - REG_R0, 21, 19);
1952 else
1953 {
9c87d6c7 1954 if (!check)
20203fb9 1955 as_bad (_("Register must be R0--R7"));
026df7c5
NC
1956 ret = -1;
1957 }
1958 continue;
1959
1960 case 'L':
1961 if (operand->mode != M_REGISTER)
1962 break;
1963 reg = exp->X_add_number;
1964 if (reg >= REG_R0 && reg <= REG_R7)
1965 INSERTU (opcode, reg - REG_R0, 24, 22);
1966 else
1967 {
9c87d6c7 1968 if (!check)
20203fb9 1969 as_bad (_("Register must be R0--R7"));
026df7c5
NC
1970 ret = -1;
1971 }
1972 continue;
1973
1974 case 'M':
1975 if (operand->mode != M_REGISTER)
1976 break;
1977 reg = exp->X_add_number;
1978 if (reg == REG_R2 || reg == REG_R3)
1979 INSERTU (opcode, reg - REG_R2, 22, 22);
1980 else
1981 {
9c87d6c7 1982 if (!check)
20203fb9 1983 as_bad (_("Destination register must be R2 or R3"));
026df7c5
NC
1984 ret = -1;
1985 }
1986 continue;
1987
1988 case 'N':
1989 if (operand->mode != M_REGISTER)
1990 break;
1991 reg = exp->X_add_number;
1992 if (reg == REG_R0 || reg == REG_R1)
1993 INSERTU (opcode, reg - REG_R0, 23, 23);
1994 else
1995 {
9c87d6c7 1996 if (!check)
20203fb9 1997 as_bad (_("Destination register must be R0 or R1"));
026df7c5
NC
1998 ret = -1;
1999 }
2000 continue;
2001
2002 case 'O':
be33c5dd 2003 if (!IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
2004 break;
2005 if (operand->mode != M_INDIRECT)
2006 break;
2007 /* Require either *+ARn(disp) or *ARn. */
2008 if (operand->expr.X_add_number != 0
2009 && operand->expr.X_add_number != 0x18)
2010 {
9c87d6c7 2011 if (!check)
20203fb9 2012 as_bad (_("Invalid indirect addressing mode"));
026df7c5
NC
2013 ret = -1;
2014 continue;
2015 }
2016 INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
2017 INSERTU (opcode, operand->disp, 15, 11);
2018 continue;
2019
2020 case 'P': /* PC relative displacement. */
2021 /* Allow br label or br @label. */
2022 if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
2023 break;
2024 if (exp->X_op == O_constant)
2025 {
2026 if (exp->X_add_number >= -32768 && exp->X_add_number <= 32767)
2027 {
2028 INSERTS (opcode, exp->X_add_number, 15, 0);
2029 continue;
2030 }
2031 else
2032 {
9c87d6c7 2033 if (!check)
20203fb9 2034 as_bad (_("Displacement value of %ld is too large"),
9c87d6c7 2035 (long) exp->X_add_number);
026df7c5
NC
2036 ret = -1;
2037 continue;
2038 }
2039 }
91d6fa6a
NC
2040 tinsn->reloc = BFD_RELOC_16_PCREL;
2041 tinsn->pcrel = 1;
2042 tinsn->exp = *exp;
026df7c5
NC
2043 continue;
2044
2045 case 'Q':
2046 if (operand->mode != M_REGISTER)
2047 break;
2048 reg = exp->X_add_number;
2049 INSERTU (opcode, reg, 15, 0);
2050 continue;
2051
44287f60
SS
2052 case 'q':
2053 if (operand->mode != M_REGISTER)
2054 break;
2055 reg = exp->X_add_number;
3739860c 2056 if ( (reg >= REG_R0 && reg <= REG_R7)
be33c5dd 2057 || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
44287f60
SS
2058 INSERTU (opcode, reg, 15, 0);
2059 else
2060 {
9c87d6c7 2061 if (!check)
20203fb9 2062 as_bad (_("Register must be Rn"));
44287f60
SS
2063 ret = -1;
2064 }
2065 continue;
2066
026df7c5
NC
2067 case 'R':
2068 if (operand->mode != M_REGISTER)
2069 break;
2070 reg = exp->X_add_number;
2071 INSERTU (opcode, reg, 20, 16);
2072 continue;
2073
44287f60
SS
2074 case 'r':
2075 if (operand->mode != M_REGISTER)
2076 break;
2077 reg = exp->X_add_number;
3739860c 2078 if ( (reg >= REG_R0 && reg <= REG_R7)
be33c5dd 2079 || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
44287f60
SS
2080 INSERTU (opcode, reg, 20, 16);
2081 else
2082 {
9c87d6c7 2083 if (!check)
20203fb9 2084 as_bad (_("Register must be Rn"));
44287f60
SS
2085 ret = -1;
2086 }
2087 continue;
2088
026df7c5
NC
2089 case 'S': /* Short immediate int. */
2090 if (operand->mode != M_IMMED && operand->mode != M_HI)
2091 break;
2092 if (exp->X_op == O_big)
2093 {
9c87d6c7 2094 if (!check)
20203fb9 2095 as_bad (_("Floating point number not valid in expression"));
026df7c5
NC
2096 ret = -1;
2097 continue;
2098 }
2099 if (exp->X_op == O_constant)
2100 {
2101 if (exp->X_add_number >= -32768 && exp->X_add_number <= 65535)
2102 {
2103 INSERTS (opcode, exp->X_add_number, 15, 0);
2104 continue;
2105 }
2106 else
2107 {
9c87d6c7 2108 if (!check)
20203fb9 2109 as_bad (_("Signed immediate value %ld too large"),
9c87d6c7 2110 (long) exp->X_add_number);
026df7c5
NC
2111 ret = -1;
2112 continue;
2113 }
2114 }
2115 else if (exp->X_op == O_symbol)
2116 {
2117 if (operand->mode == M_HI)
2118 {
91d6fa6a 2119 tinsn->reloc = BFD_RELOC_HI16;
026df7c5
NC
2120 }
2121 else
2122 {
91d6fa6a 2123 tinsn->reloc = BFD_RELOC_LO16;
026df7c5 2124 }
91d6fa6a 2125 tinsn->exp = *exp;
026df7c5
NC
2126 continue;
2127 }
2128 /* Handle cases like ldi foo - $, ar0 where foo
2129 is a forward reference. Perhaps we should check
2130 for X_op == O_symbol and disallow things like
2131 ldi foo, ar0. */
91d6fa6a
NC
2132 tinsn->reloc = BFD_RELOC_16;
2133 tinsn->exp = *exp;
026df7c5
NC
2134 continue;
2135
be33c5dd
SS
2136 case 'T': /* 5-bit immediate value for tic4x stik. */
2137 if (!IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
2138 break;
2139 if (operand->mode != M_IMMED)
2140 break;
2141 if (exp->X_op == O_constant)
2142 {
2143 if (exp->X_add_number < 16 && exp->X_add_number >= -16)
2144 {
2145 INSERTS (opcode, exp->X_add_number, 20, 16);
2146 continue;
2147 }
2148 else
2149 {
9c87d6c7 2150 if (!check)
20203fb9 2151 as_bad (_("Immediate value of %ld is too large"),
9c87d6c7 2152 (long) exp->X_add_number);
026df7c5
NC
2153 ret = -1;
2154 continue;
2155 }
2156 }
2157 break; /* No relocations allowed. */
2158
2159 case 'U': /* Unsigned integer immediate. */
2160 if (operand->mode != M_IMMED && operand->mode != M_HI)
2161 break;
2162 if (exp->X_op == O_constant)
2163 {
2164 if (exp->X_add_number < (1 << 16) && exp->X_add_number >= 0)
2165 {
2166 INSERTU (opcode, exp->X_add_number, 15, 0);
2167 continue;
2168 }
2169 else
2170 {
9c87d6c7 2171 if (!check)
20203fb9 2172 as_bad (_("Unsigned immediate value %ld too large"),
9c87d6c7 2173 (long) exp->X_add_number);
026df7c5
NC
2174 ret = -1;
2175 continue;
2176 }
2177 }
2178 else if (exp->X_op == O_symbol)
2179 {
2180 if (operand->mode == M_HI)
91d6fa6a 2181 tinsn->reloc = BFD_RELOC_HI16;
026df7c5 2182 else
91d6fa6a 2183 tinsn->reloc = BFD_RELOC_LO16;
026df7c5 2184
91d6fa6a 2185 tinsn->exp = *exp;
026df7c5
NC
2186 continue;
2187 }
91d6fa6a
NC
2188 tinsn->reloc = BFD_RELOC_16;
2189 tinsn->exp = *exp;
026df7c5
NC
2190 continue;
2191
2192 case 'V': /* Trap numbers (immediate field). */
2193 if (operand->mode != M_IMMED)
2194 break;
2195 if (exp->X_op == O_constant)
2196 {
be33c5dd 2197 if (exp->X_add_number < 512 && IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
2198 {
2199 INSERTU (opcode, exp->X_add_number, 8, 0);
2200 continue;
2201 }
be33c5dd 2202 else if (exp->X_add_number < 32 && IS_CPU_TIC3X (tic4x_cpu))
026df7c5
NC
2203 {
2204 INSERTU (opcode, exp->X_add_number | 0x20, 4, 0);
2205 continue;
2206 }
2207 else
2208 {
9c87d6c7 2209 if (!check)
20203fb9 2210 as_bad (_("Immediate value of %ld is too large"),
9c87d6c7 2211 (long) exp->X_add_number);
026df7c5
NC
2212 ret = -1;
2213 continue;
2214 }
2215 }
2216 break; /* No relocations allowed. */
2217
2218 case 'W': /* Short immediate int (0--7). */
be33c5dd 2219 if (!IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
2220 break;
2221 if (operand->mode != M_IMMED)
2222 break;
2223 if (exp->X_op == O_big)
2224 {
9c87d6c7 2225 if (!check)
20203fb9 2226 as_bad (_("Floating point number not valid in expression"));
026df7c5
NC
2227 ret = -1;
2228 continue;
2229 }
2230 if (exp->X_op == O_constant)
2231 {
2232 if (exp->X_add_number >= -256 && exp->X_add_number <= 127)
2233 {
2234 INSERTS (opcode, exp->X_add_number, 7, 0);
2235 continue;
2236 }
2237 else
2238 {
9c87d6c7 2239 if (!check)
20203fb9 2240 as_bad (_("Immediate value %ld too large"),
9c87d6c7 2241 (long) exp->X_add_number);
026df7c5
NC
2242 ret = -1;
2243 continue;
2244 }
2245 }
91d6fa6a
NC
2246 tinsn->reloc = BFD_RELOC_16;
2247 tinsn->exp = *exp;
026df7c5
NC
2248 continue;
2249
be33c5dd 2250 case 'X': /* Expansion register for tic4x. */
026df7c5
NC
2251 if (operand->mode != M_REGISTER)
2252 break;
2253 reg = exp->X_add_number;
2254 if (reg >= REG_IVTP && reg <= REG_TVTP)
2255 INSERTU (opcode, reg - REG_IVTP, 4, 0);
2256 else
2257 {
9c87d6c7 2258 if (!check)
20203fb9 2259 as_bad (_("Register must be ivtp or tvtp"));
026df7c5
NC
2260 ret = -1;
2261 }
2262 continue;
2263
be33c5dd 2264 case 'Y': /* Address register for tic4x lda. */
026df7c5
NC
2265 if (operand->mode != M_REGISTER)
2266 break;
2267 reg = exp->X_add_number;
2268 if (reg >= REG_AR0 && reg <= REG_SP)
2269 INSERTU (opcode, reg, 20, 16);
2270 else
2271 {
9c87d6c7 2272 if (!check)
20203fb9 2273 as_bad (_("Register must be address register"));
026df7c5
NC
2274 ret = -1;
2275 }
2276 continue;
2277
be33c5dd 2278 case 'Z': /* Expansion register for tic4x. */
026df7c5
NC
2279 if (operand->mode != M_REGISTER)
2280 break;
2281 reg = exp->X_add_number;
2282 if (reg >= REG_IVTP && reg <= REG_TVTP)
2283 INSERTU (opcode, reg - REG_IVTP, 20, 16);
2284 else
2285 {
9c87d6c7 2286 if (!check)
20203fb9 2287 as_bad (_("Register must be ivtp or tvtp"));
026df7c5
NC
2288 ret = -1;
2289 }
2290 continue;
2291
2292 case '*':
2293 if (operand->mode != M_INDIRECT)
2294 break;
2295 INSERTS (opcode, operand->disp, 7, 0);
2296 INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
2297 INSERTU (opcode, operand->expr.X_add_number, 15, 11);
2298 continue;
2299
2300 case '|': /* treat as `,' if have ldi_ldi form. */
91d6fa6a 2301 if (tinsn->parallel)
026df7c5
NC
2302 {
2303 if (--num_operands < 0)
2304 break; /* Too few operands. */
2305 operand++;
2306 if (operand->mode != M_PARALLEL)
2307 break;
2308 }
2309 /* Fall through. */
2310
2311 case ',': /* Another operand. */
2312 if (--num_operands < 0)
2313 break; /* Too few operands. */
2314 operand++;
2315 exp = &operand->expr;
2316 continue;
2317
2318 case ';': /* Another optional operand. */
2319 if (num_operands == 1 || operand[1].mode == M_PARALLEL)
2320 continue;
2321 if (--num_operands < 0)
2322 break; /* Too few operands. */
2323 operand++;
2324 exp = &operand->expr;
2325 continue;
2326
2327 default:
2328 BAD_CASE (*args);
2329 }
2330 return 0;
2331 }
2332}
2333
9c87d6c7 2334static void
91d6fa6a 2335tic4x_insn_check (tic4x_insn_t *tinsn)
9c87d6c7 2336{
3739860c 2337
91d6fa6a 2338 if (!strcmp (tinsn->name, "lda"))
9c87d6c7 2339 {
91d6fa6a 2340 if (tinsn->num_operands < 2 || tinsn->num_operands > 2)
9c87d6c7
SS
2341 as_fatal ("Illegal internal LDA insn definition");
2342
91d6fa6a
NC
2343 if (tinsn->operands[0].mode == M_REGISTER
2344 && tinsn->operands[1].mode == M_REGISTER
2345 && tinsn->operands[0].expr.X_add_number == tinsn->operands[1].expr.X_add_number )
20203fb9 2346 as_bad (_("Source and destination register should not be equal"));
9c87d6c7 2347 }
91d6fa6a
NC
2348 else if (!strcmp (tinsn->name, "ldi_ldi")
2349 || !strcmp (tinsn->name, "ldi1_ldi2")
2350 || !strcmp (tinsn->name, "ldi2_ldi1")
2351 || !strcmp (tinsn->name, "ldf_ldf")
2352 || !strcmp (tinsn->name, "ldf1_ldf2")
2353 || !strcmp (tinsn->name, "ldf2_ldf1") )
9c87d6c7 2354 {
88fd0449 2355 if (tinsn->num_operands < 4 || tinsn->num_operands > 5)
91d6fa6a 2356 as_fatal ("Illegal internal %s insn definition", tinsn->name);
3739860c 2357
91d6fa6a
NC
2358 if (tinsn->operands[1].mode == M_REGISTER
2359 && tinsn->operands[tinsn->num_operands-1].mode == M_REGISTER
2360 && tinsn->operands[1].expr.X_add_number == tinsn->operands[tinsn->num_operands-1].expr.X_add_number )
20203fb9 2361 as_warn (_("Equal parallell destination registers, one result will be discarded"));
9c87d6c7
SS
2362 }
2363}
2364
3739860c 2365static void
91d6fa6a 2366tic4x_insn_output (tic4x_insn_t *tinsn)
026df7c5
NC
2367{
2368 char *dst;
2369
2370 /* Grab another fragment for opcode. */
91d6fa6a 2371 dst = frag_more (tinsn->nchars);
026df7c5
NC
2372
2373 /* Put out opcode word as a series of bytes in little endian order. */
91d6fa6a 2374 md_number_to_chars (dst, tinsn->opcode, tinsn->nchars);
026df7c5
NC
2375
2376 /* Put out the symbol-dependent stuff. */
91d6fa6a 2377 if (tinsn->reloc != NO_RELOC)
026df7c5
NC
2378 {
2379 /* Where is the offset into the fragment for this instruction. */
2380 fix_new_exp (frag_now,
2381 dst - frag_now->fr_literal, /* where */
91d6fa6a
NC
2382 tinsn->nchars, /* size */
2383 &tinsn->exp,
2384 tinsn->pcrel,
2385 tinsn->reloc);
026df7c5
NC
2386 }
2387}
2388
2389/* Parse the operands. */
3739860c 2390static int
5a49b8ac 2391tic4x_operands_parse (char *s, tic4x_operand_t *operands, int num_operands)
026df7c5
NC
2392{
2393 if (!*s)
2394 return num_operands;
2395
2396 do
be33c5dd
SS
2397 s = tic4x_operand_parse (s, &operands[num_operands++]);
2398 while (num_operands < TIC4X_OPERANDS_MAX && *s++ == ',');
026df7c5 2399
be33c5dd 2400 if (num_operands > TIC4X_OPERANDS_MAX)
026df7c5 2401 {
20203fb9 2402 as_bad (_("Too many operands scanned"));
026df7c5
NC
2403 return -1;
2404 }
2405 return num_operands;
2406}
2407
2408/* Assemble a single instruction. Its label has already been handled
2409 by the generic front end. We just parse mnemonic and operands, and
2410 produce the bytes of data and relocation. */
3739860c 2411void
5a49b8ac 2412md_assemble (char *str)
026df7c5
NC
2413{
2414 int ok = 0;
2415 char *s;
2416 int i;
2417 int parsed = 0;
77ab336e 2418 size_t len;
be33c5dd
SS
2419 tic4x_inst_t *inst; /* Instruction template. */
2420 tic4x_inst_t *first_inst;
026df7c5 2421
a1f3c24c
SS
2422 /* Scan for parallel operators */
2423 if (str)
2424 {
2425 s = str;
2426 while (*s && *s != '|')
2427 s++;
3739860c 2428
a1f3c24c
SS
2429 if (*s && s[1]=='|')
2430 {
2431 if(insn->parallel)
2432 {
20203fb9 2433 as_bad (_("Parallel opcode cannot contain more than two instructions"));
a1f3c24c
SS
2434 insn->parallel = 0;
2435 insn->in_use = 0;
2436 return;
2437 }
3739860c 2438
a1f3c24c
SS
2439 /* Lets take care of the first part of the parallel insn */
2440 *s++ = 0;
2441 md_assemble(str);
2442 insn->parallel = 1;
2443 str = ++s;
2444 /* .. and let the second run though here */
2445 }
2446 }
3739860c 2447
026df7c5
NC
2448 if (str && insn->parallel)
2449 {
026df7c5
NC
2450 /* Find mnemonic (second part of parallel instruction). */
2451 s = str;
2452 /* Skip past instruction mnemonic. */
a1f3c24c 2453 while (*s && *s != ' ')
026df7c5 2454 s++;
026df7c5
NC
2455 if (*s) /* Null terminate for hash_find. */
2456 *s++ = '\0'; /* and skip past null. */
77ab336e
CG
2457 len = strlen (insn->name);
2458 snprintf (insn->name + len, TIC4X_NAME_MAX - len, "_%s", str);
026df7c5 2459
026df7c5
NC
2460 insn->operands[insn->num_operands++].mode = M_PARALLEL;
2461
be33c5dd 2462 if ((i = tic4x_operands_parse
026df7c5
NC
2463 (s, insn->operands, insn->num_operands)) < 0)
2464 {
2465 insn->parallel = 0;
2466 insn->in_use = 0;
2467 return;
2468 }
2469 insn->num_operands = i;
2470 parsed = 1;
2471 }
2472
2473 if (insn->in_use)
2474 {
be33c5dd
SS
2475 if ((insn->inst = (struct tic4x_inst *)
2476 hash_find (tic4x_op_hash, insn->name)) == NULL)
026df7c5 2477 {
20203fb9 2478 as_bad (_("Unknown opcode `%s'."), insn->name);
026df7c5
NC
2479 insn->parallel = 0;
2480 insn->in_use = 0;
2481 return;
2482 }
2483
026df7c5 2484 inst = insn->inst;
9c87d6c7 2485 first_inst = NULL;
026df7c5 2486 do
9c87d6c7 2487 {
be33c5dd 2488 ok = tic4x_operands_match (inst, insn, 1);
9c87d6c7
SS
2489 if (ok < 0)
2490 {
2491 if (!first_inst)
2492 first_inst = inst;
2493 ok = 0;
2494 }
2495 } while (!ok && !strcmp (inst->name, inst[1].name) && inst++);
026df7c5
NC
2496
2497 if (ok > 0)
9c87d6c7 2498 {
be33c5dd
SS
2499 tic4x_insn_check (insn);
2500 tic4x_insn_output (insn);
9c87d6c7 2501 }
026df7c5 2502 else if (!ok)
9c87d6c7
SS
2503 {
2504 if (first_inst)
be33c5dd 2505 tic4x_operands_match (first_inst, insn, 0);
20203fb9 2506 as_bad (_("Invalid operands for %s"), insn->name);
9c87d6c7 2507 }
026df7c5 2508 else
20203fb9 2509 as_bad (_("Invalid instruction %s"), insn->name);
026df7c5
NC
2510 }
2511
2512 if (str && !parsed)
2513 {
2514 /* Find mnemonic. */
2515 s = str;
2516 while (*s && *s != ' ') /* Skip past instruction mnemonic. */
2517 s++;
2518 if (*s) /* Null terminate for hash_find. */
2519 *s++ = '\0'; /* and skip past null. */
77ab336e
CG
2520 strncpy (insn->name, str, TIC4X_NAME_MAX - 1);
2521 insn->name[TIC4X_NAME_MAX - 1] = '\0';
026df7c5 2522
be33c5dd 2523 if ((i = tic4x_operands_parse (s, insn->operands, 0)) < 0)
026df7c5 2524 {
708587a4 2525 insn->inst = NULL; /* Flag that error occurred. */
026df7c5
NC
2526 insn->parallel = 0;
2527 insn->in_use = 0;
2528 return;
2529 }
2530 insn->num_operands = i;
2531 insn->in_use = 1;
2532 }
2533 else
2534 insn->in_use = 0;
2535 insn->parallel = 0;
2536}
2537
2538void
5a49b8ac 2539tic4x_cleanup (void)
026df7c5
NC
2540{
2541 if (insn->in_use)
2542 md_assemble (NULL);
2543}
2544
2545/* Turn a string in input_line_pointer into a floating point constant
2546 of type type, and store the appropriate bytes in *litP. The number
499ac353 2547 of chars emitted is stored in *sizeP. An error message is
026df7c5
NC
2548 returned, or NULL on OK. */
2549
6d4af3c2 2550const char *
499ac353 2551md_atof (int type, char *litP, int *sizeP)
026df7c5
NC
2552{
2553 int prec;
2554 int ieee;
2555 LITTLENUM_TYPE words[MAX_LITTLENUMS];
2556 LITTLENUM_TYPE *wordP;
2132e3a3 2557 char *t;
026df7c5
NC
2558
2559 switch (type)
2560 {
499ac353 2561 case 's': /* .single */
026df7c5
NC
2562 case 'S':
2563 ieee = 0;
2564 prec = 1;
2565 break;
2566
499ac353 2567 case 'd': /* .double */
026df7c5 2568 case 'D':
499ac353 2569 case 'f': /* .float */
026df7c5
NC
2570 case 'F':
2571 ieee = 0;
499ac353 2572 prec = 2; /* 1 32-bit word */
026df7c5
NC
2573 break;
2574
499ac353 2575 case 'i': /* .ieee */
247b1fe6 2576 case 'I':
026df7c5
NC
2577 prec = 2;
2578 ieee = 1;
499ac353 2579 type = 'f'; /* Rewrite type to be usable by atof_ieee(). */
026df7c5
NC
2580 break;
2581
499ac353 2582 case 'e': /* .ldouble */
247b1fe6 2583 case 'E':
499ac353 2584 prec = 4; /* 2 32-bit words */
247b1fe6 2585 ieee = 0;
026df7c5
NC
2586 break;
2587
2588 default:
2589 *sizeP = 0;
499ac353 2590 return _("Unrecognized or unsupported floating point constant");
026df7c5
NC
2591 }
2592
2593 if (ieee)
2594 t = atof_ieee (input_line_pointer, type, words);
2595 else
be33c5dd 2596 t = tic4x_atof (input_line_pointer, type, words);
026df7c5
NC
2597 if (t)
2598 input_line_pointer = t;
2599 *sizeP = prec * sizeof (LITTLENUM_TYPE);
2132e3a3 2600
026df7c5
NC
2601 /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
2602 little endian byte order. */
247b1fe6
SS
2603 /* SES: However it is required to put the words (32-bits) out in the
2604 correct order, hence we write 2 and 2 littlenums in little endian
499ac353
NC
2605 order, while we keep the original order on successive words. */
2606 for (wordP = words; wordP<(words+prec) ; wordP+=2)
026df7c5 2607 {
499ac353 2608 if (wordP < (words + prec - 1)) /* Dump wordP[1] (if we have one). */
247b1fe6
SS
2609 {
2610 md_number_to_chars (litP, (valueT) (wordP[1]),
2611 sizeof (LITTLENUM_TYPE));
2612 litP += sizeof (LITTLENUM_TYPE);
2613 }
2614
2615 /* Dump wordP[0] */
2616 md_number_to_chars (litP, (valueT) (wordP[0]),
2617 sizeof (LITTLENUM_TYPE));
026df7c5
NC
2618 litP += sizeof (LITTLENUM_TYPE);
2619 }
499ac353 2620 return NULL;
026df7c5
NC
2621}
2622
3739860c 2623void
5a49b8ac 2624md_apply_fix (fixS *fixP, valueT *value, segT seg ATTRIBUTE_UNUSED)
026df7c5
NC
2625{
2626 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
2627 valueT val = *value;
2628
2629 switch (fixP->fx_r_type)
2630 {
2631 case BFD_RELOC_HI16:
2632 val >>= 16;
2633 break;
2634
2635 case BFD_RELOC_LO16:
2636 val &= 0xffff;
2637 break;
2638 default:
2639 break;
2640 }
2641
2642 switch (fixP->fx_r_type)
2643 {
2644 case BFD_RELOC_32:
2645 buf[3] = val >> 24;
2646 case BFD_RELOC_24:
2647 case BFD_RELOC_24_PCREL:
2648 buf[2] = val >> 16;
2649 case BFD_RELOC_16:
2650 case BFD_RELOC_16_PCREL:
2651 case BFD_RELOC_LO16:
2652 case BFD_RELOC_HI16:
2653 buf[1] = val >> 8;
2654 buf[0] = val;
2655 break;
2656
2657 case NO_RELOC:
2658 default:
20203fb9 2659 as_bad (_("Bad relocation type: 0x%02x"), fixP->fx_r_type);
026df7c5
NC
2660 break;
2661 }
2662
2663 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1;
2664}
2665
be33c5dd 2666/* Should never be called for tic4x. */
3739860c 2667void
5a49b8ac
AM
2668md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
2669 segT sec ATTRIBUTE_UNUSED,
2670 fragS *fragP ATTRIBUTE_UNUSED)
026df7c5
NC
2671{
2672 as_fatal ("md_convert_frag");
2673}
2674
be33c5dd 2675/* Should never be called for tic4x. */
026df7c5 2676void
5a49b8ac
AM
2677md_create_short_jump (char *ptr ATTRIBUTE_UNUSED,
2678 addressT from_addr ATTRIBUTE_UNUSED,
2679 addressT to_addr ATTRIBUTE_UNUSED,
2680 fragS *frag ATTRIBUTE_UNUSED,
2681 symbolS *to_symbol ATTRIBUTE_UNUSED)
026df7c5
NC
2682{
2683 as_fatal ("md_create_short_jmp\n");
2684}
2685
be33c5dd 2686/* Should never be called for tic4x. */
026df7c5 2687void
5a49b8ac
AM
2688md_create_long_jump (char *ptr ATTRIBUTE_UNUSED,
2689 addressT from_addr ATTRIBUTE_UNUSED,
2690 addressT to_addr ATTRIBUTE_UNUSED,
2691 fragS *frag ATTRIBUTE_UNUSED,
2692 symbolS *to_symbol ATTRIBUTE_UNUSED)
026df7c5
NC
2693{
2694 as_fatal ("md_create_long_jump\n");
2695}
2696
be33c5dd 2697/* Should never be called for tic4x. */
026df7c5 2698int
5a49b8ac
AM
2699md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
2700 segT segtype ATTRIBUTE_UNUSED)
026df7c5
NC
2701{
2702 as_fatal ("md_estimate_size_before_relax\n");
2703 return 0;
2704}
2705
026df7c5
NC
2706
2707int
17b9d67d 2708md_parse_option (int c, const char *arg)
026df7c5
NC
2709{
2710 switch (c)
2711 {
9c87d6c7 2712 case OPTION_CPU: /* cpu brand */
278ed128 2713 if (TOLOWER (*arg) == 'c')
026df7c5 2714 arg++;
be33c5dd
SS
2715 tic4x_cpu = atoi (arg);
2716 if (!IS_CPU_TIC3X (tic4x_cpu) && !IS_CPU_TIC4X (tic4x_cpu))
20203fb9 2717 as_warn (_("Unsupported processor generation %d"), tic4x_cpu);
026df7c5 2718 break;
9c87d6c7
SS
2719
2720 case OPTION_REV: /* cpu revision */
be33c5dd 2721 tic4x_revision = atoi (arg);
9c87d6c7
SS
2722 break;
2723
2724 case 'b':
20203fb9 2725 as_warn (_("Option -b is depreciated, please use -mbig"));
9c87d6c7 2726 case OPTION_BIG: /* big model */
be33c5dd 2727 tic4x_big_model = 1;
9c87d6c7
SS
2728 break;
2729
2730 case 'p':
20203fb9 2731 as_warn (_("Option -p is depreciated, please use -mmemparm"));
9c87d6c7 2732 case OPTION_MEMPARM: /* push args */
be33c5dd 2733 tic4x_reg_args = 0;
026df7c5 2734 break;
9c87d6c7 2735
3739860c 2736 case 'r':
20203fb9 2737 as_warn (_("Option -r is depreciated, please use -mregparm"));
9c87d6c7 2738 case OPTION_REGPARM: /* register args */
be33c5dd 2739 tic4x_reg_args = 1;
026df7c5 2740 break;
9c87d6c7
SS
2741
2742 case 's':
20203fb9 2743 as_warn (_("Option -s is depreciated, please use -msmall"));
9c87d6c7 2744 case OPTION_SMALL: /* small model */
be33c5dd 2745 tic4x_big_model = 0;
026df7c5 2746 break;
9c87d6c7
SS
2747
2748 case OPTION_IDLE2:
be33c5dd 2749 tic4x_idle2 = 1;
9c87d6c7
SS
2750 break;
2751
2752 case OPTION_LOWPOWER:
be33c5dd 2753 tic4x_lowpower = 1;
9c87d6c7
SS
2754 break;
2755
2756 case OPTION_ENHANCED:
be33c5dd 2757 tic4x_enhanced = 1;
9c87d6c7
SS
2758 break;
2759
026df7c5
NC
2760 default:
2761 return 0;
2762 }
2763
2764 return 1;
2765}
2766
2767void
5a49b8ac 2768md_show_usage (FILE *stream)
026df7c5 2769{
9c87d6c7
SS
2770 fprintf (stream,
2771 _("\nTIC4X options:\n"
2772 " -mcpu=CPU -mCPU select architecture variant. CPU can be:\n"
2773 " 30 - TMS320C30\n"
2774 " 31 - TMS320C31, TMS320LC31\n"
2775 " 32 - TMS320C32\n"
2776 " 33 - TMS320VC33\n"
2777 " 40 - TMS320C40\n"
2778 " 44 - TMS320C44\n"
2779 " -mrev=REV set cpu hardware revision (integer numbers).\n"
2780 " Combinations of -mcpu and -mrev will enable/disable\n"
2781 " the appropriate options (-midle2, -mlowpower and\n"
2782 " -menhanced) according to the selected type\n"
2783 " -mbig select big memory model\n"
2784 " -msmall select small memory model (default)\n"
2785 " -mregparm select register parameters (default)\n"
2786 " -mmemparm select memory parameters\n"
2787 " -midle2 enable IDLE2 support\n"
2788 " -mlowpower enable LOPOWER and MAXSPEED support\n"
2789 " -menhanced enable enhanced opcode support\n"));
026df7c5
NC
2790}
2791
2792/* This is called when a line is unrecognized. This is used to handle
2793 definitions of TI C3x tools style local labels $n where n is a single
2794 decimal digit. */
3739860c 2795int
5a49b8ac 2796tic4x_unrecognized_line (int c)
026df7c5
NC
2797{
2798 int lab;
2799 char *s;
2800
278ed128 2801 if (c != '$' || ! ISDIGIT (input_line_pointer[0]))
026df7c5
NC
2802 return 0;
2803
2804 s = input_line_pointer;
2805
2806 /* Let's allow multiple digit local labels. */
2807 lab = 0;
278ed128 2808 while (ISDIGIT (*s))
026df7c5
NC
2809 {
2810 lab = lab * 10 + *s - '0';
2811 s++;
2812 }
2813
2814 if (dollar_label_defined (lab))
2815 {
20203fb9 2816 as_bad (_("Label \"$%d\" redefined"), lab);
026df7c5
NC
2817 return 0;
2818 }
2819
2820 define_dollar_label (lab);
2821 colon (dollar_label_name (lab, 0));
2822 input_line_pointer = s + 1;
2823
2824 return 1;
2825}
2826
2827/* Handle local labels peculiar to us referred to in an expression. */
2828symbolS *
5a49b8ac 2829md_undefined_symbol (char *name)
026df7c5
NC
2830{
2831 /* Look for local labels of the form $n. */
278ed128 2832 if (name[0] == '$' && ISDIGIT (name[1]))
026df7c5
NC
2833 {
2834 symbolS *symbolP;
2835 char *s = name + 1;
2836 int lab = 0;
2837
278ed128 2838 while (ISDIGIT ((unsigned char) *s))
026df7c5
NC
2839 {
2840 lab = lab * 10 + *s - '0';
2841 s++;
2842 }
2843 if (dollar_label_defined (lab))
2844 {
2845 name = dollar_label_name (lab, 0);
2846 symbolP = symbol_find (name);
2847 }
2848 else
2849 {
2850 name = dollar_label_name (lab, 1);
2851 symbolP = symbol_find_or_make (name);
2852 }
2853
2854 return symbolP;
2855 }
2856 return NULL;
2857}
2858
2859/* Parse an operand that is machine-specific. */
2860void
5a49b8ac 2861md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
026df7c5
NC
2862{
2863}
2864
2865/* Round up a section size to the appropriate boundary---do we need this? */
2866valueT
5a49b8ac 2867md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
026df7c5
NC
2868{
2869 return size; /* Byte (i.e., 32-bit) alignment is fine? */
2870}
2871
3739860c 2872static int
5a49b8ac 2873tic4x_pc_offset (unsigned int op)
026df7c5
NC
2874{
2875 /* Determine the PC offset for a C[34]x instruction.
2876 This could be simplified using some boolean algebra
2877 but at the expense of readability. */
2878 switch (op >> 24)
2879 {
2880 case 0x60: /* br */
2881 case 0x62: /* call (C4x) */
2882 case 0x64: /* rptb (C4x) */
2883 return 1;
2884 case 0x61: /* brd */
2885 case 0x63: /* laj */
2886 case 0x65: /* rptbd (C4x) */
2887 return 3;
2888 case 0x66: /* swi */
2889 case 0x67:
2890 return 0;
2891 default:
2892 break;
2893 }
2894
2895 switch ((op & 0xffe00000) >> 20)
2896 {
2897 case 0x6a0: /* bB */
2898 case 0x720: /* callB */
2899 case 0x740: /* trapB */
2900 return 1;
2901
2902 case 0x6a2: /* bBd */
2903 case 0x6a6: /* bBat */
2904 case 0x6aa: /* bBaf */
2905 case 0x722: /* lajB */
2906 case 0x748: /* latB */
2907 case 0x798: /* rptbd */
2908 return 3;
2909
2910 default:
2911 break;
2912 }
2913
2914 switch ((op & 0xfe200000) >> 20)
2915 {
2916 case 0x6e0: /* dbB */
2917 return 1;
2918
2919 case 0x6e2: /* dbBd */
2920 return 3;
2921
2922 default:
2923 break;
2924 }
2925
2926 return 0;
2927}
2928
2929/* Exactly what point is a PC-relative offset relative TO?
2930 With the C3x we have the following:
2931 DBcond, Bcond disp + PC + 1 => PC
2932 DBcondD, BcondD disp + PC + 3 => PC
2933 */
2934long
5a49b8ac 2935md_pcrel_from (fixS *fixP)
026df7c5 2936{
2132e3a3 2937 unsigned char *buf;
026df7c5
NC
2938 unsigned int op;
2939
2132e3a3 2940 buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
026df7c5
NC
2941 op = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
2942
2943 return ((fixP->fx_where + fixP->fx_frag->fr_address) >> 2) +
be33c5dd 2944 tic4x_pc_offset (op);
026df7c5
NC
2945}
2946
247b1fe6
SS
2947/* Fill the alignment area with NOP's on .text, unless fill-data
2948 was specified. */
3739860c 2949int
b9fcee79
AM
2950tic4x_do_align (int alignment,
2951 const char *fill,
2952 int len,
2953 int max)
026df7c5 2954{
33b7f697 2955 /* Because we are talking lwords, not bytes, adjust alignment to do words */
247b1fe6 2956 alignment += 2;
3739860c 2957
247b1fe6
SS
2958 if (alignment != 0 && !need_pass_2)
2959 {
2960 if (fill == NULL)
2961 {
18498503 2962 if (subseg_text_p (now_seg))
b9fcee79
AM
2963 {
2964 char nop[4];
2965
2966 md_number_to_chars (nop, TIC_NOP_OPCODE, 4);
2967 frag_align_pattern (alignment, nop, sizeof (nop), max);
2968 }
2969 else
2970 frag_align (alignment, 0, max);
247b1fe6
SS
2971 }
2972 else if (len <= 1)
2973 frag_align (alignment, *fill, max);
2974 else
2975 frag_align_pattern (alignment, fill, len, max);
2976 }
3739860c 2977
33b7f697 2978 /* Return 1 to skip the default alignment function */
026df7c5
NC
2979 return 1;
2980}
2981
2982/* Look for and remove parallel instruction operator ||. */
3739860c 2983void
5a49b8ac 2984tic4x_start_line (void)
026df7c5
NC
2985{
2986 char *s = input_line_pointer;
2987
2988 SKIP_WHITESPACE ();
2989
2990 /* If parallel instruction prefix found at start of line, skip it. */
2991 if (*input_line_pointer == '|' && input_line_pointer[1] == '|')
2992 {
2993 if (insn->in_use)
2994 {
2995 insn->parallel = 1;
a1f3c24c
SS
2996 input_line_pointer ++;
2997 *input_line_pointer = ' ';
026df7c5
NC
2998 /* So line counters get bumped. */
2999 input_line_pointer[-1] = '\n';
3000 }
3001 }
3002 else
3003 {
a1f3c24c 3004 /* Write out the previous insn here */
026df7c5
NC
3005 if (insn->in_use)
3006 md_assemble (NULL);
3007 input_line_pointer = s;
3008 }
3009}
3010
3011arelent *
5a49b8ac 3012tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixP)
026df7c5
NC
3013{
3014 arelent *reloc;
3015
3016 reloc = (arelent *) xmalloc (sizeof (arelent));
3017
3018 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
3019 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
3020 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
3021 reloc->address /= OCTETS_PER_BYTE;
3022 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
3023 if (reloc->howto == (reloc_howto_type *) NULL)
3024 {
3025 as_bad_where (fixP->fx_file, fixP->fx_line,
20203fb9 3026 _("Reloc %d not supported by object file format"),
026df7c5
NC
3027 (int) fixP->fx_r_type);
3028 return NULL;
3029 }
3030
3031 if (fixP->fx_r_type == BFD_RELOC_HI16)
3032 reloc->addend = fixP->fx_offset;
3033 else
3034 reloc->addend = fixP->fx_addnumber;
3035
3036 return reloc;
3037}
This page took 1.105568 seconds and 4 git commands to generate.