* Makefile.am: Bfin support.
[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 }
1147 symbolP = symbol_find_or_make (name);
1148 }
1149 else
1150 symbol_table_insert (symbolP);
1151
1152 pseudo_set (symbolP);
1153 demand_empty_rest_of_line ();
1154}
1155
1156/* [symbol] .usect ["]section-name["], size-in-words [, alignment-flag] */
1157static void
be33c5dd 1158tic4x_usect (x)
75d12d11 1159 int x ATTRIBUTE_UNUSED;
026df7c5
NC
1160{
1161 char c;
1162 char *name;
1163 char *section_name;
1164 segT seg;
2132e3a3 1165 offsetT size, alignment_flag;
026df7c5
NC
1166 segT current_seg;
1167 subsegT current_subseg;
1168
1169 current_seg = now_seg; /* save current seg. */
1170 current_subseg = now_subseg; /* save current subseg. */
1171
1172 SKIP_WHITESPACE ();
1173 if (*input_line_pointer == '"')
1174 input_line_pointer++;
1175 section_name = input_line_pointer;
1176 c = get_symbol_end (); /* Get terminator. */
1177 input_line_pointer++; /* Skip null symbol terminator. */
1178 name = xmalloc (input_line_pointer - section_name + 1);
1179 strcpy (name, section_name);
1180
1181 if (c == ',')
1182 input_line_pointer =
be33c5dd 1183 tic4x_expression_abs (input_line_pointer, &size);
026df7c5
NC
1184 else if (*input_line_pointer == ',')
1185 {
1186 input_line_pointer =
be33c5dd 1187 tic4x_expression_abs (++input_line_pointer, &size);
026df7c5
NC
1188 }
1189 else
1190 size = 0;
1191
1192 /* Read a possibly present third argument (alignment flag) [VK]. */
1193 if (*input_line_pointer == ',')
1194 {
1195 input_line_pointer =
be33c5dd 1196 tic4x_expression_abs (++input_line_pointer, &alignment_flag);
026df7c5
NC
1197 }
1198 else
1199 alignment_flag = 0;
1200 if (alignment_flag)
1201 as_warn (".usect: non-zero alignment flag ignored");
1202
1203 seg = subseg_new (name, 0);
1204 if (line_label != NULL)
1205 {
1206 S_SET_SEGMENT (line_label, seg);
1207 symbol_set_frag (line_label, frag_now);
1208 S_SET_VALUE (line_label, frag_now_fix ());
1209 }
1210 seg_info (seg)->bss = 1; /* Uninitialised data. */
1211 if (!bfd_set_section_flags (stdoutput, seg, SEC_ALLOC))
1212 as_warn ("Error setting flags for \"%s\": %s", name,
1213 bfd_errmsg (bfd_get_error ()));
be33c5dd 1214 tic4x_seg_alloc (name, seg, size, line_label);
026df7c5
NC
1215
1216 if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1217 S_SET_STORAGE_CLASS (line_label, C_STAT);
1218
1219 subseg_set (current_seg, current_subseg); /* Restore current seg. */
1220 demand_empty_rest_of_line ();
1221}
1222
1223/* .version cpu-version. */
1224static void
be33c5dd 1225tic4x_version (x)
75d12d11 1226 int x ATTRIBUTE_UNUSED;
026df7c5 1227{
2132e3a3 1228 offsetT temp;
026df7c5
NC
1229
1230 input_line_pointer =
be33c5dd
SS
1231 tic4x_expression_abs (input_line_pointer, &temp);
1232 if (!IS_CPU_TIC3X (temp) && !IS_CPU_TIC4X (temp))
2132e3a3
AM
1233 as_bad ("This assembler does not support processor generation %ld",
1234 (long) temp);
026df7c5 1235
2132e3a3 1236 if (tic4x_cpu && temp != (offsetT) tic4x_cpu)
9c87d6c7 1237 as_warn ("Changing processor generation on fly not supported...");
be33c5dd 1238 tic4x_cpu = temp;
026df7c5
NC
1239 demand_empty_rest_of_line ();
1240}
1241
026df7c5 1242static void
be33c5dd 1243tic4x_init_regtable ()
026df7c5
NC
1244{
1245 unsigned int i;
1246
be33c5dd
SS
1247 for (i = 0; i < tic3x_num_registers; i++)
1248 tic4x_insert_reg (tic3x_registers[i].name,
1249 tic3x_registers[i].regno);
026df7c5 1250
be33c5dd 1251 if (IS_CPU_TIC4X (tic4x_cpu))
026df7c5 1252 {
be33c5dd
SS
1253 /* Add additional Tic4x registers, overriding some C3x ones. */
1254 for (i = 0; i < tic4x_num_registers; i++)
1255 tic4x_insert_reg (tic4x_registers[i].name,
1256 tic4x_registers[i].regno);
026df7c5
NC
1257 }
1258}
1259
1260static void
be33c5dd 1261tic4x_init_symbols ()
026df7c5
NC
1262{
1263 /* The TI tools accept case insensitive versions of these symbols,
1264 we don't !
1265
1266 For TI C/Asm 5.0
1267
1268 .TMS320xx 30,31,32,40,or 44 set according to -v flag
1269 .C3X or .C3x 1 or 0 1 if -v30,-v31,or -v32
1270 .C30 1 or 0 1 if -v30
1271 .C31 1 or 0 1 if -v31
1272 .C32 1 or 0 1 if -v32
1273 .C4X or .C4x 1 or 0 1 if -v40, or -v44
1274 .C40 1 or 0 1 if -v40
1275 .C44 1 or 0 1 if -v44
1276
1277 .REGPARM 1 or 0 1 if -mr option used
1278 .BIGMODEL 1 or 0 1 if -mb option used
1279
1280 These symbols are currently supported but will be removed in a
1281 later version:
1282 .TMS320C30 1 or 0 1 if -v30,-v31,or -v32
1283 .TMS320C31 1 or 0 1 if -v31
1284 .TMS320C32 1 or 0 1 if -v32
1285 .TMS320C40 1 or 0 1 if -v40, or -v44
1286 .TMS320C44 1 or 0 1 if -v44
1287
1288 Source: TI: TMS320C3x/C4x Assembly Language Tools User's Guide,
1289 1997, SPRU035C, p. 3-17/3-18. */
be33c5dd
SS
1290 tic4x_insert_sym (".REGPARM", tic4x_reg_args);
1291 tic4x_insert_sym (".MEMPARM", !tic4x_reg_args);
1292 tic4x_insert_sym (".BIGMODEL", tic4x_big_model);
1293 tic4x_insert_sym (".C30INTERRUPT", 0);
1294 tic4x_insert_sym (".TMS320xx", tic4x_cpu == 0 ? 40 : tic4x_cpu);
1295 tic4x_insert_sym (".C3X", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1296 tic4x_insert_sym (".C3x", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1297 tic4x_insert_sym (".C4X", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
1298 tic4x_insert_sym (".C4x", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
026df7c5 1299 /* Do we need to have the following symbols also in lower case? */
be33c5dd
SS
1300 tic4x_insert_sym (".TMS320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1301 tic4x_insert_sym (".tms320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1302 tic4x_insert_sym (".TMS320C31", tic4x_cpu == 31);
1303 tic4x_insert_sym (".tms320C31", tic4x_cpu == 31);
1304 tic4x_insert_sym (".TMS320C32", tic4x_cpu == 32);
1305 tic4x_insert_sym (".tms320C32", tic4x_cpu == 32);
1306 tic4x_insert_sym (".TMS320C33", tic4x_cpu == 33);
1307 tic4x_insert_sym (".tms320C33", tic4x_cpu == 33);
1308 tic4x_insert_sym (".TMS320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
1309 tic4x_insert_sym (".tms320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
1310 tic4x_insert_sym (".TMS320C44", tic4x_cpu == 44);
1311 tic4x_insert_sym (".tms320C44", tic4x_cpu == 44);
1312 tic4x_insert_sym (".TMX320C40", 0); /* C40 first pass silicon ? */
1313 tic4x_insert_sym (".tmx320C40", 0);
026df7c5
NC
1314}
1315
1316/* Insert a new instruction template into hash table. */
1317static int
be33c5dd
SS
1318tic4x_inst_insert (inst)
1319 tic4x_inst_t *inst;
026df7c5
NC
1320{
1321 static char prev_name[16];
1322 const char *retval = NULL;
1323
1324 /* Only insert the first name if have several similar entries. */
1325 if (!strcmp (inst->name, prev_name) || inst->name[0] == '\0')
1326 return 1;
1327
be33c5dd 1328 retval = hash_insert (tic4x_op_hash, inst->name, (PTR) inst);
026df7c5
NC
1329 if (retval != NULL)
1330 fprintf (stderr, "internal error: can't hash `%s': %s\n",
1331 inst->name, retval);
1332 else
1333 strcpy (prev_name, inst->name);
1334 return retval == NULL;
1335}
1336
1337/* Make a new instruction template. */
be33c5dd
SS
1338static tic4x_inst_t *
1339tic4x_inst_make (name, opcode, args)
75d12d11
AM
1340 char *name;
1341 unsigned long opcode;
1342 char *args;
026df7c5 1343{
be33c5dd 1344 static tic4x_inst_t *insts = NULL;
026df7c5
NC
1345 static char *names = NULL;
1346 static int index = 0;
1347
1348 if (insts == NULL)
1349 {
1350 /* Allocate memory to store name strings. */
1351 names = (char *) xmalloc (sizeof (char) * 8192);
1352 /* Allocate memory for additional insts. */
be33c5dd
SS
1353 insts = (tic4x_inst_t *)
1354 xmalloc (sizeof (tic4x_inst_t) * 1024);
026df7c5
NC
1355 }
1356 insts[index].name = names;
1357 insts[index].opcode = opcode;
1358 insts[index].opmask = 0xffffffff;
1359 insts[index].args = args;
1360 index++;
1361
1362 do
1363 *names++ = *name++;
1364 while (*name);
1365 *names++ = '\0';
1366
1367 return &insts[index - 1];
1368}
1369
1370/* Add instruction template, creating dynamic templates as required. */
1371static int
be33c5dd
SS
1372tic4x_inst_add (insts)
1373 tic4x_inst_t *insts;
026df7c5
NC
1374{
1375 char *s = insts->name;
1376 char *d;
1377 unsigned int i;
1378 int ok = 1;
1379 char name[16];
1380
1381 d = name;
1382
9c87d6c7
SS
1383 /* We do not care about INSNs that is not a part of our
1384 oplevel setting */
be33c5dd 1385 if (!insts->oplevel & tic4x_oplevel)
9c87d6c7
SS
1386 return ok;
1387
026df7c5
NC
1388 while (1)
1389 {
1390 switch (*s)
1391 {
1392 case 'B':
1393 case 'C':
1394 /* Dynamically create all the conditional insts. */
be33c5dd 1395 for (i = 0; i < tic4x_num_conds; i++)
026df7c5 1396 {
be33c5dd 1397 tic4x_inst_t *inst;
026df7c5 1398 int k = 0;
be33c5dd 1399 char *c = tic4x_conds[i].name;
026df7c5
NC
1400 char *e = d;
1401
1402 while (*c)
1403 *e++ = *c++;
1404 c = s + 1;
1405 while (*c)
1406 *e++ = *c++;
1407 *e = '\0';
1408
1409 /* If instruction found then have already processed it. */
be33c5dd 1410 if (hash_find (tic4x_op_hash, name))
026df7c5
NC
1411 return 1;
1412
1413 do
1414 {
be33c5dd
SS
1415 inst = tic4x_inst_make (name, insts[k].opcode +
1416 (tic4x_conds[i].cond <<
026df7c5
NC
1417 (*s == 'B' ? 16 : 23)),
1418 insts[k].args);
1419 if (k == 0) /* Save strcmp() with following func. */
be33c5dd 1420 ok &= tic4x_inst_insert (inst);
026df7c5
NC
1421 k++;
1422 }
1423 while (!strcmp (insts->name,
1424 insts[k].name));
1425 }
1426 return ok;
1427 break;
1428
1429 case '\0':
be33c5dd 1430 return tic4x_inst_insert (insts);
026df7c5
NC
1431 break;
1432
1433 default:
1434 *d++ = *s++;
1435 break;
1436 }
1437 }
1438}
1439
1440/* This function is called once, at assembler startup time. It should
1441 set up all the tables, etc., that the MD part of the assembler will
1442 need. */
1443void
75d12d11 1444md_begin ()
026df7c5
NC
1445{
1446 int ok = 1;
1447 unsigned int i;
1448
9c87d6c7
SS
1449 /* Setup the proper opcode level according to the
1450 commandline parameters */
be33c5dd
SS
1451 tic4x_oplevel = OP_C3X;
1452
1453 if ( IS_CPU_TIC4X(tic4x_cpu) )
1454 tic4x_oplevel |= OP_C4X;
1455
1456 if ( ( tic4x_cpu == 31 && tic4x_revision >= 6)
1457 || (tic4x_cpu == 32 && tic4x_revision >= 2)
1458 || (tic4x_cpu == 33)
1459 || tic4x_enhanced )
1460 tic4x_oplevel |= OP_ENH;
1461
1462 if ( ( tic4x_cpu == 30 && tic4x_revision >= 7)
1463 || (tic4x_cpu == 31 && tic4x_revision >= 5)
1464 || (tic4x_cpu == 32)
1465 || tic4x_lowpower )
1466 tic4x_oplevel |= OP_LPWR;
1467
1468 if ( ( tic4x_cpu == 30 && tic4x_revision >= 7)
1469 || (tic4x_cpu == 31 && tic4x_revision >= 5)
1470 || (tic4x_cpu == 32)
1471 || (tic4x_cpu == 33)
1472 || (tic4x_cpu == 40 && tic4x_revision >= 5)
1473 || (tic4x_cpu == 44)
1474 || tic4x_idle2 )
1475 tic4x_oplevel |= OP_IDLE2;
9c87d6c7 1476
026df7c5 1477 /* Create hash table for mnemonics. */
be33c5dd 1478 tic4x_op_hash = hash_new ();
026df7c5
NC
1479
1480 /* Create hash table for asg pseudo. */
be33c5dd 1481 tic4x_asg_hash = hash_new ();
026df7c5
NC
1482
1483 /* Add mnemonics to hash table, expanding conditional mnemonics on fly. */
be33c5dd
SS
1484 for (i = 0; i < tic4x_num_insts; i++)
1485 ok &= tic4x_inst_add ((void *) &tic4x_insts[i]);
026df7c5
NC
1486
1487 /* Create dummy inst to avoid errors accessing end of table. */
be33c5dd 1488 tic4x_inst_make ("", 0, "");
026df7c5
NC
1489
1490 if (!ok)
1491 as_fatal ("Broken assembler. No assembly attempted.");
1492
1493 /* Add registers to symbol table. */
be33c5dd 1494 tic4x_init_regtable ();
026df7c5
NC
1495
1496 /* Add predefined symbols to symbol table. */
be33c5dd 1497 tic4x_init_symbols ();
026df7c5
NC
1498}
1499
1500void
be33c5dd 1501tic4x_end ()
026df7c5
NC
1502{
1503 bfd_set_arch_mach (stdoutput, bfd_arch_tic4x,
be33c5dd 1504 IS_CPU_TIC4X (tic4x_cpu) ? bfd_mach_tic4x : bfd_mach_tic3x);
026df7c5
NC
1505}
1506
1507static int
be33c5dd
SS
1508tic4x_indirect_parse (operand, indirect)
1509 tic4x_operand_t *operand;
1510 const tic4x_indirect_t *indirect;
026df7c5
NC
1511{
1512 char *n = indirect->name;
1513 char *s = input_line_pointer;
1514 char *b;
1515 symbolS *symbolP;
1516 char name[32];
1517
1518 operand->disp = 0;
1519 for (; *n; n++)
1520 {
1521 switch (*n)
1522 {
1523 case 'a': /* Need to match aux register. */
1524 b = name;
be33c5dd 1525#ifdef TIC4X_ALT_SYNTAX
026df7c5
NC
1526 if (*s == '%')
1527 s++;
1528#endif
278ed128 1529 while (ISALNUM (*s))
026df7c5
NC
1530 *b++ = *s++;
1531 *b++ = '\0';
1532 if (!(symbolP = symbol_find (name)))
1533 return 0;
1534
1535 if (S_GET_SEGMENT (symbolP) != reg_section)
1536 return 0;
1537
1538 operand->aregno = S_GET_VALUE (symbolP);
1539 if (operand->aregno >= REG_AR0 && operand->aregno <= REG_AR7)
1540 break;
1541
1542 as_bad ("Auxiliary register AR0--AR7 required for indirect");
1543 return -1;
1544
1545 case 'd': /* Need to match constant for disp. */
be33c5dd 1546#ifdef TIC4X_ALT_SYNTAX
026df7c5
NC
1547 if (*s == '%') /* expr() will die if we don't skip this. */
1548 s++;
1549#endif
be33c5dd 1550 s = tic4x_expression (s, &operand->expr);
026df7c5
NC
1551 if (operand->expr.X_op != O_constant)
1552 return 0;
1553 operand->disp = operand->expr.X_add_number;
1554 if (operand->disp < 0 || operand->disp > 255)
1555 {
1556 as_bad ("Bad displacement %d (require 0--255)\n",
1557 operand->disp);
1558 return -1;
1559 }
1560 break;
1561
1562 case 'y': /* Need to match IR0. */
1563 case 'z': /* Need to match IR1. */
be33c5dd 1564#ifdef TIC4X_ALT_SYNTAX
026df7c5
NC
1565 if (*s == '%')
1566 s++;
1567#endif
be33c5dd 1568 s = tic4x_expression (s, &operand->expr);
026df7c5
NC
1569 if (operand->expr.X_op != O_register)
1570 return 0;
1571 if (operand->expr.X_add_number != REG_IR0
1572 && operand->expr.X_add_number != REG_IR1)
1573 {
1574 as_bad ("Index register IR0,IR1 required for displacement");
1575 return -1;
1576 }
1577
1578 if (*n == 'y' && operand->expr.X_add_number == REG_IR0)
1579 break;
1580 if (*n == 'z' && operand->expr.X_add_number == REG_IR1)
1581 break;
1582 return 0;
1583
1584 case '(':
1585 if (*s != '(') /* No displacement, assume to be 1. */
1586 {
1587 operand->disp = 1;
1588 while (*n != ')')
1589 n++;
1590 }
1591 else
1592 s++;
1593 break;
1594
1595 default:
278ed128 1596 if (TOLOWER (*s) != *n)
026df7c5
NC
1597 return 0;
1598 s++;
1599 }
1600 }
1601 if (*s != ' ' && *s != ',' && *s != '\0')
1602 return 0;
1603 input_line_pointer = s;
1604 return 1;
1605}
1606
247b1fe6 1607static char *
be33c5dd 1608tic4x_operand_parse (s, operand)
75d12d11 1609 char *s;
be33c5dd 1610 tic4x_operand_t *operand;
026df7c5
NC
1611{
1612 unsigned int i;
1613 char c;
1614 int ret;
1615 expressionS *exp = &operand->expr;
1616 char *save = input_line_pointer;
1617 char *str;
1618 char *new;
1619 struct hash_entry *entry = NULL;
1620
1621 input_line_pointer = s;
1622 SKIP_WHITESPACE ();
1623
1624 str = input_line_pointer;
1625 c = get_symbol_end (); /* Get terminator. */
1626 new = input_line_pointer;
be33c5dd 1627 if (strlen (str) && (entry = hash_find (tic4x_asg_hash, str)) != NULL)
026df7c5
NC
1628 {
1629 *input_line_pointer = c;
1630 input_line_pointer = (char *) entry;
1631 }
1632 else
1633 {
1634 *input_line_pointer = c;
1635 input_line_pointer = str;
1636 }
1637
1638 operand->mode = M_UNKNOWN;
1639 switch (*input_line_pointer)
1640 {
be33c5dd 1641#ifdef TIC4X_ALT_SYNTAX
026df7c5 1642 case '%':
be33c5dd 1643 input_line_pointer = tic4x_expression (++input_line_pointer, exp);
026df7c5
NC
1644 if (exp->X_op != O_register)
1645 as_bad ("Expecting a register name");
1646 operand->mode = M_REGISTER;
1647 break;
1648
1649 case '^':
1650 /* Denotes high 16 bits. */
be33c5dd 1651 input_line_pointer = tic4x_expression (++input_line_pointer, exp);
026df7c5
NC
1652 if (exp->X_op == O_constant)
1653 operand->mode = M_IMMED;
1654 else if (exp->X_op == O_big)
1655 {
1656 if (exp->X_add_number)
1657 as_bad ("Number too large"); /* bignum required */
1658 else
1659 {
be33c5dd 1660 tic4x_gen_to_words (generic_floating_point_number,
026df7c5
NC
1661 operand->fwords, S_PRECISION);
1662 operand->mode = M_IMMED_F;
1663 }
1664 }
1665 /* Allow ori ^foo, ar0 to be equivalent to ldi .hi.foo, ar0 */
1666 /* WARNING : The TI C40 assembler cannot do this. */
1667 else if (exp->X_op == O_symbol)
1668 {
1669 operand->mode = M_HI;
1670 break;
1671 }
1672
1673 case '#':
be33c5dd 1674 input_line_pointer = tic4x_expression (++input_line_pointer, exp);
026df7c5
NC
1675 if (exp->X_op == O_constant)
1676 operand->mode = M_IMMED;
1677 else if (exp->X_op == O_big)
1678 {
1679 if (exp->X_add_number > 0)
1680 as_bad ("Number too large"); /* bignum required. */
1681 else
1682 {
be33c5dd 1683 tic4x_gen_to_words (generic_floating_point_number,
026df7c5
NC
1684 operand->fwords, S_PRECISION);
1685 operand->mode = M_IMMED_F;
1686 }
1687 }
1688 /* Allow ori foo, ar0 to be equivalent to ldi .lo.foo, ar0 */
1689 /* WARNING : The TI C40 assembler cannot do this. */
1690 else if (exp->X_op == O_symbol)
1691 {
1692 operand->mode = M_IMMED;
1693 break;
1694 }
1695
1696 else
1697 as_bad ("Expecting a constant value");
1698 break;
1699 case '\\':
1700#endif
1701 case '@':
be33c5dd 1702 input_line_pointer = tic4x_expression (++input_line_pointer, exp);
026df7c5
NC
1703 if (exp->X_op != O_constant && exp->X_op != O_symbol)
1704 as_bad ("Bad direct addressing construct %s", s);
1705 if (exp->X_op == O_constant)
1706 {
1707 if (exp->X_add_number < 0)
1708 as_bad ("Direct value of %ld is not suitable",
1709 (long) exp->X_add_number);
1710 }
1711 operand->mode = M_DIRECT;
1712 break;
1713
1714 case '*':
1715 ret = -1;
be33c5dd
SS
1716 for (i = 0; i < tic4x_num_indirects; i++)
1717 if ((ret = tic4x_indirect_parse (operand, &tic4x_indirects[i])))
026df7c5
NC
1718 break;
1719 if (ret < 0)
1720 break;
be33c5dd 1721 if (i < tic4x_num_indirects)
026df7c5
NC
1722 {
1723 operand->mode = M_INDIRECT;
1724 /* Indirect addressing mode number. */
be33c5dd 1725 operand->expr.X_add_number = tic4x_indirects[i].modn;
026df7c5
NC
1726 /* Convert *+ARn(0) to *ARn etc. Maybe we should
1727 squeal about silly ones? */
1728 if (operand->expr.X_add_number < 0x08 && !operand->disp)
1729 operand->expr.X_add_number = 0x18;
1730 }
1731 else
1732 as_bad ("Unknown indirect addressing mode");
1733 break;
1734
1735 default:
1736 operand->mode = M_IMMED; /* Assume immediate. */
1737 str = input_line_pointer;
be33c5dd 1738 input_line_pointer = tic4x_expression (input_line_pointer, exp);
026df7c5
NC
1739 if (exp->X_op == O_register)
1740 {
1741 know (exp->X_add_symbol == 0);
1742 know (exp->X_op_symbol == 0);
1743 operand->mode = M_REGISTER;
1744 break;
1745 }
1746 else if (exp->X_op == O_big)
1747 {
1748 if (exp->X_add_number > 0)
1749 as_bad ("Number too large"); /* bignum required. */
1750 else
1751 {
be33c5dd 1752 tic4x_gen_to_words (generic_floating_point_number,
026df7c5
NC
1753 operand->fwords, S_PRECISION);
1754 operand->mode = M_IMMED_F;
1755 }
1756 break;
1757 }
be33c5dd 1758#ifdef TIC4X_ALT_SYNTAX
026df7c5
NC
1759 /* Allow ldi foo, ar0 to be equivalent to ldi @foo, ar0. */
1760 else if (exp->X_op == O_symbol)
1761 {
1762 operand->mode = M_DIRECT;
1763 break;
1764 }
1765#endif
1766 }
1767 if (entry == NULL)
1768 new = input_line_pointer;
1769 input_line_pointer = save;
1770 return new;
1771}
1772
1773static int
be33c5dd
SS
1774tic4x_operands_match (inst, insn, check)
1775 tic4x_inst_t *inst;
1776 tic4x_insn_t *insn;
9c87d6c7 1777 int check;
026df7c5
NC
1778{
1779 const char *args = inst->args;
1780 unsigned long opcode = inst->opcode;
1781 int num_operands = insn->num_operands;
be33c5dd 1782 tic4x_operand_t *operand = insn->operands;
026df7c5
NC
1783 expressionS *exp = &operand->expr;
1784 int ret = 1;
1785 int reg;
1786
1787 /* Build the opcode, checking as we go to make sure that the
1788 operands match.
1789
1790 If an operand matches, we modify insn or opcode appropriately,
1791 and do a "continue". If an operand fails to match, we "break". */
1792
1793 insn->nchars = 4; /* Instructions always 4 bytes. */
1794 insn->reloc = NO_RELOC;
1795 insn->pcrel = 0;
1796
1797 if (*args == '\0')
1798 {
1799 insn->opcode = opcode;
1800 return num_operands == 0;
1801 }
1802
1803 for (;; ++args)
1804 {
1805 switch (*args)
1806 {
1807
1808 case '\0': /* End of args. */
1809 if (num_operands == 1)
1810 {
1811 insn->opcode = opcode;
1812 return ret;
1813 }
1814 break; /* Too many operands. */
1815
1816 case '#': /* This is only used for ldp. */
1817 if (operand->mode != M_DIRECT && operand->mode != M_IMMED)
1818 break;
1819 /* While this looks like a direct addressing mode, we actually
1820 use an immediate mode form of ldiu or ldpk instruction. */
1821 if (exp->X_op == O_constant)
1822 {
be33c5dd
SS
1823 if( ( IS_CPU_TIC4X (tic4x_cpu) && exp->X_add_number <= 65535 )
1824 || ( IS_CPU_TIC3X (tic4x_cpu) && exp->X_add_number <= 255 ) )
44287f60
SS
1825 {
1826 INSERTS (opcode, exp->X_add_number, 15, 0);
1827 continue;
1828 }
1829 else
1830 {
9c87d6c7
SS
1831 if (!check)
1832 as_bad ("Immediate value of %ld is too large for ldf",
1833 (long) exp->X_add_number);
44287f60
SS
1834 ret = -1;
1835 continue;
1836 }
026df7c5
NC
1837 }
1838 else if (exp->X_op == O_symbol)
1839 {
1840 insn->reloc = BFD_RELOC_HI16;
1841 insn->exp = *exp;
1842 continue;
1843 }
1844 break; /* Not direct (dp) addressing. */
1845
1846 case '@': /* direct. */
1847 if (operand->mode != M_DIRECT)
1848 break;
1849 if (exp->X_op == O_constant)
da91385d
SS
1850 {
1851 /* Store only the 16 LSBs of the number. */
1852 INSERTS (opcode, exp->X_add_number, 15, 0);
1853 continue;
026df7c5
NC
1854 }
1855 else if (exp->X_op == O_symbol)
1856 {
1857 insn->reloc = BFD_RELOC_LO16;
1858 insn->exp = *exp;
1859 continue;
1860 }
1861 break; /* Not direct addressing. */
1862
1863 case 'A':
1864 if (operand->mode != M_REGISTER)
1865 break;
1866 reg = exp->X_add_number;
1867 if (reg >= REG_AR0 && reg <= REG_AR7)
1868 INSERTU (opcode, reg - REG_AR0, 24, 22);
1869 else
1870 {
9c87d6c7
SS
1871 if (!check)
1872 as_bad ("Destination register must be ARn");
026df7c5
NC
1873 ret = -1;
1874 }
1875 continue;
1876
1877 case 'B': /* Unsigned integer immediate. */
1878 /* Allow br label or br @label. */
1879 if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
1880 break;
1881 if (exp->X_op == O_constant)
1882 {
1883 if (exp->X_add_number < (1 << 24))
1884 {
1885 INSERTU (opcode, exp->X_add_number, 23, 0);
1886 continue;
1887 }
1888 else
1889 {
9c87d6c7
SS
1890 if (!check)
1891 as_bad ("Immediate value of %ld is too large",
1892 (long) exp->X_add_number);
026df7c5
NC
1893 ret = -1;
1894 continue;
1895 }
1896 }
be33c5dd 1897 if (IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
1898 {
1899 insn->reloc = BFD_RELOC_24_PCREL;
1900 insn->pcrel = 1;
1901 }
1902 else
1903 {
1904 insn->reloc = BFD_RELOC_24;
1905 insn->pcrel = 0;
1906 }
1907 insn->exp = *exp;
1908 continue;
1909
1910 case 'C':
be33c5dd 1911 if (!IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
1912 break;
1913 if (operand->mode != M_INDIRECT)
1914 break;
44287f60 1915 /* Require either *+ARn(disp) or *ARn. */
026df7c5
NC
1916 if (operand->expr.X_add_number != 0
1917 && operand->expr.X_add_number != 0x18)
1918 {
9c87d6c7
SS
1919 if (!check)
1920 as_bad ("Invalid indirect addressing mode");
1921 ret = -1;
026df7c5
NC
1922 continue;
1923 }
1924 INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
1925 INSERTU (opcode, operand->disp, 7, 3);
1926 continue;
1927
1928 case 'E':
1929 if (!(operand->mode == M_REGISTER))
1930 break;
1931 INSERTU (opcode, exp->X_add_number, 7, 0);
1932 continue;
1933
44287f60
SS
1934 case 'e':
1935 if (!(operand->mode == M_REGISTER))
1936 break;
1937 reg = exp->X_add_number;
1938 if ( (reg >= REG_R0 && reg <= REG_R7)
be33c5dd 1939 || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
44287f60
SS
1940 INSERTU (opcode, reg, 7, 0);
1941 else
1942 {
9c87d6c7
SS
1943 if (!check)
1944 as_bad ("Register must be Rn");
44287f60
SS
1945 ret = -1;
1946 }
1947 continue;
1948
026df7c5
NC
1949 case 'F':
1950 if (operand->mode != M_IMMED_F
1951 && !(operand->mode == M_IMMED && exp->X_op == O_constant))
1952 break;
1953
1954 if (operand->mode != M_IMMED_F)
1955 {
1956 /* OK, we 've got something like cmpf 0, r0
1957 Why can't they stick in a bloody decimal point ?! */
1958 char string[16];
1959
1960 /* Create floating point number string. */
1961 sprintf (string, "%d.0", (int) exp->X_add_number);
be33c5dd 1962 tic4x_atof (string, 's', operand->fwords);
026df7c5
NC
1963 }
1964
1965 INSERTU (opcode, operand->fwords[0], 15, 0);
1966 continue;
1967
1968 case 'G':
1969 if (operand->mode != M_REGISTER)
1970 break;
1971 INSERTU (opcode, exp->X_add_number, 15, 8);
1972 continue;
1973
44287f60
SS
1974 case 'g':
1975 if (operand->mode != M_REGISTER)
1976 break;
1977 reg = exp->X_add_number;
1978 if ( (reg >= REG_R0 && reg <= REG_R7)
be33c5dd 1979 || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
44287f60
SS
1980 INSERTU (opcode, reg, 15, 8);
1981 else
1982 {
9c87d6c7
SS
1983 if (!check)
1984 as_bad ("Register must be Rn");
44287f60
SS
1985 ret = -1;
1986 }
1987 continue;
1988
026df7c5
NC
1989 case 'H':
1990 if (operand->mode != M_REGISTER)
1991 break;
1992 reg = exp->X_add_number;
1993 if (reg >= REG_R0 && reg <= REG_R7)
1994 INSERTU (opcode, reg - REG_R0, 18, 16);
1995 else
1996 {
9c87d6c7
SS
1997 if (!check)
1998 as_bad ("Register must be R0--R7");
026df7c5
NC
1999 ret = -1;
2000 }
2001 continue;
2002
9c87d6c7
SS
2003 case 'i':
2004 if ( operand->mode == M_REGISTER
be33c5dd 2005 && tic4x_oplevel & OP_ENH )
9c87d6c7
SS
2006 {
2007 reg = exp->X_add_number;
2008 INSERTU (opcode, reg, 4, 0);
2009 INSERTU (opcode, 7, 7, 5);
2010 continue;
2011 }
2012 /* Fallthrough */
2013
026df7c5
NC
2014 case 'I':
2015 if (operand->mode != M_INDIRECT)
2016 break;
2017 if (operand->disp != 0 && operand->disp != 1)
2018 {
be33c5dd 2019 if (IS_CPU_TIC4X (tic4x_cpu))
026df7c5 2020 break;
9c87d6c7
SS
2021 if (!check)
2022 as_bad ("Invalid indirect addressing mode displacement %d",
2023 operand->disp);
026df7c5
NC
2024 ret = -1;
2025 continue;
2026 }
2027 INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
2028 INSERTU (opcode, operand->expr.X_add_number, 7, 3);
2029 continue;
2030
9c87d6c7
SS
2031 case 'j':
2032 if ( operand->mode == M_REGISTER
be33c5dd 2033 && tic4x_oplevel & OP_ENH )
9c87d6c7
SS
2034 {
2035 reg = exp->X_add_number;
2036 INSERTU (opcode, reg, 12, 8);
2037 INSERTU (opcode, 7, 15, 13);
2038 continue;
2039 }
2040 /* Fallthrough */
2041
026df7c5
NC
2042 case 'J':
2043 if (operand->mode != M_INDIRECT)
2044 break;
2045 if (operand->disp != 0 && operand->disp != 1)
2046 {
be33c5dd 2047 if (IS_CPU_TIC4X (tic4x_cpu))
026df7c5 2048 break;
9c87d6c7
SS
2049 if (!check)
2050 as_bad ("Invalid indirect addressing mode displacement %d",
2051 operand->disp);
026df7c5
NC
2052 ret = -1;
2053 continue;
2054 }
2055 INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
2056 INSERTU (opcode, operand->expr.X_add_number, 15, 11);
2057 continue;
2058
2059 case 'K':
2060 if (operand->mode != M_REGISTER)
2061 break;
2062 reg = exp->X_add_number;
2063 if (reg >= REG_R0 && reg <= REG_R7)
2064 INSERTU (opcode, reg - REG_R0, 21, 19);
2065 else
2066 {
9c87d6c7
SS
2067 if (!check)
2068 as_bad ("Register must be R0--R7");
026df7c5
NC
2069 ret = -1;
2070 }
2071 continue;
2072
2073 case 'L':
2074 if (operand->mode != M_REGISTER)
2075 break;
2076 reg = exp->X_add_number;
2077 if (reg >= REG_R0 && reg <= REG_R7)
2078 INSERTU (opcode, reg - REG_R0, 24, 22);
2079 else
2080 {
9c87d6c7
SS
2081 if (!check)
2082 as_bad ("Register must be R0--R7");
026df7c5
NC
2083 ret = -1;
2084 }
2085 continue;
2086
2087 case 'M':
2088 if (operand->mode != M_REGISTER)
2089 break;
2090 reg = exp->X_add_number;
2091 if (reg == REG_R2 || reg == REG_R3)
2092 INSERTU (opcode, reg - REG_R2, 22, 22);
2093 else
2094 {
9c87d6c7
SS
2095 if (!check)
2096 as_bad ("Destination register must be R2 or R3");
026df7c5
NC
2097 ret = -1;
2098 }
2099 continue;
2100
2101 case 'N':
2102 if (operand->mode != M_REGISTER)
2103 break;
2104 reg = exp->X_add_number;
2105 if (reg == REG_R0 || reg == REG_R1)
2106 INSERTU (opcode, reg - REG_R0, 23, 23);
2107 else
2108 {
9c87d6c7
SS
2109 if (!check)
2110 as_bad ("Destination register must be R0 or R1");
026df7c5
NC
2111 ret = -1;
2112 }
2113 continue;
2114
2115 case 'O':
be33c5dd 2116 if (!IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
2117 break;
2118 if (operand->mode != M_INDIRECT)
2119 break;
2120 /* Require either *+ARn(disp) or *ARn. */
2121 if (operand->expr.X_add_number != 0
2122 && operand->expr.X_add_number != 0x18)
2123 {
9c87d6c7
SS
2124 if (!check)
2125 as_bad ("Invalid indirect addressing mode");
026df7c5
NC
2126 ret = -1;
2127 continue;
2128 }
2129 INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
2130 INSERTU (opcode, operand->disp, 15, 11);
2131 continue;
2132
2133 case 'P': /* PC relative displacement. */
2134 /* Allow br label or br @label. */
2135 if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
2136 break;
2137 if (exp->X_op == O_constant)
2138 {
2139 if (exp->X_add_number >= -32768 && exp->X_add_number <= 32767)
2140 {
2141 INSERTS (opcode, exp->X_add_number, 15, 0);
2142 continue;
2143 }
2144 else
2145 {
9c87d6c7
SS
2146 if (!check)
2147 as_bad ("Displacement value of %ld is too large",
2148 (long) exp->X_add_number);
026df7c5
NC
2149 ret = -1;
2150 continue;
2151 }
2152 }
2153 insn->reloc = BFD_RELOC_16_PCREL;
2154 insn->pcrel = 1;
2155 insn->exp = *exp;
2156 continue;
2157
2158 case 'Q':
2159 if (operand->mode != M_REGISTER)
2160 break;
2161 reg = exp->X_add_number;
2162 INSERTU (opcode, reg, 15, 0);
2163 continue;
2164
44287f60
SS
2165 case 'q':
2166 if (operand->mode != M_REGISTER)
2167 break;
2168 reg = exp->X_add_number;
2169 if ( (reg >= REG_R0 && reg <= REG_R7)
be33c5dd 2170 || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
44287f60
SS
2171 INSERTU (opcode, reg, 15, 0);
2172 else
2173 {
9c87d6c7
SS
2174 if (!check)
2175 as_bad ("Register must be Rn");
44287f60
SS
2176 ret = -1;
2177 }
2178 continue;
2179
026df7c5
NC
2180 case 'R':
2181 if (operand->mode != M_REGISTER)
2182 break;
2183 reg = exp->X_add_number;
2184 INSERTU (opcode, reg, 20, 16);
2185 continue;
2186
44287f60
SS
2187 case 'r':
2188 if (operand->mode != M_REGISTER)
2189 break;
2190 reg = exp->X_add_number;
2191 if ( (reg >= REG_R0 && reg <= REG_R7)
be33c5dd 2192 || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
44287f60
SS
2193 INSERTU (opcode, reg, 20, 16);
2194 else
2195 {
9c87d6c7
SS
2196 if (!check)
2197 as_bad ("Register must be Rn");
44287f60
SS
2198 ret = -1;
2199 }
2200 continue;
2201
026df7c5
NC
2202 case 'S': /* Short immediate int. */
2203 if (operand->mode != M_IMMED && operand->mode != M_HI)
2204 break;
2205 if (exp->X_op == O_big)
2206 {
9c87d6c7
SS
2207 if (!check)
2208 as_bad ("Floating point number not valid in expression");
026df7c5
NC
2209 ret = -1;
2210 continue;
2211 }
2212 if (exp->X_op == O_constant)
2213 {
2214 if (exp->X_add_number >= -32768 && exp->X_add_number <= 65535)
2215 {
2216 INSERTS (opcode, exp->X_add_number, 15, 0);
2217 continue;
2218 }
2219 else
2220 {
9c87d6c7
SS
2221 if (!check)
2222 as_bad ("Signed immediate value %ld too large",
2223 (long) exp->X_add_number);
026df7c5
NC
2224 ret = -1;
2225 continue;
2226 }
2227 }
2228 else if (exp->X_op == O_symbol)
2229 {
2230 if (operand->mode == M_HI)
2231 {
2232 insn->reloc = BFD_RELOC_HI16;
2233 }
2234 else
2235 {
2236 insn->reloc = BFD_RELOC_LO16;
2237 }
2238 insn->exp = *exp;
2239 continue;
2240 }
2241 /* Handle cases like ldi foo - $, ar0 where foo
2242 is a forward reference. Perhaps we should check
2243 for X_op == O_symbol and disallow things like
2244 ldi foo, ar0. */
2245 insn->reloc = BFD_RELOC_16;
2246 insn->exp = *exp;
2247 continue;
2248
be33c5dd
SS
2249 case 'T': /* 5-bit immediate value for tic4x stik. */
2250 if (!IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
2251 break;
2252 if (operand->mode != M_IMMED)
2253 break;
2254 if (exp->X_op == O_constant)
2255 {
2256 if (exp->X_add_number < 16 && exp->X_add_number >= -16)
2257 {
2258 INSERTS (opcode, exp->X_add_number, 20, 16);
2259 continue;
2260 }
2261 else
2262 {
9c87d6c7
SS
2263 if (!check)
2264 as_bad ("Immediate value of %ld is too large",
2265 (long) exp->X_add_number);
026df7c5
NC
2266 ret = -1;
2267 continue;
2268 }
2269 }
2270 break; /* No relocations allowed. */
2271
2272 case 'U': /* Unsigned integer immediate. */
2273 if (operand->mode != M_IMMED && operand->mode != M_HI)
2274 break;
2275 if (exp->X_op == O_constant)
2276 {
2277 if (exp->X_add_number < (1 << 16) && exp->X_add_number >= 0)
2278 {
2279 INSERTU (opcode, exp->X_add_number, 15, 0);
2280 continue;
2281 }
2282 else
2283 {
9c87d6c7
SS
2284 if (!check)
2285 as_bad ("Unsigned immediate value %ld too large",
2286 (long) exp->X_add_number);
026df7c5
NC
2287 ret = -1;
2288 continue;
2289 }
2290 }
2291 else if (exp->X_op == O_symbol)
2292 {
2293 if (operand->mode == M_HI)
2294 insn->reloc = BFD_RELOC_HI16;
2295 else
2296 insn->reloc = BFD_RELOC_LO16;
2297
2298 insn->exp = *exp;
2299 continue;
2300 }
2301 insn->reloc = BFD_RELOC_16;
2302 insn->exp = *exp;
2303 continue;
2304
2305 case 'V': /* Trap numbers (immediate field). */
2306 if (operand->mode != M_IMMED)
2307 break;
2308 if (exp->X_op == O_constant)
2309 {
be33c5dd 2310 if (exp->X_add_number < 512 && IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
2311 {
2312 INSERTU (opcode, exp->X_add_number, 8, 0);
2313 continue;
2314 }
be33c5dd 2315 else if (exp->X_add_number < 32 && IS_CPU_TIC3X (tic4x_cpu))
026df7c5
NC
2316 {
2317 INSERTU (opcode, exp->X_add_number | 0x20, 4, 0);
2318 continue;
2319 }
2320 else
2321 {
9c87d6c7
SS
2322 if (!check)
2323 as_bad ("Immediate value of %ld is too large",
2324 (long) exp->X_add_number);
026df7c5
NC
2325 ret = -1;
2326 continue;
2327 }
2328 }
2329 break; /* No relocations allowed. */
2330
2331 case 'W': /* Short immediate int (0--7). */
be33c5dd 2332 if (!IS_CPU_TIC4X (tic4x_cpu))
026df7c5
NC
2333 break;
2334 if (operand->mode != M_IMMED)
2335 break;
2336 if (exp->X_op == O_big)
2337 {
9c87d6c7
SS
2338 if (!check)
2339 as_bad ("Floating point number not valid in expression");
026df7c5
NC
2340 ret = -1;
2341 continue;
2342 }
2343 if (exp->X_op == O_constant)
2344 {
2345 if (exp->X_add_number >= -256 && exp->X_add_number <= 127)
2346 {
2347 INSERTS (opcode, exp->X_add_number, 7, 0);
2348 continue;
2349 }
2350 else
2351 {
9c87d6c7
SS
2352 if (!check)
2353 as_bad ("Immediate value %ld too large",
2354 (long) exp->X_add_number);
026df7c5
NC
2355 ret = -1;
2356 continue;
2357 }
2358 }
2359 insn->reloc = BFD_RELOC_16;
2360 insn->exp = *exp;
2361 continue;
2362
be33c5dd 2363 case 'X': /* Expansion register for tic4x. */
026df7c5
NC
2364 if (operand->mode != M_REGISTER)
2365 break;
2366 reg = exp->X_add_number;
2367 if (reg >= REG_IVTP && reg <= REG_TVTP)
2368 INSERTU (opcode, reg - REG_IVTP, 4, 0);
2369 else
2370 {
9c87d6c7
SS
2371 if (!check)
2372 as_bad ("Register must be ivtp or tvtp");
026df7c5
NC
2373 ret = -1;
2374 }
2375 continue;
2376
be33c5dd 2377 case 'Y': /* Address register for tic4x lda. */
026df7c5
NC
2378 if (operand->mode != M_REGISTER)
2379 break;
2380 reg = exp->X_add_number;
2381 if (reg >= REG_AR0 && reg <= REG_SP)
2382 INSERTU (opcode, reg, 20, 16);
2383 else
2384 {
9c87d6c7
SS
2385 if (!check)
2386 as_bad ("Register must be address register");
026df7c5
NC
2387 ret = -1;
2388 }
2389 continue;
2390
be33c5dd 2391 case 'Z': /* Expansion register for tic4x. */
026df7c5
NC
2392 if (operand->mode != M_REGISTER)
2393 break;
2394 reg = exp->X_add_number;
2395 if (reg >= REG_IVTP && reg <= REG_TVTP)
2396 INSERTU (opcode, reg - REG_IVTP, 20, 16);
2397 else
2398 {
9c87d6c7
SS
2399 if (!check)
2400 as_bad ("Register must be ivtp or tvtp");
026df7c5
NC
2401 ret = -1;
2402 }
2403 continue;
2404
2405 case '*':
2406 if (operand->mode != M_INDIRECT)
2407 break;
2408 INSERTS (opcode, operand->disp, 7, 0);
2409 INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
2410 INSERTU (opcode, operand->expr.X_add_number, 15, 11);
2411 continue;
2412
2413 case '|': /* treat as `,' if have ldi_ldi form. */
2414 if (insn->parallel)
2415 {
2416 if (--num_operands < 0)
2417 break; /* Too few operands. */
2418 operand++;
2419 if (operand->mode != M_PARALLEL)
2420 break;
2421 }
2422 /* Fall through. */
2423
2424 case ',': /* Another operand. */
2425 if (--num_operands < 0)
2426 break; /* Too few operands. */
2427 operand++;
2428 exp = &operand->expr;
2429 continue;
2430
2431 case ';': /* Another optional operand. */
2432 if (num_operands == 1 || operand[1].mode == M_PARALLEL)
2433 continue;
2434 if (--num_operands < 0)
2435 break; /* Too few operands. */
2436 operand++;
2437 exp = &operand->expr;
2438 continue;
2439
2440 default:
2441 BAD_CASE (*args);
2442 }
2443 return 0;
2444 }
2445}
2446
9c87d6c7 2447static void
be33c5dd
SS
2448tic4x_insn_check (insn)
2449 tic4x_insn_t *insn;
9c87d6c7
SS
2450{
2451
2452 if (!strcmp(insn->name, "lda"))
2453 {
2454 if (insn->num_operands < 2 || insn->num_operands > 2)
2455 as_fatal ("Illegal internal LDA insn definition");
2456
2457 if ( insn->operands[0].mode == M_REGISTER
2458 && insn->operands[1].mode == M_REGISTER
2459 && insn->operands[0].expr.X_add_number == insn->operands[1].expr.X_add_number )
2460 as_bad ("Source and destination register should not be equal");
2461 }
2462 else if( !strcmp(insn->name, "ldi_ldi")
2463 || !strcmp(insn->name, "ldi1_ldi2")
2464 || !strcmp(insn->name, "ldi2_ldi1")
2465 || !strcmp(insn->name, "ldf_ldf")
2466 || !strcmp(insn->name, "ldf1_ldf2")
2467 || !strcmp(insn->name, "ldf2_ldf1") )
2468 {
2469 if ( insn->num_operands < 4 && insn->num_operands > 5 )
2470 as_fatal ("Illegal internal %s insn definition", insn->name);
2471
2472 if ( insn->operands[1].mode == M_REGISTER
2473 && insn->operands[insn->num_operands-1].mode == M_REGISTER
2474 && insn->operands[1].expr.X_add_number == insn->operands[insn->num_operands-1].expr.X_add_number )
2475 as_warn ("Equal parallell destination registers, one result will be discarded");
2476 }
2477}
2478
247b1fe6 2479static void
be33c5dd
SS
2480tic4x_insn_output (insn)
2481 tic4x_insn_t *insn;
026df7c5
NC
2482{
2483 char *dst;
2484
2485 /* Grab another fragment for opcode. */
2486 dst = frag_more (insn->nchars);
2487
2488 /* Put out opcode word as a series of bytes in little endian order. */
2489 md_number_to_chars (dst, insn->opcode, insn->nchars);
2490
2491 /* Put out the symbol-dependent stuff. */
2492 if (insn->reloc != NO_RELOC)
2493 {
2494 /* Where is the offset into the fragment for this instruction. */
2495 fix_new_exp (frag_now,
2496 dst - frag_now->fr_literal, /* where */
2497 insn->nchars, /* size */
2498 &insn->exp,
2499 insn->pcrel,
2500 insn->reloc);
2501 }
2502}
2503
2504/* Parse the operands. */
2505int
be33c5dd 2506tic4x_operands_parse (s, operands, num_operands)
75d12d11 2507 char *s;
be33c5dd 2508 tic4x_operand_t *operands;
75d12d11 2509 int num_operands;
026df7c5
NC
2510{
2511 if (!*s)
2512 return num_operands;
2513
2514 do
be33c5dd
SS
2515 s = tic4x_operand_parse (s, &operands[num_operands++]);
2516 while (num_operands < TIC4X_OPERANDS_MAX && *s++ == ',');
026df7c5 2517
be33c5dd 2518 if (num_operands > TIC4X_OPERANDS_MAX)
026df7c5
NC
2519 {
2520 as_bad ("Too many operands scanned");
2521 return -1;
2522 }
2523 return num_operands;
2524}
2525
2526/* Assemble a single instruction. Its label has already been handled
2527 by the generic front end. We just parse mnemonic and operands, and
2528 produce the bytes of data and relocation. */
2529void
75d12d11
AM
2530md_assemble (str)
2531 char *str;
026df7c5
NC
2532{
2533 int ok = 0;
2534 char *s;
2535 int i;
2536 int parsed = 0;
be33c5dd
SS
2537 tic4x_inst_t *inst; /* Instruction template. */
2538 tic4x_inst_t *first_inst;
026df7c5 2539
a1f3c24c
SS
2540 /* Scan for parallel operators */
2541 if (str)
2542 {
2543 s = str;
2544 while (*s && *s != '|')
2545 s++;
2546
2547 if (*s && s[1]=='|')
2548 {
2549 if(insn->parallel)
2550 {
2551 as_bad ("Parallel opcode cannot contain more than two instructions");
2552 insn->parallel = 0;
2553 insn->in_use = 0;
2554 return;
2555 }
2556
2557 /* Lets take care of the first part of the parallel insn */
2558 *s++ = 0;
2559 md_assemble(str);
2560 insn->parallel = 1;
2561 str = ++s;
2562 /* .. and let the second run though here */
2563 }
2564 }
2565
026df7c5
NC
2566 if (str && insn->parallel)
2567 {
026df7c5
NC
2568 /* Find mnemonic (second part of parallel instruction). */
2569 s = str;
2570 /* Skip past instruction mnemonic. */
a1f3c24c 2571 while (*s && *s != ' ')
026df7c5 2572 s++;
026df7c5
NC
2573 if (*s) /* Null terminate for hash_find. */
2574 *s++ = '\0'; /* and skip past null. */
2575 strcat (insn->name, "_");
be33c5dd 2576 strncat (insn->name, str, TIC4X_NAME_MAX - strlen (insn->name));
026df7c5 2577
026df7c5
NC
2578 insn->operands[insn->num_operands++].mode = M_PARALLEL;
2579
be33c5dd 2580 if ((i = tic4x_operands_parse
026df7c5
NC
2581 (s, insn->operands, insn->num_operands)) < 0)
2582 {
2583 insn->parallel = 0;
2584 insn->in_use = 0;
2585 return;
2586 }
2587 insn->num_operands = i;
2588 parsed = 1;
2589 }
2590
2591 if (insn->in_use)
2592 {
be33c5dd
SS
2593 if ((insn->inst = (struct tic4x_inst *)
2594 hash_find (tic4x_op_hash, insn->name)) == NULL)
026df7c5
NC
2595 {
2596 as_bad ("Unknown opcode `%s'.", insn->name);
2597 insn->parallel = 0;
2598 insn->in_use = 0;
2599 return;
2600 }
2601
026df7c5 2602 inst = insn->inst;
9c87d6c7 2603 first_inst = NULL;
026df7c5 2604 do
9c87d6c7 2605 {
be33c5dd 2606 ok = tic4x_operands_match (inst, insn, 1);
9c87d6c7
SS
2607 if (ok < 0)
2608 {
2609 if (!first_inst)
2610 first_inst = inst;
2611 ok = 0;
2612 }
2613 } while (!ok && !strcmp (inst->name, inst[1].name) && inst++);
026df7c5
NC
2614
2615 if (ok > 0)
9c87d6c7 2616 {
be33c5dd
SS
2617 tic4x_insn_check (insn);
2618 tic4x_insn_output (insn);
9c87d6c7 2619 }
026df7c5 2620 else if (!ok)
9c87d6c7
SS
2621 {
2622 if (first_inst)
be33c5dd 2623 tic4x_operands_match (first_inst, insn, 0);
9c87d6c7
SS
2624 as_bad ("Invalid operands for %s", insn->name);
2625 }
026df7c5
NC
2626 else
2627 as_bad ("Invalid instruction %s", insn->name);
2628 }
2629
2630 if (str && !parsed)
2631 {
2632 /* Find mnemonic. */
2633 s = str;
2634 while (*s && *s != ' ') /* Skip past instruction mnemonic. */
2635 s++;
2636 if (*s) /* Null terminate for hash_find. */
2637 *s++ = '\0'; /* and skip past null. */
be33c5dd 2638 strncpy (insn->name, str, TIC4X_NAME_MAX - 3);
026df7c5 2639
be33c5dd 2640 if ((i = tic4x_operands_parse (s, insn->operands, 0)) < 0)
026df7c5
NC
2641 {
2642 insn->inst = NULL; /* Flag that error occured. */
2643 insn->parallel = 0;
2644 insn->in_use = 0;
2645 return;
2646 }
2647 insn->num_operands = i;
2648 insn->in_use = 1;
2649 }
2650 else
2651 insn->in_use = 0;
2652 insn->parallel = 0;
2653}
2654
2655void
be33c5dd 2656tic4x_cleanup ()
026df7c5
NC
2657{
2658 if (insn->in_use)
2659 md_assemble (NULL);
2660}
2661
2662/* Turn a string in input_line_pointer into a floating point constant
2663 of type type, and store the appropriate bytes in *litP. The number
2664 of LITTLENUMS emitted is stored in *sizeP. An error message is
2665 returned, or NULL on OK. */
2666
2667char *
75d12d11
AM
2668md_atof (type, litP, sizeP)
2669 int type;
2670 char *litP;
2671 int *sizeP;
026df7c5
NC
2672{
2673 int prec;
2674 int ieee;
2675 LITTLENUM_TYPE words[MAX_LITTLENUMS];
2676 LITTLENUM_TYPE *wordP;
2132e3a3 2677 char *t;
026df7c5
NC
2678
2679 switch (type)
2680 {
2681 case 's': /* .single */
2682 case 'S':
2683 ieee = 0;
2684 prec = 1;
2685 break;
2686
2687 case 'd': /* .double */
2688 case 'D':
2689 case 'f': /* .float or .single */
2690 case 'F':
2691 ieee = 0;
2692 prec = 2; /* 1 32-bit word */
2693 break;
2694
2695 case 'i': /* .ieee */
247b1fe6 2696 case 'I':
026df7c5
NC
2697 prec = 2;
2698 ieee = 1;
247b1fe6 2699 type = 'f'; /* Rewrite type to be usable by atof_ieee() */
026df7c5
NC
2700 break;
2701
247b1fe6
SS
2702 case 'e': /* .ldouble */
2703 case 'E':
026df7c5 2704 prec = 4; /* 2 32-bit words */
247b1fe6 2705 ieee = 0;
026df7c5
NC
2706 break;
2707
2708 default:
2709 *sizeP = 0;
2710 return "Bad call to md_atof()";
2711 }
2712
2713 if (ieee)
2714 t = atof_ieee (input_line_pointer, type, words);
2715 else
be33c5dd 2716 t = tic4x_atof (input_line_pointer, type, words);
026df7c5
NC
2717 if (t)
2718 input_line_pointer = t;
2719 *sizeP = prec * sizeof (LITTLENUM_TYPE);
2132e3a3 2720
026df7c5
NC
2721 /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
2722 little endian byte order. */
247b1fe6
SS
2723 /* SES: However it is required to put the words (32-bits) out in the
2724 correct order, hence we write 2 and 2 littlenums in little endian
2725 order, while we keep the original order on successive words. */
2726 for(wordP = words; wordP<(words+prec) ; wordP+=2)
026df7c5 2727 {
247b1fe6
SS
2728 if (wordP<(words+prec-1)) /* Dump wordP[1] (if we have one) */
2729 {
2730 md_number_to_chars (litP, (valueT) (wordP[1]),
2731 sizeof (LITTLENUM_TYPE));
2732 litP += sizeof (LITTLENUM_TYPE);
2733 }
2734
2735 /* Dump wordP[0] */
2736 md_number_to_chars (litP, (valueT) (wordP[0]),
2737 sizeof (LITTLENUM_TYPE));
026df7c5
NC
2738 litP += sizeof (LITTLENUM_TYPE);
2739 }
2740 return 0;
2741}
2742
2743void
55cf6793 2744md_apply_fix (fixP, value, seg)
75d12d11
AM
2745 fixS *fixP;
2746 valueT *value;
2747 segT seg ATTRIBUTE_UNUSED;
026df7c5
NC
2748{
2749 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
2750 valueT val = *value;
2751
2752 switch (fixP->fx_r_type)
2753 {
2754 case BFD_RELOC_HI16:
2755 val >>= 16;
2756 break;
2757
2758 case BFD_RELOC_LO16:
2759 val &= 0xffff;
2760 break;
2761 default:
2762 break;
2763 }
2764
2765 switch (fixP->fx_r_type)
2766 {
2767 case BFD_RELOC_32:
2768 buf[3] = val >> 24;
2769 case BFD_RELOC_24:
2770 case BFD_RELOC_24_PCREL:
2771 buf[2] = val >> 16;
2772 case BFD_RELOC_16:
2773 case BFD_RELOC_16_PCREL:
2774 case BFD_RELOC_LO16:
2775 case BFD_RELOC_HI16:
2776 buf[1] = val >> 8;
2777 buf[0] = val;
2778 break;
2779
2780 case NO_RELOC:
2781 default:
2782 as_bad ("Bad relocation type: 0x%02x", fixP->fx_r_type);
2783 break;
2784 }
2785
2786 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1;
2787}
2788
be33c5dd 2789/* Should never be called for tic4x. */
026df7c5 2790void
75d12d11
AM
2791md_convert_frag (headers, sec, fragP)
2792 bfd *headers ATTRIBUTE_UNUSED;
2793 segT sec ATTRIBUTE_UNUSED;
2794 fragS *fragP ATTRIBUTE_UNUSED;
026df7c5
NC
2795{
2796 as_fatal ("md_convert_frag");
2797}
2798
be33c5dd 2799/* Should never be called for tic4x. */
026df7c5 2800void
75d12d11
AM
2801md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
2802 char *ptr ATTRIBUTE_UNUSED;
2803 addressT from_addr ATTRIBUTE_UNUSED;
2804 addressT to_addr ATTRIBUTE_UNUSED;
2805 fragS *frag ATTRIBUTE_UNUSED;
2806 symbolS *to_symbol ATTRIBUTE_UNUSED;
026df7c5
NC
2807{
2808 as_fatal ("md_create_short_jmp\n");
2809}
2810
be33c5dd 2811/* Should never be called for tic4x. */
026df7c5 2812void
75d12d11
AM
2813md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
2814 char *ptr ATTRIBUTE_UNUSED;
2815 addressT from_addr ATTRIBUTE_UNUSED;
2816 addressT to_addr ATTRIBUTE_UNUSED;
2817 fragS *frag ATTRIBUTE_UNUSED;
2818 symbolS *to_symbol ATTRIBUTE_UNUSED;
026df7c5
NC
2819{
2820 as_fatal ("md_create_long_jump\n");
2821}
2822
be33c5dd 2823/* Should never be called for tic4x. */
026df7c5 2824int
75d12d11
AM
2825md_estimate_size_before_relax (fragP, segtype)
2826 register fragS *fragP ATTRIBUTE_UNUSED;
2827 segT segtype ATTRIBUTE_UNUSED;
026df7c5
NC
2828{
2829 as_fatal ("md_estimate_size_before_relax\n");
2830 return 0;
2831}
2832
026df7c5
NC
2833
2834int
75d12d11
AM
2835md_parse_option (c, arg)
2836 int c;
2837 char *arg;
026df7c5
NC
2838{
2839 switch (c)
2840 {
9c87d6c7 2841 case OPTION_CPU: /* cpu brand */
278ed128 2842 if (TOLOWER (*arg) == 'c')
026df7c5 2843 arg++;
be33c5dd
SS
2844 tic4x_cpu = atoi (arg);
2845 if (!IS_CPU_TIC3X (tic4x_cpu) && !IS_CPU_TIC4X (tic4x_cpu))
2846 as_warn ("Unsupported processor generation %d", tic4x_cpu);
026df7c5 2847 break;
9c87d6c7
SS
2848
2849 case OPTION_REV: /* cpu revision */
be33c5dd 2850 tic4x_revision = atoi (arg);
9c87d6c7
SS
2851 break;
2852
2853 case 'b':
2854 as_warn ("Option -b is depreciated, please use -mbig");
2855 case OPTION_BIG: /* big model */
be33c5dd 2856 tic4x_big_model = 1;
9c87d6c7
SS
2857 break;
2858
2859 case 'p':
2860 as_warn ("Option -p is depreciated, please use -mmemparm");
2861 case OPTION_MEMPARM: /* push args */
be33c5dd 2862 tic4x_reg_args = 0;
026df7c5 2863 break;
9c87d6c7
SS
2864
2865 case 'r':
2866 as_warn ("Option -r is depreciated, please use -mregparm");
2867 case OPTION_REGPARM: /* register args */
be33c5dd 2868 tic4x_reg_args = 1;
026df7c5 2869 break;
9c87d6c7
SS
2870
2871 case 's':
2872 as_warn ("Option -s is depreciated, please use -msmall");
2873 case OPTION_SMALL: /* small model */
be33c5dd 2874 tic4x_big_model = 0;
026df7c5 2875 break;
9c87d6c7
SS
2876
2877 case OPTION_IDLE2:
be33c5dd 2878 tic4x_idle2 = 1;
9c87d6c7
SS
2879 break;
2880
2881 case OPTION_LOWPOWER:
be33c5dd 2882 tic4x_lowpower = 1;
9c87d6c7
SS
2883 break;
2884
2885 case OPTION_ENHANCED:
be33c5dd 2886 tic4x_enhanced = 1;
9c87d6c7
SS
2887 break;
2888
026df7c5
NC
2889 default:
2890 return 0;
2891 }
2892
2893 return 1;
2894}
2895
2896void
75d12d11
AM
2897md_show_usage (stream)
2898 FILE *stream;
026df7c5 2899{
9c87d6c7
SS
2900 fprintf (stream,
2901 _("\nTIC4X options:\n"
2902 " -mcpu=CPU -mCPU select architecture variant. CPU can be:\n"
2903 " 30 - TMS320C30\n"
2904 " 31 - TMS320C31, TMS320LC31\n"
2905 " 32 - TMS320C32\n"
2906 " 33 - TMS320VC33\n"
2907 " 40 - TMS320C40\n"
2908 " 44 - TMS320C44\n"
2909 " -mrev=REV set cpu hardware revision (integer numbers).\n"
2910 " Combinations of -mcpu and -mrev will enable/disable\n"
2911 " the appropriate options (-midle2, -mlowpower and\n"
2912 " -menhanced) according to the selected type\n"
2913 " -mbig select big memory model\n"
2914 " -msmall select small memory model (default)\n"
2915 " -mregparm select register parameters (default)\n"
2916 " -mmemparm select memory parameters\n"
2917 " -midle2 enable IDLE2 support\n"
2918 " -mlowpower enable LOPOWER and MAXSPEED support\n"
2919 " -menhanced enable enhanced opcode support\n"));
026df7c5
NC
2920}
2921
2922/* This is called when a line is unrecognized. This is used to handle
2923 definitions of TI C3x tools style local labels $n where n is a single
2924 decimal digit. */
2925int
be33c5dd 2926tic4x_unrecognized_line (c)
75d12d11 2927 int c;
026df7c5
NC
2928{
2929 int lab;
2930 char *s;
2931
278ed128 2932 if (c != '$' || ! ISDIGIT (input_line_pointer[0]))
026df7c5
NC
2933 return 0;
2934
2935 s = input_line_pointer;
2936
2937 /* Let's allow multiple digit local labels. */
2938 lab = 0;
278ed128 2939 while (ISDIGIT (*s))
026df7c5
NC
2940 {
2941 lab = lab * 10 + *s - '0';
2942 s++;
2943 }
2944
2945 if (dollar_label_defined (lab))
2946 {
2947 as_bad ("Label \"$%d\" redefined", lab);
2948 return 0;
2949 }
2950
2951 define_dollar_label (lab);
2952 colon (dollar_label_name (lab, 0));
2953 input_line_pointer = s + 1;
2954
2955 return 1;
2956}
2957
2958/* Handle local labels peculiar to us referred to in an expression. */
2959symbolS *
75d12d11
AM
2960md_undefined_symbol (name)
2961 char *name;
026df7c5
NC
2962{
2963 /* Look for local labels of the form $n. */
278ed128 2964 if (name[0] == '$' && ISDIGIT (name[1]))
026df7c5
NC
2965 {
2966 symbolS *symbolP;
2967 char *s = name + 1;
2968 int lab = 0;
2969
278ed128 2970 while (ISDIGIT ((unsigned char) *s))
026df7c5
NC
2971 {
2972 lab = lab * 10 + *s - '0';
2973 s++;
2974 }
2975 if (dollar_label_defined (lab))
2976 {
2977 name = dollar_label_name (lab, 0);
2978 symbolP = symbol_find (name);
2979 }
2980 else
2981 {
2982 name = dollar_label_name (lab, 1);
2983 symbolP = symbol_find_or_make (name);
2984 }
2985
2986 return symbolP;
2987 }
2988 return NULL;
2989}
2990
2991/* Parse an operand that is machine-specific. */
2992void
75d12d11
AM
2993md_operand (expressionP)
2994 expressionS *expressionP ATTRIBUTE_UNUSED;
026df7c5
NC
2995{
2996}
2997
2998/* Round up a section size to the appropriate boundary---do we need this? */
2999valueT
75d12d11
AM
3000md_section_align (segment, size)
3001 segT segment ATTRIBUTE_UNUSED;
3002 valueT size;
026df7c5
NC
3003{
3004 return size; /* Byte (i.e., 32-bit) alignment is fine? */
3005}
3006
3007static int
be33c5dd 3008tic4x_pc_offset (op)
75d12d11 3009 unsigned int op;
026df7c5
NC
3010{
3011 /* Determine the PC offset for a C[34]x instruction.
3012 This could be simplified using some boolean algebra
3013 but at the expense of readability. */
3014 switch (op >> 24)
3015 {
3016 case 0x60: /* br */
3017 case 0x62: /* call (C4x) */
3018 case 0x64: /* rptb (C4x) */
3019 return 1;
3020 case 0x61: /* brd */
3021 case 0x63: /* laj */
3022 case 0x65: /* rptbd (C4x) */
3023 return 3;
3024 case 0x66: /* swi */
3025 case 0x67:
3026 return 0;
3027 default:
3028 break;
3029 }
3030
3031 switch ((op & 0xffe00000) >> 20)
3032 {
3033 case 0x6a0: /* bB */
3034 case 0x720: /* callB */
3035 case 0x740: /* trapB */
3036 return 1;
3037
3038 case 0x6a2: /* bBd */
3039 case 0x6a6: /* bBat */
3040 case 0x6aa: /* bBaf */
3041 case 0x722: /* lajB */
3042 case 0x748: /* latB */
3043 case 0x798: /* rptbd */
3044 return 3;
3045
3046 default:
3047 break;
3048 }
3049
3050 switch ((op & 0xfe200000) >> 20)
3051 {
3052 case 0x6e0: /* dbB */
3053 return 1;
3054
3055 case 0x6e2: /* dbBd */
3056 return 3;
3057
3058 default:
3059 break;
3060 }
3061
3062 return 0;
3063}
3064
3065/* Exactly what point is a PC-relative offset relative TO?
3066 With the C3x we have the following:
3067 DBcond, Bcond disp + PC + 1 => PC
3068 DBcondD, BcondD disp + PC + 3 => PC
3069 */
3070long
75d12d11
AM
3071md_pcrel_from (fixP)
3072 fixS *fixP;
026df7c5 3073{
2132e3a3 3074 unsigned char *buf;
026df7c5
NC
3075 unsigned int op;
3076
2132e3a3 3077 buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
026df7c5
NC
3078 op = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
3079
3080 return ((fixP->fx_where + fixP->fx_frag->fr_address) >> 2) +
be33c5dd 3081 tic4x_pc_offset (op);
026df7c5
NC
3082}
3083
247b1fe6
SS
3084/* Fill the alignment area with NOP's on .text, unless fill-data
3085 was specified. */
026df7c5 3086int
be33c5dd 3087tic4x_do_align (alignment, fill, len, max)
75d12d11
AM
3088 int alignment ATTRIBUTE_UNUSED;
3089 const char *fill ATTRIBUTE_UNUSED;
3090 int len ATTRIBUTE_UNUSED;
3091 int max ATTRIBUTE_UNUSED;
026df7c5 3092{
f17c130b 3093 unsigned long nop = TIC_NOP_OPCODE;
026df7c5 3094
33b7f697 3095 /* Because we are talking lwords, not bytes, adjust alignment to do words */
247b1fe6
SS
3096 alignment += 2;
3097
3098 if (alignment != 0 && !need_pass_2)
3099 {
3100 if (fill == NULL)
3101 {
33b7f697 3102 /*if (subseg_text_p (now_seg))*/ /* FIXME: doesn't work for .text for some reason */
247b1fe6
SS
3103 frag_align_pattern( alignment, (const char *)&nop, sizeof(nop), max);
3104 return 1;
3105 /*else
3106 frag_align (alignment, 0, max);*/
3107 }
3108 else if (len <= 1)
3109 frag_align (alignment, *fill, max);
3110 else
3111 frag_align_pattern (alignment, fill, len, max);
3112 }
3113
33b7f697 3114 /* Return 1 to skip the default alignment function */
026df7c5
NC
3115 return 1;
3116}
3117
3118/* Look for and remove parallel instruction operator ||. */
3119void
be33c5dd 3120tic4x_start_line ()
026df7c5
NC
3121{
3122 char *s = input_line_pointer;
3123
3124 SKIP_WHITESPACE ();
3125
3126 /* If parallel instruction prefix found at start of line, skip it. */
3127 if (*input_line_pointer == '|' && input_line_pointer[1] == '|')
3128 {
3129 if (insn->in_use)
3130 {
3131 insn->parallel = 1;
a1f3c24c
SS
3132 input_line_pointer ++;
3133 *input_line_pointer = ' ';
026df7c5
NC
3134 /* So line counters get bumped. */
3135 input_line_pointer[-1] = '\n';
3136 }
3137 }
3138 else
3139 {
a1f3c24c 3140 /* Write out the previous insn here */
026df7c5
NC
3141 if (insn->in_use)
3142 md_assemble (NULL);
3143 input_line_pointer = s;
3144 }
3145}
3146
3147arelent *
75d12d11
AM
3148tc_gen_reloc (seg, fixP)
3149 asection *seg ATTRIBUTE_UNUSED;
3150 fixS *fixP;
026df7c5
NC
3151{
3152 arelent *reloc;
3153
3154 reloc = (arelent *) xmalloc (sizeof (arelent));
3155
3156 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
3157 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
3158 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
3159 reloc->address /= OCTETS_PER_BYTE;
3160 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
3161 if (reloc->howto == (reloc_howto_type *) NULL)
3162 {
3163 as_bad_where (fixP->fx_file, fixP->fx_line,
9c87d6c7 3164 "Reloc %d not supported by object file format",
026df7c5
NC
3165 (int) fixP->fx_r_type);
3166 return NULL;
3167 }
3168
3169 if (fixP->fx_r_type == BFD_RELOC_HI16)
3170 reloc->addend = fixP->fx_offset;
3171 else
3172 reloc->addend = fixP->fx_addnumber;
3173
3174 return reloc;
3175}
This page took 0.302388 seconds and 4 git commands to generate.