1 /* tc-c4x.c -- Assemble for the Texas Instruments TMS320C[34]x.
2 Copyright (C) 1997,1998, 2002 Free Software Foundation.
4 Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
6 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
24 /* Things not currently implemented:
25 > .usect if has symbol on previous line
27 > .sym, .eos, .stag, .etag, .member
29 > Evaluation of constant floating point expressions (expr.c needs work!)
31 > Warnings issued if parallel load of same register
33 Note that this is primarily designed to handle the code generated
34 by GCC. Anything else is a bonus! */
40 #include "opcode/tic4x.h"
46 /* OK, we accept a syntax similar to the other well known C30
47 assembly tools. With C4X_ALT_SYNTAX defined we are more
48 flexible, allowing a more Unix-like syntax: `%' in front of
49 register names, `#' in front of immediate constants, and
50 not requiring `@' in front of direct addresses. */
52 #define C4X_ALT_SYNTAX
54 /* Equal to MAX_PRECISION in atof-ieee.c. */
55 #define MAX_LITTLENUMS 6 /* (12 bytes) */
57 /* Handle of the inst mnemonic hash table. */
58 static struct hash_control
*c4x_op_hash
= NULL
;
60 /* Handle asg pseudo. */
61 static struct hash_control
*c4x_asg_hash
= NULL
;
63 static unsigned int c4x_cpu
= 0; /* Default to TMS320C40. */
64 static unsigned int c4x_big_model
= 0; /* Default to small memory model. */
65 static unsigned int c4x_reg_args
= 0; /* Default to args passed on stack. */
69 M_UNKNOWN
, M_IMMED
, M_DIRECT
, M_REGISTER
, M_INDIRECT
,
70 M_IMMED_F
, M_PARALLEL
, M_HI
74 typedef struct c4x_operand
76 c4x_addr_mode_t mode
; /* Addressing mode. */
77 expressionS expr
; /* Expression. */
78 int disp
; /* Displacement for indirect addressing. */
79 int aregno
; /* Aux. register number. */
80 LITTLENUM_TYPE fwords
[MAX_LITTLENUMS
]; /* Float immed. number. */
84 typedef struct c4x_insn
86 char name
[C4X_NAME_MAX
]; /* Mnemonic of instruction. */
87 unsigned int in_use
; /* True if in_use. */
88 unsigned int parallel
; /* True if parallel instruction. */
89 unsigned int nchars
; /* This is always 4 for the C30. */
90 unsigned long opcode
; /* Opcode number. */
91 expressionS exp
; /* Expression required for relocation. */
92 int reloc
; /* Relocation type required. */
93 int pcrel
; /* True if relocation PC relative. */
94 char *pname
; /* Name of instruction in parallel. */
95 unsigned int num_operands
; /* Number of operands in total. */
96 c4x_inst_t
*inst
; /* Pointer to first template. */
97 c4x_operand_t operands
[C4X_OPERANDS_MAX
];
101 static c4x_insn_t the_insn
; /* Info about our instruction. */
102 static c4x_insn_t
*insn
= &the_insn
;
105 PARAMS ((FLONUM_TYPE
, LITTLENUM_TYPE
*, int ));
107 PARAMS ((char *, char, LITTLENUM_TYPE
* ));
108 static void c4x_insert_reg
109 PARAMS ((char *, int ));
110 static void c4x_insert_sym
111 PARAMS ((char *, int ));
112 static char *c4x_expression
113 PARAMS ((char *, expressionS
*));
114 static char *c4x_expression_abs
115 PARAMS ((char *, int *));
116 static void c4x_emit_char
118 static void c4x_seg_alloc
119 PARAMS ((char *, segT
, int, symbolS
*));
130 static void c4x_newblock
136 static void c4x_usect
138 static void c4x_version
140 static void c4x_pseudo_ignore
142 static void c4x_init_regtable
144 static void c4x_init_symbols
146 static int c4x_inst_insert
147 PARAMS ((c4x_inst_t
*));
148 static c4x_inst_t
*c4x_inst_make
149 PARAMS ((char *, unsigned long, char *));
150 static int c4x_inst_add
151 PARAMS ((c4x_inst_t
*));
156 static int c4x_indirect_parse
157 PARAMS ((c4x_operand_t
*, const c4x_indirect_t
*));
158 char *c4x_operand_parse
159 PARAMS ((char *, c4x_operand_t
*));
160 static int c4x_operands_match
161 PARAMS ((c4x_inst_t
*, c4x_insn_t
*));
163 PARAMS ((c4x_insn_t
*));
164 int c4x_operands_parse
165 PARAMS ((char *, c4x_operand_t
*, int ));
171 PARAMS ((int, char *, int *));
173 PARAMS ((fixS
*, valueT
*, segT
));
175 PARAMS ((bfd
*, segT
, fragS
*));
176 void md_create_short_jump
177 PARAMS ((char *, addressT
, addressT
, fragS
*, symbolS
*));
178 void md_create_long_jump
179 PARAMS ((char *, addressT
, addressT
, fragS
*, symbolS
*));
180 int md_estimate_size_before_relax
181 PARAMS ((register fragS
*, segT
));
183 PARAMS ((int, char *));
186 int c4x_unrecognized_line
188 symbolS
*md_undefined_symbol
191 PARAMS ((expressionS
*));
192 valueT md_section_align
193 PARAMS ((segT
, valueT
));
194 static int c4x_pc_offset
195 PARAMS ((unsigned int));
199 PARAMS ((int, const char *, int, int));
202 arelent
*tc_gen_reloc
203 PARAMS ((asection
*, fixS
*));
209 {"align", s_align_bytes
, 32},
210 {"ascii", c4x_cons
, 1},
211 {"asciz", c4x_pseudo_ignore
, 0},
213 {"asect", c4x_pseudo_ignore
, 0}, /* Absolute named section. */
214 {"block", s_space
, 0},
215 {"byte", c4x_cons
, 1},
217 {"comm", c4x_bss
, 0},
218 {"def", c4x_globl
, 0},
219 {"endfunc", c4x_pseudo_ignore
, 0},
220 {"eos", c4x_pseudo_ignore
, 0},
221 {"etag", c4x_pseudo_ignore
, 0},
223 {"eval", c4x_eval
, 0},
224 {"exitm", s_mexit
, 0},
225 {"func", c4x_pseudo_ignore
, 0},
226 {"global", c4x_globl
, 0},
227 {"globl", c4x_globl
, 0},
228 {"hword", c4x_cons
, 2},
229 {"ieee", float_cons
, 'i'},
230 {"int", c4x_cons
, 4}, /* .int allocates 4 bytes. */
231 {"length", c4x_pseudo_ignore
, 0},
232 {"ldouble", float_cons
, 'l'},
233 {"member", c4x_pseudo_ignore
, 0},
234 {"newblock", c4x_newblock
, 0},
235 {"ref", s_ignore
, 0}, /* All undefined treated as external. */
237 {"sect", c4x_sect
, 1}, /* Define named section. */
238 {"space", s_space
, 4},
239 {"stag", c4x_pseudo_ignore
, 0},
240 {"string", c4x_pseudo_ignore
, 0},
241 {"sym", c4x_pseudo_ignore
, 0},
242 {"usect", c4x_usect
, 0}, /* Reserve space in uninit. named sect. */
243 {"version", c4x_version
, 0},
244 {"width", c4x_pseudo_ignore
, 0},
245 {"word", c4x_cons
, 4}, /* .word allocates 4 bytes. */
246 {"xdef", c4x_globl
, 0},
250 int md_short_jump_size
= 4;
251 int md_long_jump_size
= 4;
252 const int md_reloc_size
= RELSZ
; /* Coff headers. */
254 /* This array holds the chars that always start a comment. If the
255 pre-processor is disabled, these aren't very useful. */
256 #ifdef C4X_ALT_SYNTAX
257 const char comment_chars
[] = ";!";
259 const char comment_chars
[] = ";";
262 /* This array holds the chars that only start a comment at the beginning of
263 a line. If the line seems to have the form '# 123 filename'
264 .line and .file directives will appear in the pre-processed output.
265 Note that input_file.c hand checks for '#' at the beginning of the
266 first line of the input file. This is because the compiler outputs
267 #NO_APP at the beginning of its output.
268 Also note that comments like this one will always work. */
269 const char line_comment_chars
[] = "#*";
271 /* We needed an unused char for line separation to work around the
272 lack of macros, using sed and such. */
273 const char line_separator_chars
[] = "&";
275 /* Chars that can be used to separate mant from exp in floating point nums. */
276 const char EXP_CHARS
[] = "eE";
278 /* Chars that mean this number is a floating point constant. */
281 const char FLT_CHARS
[] = "fFilsS";
283 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
284 changed in read.c. Ideally it shouldn't have to know about it at
285 all, but nothing is ideal around here. */
287 /* Flonums returned here. */
288 extern FLONUM_TYPE generic_floating_point_number
;
290 /* Precision in LittleNums. */
291 #define MAX_PRECISION (2)
292 #define S_PRECISION (1) /* Short float constants 16-bit. */
293 #define F_PRECISION (2) /* Float and double types 32-bit. */
297 /* Turn generic_floating_point_number into a real short/float/double. */
299 c4x_gen_to_words (flonum
, words
, precision
)
301 LITTLENUM_TYPE
*words
;
304 int return_value
= 0;
305 LITTLENUM_TYPE
*p
; /* Littlenum pointer. */
306 int mantissa_bits
; /* Bits in mantissa field. */
307 int exponent_bits
; /* Bits in exponent field. */
309 unsigned int sone
; /* Scaled one. */
310 unsigned int sfract
; /* Scaled fraction. */
311 unsigned int smant
; /* Scaled mantissa. */
313 int shift
; /* Shift count. */
315 /* Here is how a generic floating point number is stored using
316 flonums (an extension of bignums) where p is a pointer to an
319 For example 2e-3 is stored with exp = -4 and
326 with low = &bits[2], high = &bits[5], and leader = &bits[5].
328 This number can be written as
329 0x0083126e978d4fde.00000000 * 65536**-4 or
330 0x0.0083126e978d4fde * 65536**0 or
331 0x0.83126e978d4fde * 2**-8 = 2e-3
333 Note that low points to the 65536**0 littlenum (bits[2]) and
334 leader points to the most significant non-zero littlenum
337 TMS320C3X floating point numbers are a bit of a strange beast.
338 The 32-bit flavour has the 8 MSBs representing the exponent in
339 twos complement format (-128 to +127). There is then a sign bit
340 followed by 23 bits of mantissa. The mantissa is expressed in
341 twos complement format with the binary point after the most
342 significant non sign bit. The bit after the binary point is
343 suppressed since it is the complement of the sign bit. The
344 effective mantissa is thus 24 bits. Zero is represented by an
347 The 16-bit flavour has the 4 MSBs representing the exponent in
348 twos complement format (-8 to +7). There is then a sign bit
349 followed by 11 bits of mantissa. The mantissa is expressed in
350 twos complement format with the binary point after the most
351 significant non sign bit. The bit after the binary point is
352 suppressed since it is the complement of the sign bit. The
353 effective mantissa is thus 12 bits. Zero is represented by an
354 exponent of -8. For example,
356 number norm mant m x e s i fraction f
357 +0.500 => 1.00000000000 -1 -1 0 1 .00000000000 (1 + 0) * 2^(-1)
358 +0.999 => 1.11111111111 -1 -1 0 1 .11111111111 (1 + 0.99) * 2^(-1)
359 +1.000 => 1.00000000000 0 0 0 1 .00000000000 (1 + 0) * 2^(0)
360 +1.500 => 1.10000000000 0 0 0 1 .10000000000 (1 + 0.5) * 2^(0)
361 +1.999 => 1.11111111111 0 0 0 1 .11111111111 (1 + 0.9) * 2^(0)
362 +2.000 => 1.00000000000 1 1 0 1 .00000000000 (1 + 0) * 2^(1)
363 +4.000 => 1.00000000000 2 2 0 1 .00000000000 (1 + 0) * 2^(2)
364 -0.500 => 1.00000000000 -1 -1 1 0 .10000000000 (-2 + 0) * 2^(-2)
365 -1.000 => 1.00000000000 0 -1 1 0 .00000000000 (-2 + 0) * 2^(-1)
366 -1.500 => 1.10000000000 0 0 1 0 .10000000000 (-2 + 0.5) * 2^(0)
367 -1.999 => 1.11111111111 0 0 1 0 .00000000001 (-2 + 0.11) * 2^(0)
368 -2.000 => 1.00000000000 1 1 1 0 .00000000000 (-2 + 0) * 2^(0)
369 -4.000 => 1.00000000000 2 1 1 0 .00000000000 (-2 + 0) * 2^(1)
371 where e is the exponent, s is the sign bit, i is the implied bit,
372 and f is the fraction stored in the mantissa field.
374 num = (1 + f) * 2^x = m * 2^e if s = 0
375 num = (-2 + f) * 2^x = -m * 2^e if s = 1
376 where 0 <= f < 1.0 and 1.0 <= m < 2.0
378 The fraction (f) and exponent (e) fields for the TMS320C3X format
379 can be derived from the normalised mantissa (m) and exponent (x) using:
381 f = m - 1, e = x if s = 0
382 f = 2 - m, e = x if s = 1 and m != 1.0
383 f = 0, e = x - 1 if s = 1 and m = 1.0
384 f = 0, e = -8 if m = 0
387 OK, the other issue we have to consider is rounding since the
388 mantissa has a much higher potential precision than what we can
389 represent. To do this we add half the smallest storable fraction.
390 We then have to renormalise the number to allow for overflow.
392 To convert a generic flonum into a TMS320C3X floating point
393 number, here's what we try to do....
395 The first thing is to generate a normalised mantissa (m) where
396 1.0 <= m < 2 and to convert the exponent from base 16 to base 2.
397 We desire the binary point to be placed after the most significant
398 non zero bit. This process is done in two steps: firstly, the
399 littlenum with the most significant non zero bit is located (this
400 is done for us since leader points to this littlenum) and the
401 binary point (which is currently after the LSB of the littlenum
402 pointed to by low) is moved to before the MSB of the littlenum
403 pointed to by leader. This requires the exponent to be adjusted
404 by leader - low + 1. In the earlier example, the new exponent is
405 thus -4 + (5 - 2 + 1) = 0 (base 65536). We now need to convert
406 the exponent to base 2 by multiplying the exponent by 16 (log2
407 65536). The exponent base 2 is thus also zero.
409 The second step is to hunt for the most significant non zero bit
410 in the leader littlenum. We do this by left shifting a copy of
411 the leader littlenum until bit 16 is set (0x10000) and counting
412 the number of shifts, S, required. The number of shifts then has to
413 be added to correct the exponent (base 2). For our example, this
414 will require 9 shifts and thus our normalised exponent (base 2) is
415 0 + 9 = 9. Note that the worst case scenario is when the leader
416 littlenum is 1, thus requiring 16 shifts.
418 We now have to left shift the other littlenums by the same amount,
419 propagating the shifted bits into the more significant littlenums.
420 To save a lot of unecessary shifting we only have to consider
421 two or three littlenums, since the greatest number of mantissa
422 bits required is 24 + 1 rounding bit. While two littlenums
423 provide 32 bits of precision, the most significant littlenum
424 may only contain a single significant bit and thus an extra
425 littlenum is required.
427 Denoting the number of bits in the fraction field as F, we require
428 G = F + 2 bits (one extra bit is for rounding, the other gets
429 suppressed). Say we required S shifts to find the most
430 significant bit in the leader littlenum, the number of left shifts
431 required to move this bit into bit position G - 1 is L = G + S - 17.
432 Note that this shift count may be negative for the short floating
433 point flavour (where F = 11 and thus G = 13 and potentially S < 3).
434 If L > 0 we have to shunt the next littlenum into position. Bit
435 15 (the MSB) of the next littlenum needs to get moved into position
436 L - 1 (If L > 15 we need all the bits of this littlenum and
437 some more from the next one.). We subtract 16 from L and use this
438 as the left shift count; the resultant value we or with the
439 previous result. If L > 0, we repeat this operation. */
441 if (precision
!= S_PRECISION
)
445 if (flonum
.low
> flonum
.leader
)
451 /* NaN: We can't do much... */
452 if (flonum
.sign
== 0)
454 as_bad ("Nan, using zero.");
458 else if (flonum
.sign
== 'P')
460 /* +INF: Replace with maximum float. */
461 if (precision
== S_PRECISION
)
470 else if (flonum
.sign
== 'N')
472 /* -INF: Replace with maximum float. */
473 if (precision
== S_PRECISION
)
480 exponent
= (flonum
.exponent
+ flonum
.leader
- flonum
.low
+ 1) * 16;
482 if (!(tmp
= *flonum
.leader
))
483 abort (); /* Hmmm. */
484 shift
= 0; /* Find position of first sig. bit. */
487 exponent
-= (16 - shift
); /* Adjust exponent. */
489 if (precision
== S_PRECISION
) /* Allow 1 rounding bit. */
492 mantissa_bits
= 12; /* Include suppr. bit but not rounding bit. */
500 shift
= mantissa_bits
- shift
;
503 for (p
= flonum
.leader
; p
>= flonum
.low
&& shift
> -16; p
--)
505 tmp
= shift
>= 0 ? *p
<< shift
: *p
>> -shift
;
510 /* OK, we've got our scaled mantissa so let's round it up
511 and drop the rounding bit. */
515 /* The number may be unnormalised so renormalise it... */
516 if (smant
>> mantissa_bits
)
522 /* The binary point is now between bit positions 11 and 10 or 23 and 22,
523 i.e., between mantissa_bits - 1 and mantissa_bits - 2 and the
524 bit at mantissa_bits - 1 should be set. */
525 if (!(smant
>> (mantissa_bits
- 1)))
526 abort (); /* Ooops. */
528 sone
= (1 << (mantissa_bits
- 1));
529 if (flonum
.sign
== '+')
530 sfract
= smant
- sone
; /* smant - 1.0. */
533 /* This seems to work. */
540 sfract
= (sone
<< 1) - smant
; /* 2.0 - smant. */
541 sfract
|= sone
; /* Insert sign bit. */
544 if (abs (exponent
) >= (1 << (exponent_bits
- 1)))
545 as_bad ("Cannot represent exponent in %d bits", exponent_bits
);
547 /* Force exponent to fit in desired field width. */
548 exponent
&= (1 << (exponent_bits
)) - 1;
549 sfract
|= exponent
<< mantissa_bits
;
551 if (precision
== S_PRECISION
)
555 words
[0] = sfract
>> 16;
556 words
[1] = sfract
& 0xffff;
562 /* Returns pointer past text consumed. */
564 c4x_atof (str
, what_kind
, words
)
567 LITTLENUM_TYPE
*words
;
569 /* Extra bits for zeroed low-order bits. The 1st MAX_PRECISION are
570 zeroed, the last contain flonum bits. */
571 static LITTLENUM_TYPE bits
[MAX_PRECISION
+ MAX_PRECISION
+ GUARD
];
573 /* Number of 16-bit words in the format. */
575 FLONUM_TYPE save_gen_flonum
;
577 /* We have to save the generic_floating_point_number because it
578 contains storage allocation about the array of LITTLENUMs where
579 the value is actually stored. We will allocate our own array of
580 littlenums below, but have to restore the global one on exit. */
581 save_gen_flonum
= generic_floating_point_number
;
584 generic_floating_point_number
.low
= bits
+ MAX_PRECISION
;
585 generic_floating_point_number
.high
= NULL
;
586 generic_floating_point_number
.leader
= NULL
;
587 generic_floating_point_number
.exponent
= 0;
588 generic_floating_point_number
.sign
= '\0';
590 /* Use more LittleNums than seems necessary: the highest flonum may
591 have 15 leading 0 bits, so could be useless. */
593 memset (bits
, '\0', sizeof (LITTLENUM_TYPE
) * MAX_PRECISION
);
599 precision
= S_PRECISION
;
606 precision
= F_PRECISION
;
610 as_bad ("Invalid floating point number");
614 generic_floating_point_number
.high
615 = generic_floating_point_number
.low
+ precision
- 1 + GUARD
;
617 if (atof_generic (&return_value
, ".", EXP_CHARS
,
618 &generic_floating_point_number
))
620 as_bad ("Invalid floating point number");
624 c4x_gen_to_words (generic_floating_point_number
,
627 /* Restore the generic_floating_point_number's storage alloc (and
629 generic_floating_point_number
= save_gen_flonum
;
635 c4x_insert_reg (regname
, regnum
)
642 symbol_table_insert (symbol_new (regname
, reg_section
, (valueT
) regnum
,
643 &zero_address_frag
));
644 for (i
= 0; regname
[i
]; i
++)
645 buf
[i
] = islower (regname
[i
]) ? toupper (regname
[i
]) : regname
[i
];
648 symbol_table_insert (symbol_new (buf
, reg_section
, (valueT
) regnum
,
649 &zero_address_frag
));
653 c4x_insert_sym (symname
, value
)
659 symbolP
= symbol_new (symname
, absolute_section
,
660 (valueT
) value
, &zero_address_frag
);
661 SF_SET_LOCAL (symbolP
);
662 symbol_table_insert (symbolP
);
666 c4x_expression (str
, exp
)
673 t
= input_line_pointer
; /* Save line pointer. */
674 input_line_pointer
= str
;
676 s
= input_line_pointer
;
677 input_line_pointer
= t
; /* Restore line pointer. */
678 return s
; /* Return pointer to where parsing stopped. */
682 c4x_expression_abs (str
, value
)
689 t
= input_line_pointer
; /* Save line pointer. */
690 input_line_pointer
= str
;
691 *value
= get_absolute_expression ();
692 s
= input_line_pointer
;
693 input_line_pointer
= t
; /* Restore line pointer. */
703 exp
.X_op
= O_constant
;
704 exp
.X_add_number
= c
;
709 c4x_seg_alloc (name
, seg
, size
, symbolP
)
710 char *name ATTRIBUTE_UNUSED
;
711 segT seg ATTRIBUTE_UNUSED
;
715 /* Note that the size is in words
716 so we multiply it by 4 to get the number of bytes to allocate. */
718 /* If we have symbol: .usect ".fred", size etc.,
719 the symbol needs to point to the first location reserved
726 p
= frag_var (rs_fill
, 1, 1, (relax_substateT
) 0,
728 size
* OCTETS_PER_BYTE
, (char *) 0);
733 /* .asg ["]character-string["], symbol */
736 int x ATTRIBUTE_UNUSED
;
744 str
= input_line_pointer
;
746 /* Skip string expression. */
747 while (*input_line_pointer
!= ',' && *input_line_pointer
)
748 input_line_pointer
++;
749 if (*input_line_pointer
!= ',')
751 as_bad ("Comma expected\n");
754 *input_line_pointer
++ = '\0';
755 name
= input_line_pointer
;
756 c
= get_symbol_end (); /* Get terminator. */
757 tmp
= xmalloc (strlen (str
) + 1);
760 tmp
= xmalloc (strlen (name
) + 1);
763 if (hash_find (c4x_asg_hash
, name
))
764 hash_replace (c4x_asg_hash
, name
, (PTR
) str
);
766 hash_insert (c4x_asg_hash
, name
, (PTR
) str
);
767 *input_line_pointer
= c
;
768 demand_empty_rest_of_line ();
771 /* .bss symbol, size */
774 int x ATTRIBUTE_UNUSED
;
781 subsegT current_subseg
;
784 current_seg
= now_seg
; /* Save current seg. */
785 current_subseg
= now_subseg
; /* Save current subseg. */
788 name
= input_line_pointer
;
789 c
= get_symbol_end (); /* Get terminator. */
792 as_bad (".bss size argument missing\n");
797 c4x_expression_abs (++input_line_pointer
, &size
);
800 as_bad (".bss size %d < 0!", size
);
803 subseg_set (bss_section
, 0);
804 symbolP
= symbol_find_or_make (name
);
806 if (S_GET_SEGMENT (symbolP
) == bss_section
)
807 symbol_get_frag (symbolP
)->fr_symbol
= 0;
809 symbol_set_frag (symbolP
, frag_now
);
811 p
= frag_var (rs_org
, 1, 1, (relax_substateT
) 0, symbolP
,
812 size
* OCTETS_PER_BYTE
, (char *) 0);
813 *p
= 0; /* Fill char. */
815 S_SET_SEGMENT (symbolP
, bss_section
);
817 /* The symbol may already have been created with a preceding
818 ".globl" directive -- be careful not to step on storage class
819 in that case. Otherwise, set it to static. */
820 if (S_GET_STORAGE_CLASS (symbolP
) != C_EXT
)
821 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
823 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
824 demand_empty_rest_of_line ();
829 int ignore ATTRIBUTE_UNUSED
;
837 name
= input_line_pointer
;
838 c
= get_symbol_end ();
839 symbolP
= symbol_find_or_make (name
);
840 *input_line_pointer
= c
;
842 S_SET_STORAGE_CLASS (symbolP
, C_EXT
);
845 input_line_pointer
++;
847 if (*input_line_pointer
== '\n')
853 demand_empty_rest_of_line ();
856 /* Handle .byte, .word. .int, .long */
861 register unsigned int c
;
865 if (*input_line_pointer
== '"')
867 input_line_pointer
++;
868 while (is_a_char (c
= next_char_of_string ()))
870 know (input_line_pointer
[-1] == '\"');
876 input_line_pointer
= c4x_expression (input_line_pointer
, &exp
);
877 if (exp
.X_op
== O_constant
)
882 exp
.X_add_number
&= 255;
885 exp
.X_add_number
&= 65535;
889 /* Perhaps we should disallow .byte and .hword with
890 a non constant expression that will require relocation. */
894 while (*input_line_pointer
++ == ',');
896 input_line_pointer
--; /* Put terminator back into stream. */
897 demand_empty_rest_of_line ();
900 /* .eval expression, symbol */
903 int x ATTRIBUTE_UNUSED
;
911 c4x_expression_abs (input_line_pointer
, &value
);
912 if (*input_line_pointer
++ != ',')
914 as_bad ("Symbol missing\n");
917 name
= input_line_pointer
;
918 c
= get_symbol_end (); /* Get terminator. */
919 demand_empty_rest_of_line ();
920 c4x_insert_sym (name
, value
);
923 /* Reset local labels. */
926 int x ATTRIBUTE_UNUSED
;
928 dollar_label_clear ();
931 /* .sect "section-name" [, value] */
932 /* .sect ["]section-name[:subsection-name]["] [, value] */
935 int x ATTRIBUTE_UNUSED
;
939 char *subsection_name
;
945 if (*input_line_pointer
== '"')
946 input_line_pointer
++;
947 section_name
= input_line_pointer
;
948 c
= get_symbol_end (); /* Get terminator. */
949 input_line_pointer
++; /* Skip null symbol terminator. */
950 name
= xmalloc (input_line_pointer
- section_name
+ 1);
951 strcpy (name
, section_name
);
953 /* TI C from version 5.0 allows a section name to contain a
954 subsection name as well. The subsection name is separated by a
955 ':' from the section name. Currently we scan the subsection
957 Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>. */
960 subsection_name
= input_line_pointer
;
961 c
= get_symbol_end (); /* Get terminator. */
962 input_line_pointer
++; /* Skip null symbol terminator. */
963 as_warn (".sect: subsection name ignored");
966 /* We might still have a '"' to discard, but the character after a
967 symbol name will be overwritten with a \0 by get_symbol_end()
972 c4x_expression_abs (input_line_pointer
, &num
);
973 else if (*input_line_pointer
== ',')
976 c4x_expression_abs (++input_line_pointer
, &num
);
981 seg
= subseg_new (name
, num
);
982 if (line_label
!= NULL
)
984 S_SET_SEGMENT (line_label
, seg
);
985 symbol_set_frag (line_label
, frag_now
);
988 if (bfd_get_section_flags (stdoutput
, seg
) == SEC_NO_FLAGS
)
990 if (!bfd_set_section_flags (stdoutput
, seg
, SEC_DATA
))
991 as_warn ("Error setting flags for \"%s\": %s", name
,
992 bfd_errmsg (bfd_get_error ()));
995 /* If the last character overwritten by get_symbol_end() was an
996 end-of-line, we must restore it or the end of the line will not be
997 recognised and scanning extends into the next line, stopping with
998 an error (blame Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>
999 if this is not true). */
1000 if (is_end_of_line
[(unsigned char) c
])
1001 *(--input_line_pointer
) = c
;
1003 demand_empty_rest_of_line ();
1006 /* symbol[:] .set value or .set symbol, value */
1009 int x ATTRIBUTE_UNUSED
;
1014 if ((symbolP
= line_label
) == NULL
)
1019 name
= input_line_pointer
;
1020 c
= get_symbol_end (); /* Get terminator. */
1023 as_bad (".set syntax invalid\n");
1024 ignore_rest_of_line ();
1027 symbolP
= symbol_find_or_make (name
);
1030 symbol_table_insert (symbolP
);
1032 pseudo_set (symbolP
);
1033 demand_empty_rest_of_line ();
1036 /* [symbol] .usect ["]section-name["], size-in-words [, alignment-flag] */
1039 int x ATTRIBUTE_UNUSED
;
1045 int size
, alignment_flag
;
1047 subsegT current_subseg
;
1049 current_seg
= now_seg
; /* save current seg. */
1050 current_subseg
= now_subseg
; /* save current subseg. */
1053 if (*input_line_pointer
== '"')
1054 input_line_pointer
++;
1055 section_name
= input_line_pointer
;
1056 c
= get_symbol_end (); /* Get terminator. */
1057 input_line_pointer
++; /* Skip null symbol terminator. */
1058 name
= xmalloc (input_line_pointer
- section_name
+ 1);
1059 strcpy (name
, section_name
);
1062 input_line_pointer
=
1063 c4x_expression_abs (input_line_pointer
, &size
);
1064 else if (*input_line_pointer
== ',')
1066 input_line_pointer
=
1067 c4x_expression_abs (++input_line_pointer
, &size
);
1072 /* Read a possibly present third argument (alignment flag) [VK]. */
1073 if (*input_line_pointer
== ',')
1075 input_line_pointer
=
1076 c4x_expression_abs (++input_line_pointer
, &alignment_flag
);
1081 as_warn (".usect: non-zero alignment flag ignored");
1083 seg
= subseg_new (name
, 0);
1084 if (line_label
!= NULL
)
1086 S_SET_SEGMENT (line_label
, seg
);
1087 symbol_set_frag (line_label
, frag_now
);
1088 S_SET_VALUE (line_label
, frag_now_fix ());
1090 seg_info (seg
)->bss
= 1; /* Uninitialised data. */
1091 if (!bfd_set_section_flags (stdoutput
, seg
, SEC_ALLOC
))
1092 as_warn ("Error setting flags for \"%s\": %s", name
,
1093 bfd_errmsg (bfd_get_error ()));
1094 c4x_seg_alloc (name
, seg
, size
, line_label
);
1096 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1097 S_SET_STORAGE_CLASS (line_label
, C_STAT
);
1099 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
1100 demand_empty_rest_of_line ();
1103 /* .version cpu-version. */
1106 int x ATTRIBUTE_UNUSED
;
1110 input_line_pointer
=
1111 c4x_expression_abs (input_line_pointer
, &temp
);
1112 if (!IS_CPU_C3X (temp
) && !IS_CPU_C4X (temp
))
1113 as_bad ("This assembler does not support processor generation %d\n",
1116 if (c4x_cpu
&& temp
!= c4x_cpu
)
1117 as_warn ("Changing processor generation on fly not supported...\n");
1119 demand_empty_rest_of_line ();
1123 c4x_pseudo_ignore (x
)
1124 int x ATTRIBUTE_UNUSED
;
1126 /* We could print warning message here... */
1128 /* Ignore everything until end of line. */
1129 while (!is_end_of_line
[(unsigned char) *input_line_pointer
++]);
1133 c4x_init_regtable ()
1137 for (i
= 0; i
< c3x_num_registers
; i
++)
1138 c4x_insert_reg (c3x_registers
[i
].name
,
1139 c3x_registers
[i
].regno
);
1141 if (IS_CPU_C4X (c4x_cpu
))
1143 /* Add additional C4x registers, overriding some C3x ones. */
1144 for (i
= 0; i
< c4x_num_registers
; i
++)
1145 c4x_insert_reg (c4x_registers
[i
].name
,
1146 c4x_registers
[i
].regno
);
1153 /* The TI tools accept case insensitive versions of these symbols,
1158 .TMS320xx 30,31,32,40,or 44 set according to -v flag
1159 .C3X or .C3x 1 or 0 1 if -v30,-v31,or -v32
1160 .C30 1 or 0 1 if -v30
1161 .C31 1 or 0 1 if -v31
1162 .C32 1 or 0 1 if -v32
1163 .C4X or .C4x 1 or 0 1 if -v40, or -v44
1164 .C40 1 or 0 1 if -v40
1165 .C44 1 or 0 1 if -v44
1167 .REGPARM 1 or 0 1 if -mr option used
1168 .BIGMODEL 1 or 0 1 if -mb option used
1170 These symbols are currently supported but will be removed in a
1172 .TMS320C30 1 or 0 1 if -v30,-v31,or -v32
1173 .TMS320C31 1 or 0 1 if -v31
1174 .TMS320C32 1 or 0 1 if -v32
1175 .TMS320C40 1 or 0 1 if -v40, or -v44
1176 .TMS320C44 1 or 0 1 if -v44
1178 Source: TI: TMS320C3x/C4x Assembly Language Tools User's Guide,
1179 1997, SPRU035C, p. 3-17/3-18. */
1180 c4x_insert_sym (".REGPARM", c4x_reg_args
);
1181 c4x_insert_sym (".MEMPARM", !c4x_reg_args
);
1182 c4x_insert_sym (".BIGMODEL", c4x_big_model
);
1183 c4x_insert_sym (".C30INTERRUPT", 0);
1184 c4x_insert_sym (".TMS320xx", c4x_cpu
== 0 ? 40 : c4x_cpu
);
1185 c4x_insert_sym (".C3X", c4x_cpu
== 30 || c4x_cpu
== 31 || c4x_cpu
== 32);
1186 c4x_insert_sym (".C3x", c4x_cpu
== 30 || c4x_cpu
== 31 || c4x_cpu
== 32);
1187 c4x_insert_sym (".C4X", c4x_cpu
== 0 || c4x_cpu
== 40 || c4x_cpu
== 44);
1188 c4x_insert_sym (".C4x", c4x_cpu
== 0 || c4x_cpu
== 40 || c4x_cpu
== 44);
1189 /* Do we need to have the following symbols also in lower case? */
1190 c4x_insert_sym (".TMS320C30", c4x_cpu
== 30 || c4x_cpu
== 31 || c4x_cpu
== 32);
1191 c4x_insert_sym (".tms320C30", c4x_cpu
== 30 || c4x_cpu
== 31 || c4x_cpu
== 32);
1192 c4x_insert_sym (".TMS320C31", c4x_cpu
== 31);
1193 c4x_insert_sym (".tms320C31", c4x_cpu
== 31);
1194 c4x_insert_sym (".TMS320C32", c4x_cpu
== 32);
1195 c4x_insert_sym (".tms320C32", c4x_cpu
== 32);
1196 c4x_insert_sym (".TMS320C40", c4x_cpu
== 40 || c4x_cpu
== 44 || c4x_cpu
== 0);
1197 c4x_insert_sym (".tms320C40", c4x_cpu
== 40 || c4x_cpu
== 44 || c4x_cpu
== 0);
1198 c4x_insert_sym (".TMS320C44", c4x_cpu
== 44);
1199 c4x_insert_sym (".tms320C44", c4x_cpu
== 44);
1200 c4x_insert_sym (".TMX320C40", 0); /* C40 first pass silicon ? */
1201 c4x_insert_sym (".tmx320C40", 0);
1204 /* Insert a new instruction template into hash table. */
1206 c4x_inst_insert (inst
)
1209 static char prev_name
[16];
1210 const char *retval
= NULL
;
1212 /* Only insert the first name if have several similar entries. */
1213 if (!strcmp (inst
->name
, prev_name
) || inst
->name
[0] == '\0')
1216 retval
= hash_insert (c4x_op_hash
, inst
->name
, (PTR
) inst
);
1218 fprintf (stderr
, "internal error: can't hash `%s': %s\n",
1219 inst
->name
, retval
);
1221 strcpy (prev_name
, inst
->name
);
1222 return retval
== NULL
;
1225 /* Make a new instruction template. */
1227 c4x_inst_make (name
, opcode
, args
)
1229 unsigned long opcode
;
1232 static c4x_inst_t
*insts
= NULL
;
1233 static char *names
= NULL
;
1234 static int index
= 0;
1238 /* Allocate memory to store name strings. */
1239 names
= (char *) xmalloc (sizeof (char) * 8192);
1240 /* Allocate memory for additional insts. */
1241 insts
= (c4x_inst_t
*)
1242 xmalloc (sizeof (c4x_inst_t
) * 1024);
1244 insts
[index
].name
= names
;
1245 insts
[index
].opcode
= opcode
;
1246 insts
[index
].opmask
= 0xffffffff;
1247 insts
[index
].args
= args
;
1255 return &insts
[index
- 1];
1258 /* Add instruction template, creating dynamic templates as required. */
1260 c4x_inst_add (insts
)
1263 char *s
= insts
->name
;
1277 /* Dynamically create all the conditional insts. */
1278 for (i
= 0; i
< num_conds
; i
++)
1282 char *c
= c4x_conds
[i
].name
;
1292 /* If instruction found then have already processed it. */
1293 if (hash_find (c4x_op_hash
, name
))
1298 inst
= c4x_inst_make (name
, insts
[k
].opcode
+
1299 (c4x_conds
[i
].cond
<<
1300 (*s
== 'B' ? 16 : 23)),
1302 if (k
== 0) /* Save strcmp() with following func. */
1303 ok
&= c4x_inst_insert (inst
);
1306 while (!strcmp (insts
->name
,
1313 return c4x_inst_insert (insts
);
1323 /* This function is called once, at assembler startup time. It should
1324 set up all the tables, etc., that the MD part of the assembler will
1332 /* Create hash table for mnemonics. */
1333 c4x_op_hash
= hash_new ();
1335 /* Create hash table for asg pseudo. */
1336 c4x_asg_hash
= hash_new ();
1338 /* Add mnemonics to hash table, expanding conditional mnemonics on fly. */
1339 for (i
= 0; i
< c3x_num_insts
; i
++)
1340 ok
&= c4x_inst_add ((void *) &c3x_insts
[i
]);
1342 if (IS_CPU_C4X (c4x_cpu
))
1344 for (i
= 0; i
< c4x_num_insts
; i
++)
1345 ok
&= c4x_inst_add ((void *) &c4x_insts
[i
]);
1348 /* Create dummy inst to avoid errors accessing end of table. */
1349 c4x_inst_make ("", 0, "");
1352 as_fatal ("Broken assembler. No assembly attempted.");
1354 /* Add registers to symbol table. */
1355 c4x_init_regtable ();
1357 /* Add predefined symbols to symbol table. */
1358 c4x_init_symbols ();
1364 bfd_set_arch_mach (stdoutput
, bfd_arch_tic4x
,
1365 IS_CPU_C4X (c4x_cpu
) ? bfd_mach_c4x
: bfd_mach_c3x
);
1369 c4x_indirect_parse (operand
, indirect
)
1370 c4x_operand_t
*operand
;
1371 const c4x_indirect_t
*indirect
;
1373 char *n
= indirect
->name
;
1374 char *s
= input_line_pointer
;
1384 case 'a': /* Need to match aux register. */
1386 #ifdef C4X_ALT_SYNTAX
1390 while (isalnum (*s
))
1393 if (!(symbolP
= symbol_find (name
)))
1396 if (S_GET_SEGMENT (symbolP
) != reg_section
)
1399 operand
->aregno
= S_GET_VALUE (symbolP
);
1400 if (operand
->aregno
>= REG_AR0
&& operand
->aregno
<= REG_AR7
)
1403 as_bad ("Auxiliary register AR0--AR7 required for indirect");
1406 case 'd': /* Need to match constant for disp. */
1407 #ifdef C4X_ALT_SYNTAX
1408 if (*s
== '%') /* expr() will die if we don't skip this. */
1411 s
= c4x_expression (s
, &operand
->expr
);
1412 if (operand
->expr
.X_op
!= O_constant
)
1414 operand
->disp
= operand
->expr
.X_add_number
;
1415 if (operand
->disp
< 0 || operand
->disp
> 255)
1417 as_bad ("Bad displacement %d (require 0--255)\n",
1423 case 'y': /* Need to match IR0. */
1424 case 'z': /* Need to match IR1. */
1425 #ifdef C4X_ALT_SYNTAX
1429 s
= c4x_expression (s
, &operand
->expr
);
1430 if (operand
->expr
.X_op
!= O_register
)
1432 if (operand
->expr
.X_add_number
!= REG_IR0
1433 && operand
->expr
.X_add_number
!= REG_IR1
)
1435 as_bad ("Index register IR0,IR1 required for displacement");
1439 if (*n
== 'y' && operand
->expr
.X_add_number
== REG_IR0
)
1441 if (*n
== 'z' && operand
->expr
.X_add_number
== REG_IR1
)
1446 if (*s
!= '(') /* No displacement, assume to be 1. */
1457 if (tolower (*s
) != *n
)
1462 if (*s
!= ' ' && *s
!= ',' && *s
!= '\0')
1464 input_line_pointer
= s
;
1469 c4x_operand_parse (s
, operand
)
1471 c4x_operand_t
*operand
;
1476 expressionS
*exp
= &operand
->expr
;
1477 char *save
= input_line_pointer
;
1480 struct hash_entry
*entry
= NULL
;
1482 input_line_pointer
= s
;
1485 str
= input_line_pointer
;
1486 c
= get_symbol_end (); /* Get terminator. */
1487 new = input_line_pointer
;
1488 if (strlen (str
) && (entry
= hash_find (c4x_asg_hash
, str
)) != NULL
)
1490 *input_line_pointer
= c
;
1491 input_line_pointer
= (char *) entry
;
1495 *input_line_pointer
= c
;
1496 input_line_pointer
= str
;
1499 operand
->mode
= M_UNKNOWN
;
1500 switch (*input_line_pointer
)
1502 #ifdef C4X_ALT_SYNTAX
1504 input_line_pointer
= c4x_expression (++input_line_pointer
, exp
);
1505 if (exp
->X_op
!= O_register
)
1506 as_bad ("Expecting a register name");
1507 operand
->mode
= M_REGISTER
;
1511 /* Denotes high 16 bits. */
1512 input_line_pointer
= c4x_expression (++input_line_pointer
, exp
);
1513 if (exp
->X_op
== O_constant
)
1514 operand
->mode
= M_IMMED
;
1515 else if (exp
->X_op
== O_big
)
1517 if (exp
->X_add_number
)
1518 as_bad ("Number too large"); /* bignum required */
1521 c4x_gen_to_words (generic_floating_point_number
,
1522 operand
->fwords
, S_PRECISION
);
1523 operand
->mode
= M_IMMED_F
;
1526 /* Allow ori ^foo, ar0 to be equivalent to ldi .hi.foo, ar0 */
1527 /* WARNING : The TI C40 assembler cannot do this. */
1528 else if (exp
->X_op
== O_symbol
)
1530 operand
->mode
= M_HI
;
1535 input_line_pointer
= c4x_expression (++input_line_pointer
, exp
);
1536 if (exp
->X_op
== O_constant
)
1537 operand
->mode
= M_IMMED
;
1538 else if (exp
->X_op
== O_big
)
1540 if (exp
->X_add_number
> 0)
1541 as_bad ("Number too large"); /* bignum required. */
1544 c4x_gen_to_words (generic_floating_point_number
,
1545 operand
->fwords
, S_PRECISION
);
1546 operand
->mode
= M_IMMED_F
;
1549 /* Allow ori foo, ar0 to be equivalent to ldi .lo.foo, ar0 */
1550 /* WARNING : The TI C40 assembler cannot do this. */
1551 else if (exp
->X_op
== O_symbol
)
1553 operand
->mode
= M_IMMED
;
1558 as_bad ("Expecting a constant value");
1563 input_line_pointer
= c4x_expression (++input_line_pointer
, exp
);
1564 if (exp
->X_op
!= O_constant
&& exp
->X_op
!= O_symbol
)
1565 as_bad ("Bad direct addressing construct %s", s
);
1566 if (exp
->X_op
== O_constant
)
1568 if (exp
->X_add_number
< 0)
1569 as_bad ("Direct value of %ld is not suitable",
1570 (long) exp
->X_add_number
);
1572 operand
->mode
= M_DIRECT
;
1577 for (i
= 0; i
< num_indirects
; i
++)
1578 if ((ret
= c4x_indirect_parse (operand
, &c4x_indirects
[i
])))
1582 if (i
< num_indirects
)
1584 operand
->mode
= M_INDIRECT
;
1585 /* Indirect addressing mode number. */
1586 operand
->expr
.X_add_number
= c4x_indirects
[i
].modn
;
1587 /* Convert *+ARn(0) to *ARn etc. Maybe we should
1588 squeal about silly ones? */
1589 if (operand
->expr
.X_add_number
< 0x08 && !operand
->disp
)
1590 operand
->expr
.X_add_number
= 0x18;
1593 as_bad ("Unknown indirect addressing mode");
1597 operand
->mode
= M_IMMED
; /* Assume immediate. */
1598 str
= input_line_pointer
;
1599 input_line_pointer
= c4x_expression (input_line_pointer
, exp
);
1600 if (exp
->X_op
== O_register
)
1602 know (exp
->X_add_symbol
== 0);
1603 know (exp
->X_op_symbol
== 0);
1604 operand
->mode
= M_REGISTER
;
1607 else if (exp
->X_op
== O_big
)
1609 if (exp
->X_add_number
> 0)
1610 as_bad ("Number too large"); /* bignum required. */
1613 c4x_gen_to_words (generic_floating_point_number
,
1614 operand
->fwords
, S_PRECISION
);
1615 operand
->mode
= M_IMMED_F
;
1619 #ifdef C4X_ALT_SYNTAX
1620 /* Allow ldi foo, ar0 to be equivalent to ldi @foo, ar0. */
1621 else if (exp
->X_op
== O_symbol
)
1623 operand
->mode
= M_DIRECT
;
1629 new = input_line_pointer
;
1630 input_line_pointer
= save
;
1635 c4x_operands_match (inst
, insn
)
1639 const char *args
= inst
->args
;
1640 unsigned long opcode
= inst
->opcode
;
1641 int num_operands
= insn
->num_operands
;
1642 c4x_operand_t
*operand
= insn
->operands
;
1643 expressionS
*exp
= &operand
->expr
;
1647 /* Build the opcode, checking as we go to make sure that the
1650 If an operand matches, we modify insn or opcode appropriately,
1651 and do a "continue". If an operand fails to match, we "break". */
1653 insn
->nchars
= 4; /* Instructions always 4 bytes. */
1654 insn
->reloc
= NO_RELOC
;
1659 insn
->opcode
= opcode
;
1660 return num_operands
== 0;
1668 case '\0': /* End of args. */
1669 if (num_operands
== 1)
1671 insn
->opcode
= opcode
;
1674 break; /* Too many operands. */
1676 case '#': /* This is only used for ldp. */
1677 if (operand
->mode
!= M_DIRECT
&& operand
->mode
!= M_IMMED
)
1679 /* While this looks like a direct addressing mode, we actually
1680 use an immediate mode form of ldiu or ldpk instruction. */
1681 if (exp
->X_op
== O_constant
)
1683 /* Maybe for C3x we should check for 8 bit number. */
1684 INSERTS (opcode
, exp
->X_add_number
, 15, 0);
1687 else if (exp
->X_op
== O_symbol
)
1689 insn
->reloc
= BFD_RELOC_HI16
;
1693 break; /* Not direct (dp) addressing. */
1695 case '@': /* direct. */
1696 if (operand
->mode
!= M_DIRECT
)
1698 if (exp
->X_op
== O_constant
)
1700 /* Store only the 16 LSBs of the number. */
1701 INSERTS (opcode
, exp
->X_add_number
, 15, 0);
1704 else if (exp
->X_op
== O_symbol
)
1706 insn
->reloc
= BFD_RELOC_LO16
;
1710 break; /* Not direct addressing. */
1713 if (operand
->mode
!= M_REGISTER
)
1715 reg
= exp
->X_add_number
;
1716 if (reg
>= REG_AR0
&& reg
<= REG_AR7
)
1717 INSERTU (opcode
, reg
- REG_AR0
, 24, 22);
1720 as_bad ("Destination register must be ARn");
1725 case 'B': /* Unsigned integer immediate. */
1726 /* Allow br label or br @label. */
1727 if (operand
->mode
!= M_IMMED
&& operand
->mode
!= M_DIRECT
)
1729 if (exp
->X_op
== O_constant
)
1731 if (exp
->X_add_number
< (1 << 24))
1733 INSERTU (opcode
, exp
->X_add_number
, 23, 0);
1738 as_bad ("Immediate value of %ld is too large",
1739 (long) exp
->X_add_number
);
1744 if (IS_CPU_C4X (c4x_cpu
))
1746 insn
->reloc
= BFD_RELOC_24_PCREL
;
1751 insn
->reloc
= BFD_RELOC_24
;
1758 if (!IS_CPU_C4X (c4x_cpu
))
1760 if (operand
->mode
!= M_INDIRECT
)
1762 if (operand
->expr
.X_add_number
!= 0
1763 && operand
->expr
.X_add_number
!= 0x18)
1765 as_bad ("Invalid indirect addressing mode");
1769 INSERTU (opcode
, operand
->aregno
- REG_AR0
, 2, 0);
1770 INSERTU (opcode
, operand
->disp
, 7, 3);
1774 if (!(operand
->mode
== M_REGISTER
))
1776 INSERTU (opcode
, exp
->X_add_number
, 7, 0);
1780 if (operand
->mode
!= M_IMMED_F
1781 && !(operand
->mode
== M_IMMED
&& exp
->X_op
== O_constant
))
1784 if (operand
->mode
!= M_IMMED_F
)
1786 /* OK, we 've got something like cmpf 0, r0
1787 Why can't they stick in a bloody decimal point ?! */
1790 /* Create floating point number string. */
1791 sprintf (string
, "%d.0", (int) exp
->X_add_number
);
1792 c4x_atof (string
, 's', operand
->fwords
);
1795 INSERTU (opcode
, operand
->fwords
[0], 15, 0);
1799 if (operand
->mode
!= M_REGISTER
)
1801 INSERTU (opcode
, exp
->X_add_number
, 15, 8);
1805 if (operand
->mode
!= M_REGISTER
)
1807 reg
= exp
->X_add_number
;
1808 if (reg
>= REG_R0
&& reg
<= REG_R7
)
1809 INSERTU (opcode
, reg
- REG_R0
, 18, 16);
1812 as_bad ("Register must be R0--R7");
1818 if (operand
->mode
!= M_INDIRECT
)
1820 if (operand
->disp
!= 0 && operand
->disp
!= 1)
1822 if (IS_CPU_C4X (c4x_cpu
))
1824 as_bad ("Invalid indirect addressing mode displacement %d",
1829 INSERTU (opcode
, operand
->aregno
- REG_AR0
, 2, 0);
1830 INSERTU (opcode
, operand
->expr
.X_add_number
, 7, 3);
1834 if (operand
->mode
!= M_INDIRECT
)
1836 if (operand
->disp
!= 0 && operand
->disp
!= 1)
1838 if (IS_CPU_C4X (c4x_cpu
))
1840 as_bad ("Invalid indirect addressing mode displacement %d",
1845 INSERTU (opcode
, operand
->aregno
- REG_AR0
, 10, 8);
1846 INSERTU (opcode
, operand
->expr
.X_add_number
, 15, 11);
1850 if (operand
->mode
!= M_REGISTER
)
1852 reg
= exp
->X_add_number
;
1853 if (reg
>= REG_R0
&& reg
<= REG_R7
)
1854 INSERTU (opcode
, reg
- REG_R0
, 21, 19);
1857 as_bad ("Register must be R0--R7");
1863 if (operand
->mode
!= M_REGISTER
)
1865 reg
= exp
->X_add_number
;
1866 if (reg
>= REG_R0
&& reg
<= REG_R7
)
1867 INSERTU (opcode
, reg
- REG_R0
, 24, 22);
1870 as_bad ("Register must be R0--R7");
1876 if (operand
->mode
!= M_REGISTER
)
1878 reg
= exp
->X_add_number
;
1879 if (reg
== REG_R2
|| reg
== REG_R3
)
1880 INSERTU (opcode
, reg
- REG_R2
, 22, 22);
1883 as_bad ("Destination register must be R2 or R3");
1889 if (operand
->mode
!= M_REGISTER
)
1891 reg
= exp
->X_add_number
;
1892 if (reg
== REG_R0
|| reg
== REG_R1
)
1893 INSERTU (opcode
, reg
- REG_R0
, 23, 23);
1896 as_bad ("Destination register must be R0 or R1");
1902 if (!IS_CPU_C4X (c4x_cpu
))
1904 if (operand
->mode
!= M_INDIRECT
)
1906 /* Require either *+ARn(disp) or *ARn. */
1907 if (operand
->expr
.X_add_number
!= 0
1908 && operand
->expr
.X_add_number
!= 0x18)
1910 as_bad ("Invalid indirect addressing mode");
1914 INSERTU (opcode
, operand
->aregno
- REG_AR0
, 10, 8);
1915 INSERTU (opcode
, operand
->disp
, 15, 11);
1918 case 'P': /* PC relative displacement. */
1919 /* Allow br label or br @label. */
1920 if (operand
->mode
!= M_IMMED
&& operand
->mode
!= M_DIRECT
)
1922 if (exp
->X_op
== O_constant
)
1924 if (exp
->X_add_number
>= -32768 && exp
->X_add_number
<= 32767)
1926 INSERTS (opcode
, exp
->X_add_number
, 15, 0);
1931 as_bad ("Displacement value of %ld is too large",
1932 (long) exp
->X_add_number
);
1937 insn
->reloc
= BFD_RELOC_16_PCREL
;
1943 if (operand
->mode
!= M_REGISTER
)
1945 reg
= exp
->X_add_number
;
1946 INSERTU (opcode
, reg
, 15, 0);
1950 if (operand
->mode
!= M_REGISTER
)
1952 reg
= exp
->X_add_number
;
1953 INSERTU (opcode
, reg
, 20, 16);
1956 case 'S': /* Short immediate int. */
1957 if (operand
->mode
!= M_IMMED
&& operand
->mode
!= M_HI
)
1959 if (exp
->X_op
== O_big
)
1961 as_bad ("Floating point number not valid in expression");
1965 if (exp
->X_op
== O_constant
)
1967 if (exp
->X_add_number
>= -32768 && exp
->X_add_number
<= 65535)
1969 INSERTS (opcode
, exp
->X_add_number
, 15, 0);
1974 as_bad ("Signed immediate value %ld too large",
1975 (long) exp
->X_add_number
);
1980 else if (exp
->X_op
== O_symbol
)
1982 if (operand
->mode
== M_HI
)
1984 insn
->reloc
= BFD_RELOC_HI16
;
1988 insn
->reloc
= BFD_RELOC_LO16
;
1993 /* Handle cases like ldi foo - $, ar0 where foo
1994 is a forward reference. Perhaps we should check
1995 for X_op == O_symbol and disallow things like
1997 insn
->reloc
= BFD_RELOC_16
;
2001 case 'T': /* 5-bit immediate value for c4x stik. */
2002 if (!IS_CPU_C4X (c4x_cpu
))
2004 if (operand
->mode
!= M_IMMED
)
2006 if (exp
->X_op
== O_constant
)
2008 if (exp
->X_add_number
< 16 && exp
->X_add_number
>= -16)
2010 INSERTS (opcode
, exp
->X_add_number
, 20, 16);
2015 as_bad ("Immediate value of %ld is too large",
2016 (long) exp
->X_add_number
);
2021 break; /* No relocations allowed. */
2023 case 'U': /* Unsigned integer immediate. */
2024 if (operand
->mode
!= M_IMMED
&& operand
->mode
!= M_HI
)
2026 if (exp
->X_op
== O_constant
)
2028 if (exp
->X_add_number
< (1 << 16) && exp
->X_add_number
>= 0)
2030 INSERTU (opcode
, exp
->X_add_number
, 15, 0);
2035 as_bad ("Unsigned immediate value %ld too large",
2036 (long) exp
->X_add_number
);
2041 else if (exp
->X_op
== O_symbol
)
2043 if (operand
->mode
== M_HI
)
2044 insn
->reloc
= BFD_RELOC_HI16
;
2046 insn
->reloc
= BFD_RELOC_LO16
;
2051 insn
->reloc
= BFD_RELOC_16
;
2055 case 'V': /* Trap numbers (immediate field). */
2056 if (operand
->mode
!= M_IMMED
)
2058 if (exp
->X_op
== O_constant
)
2060 if (exp
->X_add_number
< 512 && IS_CPU_C4X (c4x_cpu
))
2062 INSERTU (opcode
, exp
->X_add_number
, 8, 0);
2065 else if (exp
->X_add_number
< 32 && IS_CPU_C3X (c4x_cpu
))
2067 INSERTU (opcode
, exp
->X_add_number
| 0x20, 4, 0);
2072 as_bad ("Immediate value of %ld is too large",
2073 (long) exp
->X_add_number
);
2078 break; /* No relocations allowed. */
2080 case 'W': /* Short immediate int (0--7). */
2081 if (!IS_CPU_C4X (c4x_cpu
))
2083 if (operand
->mode
!= M_IMMED
)
2085 if (exp
->X_op
== O_big
)
2087 as_bad ("Floating point number not valid in expression");
2091 if (exp
->X_op
== O_constant
)
2093 if (exp
->X_add_number
>= -256 && exp
->X_add_number
<= 127)
2095 INSERTS (opcode
, exp
->X_add_number
, 7, 0);
2100 as_bad ("Immediate value %ld too large",
2101 (long) exp
->X_add_number
);
2106 insn
->reloc
= BFD_RELOC_16
;
2110 case 'X': /* Expansion register for c4x. */
2111 if (operand
->mode
!= M_REGISTER
)
2113 reg
= exp
->X_add_number
;
2114 if (reg
>= REG_IVTP
&& reg
<= REG_TVTP
)
2115 INSERTU (opcode
, reg
- REG_IVTP
, 4, 0);
2118 as_bad ("Register must be ivtp or tvtp");
2123 case 'Y': /* Address register for c4x lda. */
2124 if (operand
->mode
!= M_REGISTER
)
2126 reg
= exp
->X_add_number
;
2127 if (reg
>= REG_AR0
&& reg
<= REG_SP
)
2128 INSERTU (opcode
, reg
, 20, 16);
2131 as_bad ("Register must be address register");
2136 case 'Z': /* Expansion register for c4x. */
2137 if (operand
->mode
!= M_REGISTER
)
2139 reg
= exp
->X_add_number
;
2140 if (reg
>= REG_IVTP
&& reg
<= REG_TVTP
)
2141 INSERTU (opcode
, reg
- REG_IVTP
, 20, 16);
2144 as_bad ("Register must be ivtp or tvtp");
2150 if (operand
->mode
!= M_INDIRECT
)
2152 INSERTS (opcode
, operand
->disp
, 7, 0);
2153 INSERTU (opcode
, operand
->aregno
- REG_AR0
, 10, 8);
2154 INSERTU (opcode
, operand
->expr
.X_add_number
, 15, 11);
2157 case '|': /* treat as `,' if have ldi_ldi form. */
2160 if (--num_operands
< 0)
2161 break; /* Too few operands. */
2163 if (operand
->mode
!= M_PARALLEL
)
2168 case ',': /* Another operand. */
2169 if (--num_operands
< 0)
2170 break; /* Too few operands. */
2172 exp
= &operand
->expr
;
2175 case ';': /* Another optional operand. */
2176 if (num_operands
== 1 || operand
[1].mode
== M_PARALLEL
)
2178 if (--num_operands
< 0)
2179 break; /* Too few operands. */
2181 exp
= &operand
->expr
;
2192 c4x_insn_output (insn
)
2197 /* Grab another fragment for opcode. */
2198 dst
= frag_more (insn
->nchars
);
2200 /* Put out opcode word as a series of bytes in little endian order. */
2201 md_number_to_chars (dst
, insn
->opcode
, insn
->nchars
);
2203 /* Put out the symbol-dependent stuff. */
2204 if (insn
->reloc
!= NO_RELOC
)
2206 /* Where is the offset into the fragment for this instruction. */
2207 fix_new_exp (frag_now
,
2208 dst
- frag_now
->fr_literal
, /* where */
2209 insn
->nchars
, /* size */
2216 /* Parse the operands. */
2218 c4x_operands_parse (s
, operands
, num_operands
)
2220 c4x_operand_t
*operands
;
2224 return num_operands
;
2227 s
= c4x_operand_parse (s
, &operands
[num_operands
++]);
2228 while (num_operands
< C4X_OPERANDS_MAX
&& *s
++ == ',');
2230 if (num_operands
> C4X_OPERANDS_MAX
)
2232 as_bad ("Too many operands scanned");
2235 return num_operands
;
2238 /* Assemble a single instruction. Its label has already been handled
2239 by the generic front end. We just parse mnemonic and operands, and
2240 produce the bytes of data and relocation. */
2249 c4x_inst_t
*inst
; /* Instruction template. */
2251 if (str
&& insn
->parallel
)
2255 /* Find mnemonic (second part of parallel instruction). */
2257 /* Skip past instruction mnemonic. */
2258 while (*s
&& *s
!= ' ' && *s
!= '*')
2261 if (*s
) /* Null terminate for hash_find. */
2262 *s
++ = '\0'; /* and skip past null. */
2263 strcat (insn
->name
, "_");
2264 strncat (insn
->name
, str
, C4X_NAME_MAX
- strlen (insn
->name
));
2266 /* Kludge to overcome problems with scrubber removing
2267 space between mnemonic and indirect operand (starting with *)
2268 on second line of parallel instruction. */
2272 insn
->operands
[insn
->num_operands
++].mode
= M_PARALLEL
;
2274 if ((i
= c4x_operands_parse
2275 (s
, insn
->operands
, insn
->num_operands
)) < 0)
2281 insn
->num_operands
= i
;
2287 if ((insn
->inst
= (struct c4x_inst
*)
2288 hash_find (c4x_op_hash
, insn
->name
)) == NULL
)
2290 as_bad ("Unknown opcode `%s'.", insn
->name
);
2296 /* FIXME: The list of templates should be scanned
2297 for the candidates with the desired number of operands.
2298 We shouldn't issue error messages until we have
2299 whittled the list of candidate templates to the most
2300 likely one... We could cache a parsed form of the templates
2301 to reduce the time required to match a template. */
2306 ok
= c4x_operands_match (inst
, insn
);
2307 while (!ok
&& !strcmp (inst
->name
, inst
[1].name
) && inst
++);
2310 c4x_insn_output (insn
);
2312 as_bad ("Invalid operands for %s", insn
->name
);
2314 as_bad ("Invalid instruction %s", insn
->name
);
2319 /* Find mnemonic. */
2321 while (*s
&& *s
!= ' ') /* Skip past instruction mnemonic. */
2323 if (*s
) /* Null terminate for hash_find. */
2324 *s
++ = '\0'; /* and skip past null. */
2325 strncpy (insn
->name
, str
, C4X_NAME_MAX
- 3);
2327 if ((i
= c4x_operands_parse (s
, insn
->operands
, 0)) < 0)
2329 insn
->inst
= NULL
; /* Flag that error occured. */
2334 insn
->num_operands
= i
;
2349 /* Turn a string in input_line_pointer into a floating point constant
2350 of type type, and store the appropriate bytes in *litP. The number
2351 of LITTLENUMS emitted is stored in *sizeP. An error message is
2352 returned, or NULL on OK. */
2355 md_atof (type
, litP
, sizeP
)
2362 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
2363 LITTLENUM_TYPE
*wordP
;
2368 case 's': /* .single */
2374 case 'd': /* .double */
2376 case 'f': /* .float or .single */
2379 prec
= 2; /* 1 32-bit word */
2382 case 'i': /* .ieee */
2387 case 'l': /* .ldouble */
2388 prec
= 4; /* 2 32-bit words */
2394 return "Bad call to md_atof()";
2398 t
= atof_ieee (input_line_pointer
, type
, words
);
2400 t
= c4x_atof (input_line_pointer
, type
, words
);
2402 input_line_pointer
= t
;
2403 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
2405 /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
2406 little endian byte order. */
2407 for (wordP
= words
+ prec
- 1; prec
--;)
2409 md_number_to_chars (litP
, (valueT
) (*wordP
--),
2410 sizeof (LITTLENUM_TYPE
));
2411 litP
+= sizeof (LITTLENUM_TYPE
);
2417 md_apply_fix3 (fixP
, value
, seg
)
2420 segT seg ATTRIBUTE_UNUSED
;
2422 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
2423 valueT val
= *value
;
2425 switch (fixP
->fx_r_type
)
2427 case BFD_RELOC_HI16
:
2431 case BFD_RELOC_LO16
:
2438 switch (fixP
->fx_r_type
)
2443 case BFD_RELOC_24_PCREL
:
2446 case BFD_RELOC_16_PCREL
:
2447 case BFD_RELOC_LO16
:
2448 case BFD_RELOC_HI16
:
2455 as_bad ("Bad relocation type: 0x%02x", fixP
->fx_r_type
);
2459 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0) fixP
->fx_done
= 1;
2462 /* Should never be called for c4x. */
2464 md_convert_frag (headers
, sec
, fragP
)
2465 bfd
*headers ATTRIBUTE_UNUSED
;
2466 segT sec ATTRIBUTE_UNUSED
;
2467 fragS
*fragP ATTRIBUTE_UNUSED
;
2469 as_fatal ("md_convert_frag");
2472 /* Should never be called for c4x. */
2474 md_create_short_jump (ptr
, from_addr
, to_addr
, frag
, to_symbol
)
2475 char *ptr ATTRIBUTE_UNUSED
;
2476 addressT from_addr ATTRIBUTE_UNUSED
;
2477 addressT to_addr ATTRIBUTE_UNUSED
;
2478 fragS
*frag ATTRIBUTE_UNUSED
;
2479 symbolS
*to_symbol ATTRIBUTE_UNUSED
;
2481 as_fatal ("md_create_short_jmp\n");
2484 /* Should never be called for c4x. */
2486 md_create_long_jump (ptr
, from_addr
, to_addr
, frag
, to_symbol
)
2487 char *ptr ATTRIBUTE_UNUSED
;
2488 addressT from_addr ATTRIBUTE_UNUSED
;
2489 addressT to_addr ATTRIBUTE_UNUSED
;
2490 fragS
*frag ATTRIBUTE_UNUSED
;
2491 symbolS
*to_symbol ATTRIBUTE_UNUSED
;
2493 as_fatal ("md_create_long_jump\n");
2496 /* Should never be called for c4x. */
2498 md_estimate_size_before_relax (fragP
, segtype
)
2499 register fragS
*fragP ATTRIBUTE_UNUSED
;
2500 segT segtype ATTRIBUTE_UNUSED
;
2502 as_fatal ("md_estimate_size_before_relax\n");
2506 CONST
char *md_shortopts
= "bm:prs";
2507 struct option md_longopts
[] =
2509 {NULL
, no_argument
, NULL
, 0}
2512 size_t md_longopts_size
= sizeof (md_longopts
);
2515 md_parse_option (c
, arg
)
2521 case 'b': /* big model */
2524 case 'm': /* -m[c][34]x */
2525 if (tolower (*arg
) == 'c')
2527 c4x_cpu
= atoi (arg
);
2528 if (!IS_CPU_C3X (c4x_cpu
) && !IS_CPU_C4X (c4x_cpu
))
2529 as_warn ("Unsupported processor generation %d\n", c4x_cpu
);
2531 case 'p': /* push args */
2534 case 'r': /* register args */
2537 case 's': /* small model */
2548 md_show_usage (stream
)
2553 -m30 | -m31 | -m32 | -m40 | -m44\n\
2554 specify variant of architecture\n\
2555 -b big memory model\n\
2556 -p pass arguments on stack\n\
2557 -r pass arguments in registers (default)\n\
2558 -s small memory model (default)\n",
2562 /* This is called when a line is unrecognized. This is used to handle
2563 definitions of TI C3x tools style local labels $n where n is a single
2566 c4x_unrecognized_line (c
)
2572 if (c
!= '$' || !isdigit (input_line_pointer
[0]))
2575 s
= input_line_pointer
;
2577 /* Let's allow multiple digit local labels. */
2579 while (isdigit (*s
))
2581 lab
= lab
* 10 + *s
- '0';
2585 if (dollar_label_defined (lab
))
2587 as_bad ("Label \"$%d\" redefined", lab
);
2591 define_dollar_label (lab
);
2592 colon (dollar_label_name (lab
, 0));
2593 input_line_pointer
= s
+ 1;
2598 /* Handle local labels peculiar to us referred to in an expression. */
2600 md_undefined_symbol (name
)
2603 /* Look for local labels of the form $n. */
2604 if (name
[0] == '$' && isdigit (name
[1]))
2610 while (isdigit ((unsigned char) *s
))
2612 lab
= lab
* 10 + *s
- '0';
2615 if (dollar_label_defined (lab
))
2617 name
= dollar_label_name (lab
, 0);
2618 symbolP
= symbol_find (name
);
2622 name
= dollar_label_name (lab
, 1);
2623 symbolP
= symbol_find_or_make (name
);
2631 /* Parse an operand that is machine-specific. */
2633 md_operand (expressionP
)
2634 expressionS
*expressionP ATTRIBUTE_UNUSED
;
2638 /* Round up a section size to the appropriate boundary---do we need this? */
2640 md_section_align (segment
, size
)
2641 segT segment ATTRIBUTE_UNUSED
;
2644 return size
; /* Byte (i.e., 32-bit) alignment is fine? */
2651 /* Determine the PC offset for a C[34]x instruction.
2652 This could be simplified using some boolean algebra
2653 but at the expense of readability. */
2657 case 0x62: /* call (C4x) */
2658 case 0x64: /* rptb (C4x) */
2660 case 0x61: /* brd */
2661 case 0x63: /* laj */
2662 case 0x65: /* rptbd (C4x) */
2664 case 0x66: /* swi */
2671 switch ((op
& 0xffe00000) >> 20)
2673 case 0x6a0: /* bB */
2674 case 0x720: /* callB */
2675 case 0x740: /* trapB */
2678 case 0x6a2: /* bBd */
2679 case 0x6a6: /* bBat */
2680 case 0x6aa: /* bBaf */
2681 case 0x722: /* lajB */
2682 case 0x748: /* latB */
2683 case 0x798: /* rptbd */
2690 switch ((op
& 0xfe200000) >> 20)
2692 case 0x6e0: /* dbB */
2695 case 0x6e2: /* dbBd */
2705 /* Exactly what point is a PC-relative offset relative TO?
2706 With the C3x we have the following:
2707 DBcond, Bcond disp + PC + 1 => PC
2708 DBcondD, BcondD disp + PC + 3 => PC
2711 md_pcrel_from (fixP
)
2714 unsigned char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
2717 op
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
2719 return ((fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) >> 2) +
2723 /* This is probably not necessary, if we have played our cards right,
2724 since everything should be already aligned on a 4-byte boundary. */
2726 c4x_do_align (alignment
, fill
, len
, max
)
2727 int alignment ATTRIBUTE_UNUSED
;
2728 const char *fill ATTRIBUTE_UNUSED
;
2729 int len ATTRIBUTE_UNUSED
;
2730 int max ATTRIBUTE_UNUSED
;
2734 p
= frag_var (rs_align
, 1, 1, (relax_substateT
) 0,
2735 (symbolS
*) 0, (long) 2, (char *) 0);
2737 /* We could use frag_align_pattern (n, nop_pattern, sizeof (nop_pattern));
2738 to fill with our 32-bit nop opcode. */
2742 /* Look for and remove parallel instruction operator ||. */
2746 char *s
= input_line_pointer
;
2750 /* If parallel instruction prefix found at start of line, skip it. */
2751 if (*input_line_pointer
== '|' && input_line_pointer
[1] == '|')
2756 input_line_pointer
+= 2;
2757 /* So line counters get bumped. */
2758 input_line_pointer
[-1] = '\n';
2765 input_line_pointer
= s
;
2770 tc_gen_reloc (seg
, fixP
)
2771 asection
*seg ATTRIBUTE_UNUSED
;
2776 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
2778 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
2779 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixP
->fx_addsy
);
2780 reloc
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
2781 reloc
->address
/= OCTETS_PER_BYTE
;
2782 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixP
->fx_r_type
);
2783 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
2785 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
2786 "reloc %d not supported by object file format",
2787 (int) fixP
->fx_r_type
);
2791 if (fixP
->fx_r_type
== BFD_RELOC_HI16
)
2792 reloc
->addend
= fixP
->fx_offset
;
2794 reloc
->addend
= fixP
->fx_addnumber
;