1 /* tc-i860.c -- Assembler for the Intel i860 architecture.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1998, 1999, 2000
3 Free Software Foundation, Inc.
5 Brought back from the dead and completely reworked
6 by Jason Eckhardt <jle@cygnus.com>.
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License along
21 with GAS; see the file COPYING. If not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
29 #include "opcode/i860.h"
33 /* Defined by default since this is primarily a SVR4/860 assembler.
34 However, I'm trying to leave the door open for Intel syntax. Of course,
35 if full support for anything other than SVR4 is done, then we should
36 select this based on a command-line flag. */
40 /* The opcode hash table. */
41 static struct hash_control
*op_hash
= NULL
;
43 /* These characters always start a comment. */
44 const char comment_chars
[] = "#!/";
46 /* These characters start a comment at the beginning of a line. */
47 const char line_comment_chars
[] = "#/";
49 const char line_separator_chars
[] = ";";
51 /* Characters that can be used to separate the mantissa from the exponent
52 in floating point numbers. */
53 const char EXP_CHARS
[] = "eE";
55 /* Characters that indicate this number is a floating point constant.
56 As in 0f12.456 or 0d1.2345e12. */
57 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
60 /* Register prefix. */
62 static const char reg_prefix
= '%';
64 static const char reg_prefix
= 0;
73 enum expand_type expand
;
74 bfd_reloc_code_real_type reloc
;
79 static char *expr_end
;
81 /* Indicates error if a pseudo operation was expanded after a branch. */
82 static char last_expand
;
84 /* If true, then warn if any pseudo operations were expanded. */
85 static int target_warn_expand
= 0;
89 static void i860_process_insn
PARAMS ((char *));
90 static void s_dual
PARAMS ((int));
91 static void s_enddual
PARAMS ((int));
92 static void s_atmp
PARAMS ((int));
93 static int i860_get_expression
PARAMS ((char *));
94 static bfd_reloc_code_real_type obtain_reloc_for_imm16
95 PARAMS ((fixS
*, long *));
97 static void print_insn
PARAMS ((struct i860_it
*));
101 const pseudo_typeS md_pseudo_table
[] =
104 {"align", s_align_bytes
, 0},
107 {"enddual", s_enddual
, 0},
113 /* Dual-instruction mode handling. */
116 DUAL_OFF
= 0, DUAL_ON
, DUAL_DDOT
, DUAL_ONDDOT
,
118 static enum dual dual_mode
= DUAL_OFF
;
121 /* Handle ".dual" directive. */
124 int ignore ATTRIBUTE_UNUSED
;
130 /* Handle ".enddual" directive. */
133 int ignore ATTRIBUTE_UNUSED
;
135 dual_mode
= DUAL_OFF
;
139 /* Temporary register used when expanding assembler pseudo operations. */
140 static int atmp
= 31;
144 int ignore ATTRIBUTE_UNUSED
;
147 if (strncmp (input_line_pointer
, "sp", 2) == 0)
149 input_line_pointer
+= 2;
152 else if (strncmp (input_line_pointer
, "fp", 2) == 0)
154 input_line_pointer
+= 2;
157 else if (strncmp (input_line_pointer
, "r", 1) == 0)
159 input_line_pointer
+= 1;
160 temp
= get_absolute_expression ();
161 if (temp
>= 0 && temp
<= 31)
164 as_bad (_("Unknown temporary pseudo register"));
168 as_bad (_("Unknown temporary pseudo register"));
170 demand_empty_rest_of_line ();
174 /* This function is called once, at assembler startup time. It should
175 set up all the tables and data structures that the MD part of the
176 assembler will need. */
180 const char *retval
= NULL
;
184 op_hash
= hash_new ();
186 while (i860_opcodes
[i
].name
!= NULL
)
188 const char *name
= i860_opcodes
[i
].name
;
189 retval
= hash_insert (op_hash
, name
, (PTR
)&i860_opcodes
[i
]);
192 fprintf (stderr
, _("internal error: can't hash `%s': %s\n"),
193 i860_opcodes
[i
].name
, retval
);
198 if (i860_opcodes
[i
].match
& i860_opcodes
[i
].lose
)
201 _("internal error: losing opcode: `%s' \"%s\"\n"),
202 i860_opcodes
[i
].name
, i860_opcodes
[i
].args
);
207 while (i860_opcodes
[i
].name
!= NULL
208 && strcmp (i860_opcodes
[i
].name
, name
) == 0);
212 as_fatal (_("Defective assembler. No assembly attempted."));
216 /* This is the core of the machine-dependent assembler. STR points to a
217 machine dependent instruction. This function emits the frags/bytes
226 struct i860_it pseudo
[3];
230 /* Assemble the instruction. */
231 i860_process_insn (str
);
233 /* Check for expandable flag to produce pseudo-instructions. This
234 is an undesirable feature that should be avoided. */
235 if (the_insn
.expand
!= 0
236 && ! (the_insn
.fup
& (OP_SEL_HA
| OP_SEL_H
| OP_SEL_L
| OP_SEL_GOT
237 | OP_SEL_GOTOFF
| OP_SEL_PLT
)))
239 for (i
= 0; i
< 3; i
++)
240 pseudo
[i
] = the_insn
;
242 switch (the_insn
.expand
)
250 if (the_insn
.exp
.X_add_symbol
== NULL
251 && the_insn
.exp
.X_op_symbol
== NULL
252 && (the_insn
.exp
.X_add_number
< (1 << 15)
253 && the_insn
.exp
.X_add_number
>= -(1 << 15)))
256 /* Emit "or l%const,r0,ireg_dest". */
257 pseudo
[0].opcode
= (the_insn
.opcode
& 0x001f0000) | 0xe4000000;
258 pseudo
[0].fup
= (OP_IMM_S16
| OP_SEL_L
);
260 /* Emit "orh h%const,ireg_dest,ireg_dest". */
261 pseudo
[1].opcode
= (the_insn
.opcode
& 0x03ffffff) | 0xec000000
262 | ((the_insn
.opcode
& 0x001f0000) << 5);
263 pseudo
[1].fup
= (OP_IMM_S16
| OP_SEL_H
);
269 if (the_insn
.exp
.X_add_symbol
== NULL
270 && the_insn
.exp
.X_op_symbol
== NULL
271 && (the_insn
.exp
.X_add_number
< (1 << 15)
272 && the_insn
.exp
.X_add_number
>= -(1 << 15)))
275 /* Emit "orh ha%addr_expr,r0,r31". */
276 pseudo
[0].opcode
= 0xec000000 | (atmp
<< 16);
277 pseudo
[0].fup
= (OP_IMM_S16
| OP_SEL_HA
);
279 /* Emit "l%addr_expr(r31),ireg_dest". We pick up the fixup
280 information from the original instruction. */
281 pseudo
[1].opcode
= (the_insn
.opcode
& ~0x03e00000) | (atmp
<< 21);
282 pseudo
[1].fup
= the_insn
.fup
| OP_SEL_L
;
288 if (the_insn
.exp
.X_add_symbol
== NULL
289 && the_insn
.exp
.X_op_symbol
== NULL
290 && (the_insn
.exp
.X_add_number
< (1 << 16)
291 && the_insn
.exp
.X_add_number
>= 0))
294 /* Emit "$(opcode)h h%const,ireg_src2,r31". */
295 pseudo
[0].opcode
= (the_insn
.opcode
& 0xf3e0ffff) | 0x0c000000
297 pseudo
[0].fup
= (OP_IMM_S16
| OP_SEL_H
);
299 /* Emit "$(opcode) l%const,r31,ireg_dest". */
300 pseudo
[1].opcode
= (the_insn
.opcode
& 0xf01f0000) | 0x04000000
302 pseudo
[1].fup
= (OP_IMM_S16
| OP_SEL_L
);
308 if (the_insn
.exp
.X_add_symbol
== NULL
309 && the_insn
.exp
.X_op_symbol
== NULL
310 && (the_insn
.exp
.X_add_number
< (1 << 16)
311 && the_insn
.exp
.X_add_number
>= 0))
314 /* Emit "andnot h%const,ireg_src2,r31". */
315 pseudo
[0].opcode
= (the_insn
.opcode
& 0x03e0ffff) | 0xd4000000
317 pseudo
[0].fup
= (OP_IMM_S16
| OP_SEL_H
);
318 pseudo
[0].exp
.X_add_number
= -1 - the_insn
.exp
.X_add_number
;
320 /* Emit "andnot l%const,r31,ireg_dest". */
321 pseudo
[1].opcode
= (the_insn
.opcode
& 0x001f0000) | 0xd4000000
323 pseudo
[1].fup
= (OP_IMM_S16
| OP_SEL_L
);
324 pseudo
[1].exp
.X_add_number
= -1 - the_insn
.exp
.X_add_number
;
330 if (the_insn
.exp
.X_add_symbol
== NULL
331 && the_insn
.exp
.X_op_symbol
== NULL
332 && (the_insn
.exp
.X_add_number
< (1 << 15)
333 && the_insn
.exp
.X_add_number
>= -(1 << 15)))
336 /* Emit "orh h%const,r0,r31". */
337 pseudo
[0].opcode
= 0xec000000 | (atmp
<< 16);
338 pseudo
[0].fup
= (OP_IMM_S16
| OP_SEL_H
);
340 /* Emit "or l%const,r31,r31". */
341 pseudo
[1].opcode
= 0xe4000000 | (atmp
<< 21) | (atmp
<< 16);
342 pseudo
[1].fup
= (OP_IMM_S16
| OP_SEL_L
);
344 /* Emit "r31,ireg_src2,ireg_dest". */
345 pseudo
[2].opcode
= (the_insn
.opcode
& ~0x0400ffff) | (atmp
<< 11);
346 pseudo
[2].fup
= OP_IMM_S16
;
352 as_fatal (_("failed sanity check."));
355 the_insn
= pseudo
[0];
357 /* Warn if an opcode is expanded after a delayed branch. */
358 if (num_opcodes
> 1 && last_expand
== 1)
359 as_warn (_("Expanded opcode after delayed branch: `%s'"), str
);
361 /* Warn if an opcode is expanded in dual mode. */
362 if (num_opcodes
> 1 && dual_mode
!= DUAL_OFF
)
363 as_warn (_("Expanded opcode in dual mode: `%s'"), str
);
365 /* Notify if any expansions happen. */
366 if (target_warn_expand
&& num_opcodes
> 1)
367 as_warn (_("An instruction was expanded (%s)"), str
);
373 /* Output the opcode. Note that the i860 always reads instructions
374 as little-endian data. */
375 destp
= frag_more (4);
376 number_to_chars_littleendian (destp
, the_insn
.opcode
, 4);
378 /* Check for expanded opcode after branch or in dual mode. */
379 last_expand
= the_insn
.pcrel
;
381 /* Output the symbol-dependent stuff. */
382 if (the_insn
.fup
!= OP_NONE
)
385 fix
= fix_new_exp (frag_now
,
386 destp
- frag_now
->fr_literal
,
392 /* Despite the odd name, this is a scratch field. We use
393 it to encode operand type information. */
394 fix
->fx_addnumber
= the_insn
.fup
;
396 the_insn
= pseudo
[++i
];
398 while (--num_opcodes
> 0);
403 /* Assemble the instruction pointed to by STR. */
405 i860_process_insn (str
)
411 struct i860_opcode
*insn
;
413 unsigned long opcode
;
418 #if 1 /* For compiler warnings. */
425 for (s
= str
; islower (*s
) || *s
== '.' || *s
== '3'
426 || *s
== '2' || *s
== '1'; ++s
)
444 as_fatal (_("Unknown opcode: `%s'"), str
);
447 /* Check for dual mode ("d.") opcode prefix. */
448 if (strncmp (str
, "d.", 2) == 0)
450 if (dual_mode
== DUAL_ON
)
451 dual_mode
= DUAL_ONDDOT
;
453 dual_mode
= DUAL_DDOT
;
457 if ((insn
= (struct i860_opcode
*) hash_find (op_hash
, str
)) == NULL
)
459 if (dual_mode
== DUAL_DDOT
|| dual_mode
== DUAL_ONDDOT
)
461 as_bad (_("Unknown opcode: `%s'"), str
);
471 opcode
= insn
->match
;
472 memset (&the_insn
, '\0', sizeof (the_insn
));
473 the_insn
.reloc
= BFD_RELOC_NONE
;
475 the_insn
.fup
= OP_NONE
;
477 /* Build the opcode, checking as we go that the operands match. */
478 for (args
= insn
->args
; ; ++args
)
489 /* These must match exactly. */
499 /* Must be at least one digit. */
509 /* Next operand must be a register. */
513 /* Check for register prefix if necessary. */
514 if (reg_prefix
&& *s
!= reg_prefix
)
541 /* Any register r0..r31. */
544 if (!isdigit (c
= *s
++))
550 if ((c
= 10 * (c
- '0') + (*s
++ - '0')) >= 32)
558 /* Not this opcode. */
563 /* Obtained the register, now place it in the opcode. */
567 opcode
|= mask
<< 11;
571 opcode
|= mask
<< 21;
575 opcode
|= mask
<< 16;
581 /* Next operand is a floating point register. */
585 /* Check for register prefix if necessary. */
586 if (reg_prefix
&& *s
!= reg_prefix
)
591 if (*s
++ == 'f' && isdigit (*s
))
596 mask
= 10 * (mask
- '0') + (*s
++ - '0');
609 opcode
|= mask
<< 11;
613 opcode
|= mask
<< 21;
617 opcode
|= mask
<< 16;
618 if (dual_mode
!= DUAL_OFF
)
620 if (dual_mode
== DUAL_DDOT
)
621 dual_mode
= DUAL_OFF
;
622 if (dual_mode
== DUAL_ONDDOT
)
624 if ((opcode
& (1 << 10)) && mask
!= 0
625 && (mask
== ((opcode
>> 11) & 0x1f)))
626 as_warn (_("Pipelined instruction: fsrc1 = fdest"));
632 /* Next operand must be a control register. */
634 /* Check for register prefix if necessary. */
635 if (reg_prefix
&& *s
!= reg_prefix
)
640 if (strncmp (s
, "fir", 3) == 0)
646 if (strncmp (s
, "psr", 3) == 0)
652 if (strncmp (s
, "dirbase", 7) == 0)
658 if (strncmp (s
, "db", 2) == 0)
664 if (strncmp (s
, "fsr", 3) == 0)
670 if (strncmp (s
, "epsr", 4) == 0)
678 /* 5-bit immediate in src1. */
680 if (! i860_get_expression (s
))
683 the_insn
.fup
|= OP_IMM_U5
;
688 /* 26-bit immediate, relative branch (lbroff). */
691 the_insn
.fup
|= OP_IMM_BR26
;
694 /* 16-bit split immediate, relative branch (sbroff). */
697 the_insn
.fup
|= OP_IMM_BR16
;
700 /* 16-bit split immediate. */
702 the_insn
.fup
|= OP_IMM_SPLIT16
;
705 /* 16-bit split immediate, byte aligned (st.b). */
707 the_insn
.fup
|= OP_IMM_SPLIT16
;
710 /* 16-bit split immediate, half-word aligned (st.s). */
712 the_insn
.fup
|= (OP_IMM_SPLIT16
| OP_ENCODE1
| OP_ALIGN2
);
715 /* 16-bit split immediate, word aligned (st.l). */
717 the_insn
.fup
|= (OP_IMM_SPLIT16
| OP_ENCODE1
| OP_ALIGN4
);
720 /* 16-bit immediate. */
722 the_insn
.fup
|= OP_IMM_S16
;
725 /* 16-bit immediate, byte aligned (ld.b). */
727 the_insn
.fup
|= OP_IMM_S16
;
730 /* 16-bit immediate, half-word aligned (ld.s). */
732 the_insn
.fup
|= (OP_IMM_S16
| OP_ENCODE1
| OP_ALIGN2
);
735 /* 16-bit immediate, word aligned (ld.l, {p}fld.l, fst.l). */
737 if (insn
->name
[0] == 'l')
738 the_insn
.fup
|= (OP_IMM_S16
| OP_ENCODE1
| OP_ALIGN4
);
740 the_insn
.fup
|= (OP_IMM_S16
| OP_ENCODE2
| OP_ALIGN4
);
743 /* 16-bit immediate, double-word aligned ({p}fld.d, fst.d). */
745 the_insn
.fup
|= (OP_IMM_S16
| OP_ENCODE3
| OP_ALIGN8
);
748 /* 16-bit immediate, quad-word aligned (fld.q, fst.q). */
750 the_insn
.fup
|= (OP_IMM_S16
| OP_ENCODE3
| OP_ALIGN16
);
754 /* Handle the immediate for either the Intel syntax or
755 SVR4 syntax. The Intel syntax is "ha%immediate"
756 whereas SVR4 syntax is "[immediate]@ha". */
762 /* Note that if i860_get_expression() fails, we will still
763 have created U entries in the symbol table for the
764 'symbols' in the input string. Try not to create U
765 symbols for registers, etc. */
766 if (! i860_get_expression (s
))
771 if (strncmp (s
, "@ha", 3) == 0)
773 the_insn
.fup
|= OP_SEL_HA
;
776 else if (strncmp (s
, "@h", 2) == 0)
778 the_insn
.fup
|= OP_SEL_H
;
781 else if (strncmp (s
, "@l", 2) == 0)
783 the_insn
.fup
|= OP_SEL_L
;
786 else if (strncmp (s
, "@gotoff", 7) == 0
787 || strncmp (s
, "@GOTOFF", 7) == 0)
789 as_bad (_("Assembler does not yet support PIC"));
790 the_insn
.fup
|= OP_SEL_GOTOFF
;
793 else if (strncmp (s
, "@got", 4) == 0
794 || strncmp (s
, "@GOT", 4) == 0)
796 as_bad (_("Assembler does not yet support PIC"));
797 the_insn
.fup
|= OP_SEL_GOT
;
800 else if (strncmp (s
, "@plt", 4) == 0
801 || strncmp (s
, "@PLT", 4) == 0)
803 as_bad (_("Assembler does not yet support PIC"));
804 the_insn
.fup
|= OP_SEL_PLT
;
808 the_insn
.expand
= insn
->expand
;
811 #else /* ! SYNTAX_SVR4 */
814 if (strncmp (s
, "ha%", 3) == 0)
816 the_insn
.fup
|= OP_SEL_HA
;
819 else if (strncmp (s
, "h%", 2) == 0)
821 the_insn
.fup
|= OP_SEL_H
;
824 else if (strncmp (s
, "l%", 2) == 0)
826 the_insn
.fup
|= OP_SEL_L
;
829 the_insn
.expand
= insn
->expand
;
831 /* Note that if i860_get_expression() fails, we will still
832 have created U entries in the symbol table for the
833 'symbols' in the input string. Try not to create U
834 symbols for registers, etc. */
835 if (! i860_get_expression (s
))
841 #endif /* SYNTAX_SVR4 */
845 as_fatal (_("failed sanity check."));
852 /* Args don't match. */
853 if (insn
[1].name
!= NULL
854 && ! strcmp (insn
->name
, insn
[1].name
))
862 as_bad (_("Illegal operands for %s"), insn
->name
);
869 the_insn
.opcode
= opcode
;
874 i860_get_expression (str
)
880 save_in
= input_line_pointer
;
881 input_line_pointer
= str
;
882 seg
= expression (&the_insn
.exp
);
883 if (seg
!= absolute_section
884 && seg
!= undefined_section
885 && ! SEG_NORMAL (seg
))
887 the_insn
.error
= _("bad segment");
888 expr_end
= input_line_pointer
;
889 input_line_pointer
= save_in
;
892 expr_end
= input_line_pointer
;
893 input_line_pointer
= save_in
;
898 /* Turn a string in input_line_pointer into a floating point constant of
899 type TYPE, and store the appropriate bytes in *LITP. The number of
900 LITTLENUMS emitted is stored in *SIZEP. An error message is returned,
903 /* Equal to MAX_PRECISION in atof-ieee.c. */
904 #define MAX_LITTLENUMS 6
907 md_atof (type
, litP
, sizeP
)
913 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
914 LITTLENUM_TYPE
*wordP
;
946 return _("Bad call to MD_ATOF()");
948 t
= atof_ieee (input_line_pointer
, type
, words
);
950 input_line_pointer
= t
;
951 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
952 for (wordP
= words
; prec
--;)
954 md_number_to_chars (litP
, (long) (*wordP
++), sizeof (LITTLENUM_TYPE
));
955 litP
+= sizeof (LITTLENUM_TYPE
);
961 /* Write out in current endian mode. */
963 md_number_to_chars (buf
, val
, n
)
968 if (target_big_endian
)
969 number_to_chars_bigendian (buf
, val
, n
);
971 number_to_chars_littleendian (buf
, val
, n
);
975 /* This should never be called for i860. */
977 md_number_to_disp (buf
, val
, n
)
978 char *buf ATTRIBUTE_UNUSED
;
979 long val ATTRIBUTE_UNUSED
;
980 int n ATTRIBUTE_UNUSED
;
982 as_fatal (_("md_number_to_disp\n"));
986 /* This should never be called for i860. */
988 md_number_to_field (buf
, val
, fix
)
989 char *buf ATTRIBUTE_UNUSED
;
990 long val ATTRIBUTE_UNUSED
;
991 void *fix ATTRIBUTE_UNUSED
;
993 as_fatal (_("i860_number_to_field\n"));
997 /* This should never be called for i860. */
999 md_estimate_size_before_relax (fragP
, segtype
)
1000 register fragS
*fragP ATTRIBUTE_UNUSED
;
1001 segT segtype ATTRIBUTE_UNUSED
;
1003 as_fatal (_("i860_estimate_size_before_relax\n"));
1010 struct i860_it
*insn
;
1013 fprintf (stderr
, "ERROR: %s\n", insn
->error
);
1015 fprintf (stderr
, "opcode = 0x%08lx\t", insn
->opcode
);
1016 fprintf (stderr
, "expand = 0x%x\t", insn
->expand
);
1017 fprintf (stderr
, "reloc = %s\t\n",
1018 bfd_get_reloc_code_name (insn
->reloc
));
1019 fprintf (stderr
, "exp = {\n");
1020 fprintf (stderr
, "\t\tX_add_symbol = %s\n",
1021 insn
->exp
.X_add_symbol
?
1022 (S_GET_NAME (insn
->exp
.X_add_symbol
) ?
1023 S_GET_NAME (insn
->exp
.X_add_symbol
) : "???") : "0");
1024 fprintf (stderr
, "\t\tX_op_symbol = %s\n",
1025 insn
->exp
.X_op_symbol
?
1026 (S_GET_NAME (insn
->exp
.X_op_symbol
) ?
1027 S_GET_NAME (insn
->exp
.X_op_symbol
) : "???") : "0");
1028 fprintf (stderr
, "\t\tX_add_number = %lx\n",
1029 insn
->exp
.X_add_number
);
1030 fprintf (stderr
, "}\n");
1032 #endif /* DEBUG_I860 */
1037 CONST
char *md_shortopts
= "VQ:";
1039 CONST
char *md_shortopts
= "";
1043 #define OPTION_EB (OPTION_MD_BASE + 0)
1044 #define OPTION_EL (OPTION_MD_BASE + 1)
1045 #define OPTION_WARN_EXPAND (OPTION_MD_BASE + 2)
1047 struct option md_longopts
[] = {
1048 { "EB", no_argument
, NULL
, OPTION_EB
},
1049 { "EL", no_argument
, NULL
, OPTION_EL
},
1050 { "mwarn-expand", no_argument
, NULL
, OPTION_WARN_EXPAND
},
1051 { NULL
, no_argument
, NULL
, 0 }
1053 size_t md_longopts_size
= sizeof (md_longopts
);
1057 md_parse_option (c
, arg
)
1059 char *arg ATTRIBUTE_UNUSED
;
1064 target_big_endian
= 1;
1068 target_big_endian
= 0;
1071 case OPTION_WARN_EXPAND
:
1072 target_warn_expand
= 1;
1076 /* SVR4 argument compatibility (-V): print version ID. */
1078 print_version_id ();
1081 /* SVR4 argument compatibility (-Qy, -Qn): controls whether
1082 a .comment section should be emitted or not (ignored). */
1096 md_show_usage (stream
)
1099 fprintf (stream
, _("\
1100 -EL generate code for little endian mode (default)\n\
1101 -EB generate code for big endian mode\n\
1102 -mwarn-expand warn if pseudo operations are expanded\n"));
1104 /* SVR4 compatibility flags. */
1105 fprintf (stream
, _("\
1106 -V print assembler version number\n\
1107 -Qy, -Qn ignored\n"));
1112 /* We have no need to default values of symbols. */
1114 md_undefined_symbol (name
)
1115 char *name ATTRIBUTE_UNUSED
;
1121 /* The i860 denotes auto-increment with '++'. */
1128 for (s
= input_line_pointer
; *s
; s
++)
1130 if (s
[0] == '+' && s
[1] == '+')
1132 input_line_pointer
+= 2;
1133 exp
->X_op
= O_register
;
1140 /* Round up a section size to the appropriate boundary. */
1142 md_section_align (segment
, size
)
1143 segT segment ATTRIBUTE_UNUSED
;
1144 valueT size ATTRIBUTE_UNUSED
;
1146 /* Byte alignment is fine. */
1151 /* On the i860, a PC-relative offset is relative to the address of the
1152 of the offset plus its size. */
1154 md_pcrel_from (fixP
)
1157 return fixP
->fx_size
+ fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1161 /* Determine the relocation needed for non PC-relative 16-bit immediates.
1162 Also adjust the given immediate as necessary. Finally, check that
1163 all constraints (such as alignment) are satisfied. */
1164 static bfd_reloc_code_real_type
1165 obtain_reloc_for_imm16 (fix
, val
)
1169 valueT fup
= fix
->fx_addnumber
;
1170 bfd_reloc_code_real_type reloc
;
1175 /* Check alignment restrictions. */
1176 if ((fup
& OP_ALIGN2
) && (*val
& 0x1))
1177 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1178 _("This immediate requires 0 MOD 2 alignment"));
1179 else if ((fup
& OP_ALIGN4
) && (*val
& 0x3))
1180 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1181 _("This immediate requires 0 MOD 4 alignment"));
1182 else if ((fup
& OP_ALIGN8
) && (*val
& 0x7))
1183 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1184 _("This immediate requires 0 MOD 8 alignment"));
1185 else if ((fup
& OP_ALIGN16
) && (*val
& 0xf))
1186 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1187 _("This immediate requires 0 MOD 16 alignment"));
1189 if (fup
& OP_SEL_HA
)
1191 *val
= (*val
>> 16) + (*val
& 0x8000 ? 1 : 0);
1192 reloc
= BFD_RELOC_860_HIGHADJ
;
1194 else if (fup
& OP_SEL_H
)
1197 reloc
= BFD_RELOC_860_HIGH
;
1199 else if (fup
& OP_SEL_L
)
1202 if (fup
& OP_IMM_SPLIT16
)
1204 if (fup
& OP_ENCODE1
)
1207 reloc
= BFD_RELOC_860_SPLIT1
;
1209 else if (fup
& OP_ENCODE2
)
1212 reloc
= BFD_RELOC_860_SPLIT2
;
1217 reloc
= BFD_RELOC_860_SPLIT0
;
1222 if (fup
& OP_ENCODE1
)
1225 reloc
= BFD_RELOC_860_LOW1
;
1227 else if (fup
& OP_ENCODE2
)
1230 reloc
= BFD_RELOC_860_LOW2
;
1232 else if (fup
& OP_ENCODE3
)
1235 reloc
= BFD_RELOC_860_LOW3
;
1240 reloc
= BFD_RELOC_860_LOW0
;
1244 /* Preserve size encode bits. */
1245 *val
&= ~((1 << num_encode
) - 1);
1249 /* No selector. What reloc do we generate (???)? */
1250 reloc
= BFD_RELOC_32
;
1257 /* Attempt to simplify or eliminate a fixup. To indicate that a fixup
1258 has been eliminated, set fix->fx_done. If fix->fx_addsy is non-NULL,
1259 we will have to generate a reloc entry. */
1261 md_apply_fix3 (fix
, valuep
, seg
)
1264 segT seg ATTRIBUTE_UNUSED
;
1268 long val
= (long)(*valuep
);
1272 buf
= fix
->fx_frag
->fr_literal
+ fix
->fx_where
;
1274 /* Recall that earlier we stored the opcode little-endian. */
1275 insn
= bfd_getl32 (buf
);
1277 /* We stored a fix-up in this oddly-named scratch field. */
1278 fup
= fix
->fx_addnumber
;
1280 /* Determine the necessary relocations as well as inserting an
1281 immediate into the instruction. */
1282 if (fup
== OP_IMM_U5
)
1285 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1286 _("5-bit immediate too large"));
1288 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1289 _("5-bit field must be absolute"));
1291 insn
|= (val
& 0x1f) << 11;
1292 bfd_putl32 (insn
, buf
);
1293 fix
->fx_r_type
= BFD_RELOC_NONE
;
1296 else if (fup
& OP_IMM_S16
)
1298 fix
->fx_r_type
= obtain_reloc_for_imm16 (fix
, &val
);
1300 /* Insert the immediate. */
1305 insn
|= val
& 0xffff;
1306 bfd_putl32 (insn
, buf
);
1307 fix
->fx_r_type
= BFD_RELOC_NONE
;
1311 else if (fup
& OP_IMM_U16
)
1315 else if (fup
& OP_IMM_SPLIT16
)
1317 fix
->fx_r_type
= obtain_reloc_for_imm16 (fix
, &val
);
1319 /* Insert the immediate. */
1324 insn
|= val
& 0x7ff;
1325 insn
|= (val
& 0xf800) << 5;
1326 bfd_putl32 (insn
, buf
);
1327 fix
->fx_r_type
= BFD_RELOC_NONE
;
1331 else if (fup
& OP_IMM_BR16
)
1334 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1335 _("A branch offset requires 0 MOD 4 alignment"));
1339 /* Insert the immediate. */
1343 fix
->fx_r_type
= BFD_RELOC_860_PC16
;
1347 insn
|= (val
& 0x7ff);
1348 insn
|= ((val
& 0xf800) << 5);
1349 bfd_putl32 (insn
, buf
);
1350 fix
->fx_r_type
= BFD_RELOC_NONE
;
1354 else if (fup
& OP_IMM_BR26
)
1357 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1358 _("A branch offset requires 0 MOD 4 alignment"));
1362 /* Insert the immediate. */
1365 fix
->fx_r_type
= BFD_RELOC_860_PC26
;
1370 insn
|= (val
& 0x3ffffff);
1371 bfd_putl32 (insn
, buf
);
1372 fix
->fx_r_type
= BFD_RELOC_NONE
;
1376 else if (fup
!= OP_NONE
)
1378 as_bad_where (fix
->fx_file
, fix
->fx_line
,
1379 _("Unrecognized fix-up (0x%08x)"), fup
);
1384 /* I believe only fix-ups such as ".long .ep.main-main+0xc8000000"
1385 reach here (???). */
1388 fix
->fx_r_type
= BFD_RELOC_32
;
1393 insn
|= (val
& 0xffffffff);
1394 bfd_putl32 (insn
, buf
);
1395 fix
->fx_r_type
= BFD_RELOC_NONE
;
1400 /* Return value ignored. */
1405 /* Generate a machine dependent reloc from a fixup. */
1407 tc_gen_reloc (section
, fixp
)
1408 asection
*section ATTRIBUTE_UNUSED
;
1413 reloc
= xmalloc (sizeof (*reloc
));
1414 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
1415 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
1416 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
1417 reloc
->addend
= fixp
->fx_offset
;
1418 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
1422 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
1423 "Cannot represent %s relocation in object file",
1424 bfd_get_reloc_code_name (fixp
->fx_r_type
));