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