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