1 /* tc-arc.c -- Assembler for the ARC
2 Copyright (C) 1994 Free Software Foundation, Inc.
3 Contributed by Doug Evans (dje@cygnus.com).
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 #include "opcode/arc.h"
27 extern int target_big_endian
;
29 static arc_insn arc_insert_operand
PARAMS ((arc_insn insn
,
30 const struct arc_operand
*operand
,
32 const struct arc_operand_value
*reg
,
34 char *file
, unsigned int line
));
36 static void s_data1
PARAMS ((void));
37 static void s_seg
PARAMS ((int));
38 static void s_proc
PARAMS ((int));
39 static void s_reserve
PARAMS ((int));
40 static void s_common
PARAMS ((int));
42 const pseudo_typeS md_pseudo_table
[] =
44 {"align", s_align_bytes
, 0}, /* Defaulting is invalid (0) */
45 {"common", s_common
, 0},
46 {"global", s_globl
, 0},
48 {"optim", s_ignore
, 0},
50 {"reserve", s_reserve
, 0},
55 {"pushsection", obj_elf_section
, 0},
56 {"popsection", obj_elf_previous
, 0},
63 const int md_short_jump_size
= 4;
64 const int md_long_jump_size
= 4;
65 const int md_reloc_size
= 12; /* Size of relocation record */
67 /* This array holds the chars that always start a comment. If the
68 pre-processor is disabled, these aren't very useful */
69 const char comment_chars
[] = "#";
71 /* This array holds the chars that only start a comment at the beginning of
72 a line. If the line seems to have the form '# 123 filename'
73 .line and .file directives will appear in the pre-processed output */
74 /* Note that input_file.c hand checks for '#' at the beginning of the
75 first line of the input file. This is because the compiler outputs
76 #NO_APP at the beginning of its output. */
77 /* Also note that comments started like this one will always
78 work if '/' isn't otherwise defined. */
79 const char line_comment_chars
[] = "#";
81 const char line_separator_chars
[] = "";
83 /* Chars that can be used to separate mant from exp in floating point nums */
84 const char EXP_CHARS
[] = "eE";
86 /* Chars that mean this number is a floating point constant */
89 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
91 static const char *arc_condition_codes
[] =
93 "al", "eq", "ne", "p", "n", "c", "nc", "v",
94 "nv", "gt", "ge", "lt", "le", "hi", "ls", "pnz"
97 static struct hash_control
*arc_ops_hash
= NULL
;
98 static struct hash_control
*arc_suffix_hash
= NULL
;
99 static struct hash_control
*arc_reg_hash
= NULL
;
101 const char *md_shortopts
= "m:";
102 struct option md_longopts
[] = {
103 {NULL
, no_argument
, NULL
, 0}
105 size_t md_longopts_size
= sizeof(md_longopts
);
107 /* Non-zero if we accept the mul/mulu and variable shift insns. */
108 static int have_mult
= 0;
113 * Invocation line includes a switch not recognized by the base assembler.
114 * See if it's a processor-specific option.
118 md_parse_option (c
, arg
)
125 if (strcmp (arg
, "mult") == 0)
129 as_bad ("invalid architecture -m%s", arg
);
142 md_show_usage (stream
)
147 -mmult recognize the mul/mulu and variable shift instructions\n");
150 /* This function is called once, at assembler startup time. It should
151 set up all the tables, etc. that the MD part of the assembler will need. */
155 register unsigned int i
= 0;
158 target_big_endian
= 1;
160 if ((arc_ops_hash
= hash_new ()) == NULL
161 || (arc_suffix_hash
= hash_new ()) == NULL
162 || (arc_reg_hash
= hash_new ()) == NULL
)
163 as_fatal ("Virtual memory exhausted");
166 for (i
= 0; i
< arc_opcodes_count
; i
++)
167 hash_insert (arc_ops_hash
, arc_opcodes
[i
].name
, (PTR
) (arc_opcodes
+ i
));
170 /* Only put the first entry of each equivalently named suffix in the
173 for (i
= 0; i
< arc_suffixes_count
; i
++)
175 if (strcmp (arc_suffixes
[i
].name
, last
) != 0)
176 hash_insert (arc_suffix_hash
, arc_suffixes
[i
].name
, (PTR
) (arc_suffixes
+ i
));
177 last
= arc_suffixes
[i
].name
;
180 /* ??? This is the simple version. See tc-arm.c for something snazzier. */
181 for (i
= 0; i
< arc_reg_names_count
; i
++)
182 hash_insert (arc_reg_hash
, arc_reg_names
[i
].name
, (PTR
) (arc_reg_names
+ i
));
184 /* This initializes a few things in arc-opc.c that we need. */
185 arc_opcode_init_tables (have_mult
? ARC_HAVE_MULT_SHIFT
: 0);
188 /* Insert an operand value into an instruction.
189 If REG is non-NULL, it is a register number and ignore VAL. */
192 arc_insert_operand (insn
, operand
, mods
, reg
, val
, file
, line
)
194 const struct arc_operand
*operand
;
196 const struct arc_operand_value
*reg
;
201 if (operand
->bits
!= 32)
206 if ((operand
->flags
& ARC_OPERAND_SIGNED
) != 0)
208 if ((operand
->flags
& ARC_OPERAND_SIGNOPT
) != 0)
209 max
= (1 << operand
->bits
) - 1;
211 max
= (1 << (operand
->bits
- 1)) - 1;
212 min
= - (1 << (operand
->bits
- 1));
216 max
= (1 << operand
->bits
) - 1;
220 if ((operand
->flags
& ARC_OPERAND_NEGATIVE
) != 0)
225 if (test
< (offsetT
) min
|| test
> (offsetT
) max
)
228 "operand out of range (%s not between %ld and %ld)";
231 sprint_value (buf
, test
);
232 if (file
== (char *) NULL
)
233 as_warn (err
, buf
, min
, max
);
235 as_warn_where (file
, line
, err
, buf
, min
, max
);
244 insn
= (*operand
->insert
) (insn
, operand
, mods
, reg
, (long) val
, &errmsg
);
245 if (errmsg
!= (const char *) NULL
)
249 insn
|= (((long) val
& ((1 << operand
->bits
) - 1))
255 /* We need to keep a list of fixups. We can't simply generate them as
256 we go, because that would require us to first create the frag, and
257 that would screw up references to ``.''. */
262 /* index into `arc_operands' */
266 #define MAX_INSN_FIXUPS 5
268 /* This routine is called for each instruction to be assembled. */
274 const struct arc_opcode
*opcode
,*opcode_end
;
277 bfd_reloc_code_real_type reloc
;
279 /* Skip leading white space. */
280 while (isspace (*str
))
283 /* The instructions are sorted by the first letter. Scan the opcode table
284 until we find the right one. */
285 opcode_end
= arc_opcodes
+ arc_opcodes_count
;
286 for (opcode
= arc_opcodes
; opcode
< opcode_end
; opcode
++)
287 if (*opcode
->syntax
== *str
)
289 if (opcode
== opcode_end
)
291 as_bad ("bad instruction `%s'", str
);
295 /* Keep looking until we find a match. If we haven't found a match, and the
296 first character no longer matches, we needn't look any further. */
298 for ( ; opcode
< opcode_end
&& *opcode
->syntax
== *start
; ++opcode
)
302 struct arc_fixup fixups
[MAX_INSN_FIXUPS
];
305 /* Scan the syntax string. If it doesn't match, try the next one. */
307 arc_opcode_init_insert ();
308 insn
= opcode
->value
;
309 reloc
= BFD_RELOC_NONE
;
313 /* Used as a sanity check. If we need a limm reloc, make sure we ask
314 for an extra 4 bytes from frag_more. */
317 /* We don't check for (*str != '\0') here because we want to parse
318 any trailing fake arguments in the syntax string. */
319 for (str
= start
, syn
= opcode
->syntax
; *syn
!= '\0'; )
322 const struct arc_operand
*operand
;
324 /* Non operand chars must match exactly. */
325 if (*syn
!= '%' || *++syn
== '%')
327 /* Handle '+' specially as we want to allow "ld r0,[sp-4]". */
328 if (*syn
== '+' && *str
== '-')
330 /* Skip over syn's +, but leave str's - alone.
331 That makes the case identical to "ld r0,[sp+-4]". */
334 else if (*str
!= *syn
)
346 /* We have an operand. Pick out any modifiers. */
348 while (ARC_MOD_P (arc_operands
[arc_operand_map
[*syn
]].flags
))
350 mods
|= arc_operands
[arc_operand_map
[*syn
]].flags
& ARC_MOD_BITS
;
353 operand
= arc_operands
+ arc_operand_map
[*syn
];
354 if (operand
->fmt
== 0)
355 as_fatal ("unknown syntax format character `%c'", *syn
);
357 if (operand
->flags
& ARC_OPERAND_FAKE
)
359 const char *errmsg
= NULL
;
362 insn
= (*operand
->insert
) (insn
, operand
, mods
, NULL
, 0, &errmsg
);
363 /* If we get an error, go on to try the next insn. */
369 /* Are we finished with suffixes? */
370 else if (!past_opcode_p
)
375 const struct arc_operand_value
*suf
,*suffix
,*suffix_end
;
377 if (!(operand
->flags
& ARC_OPERAND_SUFFIX
))
380 /* If we're at a space in the input string, we want to skip the
381 remaining suffixes. There may be some fake ones though, so
382 just go on to try the next one. */
390 if (mods
& ARC_MOD_DOT
)
398 /* This can happen in "b.nd foo" and we're currently looking
399 for "%q" (ie: a condition code suffix). */
407 /* Pick the suffix out and look it up via the hash table. */
408 for (t
= s
; *t
&& isalpha (*t
); ++t
)
412 suf
= hash_find (arc_suffix_hash
, s
);
416 /* This can happen in "blle foo" and we're currently using
417 the template "b%q%.n %j". The "bl" insn occurs later in
418 the table so "lle" isn't an illegal suffix. */
422 /* Is it the right type? Note that the same character is used
423 several times, so we have to examine all of them. This is
424 relatively efficient as equivalent entries are kept
425 together. If it's not the right type, don't increment `str'
426 so we try the next one in the series. */
428 suffix_end
= arc_suffixes
+ arc_suffixes_count
;
430 suffix
< suffix_end
&& strcmp (suffix
->name
, suf
->name
) == 0;
433 if (arc_operands
[suffix
->type
].fmt
== *syn
)
435 /* Insert the suffix's value into the insn. */
437 insn
= (*operand
->insert
) (insn
, operand
,
438 mods
, NULL
, suffix
->value
,
441 insn
|= suffix
->value
<< operand
->shift
;
450 /* There's nothing to do except, go on to try the next one.
451 ??? This test can be deleted when we're done. */
455 /* This is either a register or an expression of some kind. */
459 const struct arc_operand_value
*reg
;
463 if (operand
->flags
& ARC_OPERAND_SUFFIX
)
466 /* Is there anything left to parse?
467 We don't check for this at the top because we want to parse
468 any trailing fake arguments in the syntax string. */
472 /* Is this a syntax character? Eg: is there a '[' present when
473 there shouldn't be? */
475 /* '.' as in ".LLC0" */
477 /* '_' as in "_print" */
479 /* '-' as in "[fp-4]" */
483 /* Is it a register? */
486 while (*str
&& (isalnum (*str
) || *str
== '_'))
490 reg
= hash_find (arc_reg_hash
, hold
);
494 /* Restore `str', it wasn't a register. */
497 /* Gather the operand. */
498 hold
= input_line_pointer
;
499 input_line_pointer
= str
;
501 str
= input_line_pointer
;
502 input_line_pointer
= hold
;
504 if (ex
.X_op
== O_illegal
)
505 as_bad ("illegal operand");
506 else if (ex
.X_op
== O_absent
)
507 as_bad ("missing operand");
508 else if (ex
.X_op
== O_constant
)
510 value
= ex
.X_add_number
;
514 /* We need to generate a fixup for this expression.
515 If this is a register constant (IE: one whose register
516 value gets stored as 61-63) then this must be a limm.
517 We don't support shimm relocs. */
518 if (fc
>= MAX_INSN_FIXUPS
)
519 as_fatal ("too many fixups");
522 /* ??? This bit could use some cleaning up. Referencing
523 the format chars like this goes against style. */
524 #define IS_REG_OPERAND(o) ((o) == 'a' || (o) == 'b' || (o) == 'c')
525 if (IS_REG_OPERAND (*syn
))
528 fixups
[fc
].opindex
= arc_operand_map
['L'];
530 /* Tell insert_reg we need a limm. This is needed
531 because the value at this point is zero, a shimm.
533 (*arc_operands
[arc_operand_map
['Q']].insert
)
534 (insn
, operand
, mods
, reg
, 0L, &junk
);
537 fixups
[fc
].opindex
= arc_operand_map
[*syn
];
543 /* Insert the register or expression into the instruction. */
546 const char *errmsg
= NULL
;
547 insn
= (*operand
->insert
) (insn
, operand
, mods
,
548 reg
, (long) value
, &errmsg
);
550 if (errmsg
!= (const char *) NULL
)
553 /* FIXME: We want to try shimm insns for limm ones. But if
554 the constant won't fit, we must go on to try the next
555 possibility. Where do we issue warnings for constants
556 that are too big then? At present, we'll flag the insn
557 as unrecognizable! Maybe have the "bad instruction"
558 error message include our `errmsg'? */
559 if (errmsg
!= (const char *) NULL
)
563 insn
|= (value
& ((1 << operand
->bits
) - 1)) << operand
->shift
;
575 /* We've found a matching insn.
576 ??? For the moment we assume a valid `str' can only contain blanks
577 now. IE: We needn't try again with a longer version of the
580 while (isspace (*str
))
584 as_bad ("junk at end of line: `%s'", str
);
586 /* Write out the instruction. */
588 md_number_to_chars (f
, insn
, 4);
590 if (arc_opcode_limm_p (&limm
))
592 char *f2
= frag_more (4);
593 md_number_to_chars (f2
, limm
, 4);
595 else if (limm_reloc_p
)
596 /* Ahh! We need a limm reloc, but the tables think we don't. */
599 /* Create any fixups. At this point we do not use a
600 bfd_reloc_code_real_type, but instead just use the operand index.
601 This lets us easily handle fixups for any operand type, although
602 that is admittedly not a very exciting feature. We pick a BFD
603 reloc type in md_apply_fix. */
604 for (i
= 0; i
< fc
; i
++)
606 const struct arc_operand
*operand
;
608 operand
= &arc_operands
[fixups
[i
].opindex
];
609 fix_new_exp (frag_now
,
610 ((f
- frag_now
->fr_literal
)
611 + (operand
->fmt
== 'L' ? 4 : 0)), 4,
613 (operand
->flags
& ARC_OPERAND_RELATIVE
) != 0,
614 ((bfd_reloc_code_real_type
)
615 (fixups
[i
].opindex
+ (int) BFD_RELOC_UNUSED
)));
622 /* Try the next entry. */
625 as_bad ("bad instruction `%s'", start
);
629 * sort of like s_lcomm
633 static int max_alignment
= 15;
648 name
= input_line_pointer
;
649 c
= get_symbol_end ();
650 p
= input_line_pointer
;
654 if (*input_line_pointer
!= ',')
656 as_bad ("Expected comma after name");
657 ignore_rest_of_line ();
661 ++input_line_pointer
;
663 if ((size
= get_absolute_expression ()) < 0)
665 as_bad ("BSS length (%d.) <0! Ignored.", size
);
666 ignore_rest_of_line ();
671 symbolP
= symbol_find_or_make (name
);
674 if (strncmp (input_line_pointer
, ",\"bss\"", 6) != 0
675 && strncmp (input_line_pointer
, ",\".bss\"", 7) != 0)
677 as_bad ("bad .reserve segment -- expected BSS segment");
681 if (input_line_pointer
[2] == '.')
682 input_line_pointer
+= 7;
684 input_line_pointer
+= 6;
687 if (*input_line_pointer
== ',')
689 ++input_line_pointer
;
692 if (*input_line_pointer
== '\n')
694 as_bad ("Missing alignment");
698 align
= get_absolute_expression ();
700 if (align
> max_alignment
)
702 align
= max_alignment
;
703 as_warn ("Alignment too large: %d. assumed.", align
);
709 as_warn ("Alignment negative. 0 assumed.");
712 record_alignment (bss_section
, align
);
714 /* convert to a power of 2 alignment */
715 for (temp
= 0; (align
& 1) == 0; align
>>= 1, ++temp
);;
719 as_bad ("Alignment not a power of 2");
720 ignore_rest_of_line ();
722 } /* not a power of two */
725 } /* if has optional alignment */
729 if ((S_GET_SEGMENT (symbolP
) == bss_section
730 || !S_IS_DEFINED (symbolP
))
732 && S_GET_OTHER (symbolP
) == 0
733 && S_GET_DESC (symbolP
) == 0
740 segT current_seg
= now_seg
;
741 subsegT current_subseg
= now_subseg
;
743 subseg_set (bss_section
, 1); /* switch to bss */
746 frag_align (align
, 0); /* do alignment */
748 /* detach from old frag */
749 if (S_GET_SEGMENT(symbolP
) == bss_section
)
750 symbolP
->sy_frag
->fr_symbol
= NULL
;
752 symbolP
->sy_frag
= frag_now
;
753 pfrag
= frag_var (rs_org
, 1, 1, (relax_substateT
)0, symbolP
,
757 S_SET_SEGMENT (symbolP
, bss_section
);
759 subseg_set (current_seg
, current_subseg
);
764 as_warn("Ignoring attempt to re-define symbol %s.", name
);
765 } /* if not redefining */
767 demand_empty_rest_of_line ();
780 name
= input_line_pointer
;
781 c
= get_symbol_end ();
782 /* just after name is now '\0' */
783 p
= input_line_pointer
;
786 if (*input_line_pointer
!= ',')
788 as_bad ("Expected comma after symbol-name");
789 ignore_rest_of_line ();
792 input_line_pointer
++; /* skip ',' */
793 if ((temp
= get_absolute_expression ()) < 0)
795 as_bad (".COMMon length (%d.) <0! Ignored.", temp
);
796 ignore_rest_of_line ();
801 symbolP
= symbol_find_or_make (name
);
803 if (S_IS_DEFINED (symbolP
))
805 as_bad ("Ignoring attempt to re-define symbol");
806 ignore_rest_of_line ();
809 if (S_GET_VALUE (symbolP
) != 0)
811 if (S_GET_VALUE (symbolP
) != size
)
813 as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
814 S_GET_NAME (symbolP
), (long) S_GET_VALUE (symbolP
), size
);
820 S_SET_VALUE (symbolP
, (valueT
) size
);
821 S_SET_EXTERNAL (symbolP
);
824 assert (symbolP
->sy_frag
== &zero_address_frag
);
825 if (*input_line_pointer
!= ',')
827 as_bad ("Expected comma after common length");
828 ignore_rest_of_line ();
831 input_line_pointer
++;
833 if (*input_line_pointer
!= '"')
835 temp
= get_absolute_expression ();
837 if (temp
> max_alignment
)
839 temp
= max_alignment
;
840 as_warn ("Common alignment too large: %d. assumed", temp
);
846 as_warn ("Common alignment negative; 0 assumed");
858 old_subsec
= now_subseg
;
860 record_alignment (bss_section
, align
);
861 subseg_set (bss_section
, 0);
863 frag_align (align
, 0);
864 if (S_GET_SEGMENT (symbolP
) == bss_section
)
865 symbolP
->sy_frag
->fr_symbol
= 0;
866 symbolP
->sy_frag
= frag_now
;
867 p
= frag_var (rs_org
, 1, 1, (relax_substateT
) 0, symbolP
, size
,
870 S_SET_SEGMENT (symbolP
, bss_section
);
871 S_CLEAR_EXTERNAL (symbolP
);
872 subseg_set (old_sec
, old_subsec
);
878 S_SET_VALUE (symbolP
, (valueT
) size
);
880 S_SET_ALIGN (symbolP
, temp
);
882 S_SET_EXTERNAL (symbolP
);
883 /* should be common, but this is how gas does it for now */
884 S_SET_SEGMENT (symbolP
, bfd_und_section_ptr
);
889 input_line_pointer
++;
890 /* @@ Some use the dot, some don't. Can we get some consistency?? */
891 if (*input_line_pointer
== '.')
892 input_line_pointer
++;
893 /* @@ Some say data, some say bss. */
894 if (strncmp (input_line_pointer
, "bss\"", 4)
895 && strncmp (input_line_pointer
, "data\"", 5))
897 while (*--input_line_pointer
!= '"')
899 input_line_pointer
--;
900 goto bad_common_segment
;
902 while (*input_line_pointer
++ != '"')
904 goto allocate_common
;
906 demand_empty_rest_of_line ();
911 p
= input_line_pointer
;
912 while (*p
&& *p
!= '\n')
916 as_bad ("bad .common segment %s", input_line_pointer
+ 1);
918 input_line_pointer
= p
;
919 ignore_rest_of_line ();
929 if (strncmp (input_line_pointer
, "\"text\"", 6) == 0)
931 input_line_pointer
+= 6;
935 if (strncmp (input_line_pointer
, "\"data\"", 6) == 0)
937 input_line_pointer
+= 6;
941 if (strncmp (input_line_pointer
, "\"data1\"", 7) == 0)
943 input_line_pointer
+= 7;
947 if (strncmp (input_line_pointer
, "\"bss\"", 5) == 0)
949 input_line_pointer
+= 5;
950 /* We only support 2 segments -- text and data -- for now, so
951 things in the "bss segment" will have to go into data for now.
952 You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
953 subseg_set (data_section
, 255); /* FIXME-SOMEDAY */
956 as_bad ("Unknown segment type");
957 demand_empty_rest_of_line ();
963 subseg_set (data_section
, 1);
964 demand_empty_rest_of_line ();
971 while (!is_end_of_line
[(unsigned char) *input_line_pointer
])
973 ++input_line_pointer
;
975 ++input_line_pointer
;
978 /* Turn a string in input_line_pointer into a floating point constant of type
979 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
980 emitted is stored in *sizeP.
981 An error message is returned, or NULL on OK. */
983 /* Equal to MAX_PRECISION in atof-ieee.c */
984 #define MAX_LITTLENUMS 6
987 md_atof (type
, litP
, sizeP
)
993 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
994 LITTLENUM_TYPE
*wordP
;
1012 return "bad call to md_atof";
1015 t
= atof_ieee (input_line_pointer
, type
, words
);
1017 input_line_pointer
= t
;
1018 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
1019 for (wordP
= words
; prec
--;)
1021 md_number_to_chars (litP
, (valueT
) (*wordP
++), sizeof (LITTLENUM_TYPE
));
1022 litP
+= sizeof (LITTLENUM_TYPE
);
1028 /* Write a value out to the object file, using the appropriate
1032 md_number_to_chars (buf
, val
, n
)
1037 number_to_chars_bigendian (buf
, val
, n
);
1040 /* Round up a section size to the appropriate boundary. */
1043 md_section_align (segment
, size
)
1047 int align
= bfd_get_section_alignment (stdoutput
, segment
);
1049 return ((size
+ (1 << align
) - 1) & (-1 << align
));
1052 /* We don't have any form of relaxing. */
1055 md_estimate_size_before_relax (fragp
, seg
)
1062 const relax_typeS md_relax_table
[] =
1067 /* Convert a machine dependent frag. We never generate these. */
1070 md_convert_frag (abfd
, sec
, fragp
)
1078 /* Parse an operand that is machine-specific.
1079 We just return without modifying the expression if we have nothing to do. */
1083 md_operand (expressionP
)
1084 expressionS
*expressionP
;
1088 /* We have no need to default values of symbols. */
1092 md_undefined_symbol (name
)
1096 } /* md_undefined_symbol() */
1098 /* Functions concerning relocs. */
1100 /* The location from which a PC relative jump should be calculated,
1101 given a PC relative reloc. */
1104 md_pcrel_from (fixP
)
1107 if (fixP
->fx_addsy
!= (symbolS
*) NULL
1108 && ! S_IS_DEFINED (fixP
->fx_addsy
))
1110 /* This makes a branch to an undefined symbol be a branch to the
1111 current location. */
1115 /* Return the address of the delay slot. */
1116 return fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ fixP
->fx_size
;
1119 /* Apply a fixup to the object code. This is called for all the
1120 fixups we generated by the call to fix_new_exp, above. In the call
1121 above we used a reloc code which was the largest legal reloc code
1122 plus the operand index. Here we undo that to recover the operand
1123 index. At this point all symbol values should be fully resolved,
1124 and we attempt to completely resolve the reloc. If we can not do
1125 that, we determine the correct reloc code and put it back in the
1129 md_apply_fix (fixP
, valueP
)
1133 /*char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;*/
1136 /* FIXME FIXME FIXME: The value we are passed in *valueP includes
1137 the symbol values. Since we are using BFD_ASSEMBLER, if we are
1138 doing this relocation the code in write.c is going to call
1139 bfd_perform_relocation, which is also going to use the symbol
1140 value. That means that if the reloc is fully resolved we want to
1141 use *valueP since bfd_perform_relocation is not being used.
1142 However, if the reloc is not fully resolved we do not want to use
1143 *valueP, and must use fx_offset instead. However, if the reloc
1144 is PC relative, we do want to use *valueP since it includes the
1145 result of md_pcrel_from. This is confusing. */
1147 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
1152 else if (fixP
->fx_pcrel
)
1156 value
= fixP
->fx_offset
;
1157 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
1159 if (S_GET_SEGMENT (fixP
->fx_subsy
) == absolute_section
)
1160 value
-= S_GET_VALUE (fixP
->fx_subsy
);
1163 /* We can't actually support subtracting a symbol. */
1164 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
1165 "expression too complex");
1170 if ((int) fixP
->fx_r_type
>= (int) BFD_RELOC_UNUSED
)
1173 const struct arc_operand
*operand
;
1177 opindex
= (int) fixP
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1179 operand
= &arc_operands
[opindex
];
1181 /* Fetch the instruction, insert the fully resolved operand
1182 value, and stuff the instruction back again. */
1183 where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
1184 insn
= bfd_getb32 ((unsigned char *) where
);
1185 insn
= arc_insert_operand (insn
, operand
, -1, NULL
, (offsetT
) value
,
1186 fixP
->fx_file
, fixP
->fx_line
);
1187 bfd_putb32 ((bfd_vma
) insn
, (unsigned char *) where
);
1191 /* Nothing else to do here. */
1195 /* Determine a BFD reloc value based on the operand information.
1196 We are only prepared to turn a few of the operands into relocs.
1197 FIXME: Selecting the reloc type is a bit haphazard; perhaps
1198 there should be a new field in the operand table. */
1199 if ((operand
->flags
& ARC_OPERAND_RELATIVE
) != 0
1200 && operand
->bits
== 20
1201 && operand
->shift
== 7)
1202 fixP
->fx_r_type
= BFD_RELOC_ARC_B22_PCREL
;
1203 else if ((operand
->flags
& ARC_OPERAND_ABSOLUTE
) != 0
1204 && operand
->bits
== 32
1205 && operand
->shift
== 32)
1206 fixP
->fx_r_type
= BFD_RELOC_32
;
1209 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
1210 "unresolved expression that must be resolved");
1217 switch (fixP
->fx_r_type
)
1220 md_number_to_chars (fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
,
1224 md_number_to_chars (fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
,
1228 md_number_to_chars (fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
,
1237 fixP
->fx_addnumber
= value
;
1239 fixP
->fx_addnumber
= 0;
1245 /* Translate internal representation of relocation info to BFD target
1249 tc_gen_reloc (section
, fixP
)
1255 reloc
= (arelent
*) bfd_alloc_by_size_t (stdoutput
, sizeof (arelent
));
1257 reloc
->sym_ptr_ptr
= &fixP
->fx_addsy
->bsym
;
1258 reloc
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
1259 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixP
->fx_r_type
);
1260 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
1262 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
1263 "internal error: can't export reloc type %d (`%s')",
1264 fixP
->fx_r_type
, bfd_get_reloc_code_name (fixP
->fx_r_type
));
1267 reloc
->addend
= fixP
->fx_addnumber
;
1269 assert (!fixP
->fx_pcrel
== !reloc
->howto
->pc_relative
);