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