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