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