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