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