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