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