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