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