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