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