source: trunk/binutils/gas/config/tc-i860.c@ 2562

Last change on this file since 2562 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 31.1 KB
Line 
1/* tc-i860.c -- Assembler for the Intel i860 architecture.
2 Copyright 1989, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4
5 Brought back from the dead and completely reworked
6 by Jason Eckhardt <jle@cygnus.com>.
7
8 This file is part of GAS, the GNU Assembler.
9
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)
13 any later version.
14
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.
19
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. */
23
24#include <stdio.h>
25#include <string.h>
26#include "as.h"
27#include "safe-ctype.h"
28#include "subsegs.h"
29#include "opcode/i860.h"
30#include "elf/i860.h"
31
32/* Defined by default since this is primarily a SVR4/860 assembler.
33 However, I'm trying to leave the door open for Intel syntax. Of course,
34 if full support for anything other than SVR4 is done, then we should
35 select this based on a command-line flag. */
36#define SYNTAX_SVR4
37
38/* The opcode hash table. */
39static struct hash_control *op_hash = NULL;
40
41/* These characters always start a comment. */
42const char comment_chars[] = "#!/";
43
44/* These characters start a comment at the beginning of a line. */
45const char line_comment_chars[] = "#/";
46
47const char line_separator_chars[] = ";";
48
49/* Characters that can be used to separate the mantissa from the exponent
50 in floating point numbers. */
51const char EXP_CHARS[] = "eE";
52
53/* Characters that indicate this number is a floating point constant.
54 As in 0f12.456 or 0d1.2345e12. */
55const char FLT_CHARS[] = "rRsSfFdDxXpP";
56
57/* Register prefix. */
58#ifdef SYNTAX_SVR4
59static const char reg_prefix = '%';
60#else
61static const char reg_prefix = 0;
62#endif
63
64struct i860_it
65{
66 char *error;
67 unsigned long opcode;
68 expressionS exp;
69 enum expand_type expand;
70 bfd_reloc_code_real_type reloc;
71 int pcrel;
72 valueT fup;
73} the_insn;
74
75static char *expr_end;
76
77/* Indicates error if a pseudo operation was expanded after a branch. */
78static char last_expand;
79
80/* If true, then warn if any pseudo operations were expanded. */
81static int target_warn_expand = 0;
82
83/* Prototypes. */
84static void i860_process_insn PARAMS ((char *));
85static void s_dual PARAMS ((int));
86static void s_enddual PARAMS ((int));
87static void s_atmp PARAMS ((int));
88static int i860_get_expression PARAMS ((char *));
89static bfd_reloc_code_real_type obtain_reloc_for_imm16
90 PARAMS ((fixS *, long *));
91#ifdef DEBUG_I860
92static void print_insn PARAMS ((struct i860_it *));
93#endif
94
95const pseudo_typeS md_pseudo_table[] =
96{
97#ifdef OBJ_ELF
98 {"align", s_align_bytes, 0},
99#endif
100 {"dual", s_dual, 0},
101 {"enddual", s_enddual, 0},
102 {"atmp", s_atmp, 0},
103 {NULL, 0, 0},
104};
105
106/* Dual-instruction mode handling. */
107enum dual
108{
109 DUAL_OFF = 0, DUAL_ON, DUAL_DDOT, DUAL_ONDDOT,
110};
111static enum dual dual_mode = DUAL_OFF;
112
113/* Handle ".dual" directive. */
114static void
115s_dual (ignore)
116 int ignore ATTRIBUTE_UNUSED;
117{
118 dual_mode = DUAL_ON;
119}
120
121/* Handle ".enddual" directive. */
122static void
123s_enddual (ignore)
124 int ignore ATTRIBUTE_UNUSED;
125{
126 dual_mode = DUAL_OFF;
127}
128
129/* Temporary register used when expanding assembler pseudo operations. */
130static int atmp = 31;
131
132static void
133s_atmp (ignore)
134 int ignore ATTRIBUTE_UNUSED;
135{
136 register int temp;
137 if (strncmp (input_line_pointer, "sp", 2) == 0)
138 {
139 input_line_pointer += 2;
140 atmp = 2;
141 }
142 else if (strncmp (input_line_pointer, "fp", 2) == 0)
143 {
144 input_line_pointer += 2;
145 atmp = 3;
146 }
147 else if (strncmp (input_line_pointer, "r", 1) == 0)
148 {
149 input_line_pointer += 1;
150 temp = get_absolute_expression ();
151 if (temp >= 0 && temp <= 31)
152 atmp = temp;
153 else
154 as_bad (_("Unknown temporary pseudo register"));
155 }
156 else
157 {
158 as_bad (_("Unknown temporary pseudo register"));
159 }
160 demand_empty_rest_of_line ();
161}
162
163/* This function is called once, at assembler startup time. It should
164 set up all the tables and data structures that the MD part of the
165 assembler will need. */
166void
167md_begin ()
168{
169 const char *retval = NULL;
170 int lose = 0;
171 unsigned int i = 0;
172
173 op_hash = hash_new ();
174
175 while (i860_opcodes[i].name != NULL)
176 {
177 const char *name = i860_opcodes[i].name;
178 retval = hash_insert (op_hash, name, (PTR)&i860_opcodes[i]);
179 if (retval != NULL)
180 {
181 fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
182 i860_opcodes[i].name, retval);
183 lose = 1;
184 }
185 do
186 {
187 if (i860_opcodes[i].match & i860_opcodes[i].lose)
188 {
189 fprintf (stderr,
190 _("internal error: losing opcode: `%s' \"%s\"\n"),
191 i860_opcodes[i].name, i860_opcodes[i].args);
192 lose = 1;
193 }
194 ++i;
195 }
196 while (i860_opcodes[i].name != NULL
197 && strcmp (i860_opcodes[i].name, name) == 0);
198 }
199
200 if (lose)
201 as_fatal (_("Defective assembler. No assembly attempted."));
202}
203
204/* This is the core of the machine-dependent assembler. STR points to a
205 machine dependent instruction. This function emits the frags/bytes
206 it assembles to. */
207void
208md_assemble (str)
209 char *str;
210{
211 char *destp;
212 int num_opcodes = 1;
213 int i;
214 struct i860_it pseudo[3];
215
216 assert (str);
217
218 /* Assemble the instruction. */
219 i860_process_insn (str);
220
221 /* Check for expandable flag to produce pseudo-instructions. This
222 is an undesirable feature that should be avoided. */
223 if (the_insn.expand != 0
224 && ! (the_insn.fup & (OP_SEL_HA | OP_SEL_H | OP_SEL_L | OP_SEL_GOT
225 | OP_SEL_GOTOFF | OP_SEL_PLT)))
226 {
227 for (i = 0; i < 3; i++)
228 pseudo[i] = the_insn;
229
230 switch (the_insn.expand)
231 {
232
233 case E_DELAY:
234 num_opcodes = 1;
235 break;
236
237 case E_MOV:
238 if (the_insn.exp.X_add_symbol == NULL
239 && the_insn.exp.X_op_symbol == NULL
240 && (the_insn.exp.X_add_number < (1 << 15)
241 && the_insn.exp.X_add_number >= -(1 << 15)))
242 break;
243
244 /* Emit "or l%const,r0,ireg_dest". */
245 pseudo[0].opcode = (the_insn.opcode & 0x001f0000) | 0xe4000000;
246 pseudo[0].fup = (OP_IMM_S16 | OP_SEL_L);
247
248 /* Emit "orh h%const,ireg_dest,ireg_dest". */
249 pseudo[1].opcode = (the_insn.opcode & 0x03ffffff) | 0xec000000
250 | ((the_insn.opcode & 0x001f0000) << 5);
251 pseudo[1].fup = (OP_IMM_S16 | OP_SEL_H);
252
253 num_opcodes = 2;
254 break;
255
256 case E_ADDR:
257 if (the_insn.exp.X_add_symbol == NULL
258 && the_insn.exp.X_op_symbol == NULL
259 && (the_insn.exp.X_add_number < (1 << 15)
260 && the_insn.exp.X_add_number >= -(1 << 15)))
261 break;
262
263 /* Emit "orh ha%addr_expr,r0,r31". */
264 pseudo[0].opcode = 0xec000000 | (atmp << 16);
265 pseudo[0].fup = (OP_IMM_S16 | OP_SEL_HA);
266
267 /* Emit "l%addr_expr(r31),ireg_dest". We pick up the fixup
268 information from the original instruction. */
269 pseudo[1].opcode = (the_insn.opcode & ~0x03e00000) | (atmp << 21);
270 pseudo[1].fup = the_insn.fup | OP_SEL_L;
271
272 num_opcodes = 2;
273 break;
274
275 case E_U32:
276 if (the_insn.exp.X_add_symbol == NULL
277 && the_insn.exp.X_op_symbol == NULL
278 && (the_insn.exp.X_add_number < (1 << 16)
279 && the_insn.exp.X_add_number >= 0))
280 break;
281
282 /* Emit "$(opcode)h h%const,ireg_src2,r31". */
283 pseudo[0].opcode = (the_insn.opcode & 0xf3e0ffff) | 0x0c000000
284 | (atmp << 16);
285 pseudo[0].fup = (OP_IMM_S16 | OP_SEL_H);
286
287 /* Emit "$(opcode) l%const,r31,ireg_dest". */
288 pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000
289 | (atmp << 21);
290 pseudo[1].fup = (OP_IMM_S16 | OP_SEL_L);
291
292 num_opcodes = 2;
293 break;
294
295 case E_AND:
296 if (the_insn.exp.X_add_symbol == NULL
297 && the_insn.exp.X_op_symbol == NULL
298 && (the_insn.exp.X_add_number < (1 << 16)
299 && the_insn.exp.X_add_number >= 0))
300 break;
301
302 /* Emit "andnot h%const,ireg_src2,r31". */
303 pseudo[0].opcode = (the_insn.opcode & 0x03e0ffff) | 0xd4000000
304 | (atmp << 16);
305 pseudo[0].fup = (OP_IMM_S16 | OP_SEL_H);
306 pseudo[0].exp.X_add_number = -1 - the_insn.exp.X_add_number;
307
308 /* Emit "andnot l%const,r31,ireg_dest". */
309 pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000
310 | (atmp << 21);
311 pseudo[1].fup = (OP_IMM_S16 | OP_SEL_L);
312 pseudo[1].exp.X_add_number = -1 - the_insn.exp.X_add_number;
313
314 num_opcodes = 2;
315 break;
316
317 case E_S32:
318 if (the_insn.exp.X_add_symbol == NULL
319 && the_insn.exp.X_op_symbol == NULL
320 && (the_insn.exp.X_add_number < (1 << 15)
321 && the_insn.exp.X_add_number >= -(1 << 15)))
322 break;
323
324 /* Emit "orh h%const,r0,r31". */
325 pseudo[0].opcode = 0xec000000 | (atmp << 16);
326 pseudo[0].fup = (OP_IMM_S16 | OP_SEL_H);
327
328 /* Emit "or l%const,r31,r31". */
329 pseudo[1].opcode = 0xe4000000 | (atmp << 21) | (atmp << 16);
330 pseudo[1].fup = (OP_IMM_S16 | OP_SEL_L);
331
332 /* Emit "r31,ireg_src2,ireg_dest". */
333 pseudo[2].opcode = (the_insn.opcode & ~0x0400ffff) | (atmp << 11);
334 pseudo[2].fup = OP_IMM_S16;
335
336 num_opcodes = 3;
337 break;
338
339 default:
340 as_fatal (_("failed sanity check."));
341 }
342
343 the_insn = pseudo[0];
344
345 /* Warn if an opcode is expanded after a delayed branch. */
346 if (num_opcodes > 1 && last_expand == 1)
347 as_warn (_("Expanded opcode after delayed branch: `%s'"), str);
348
349 /* Warn if an opcode is expanded in dual mode. */
350 if (num_opcodes > 1 && dual_mode != DUAL_OFF)
351 as_warn (_("Expanded opcode in dual mode: `%s'"), str);
352
353 /* Notify if any expansions happen. */
354 if (target_warn_expand && num_opcodes > 1)
355 as_warn (_("An instruction was expanded (%s)"), str);
356 }
357
358 i = 0;
359 do
360 {
361 /* Output the opcode. Note that the i860 always reads instructions
362 as little-endian data. */
363 destp = frag_more (4);
364 number_to_chars_littleendian (destp, the_insn.opcode, 4);
365
366 /* Check for expanded opcode after branch or in dual mode. */
367 last_expand = the_insn.pcrel;
368
369 /* Output the symbol-dependent stuff. */
370 if (the_insn.fup != OP_NONE)
371 {
372 fixS *fix;
373 fix = fix_new_exp (frag_now,
374 destp - frag_now->fr_literal,
375 4,
376 &the_insn.exp,
377 the_insn.pcrel,
378 the_insn.reloc);
379
380 /* Despite the odd name, this is a scratch field. We use
381 it to encode operand type information. */
382 fix->fx_addnumber = the_insn.fup;
383 }
384 the_insn = pseudo[++i];
385 }
386 while (--num_opcodes > 0);
387
388}
389
390/* Assemble the instruction pointed to by STR. */
391static void
392i860_process_insn (str)
393 char *str;
394{
395 char *s;
396 const char *args;
397 char c;
398 struct i860_opcode *insn;
399 char *args_start;
400 unsigned long opcode;
401 unsigned int mask;
402 int match = 0;
403 int comma = 0;
404
405#if 1 /* For compiler warnings. */
406 args = 0;
407 insn = 0;
408 args_start = 0;
409 opcode = 0;
410#endif
411
412 for (s = str; ISLOWER (*s) || *s == '.' || *s == '3'
413 || *s == '2' || *s == '1'; ++s)
414 ;
415
416 switch (*s)
417 {
418 case '\0':
419 break;
420
421 case ',':
422 comma = 1;
423
424 /*FALLTHROUGH*/
425
426 case ' ':
427 *s++ = '\0';
428 break;
429
430 default:
431 as_fatal (_("Unknown opcode: `%s'"), str);
432 }
433
434 /* Check for dual mode ("d.") opcode prefix. */
435 if (strncmp (str, "d.", 2) == 0)
436 {
437 if (dual_mode == DUAL_ON)
438 dual_mode = DUAL_ONDDOT;
439 else
440 dual_mode = DUAL_DDOT;
441 str += 2;
442 }
443
444 if ((insn = (struct i860_opcode *) hash_find (op_hash, str)) == NULL)
445 {
446 if (dual_mode == DUAL_DDOT || dual_mode == DUAL_ONDDOT)
447 str -= 2;
448 as_bad (_("Unknown opcode: `%s'"), str);
449 return;
450 }
451
452 if (comma)
453 *--s = ',';
454
455 args_start = s;
456 for (;;)
457 {
458 opcode = insn->match;
459 memset (&the_insn, '\0', sizeof (the_insn));
460 the_insn.reloc = BFD_RELOC_NONE;
461 the_insn.pcrel = 0;
462 the_insn.fup = OP_NONE;
463
464 /* Build the opcode, checking as we go that the operands match. */
465 for (args = insn->args; ; ++args)
466 {
467 switch (*args)
468 {
469
470 /* End of args. */
471 case '\0':
472 if (*s == '\0')
473 match = 1;
474 break;
475
476 /* These must match exactly. */
477 case '+':
478 case '(':
479 case ')':
480 case ',':
481 case ' ':
482 if (*s++ == *args)
483 continue;
484 break;
485
486 /* Must be at least one digit. */
487 case '#':
488 if (ISDIGIT (*s++))
489 {
490 while (ISDIGIT (*s))
491 ++s;
492 continue;
493 }
494 break;
495
496 /* Next operand must be a register. */
497 case '1':
498 case '2':
499 case 'd':
500 /* Check for register prefix if necessary. */
501 if (reg_prefix && *s != reg_prefix)
502 goto error;
503 else
504 s++;
505
506 switch (*s)
507 {
508 /* Frame pointer. */
509 case 'f':
510 s++;
511 if (*s++ == 'p')
512 {
513 mask = 0x3;
514 break;
515 }
516 goto error;
517
518 /* Stack pointer. */
519 case 's':
520 s++;
521 if (*s++ == 'p')
522 {
523 mask = 0x2;
524 break;
525 }
526 goto error;
527
528 /* Any register r0..r31. */
529 case 'r':
530 s++;
531 if (!ISDIGIT (c = *s++))
532 {
533 goto error;
534 }
535 if (ISDIGIT (*s))
536 {
537 if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
538 goto error;
539 }
540 else
541 c -= '0';
542 mask = c;
543 break;
544
545 /* Not this opcode. */
546 default:
547 goto error;
548 }
549
550 /* Obtained the register, now place it in the opcode. */
551 switch (*args)
552 {
553 case '1':
554 opcode |= mask << 11;
555 continue;
556
557 case '2':
558 opcode |= mask << 21;
559 continue;
560
561 case 'd':
562 opcode |= mask << 16;
563 continue;
564
565 }
566 break;
567
568 /* Next operand is a floating point register. */
569 case 'e':
570 case 'f':
571 case 'g':
572 /* Check for register prefix if necessary. */
573 if (reg_prefix && *s != reg_prefix)
574 goto error;
575 else
576 s++;
577
578 if (*s++ == 'f' && ISDIGIT (*s))
579 {
580 mask = *s++;
581 if (ISDIGIT (*s))
582 {
583 mask = 10 * (mask - '0') + (*s++ - '0');
584 if (mask >= 32)
585 {
586 break;
587 }
588 }
589 else
590 mask -= '0';
591
592 switch (*args)
593 {
594
595 case 'e':
596 opcode |= mask << 11;
597 continue;
598
599 case 'f':
600 opcode |= mask << 21;
601 continue;
602
603 case 'g':
604 opcode |= mask << 16;
605 if (dual_mode != DUAL_OFF)
606 opcode |= (1 << 9);
607 if (dual_mode == DUAL_DDOT)
608 dual_mode = DUAL_OFF;
609 if (dual_mode == DUAL_ONDDOT)
610 dual_mode = DUAL_ON;
611 if ((opcode & (1 << 10)) && mask != 0
612 && (mask == ((opcode >> 11) & 0x1f)))
613 as_warn (_("Pipelined instruction: fsrc1 = fdest"));
614 continue;
615 }
616 }
617 break;
618
619 /* Next operand must be a control register. */
620 case 'c':
621 /* Check for register prefix if necessary. */
622 if (reg_prefix && *s != reg_prefix)
623 goto error;
624 else
625 s++;
626
627 if (strncmp (s, "fir", 3) == 0)
628 {
629 opcode |= 0x0 << 21;
630 s += 3;
631 continue;
632 }
633 if (strncmp (s, "psr", 3) == 0)
634 {
635 opcode |= 0x1 << 21;
636 s += 3;
637 continue;
638 }
639 if (strncmp (s, "dirbase", 7) == 0)
640 {
641 opcode |= 0x2 << 21;
642 s += 7;
643 continue;
644 }
645 if (strncmp (s, "db", 2) == 0)
646 {
647 opcode |= 0x3 << 21;
648 s += 2;
649 continue;
650 }
651 if (strncmp (s, "fsr", 3) == 0)
652 {
653 opcode |= 0x4 << 21;
654 s += 3;
655 continue;
656 }
657 if (strncmp (s, "epsr", 4) == 0)
658 {
659 opcode |= 0x5 << 21;
660 s += 4;
661 continue;
662 }
663 break;
664
665 /* 5-bit immediate in src1. */
666 case '5':
667 if (! i860_get_expression (s))
668 {
669 s = expr_end;
670 the_insn.fup |= OP_IMM_U5;
671 continue;
672 }
673 break;
674
675 /* 26-bit immediate, relative branch (lbroff). */
676 case 'l':
677 the_insn.pcrel = 1;
678 the_insn.fup |= OP_IMM_BR26;
679 goto immediate;
680
681 /* 16-bit split immediate, relative branch (sbroff). */
682 case 'r':
683 the_insn.pcrel = 1;
684 the_insn.fup |= OP_IMM_BR16;
685 goto immediate;
686
687 /* 16-bit split immediate. */
688 case 's':
689 the_insn.fup |= OP_IMM_SPLIT16;
690 goto immediate;
691
692 /* 16-bit split immediate, byte aligned (st.b). */
693 case 'S':
694 the_insn.fup |= OP_IMM_SPLIT16;
695 goto immediate;
696
697 /* 16-bit split immediate, half-word aligned (st.s). */
698 case 'T':
699 the_insn.fup |= (OP_IMM_SPLIT16 | OP_ENCODE1 | OP_ALIGN2);
700 goto immediate;
701
702 /* 16-bit split immediate, word aligned (st.l). */
703 case 'U':
704 the_insn.fup |= (OP_IMM_SPLIT16 | OP_ENCODE1 | OP_ALIGN4);
705 goto immediate;
706
707 /* 16-bit immediate. */
708 case 'i':
709 the_insn.fup |= OP_IMM_S16;
710 goto immediate;
711
712 /* 16-bit immediate, byte aligned (ld.b). */
713 case 'I':
714 the_insn.fup |= OP_IMM_S16;
715 goto immediate;
716
717 /* 16-bit immediate, half-word aligned (ld.s). */
718 case 'J':
719 the_insn.fup |= (OP_IMM_S16 | OP_ENCODE1 | OP_ALIGN2);
720 goto immediate;
721
722 /* 16-bit immediate, word aligned (ld.l, {p}fld.l, fst.l). */
723 case 'K':
724 if (insn->name[0] == 'l')
725 the_insn.fup |= (OP_IMM_S16 | OP_ENCODE1 | OP_ALIGN4);
726 else
727 the_insn.fup |= (OP_IMM_S16 | OP_ENCODE2 | OP_ALIGN4);
728 goto immediate;
729
730 /* 16-bit immediate, double-word aligned ({p}fld.d, fst.d). */
731 case 'L':
732 the_insn.fup |= (OP_IMM_S16 | OP_ENCODE3 | OP_ALIGN8);
733 goto immediate;
734
735 /* 16-bit immediate, quad-word aligned (fld.q, fst.q). */
736 case 'M':
737 the_insn.fup |= (OP_IMM_S16 | OP_ENCODE3 | OP_ALIGN16);
738
739 /*FALLTHROUGH*/
740
741 /* Handle the immediate for either the Intel syntax or
742 SVR4 syntax. The Intel syntax is "ha%immediate"
743 whereas SVR4 syntax is "[immediate]@ha". */
744 immediate:
745#ifdef SYNTAX_SVR4
746 if (*s == ' ')
747 s++;
748
749 /* Note that if i860_get_expression() fails, we will still
750 have created U entries in the symbol table for the
751 'symbols' in the input string. Try not to create U
752 symbols for registers, etc. */
753 if (! i860_get_expression (s))
754 s = expr_end;
755 else
756 goto error;
757
758 if (strncmp (s, "@ha", 3) == 0)
759 {
760 the_insn.fup |= OP_SEL_HA;
761 s += 3;
762 }
763 else if (strncmp (s, "@h", 2) == 0)
764 {
765 the_insn.fup |= OP_SEL_H;
766 s += 2;
767 }
768 else if (strncmp (s, "@l", 2) == 0)
769 {
770 the_insn.fup |= OP_SEL_L;
771 s += 2;
772 }
773 else if (strncmp (s, "@gotoff", 7) == 0
774 || strncmp (s, "@GOTOFF", 7) == 0)
775 {
776 as_bad (_("Assembler does not yet support PIC"));
777 the_insn.fup |= OP_SEL_GOTOFF;
778 s += 7;
779 }
780 else if (strncmp (s, "@got", 4) == 0
781 || strncmp (s, "@GOT", 4) == 0)
782 {
783 as_bad (_("Assembler does not yet support PIC"));
784 the_insn.fup |= OP_SEL_GOT;
785 s += 4;
786 }
787 else if (strncmp (s, "@plt", 4) == 0
788 || strncmp (s, "@PLT", 4) == 0)
789 {
790 as_bad (_("Assembler does not yet support PIC"));
791 the_insn.fup |= OP_SEL_PLT;
792 s += 4;
793 }
794
795 the_insn.expand = insn->expand;
796
797 continue;
798#else /* ! SYNTAX_SVR4 */
799 if (*s == ' ')
800 s++;
801 if (strncmp (s, "ha%", 3) == 0)
802 {
803 the_insn.fup |= OP_SEL_HA;
804 s += 3;
805 }
806 else if (strncmp (s, "h%", 2) == 0)
807 {
808 the_insn.fup |= OP_SEL_H;
809 s += 2;
810 }
811 else if (strncmp (s, "l%", 2) == 0)
812 {
813 the_insn.fup |= OP_SEL_L;
814 s += 2;
815 }
816 the_insn.expand = insn->expand;
817
818 /* Note that if i860_get_expression() fails, we will still
819 have created U entries in the symbol table for the
820 'symbols' in the input string. Try not to create U
821 symbols for registers, etc. */
822 if (! i860_get_expression (s))
823 s = expr_end;
824 else
825 goto error;
826
827 continue;
828#endif /* SYNTAX_SVR4 */
829 break;
830
831 default:
832 as_fatal (_("failed sanity check."));
833 }
834 break;
835 }
836 error:
837 if (match == 0)
838 {
839 /* Args don't match. */
840 if (insn[1].name != NULL
841 && ! strcmp (insn->name, insn[1].name))
842 {
843 ++insn;
844 s = args_start;
845 continue;
846 }
847 else
848 {
849 as_bad (_("Illegal operands for %s"), insn->name);
850 return;
851 }
852 }
853 break;
854 }
855
856 the_insn.opcode = opcode;
857}
858
859static int
860i860_get_expression (str)
861 char *str;
862{
863 char *save_in;
864 segT seg;
865
866 save_in = input_line_pointer;
867 input_line_pointer = str;
868 seg = expression (&the_insn.exp);
869 if (seg != absolute_section
870 && seg != undefined_section
871 && ! SEG_NORMAL (seg))
872 {
873 the_insn.error = _("bad segment");
874 expr_end = input_line_pointer;
875 input_line_pointer = save_in;
876 return 1;
877 }
878 expr_end = input_line_pointer;
879 input_line_pointer = save_in;
880 return 0;
881}
882
883/* Turn a string in input_line_pointer into a floating point constant of
884 type TYPE, and store the appropriate bytes in *LITP. The number of
885 LITTLENUMS emitted is stored in *SIZEP. An error message is returned,
886 or NULL on OK. */
887
888/* Equal to MAX_PRECISION in atof-ieee.c. */
889#define MAX_LITTLENUMS 6
890
891char *
892md_atof (type, litP, sizeP)
893 char type;
894 char *litP;
895 int *sizeP;
896{
897 int prec;
898 LITTLENUM_TYPE words[MAX_LITTLENUMS];
899 LITTLENUM_TYPE *wordP;
900 char *t;
901
902 switch (type)
903 {
904 case 'f':
905 case 'F':
906 case 's':
907 case 'S':
908 prec = 2;
909 break;
910
911 case 'd':
912 case 'D':
913 case 'r':
914 case 'R':
915 prec = 4;
916 break;
917
918 case 'x':
919 case 'X':
920 prec = 6;
921 break;
922
923 case 'p':
924 case 'P':
925 prec = 6;
926 break;
927
928 default:
929 *sizeP = 0;
930 return _("Bad call to MD_ATOF()");
931 }
932 t = atof_ieee (input_line_pointer, type, words);
933 if (t)
934 input_line_pointer = t;
935 *sizeP = prec * sizeof (LITTLENUM_TYPE);
936 for (wordP = words; prec--;)
937 {
938 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
939 litP += sizeof (LITTLENUM_TYPE);
940 }
941 return 0;
942}
943
944/* Write out in current endian mode. */
945void
946md_number_to_chars (buf, val, n)
947 char *buf;
948 valueT val;
949 int n;
950{
951 if (target_big_endian)
952 number_to_chars_bigendian (buf, val, n);
953 else
954 number_to_chars_littleendian (buf, val, n);
955}
956
957/* This should never be called for i860. */
958int
959md_estimate_size_before_relax (fragP, segtype)
960 register fragS *fragP ATTRIBUTE_UNUSED;
961 segT segtype ATTRIBUTE_UNUSED;
962{
963 as_fatal (_("i860_estimate_size_before_relax\n"));
964}
965
966#ifdef DEBUG_I860
967static void
968print_insn (insn)
969 struct i860_it *insn;
970{
971 if (insn->error)
972 fprintf (stderr, "ERROR: %s\n", insn->error);
973
974 fprintf (stderr, "opcode = 0x%08lx\t", insn->opcode);
975 fprintf (stderr, "expand = 0x%x\t", insn->expand);
976 fprintf (stderr, "reloc = %s\t\n",
977 bfd_get_reloc_code_name (insn->reloc));
978 fprintf (stderr, "exp = {\n");
979 fprintf (stderr, "\t\tX_add_symbol = %s\n",
980 insn->exp.X_add_symbol ?
981 (S_GET_NAME (insn->exp.X_add_symbol) ?
982 S_GET_NAME (insn->exp.X_add_symbol) : "???") : "0");
983 fprintf (stderr, "\t\tX_op_symbol = %s\n",
984 insn->exp.X_op_symbol ?
985 (S_GET_NAME (insn->exp.X_op_symbol) ?
986 S_GET_NAME (insn->exp.X_op_symbol) : "???") : "0");
987 fprintf (stderr, "\t\tX_add_number = %lx\n",
988 insn->exp.X_add_number);
989 fprintf (stderr, "}\n");
990}
991#endif /* DEBUG_I860 */
992
993
994
995#ifdef OBJ_ELF
996const char *md_shortopts = "VQ:";
997#else
998const char *md_shortopts = "";
999#endif
1000
1001#define OPTION_EB (OPTION_MD_BASE + 0)
1002#define OPTION_EL (OPTION_MD_BASE + 1)
1003#define OPTION_WARN_EXPAND (OPTION_MD_BASE + 2)
1004
1005struct option md_longopts[] = {
1006 { "EB", no_argument, NULL, OPTION_EB },
1007 { "EL", no_argument, NULL, OPTION_EL },
1008 { "mwarn-expand", no_argument, NULL, OPTION_WARN_EXPAND },
1009 { NULL, no_argument, NULL, 0 }
1010};
1011size_t md_longopts_size = sizeof (md_longopts);
1012
1013int
1014md_parse_option (c, arg)
1015 int c;
1016 char *arg ATTRIBUTE_UNUSED;
1017{
1018 switch (c)
1019 {
1020 case OPTION_EB:
1021 target_big_endian = 1;
1022 break;
1023
1024 case OPTION_EL:
1025 target_big_endian = 0;
1026 break;
1027
1028 case OPTION_WARN_EXPAND:
1029 target_warn_expand = 1;
1030 break;
1031
1032#ifdef OBJ_ELF
1033 /* SVR4 argument compatibility (-V): print version ID. */
1034 case 'V':
1035 print_version_id ();
1036 break;
1037
1038 /* SVR4 argument compatibility (-Qy, -Qn): controls whether
1039 a .comment section should be emitted or not (ignored). */
1040 case 'Q':
1041 break;
1042#endif
1043
1044 default:
1045 return 0;
1046 }
1047
1048 return 1;
1049}
1050
1051void
1052md_show_usage (stream)
1053 FILE *stream;
1054{
1055 fprintf (stream, _("\
1056 -EL generate code for little endian mode (default)\n\
1057 -EB generate code for big endian mode\n\
1058 -mwarn-expand warn if pseudo operations are expanded\n"));
1059#ifdef OBJ_ELF
1060 /* SVR4 compatibility flags. */
1061 fprintf (stream, _("\
1062 -V print assembler version number\n\
1063 -Qy, -Qn ignored\n"));
1064#endif
1065}
1066
1067
1068
1069/* We have no need to default values of symbols. */
1070symbolS *
1071md_undefined_symbol (name)
1072 char *name ATTRIBUTE_UNUSED;
1073{
1074 return 0;
1075}
1076
1077/* The i860 denotes auto-increment with '++'. */
1078void
1079md_operand (exp)
1080 expressionS *exp;
1081{
1082 char *s;
1083
1084 for (s = input_line_pointer; *s; s++)
1085 {
1086 if (s[0] == '+' && s[1] == '+')
1087 {
1088 input_line_pointer += 2;
1089 exp->X_op = O_register;
1090 break;
1091 }
1092 }
1093}
1094
1095/* Round up a section size to the appropriate boundary. */
1096valueT
1097md_section_align (segment, size)
1098 segT segment ATTRIBUTE_UNUSED;
1099 valueT size ATTRIBUTE_UNUSED;
1100{
1101 /* Byte alignment is fine. */
1102 return size;
1103}
1104
1105/* On the i860, a PC-relative offset is relative to the address of the
1106 of the offset plus its size. */
1107long
1108md_pcrel_from (fixP)
1109 fixS *fixP;
1110{
1111 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
1112}
1113
1114/* Determine the relocation needed for non PC-relative 16-bit immediates.
1115 Also adjust the given immediate as necessary. Finally, check that
1116 all constraints (such as alignment) are satisfied. */
1117static bfd_reloc_code_real_type
1118obtain_reloc_for_imm16 (fix, val)
1119 fixS *fix;
1120 long *val;
1121{
1122 valueT fup = fix->fx_addnumber;
1123 bfd_reloc_code_real_type reloc;
1124
1125 if (fix->fx_pcrel)
1126 abort ();
1127
1128 /* Check alignment restrictions. */
1129 if ((fup & OP_ALIGN2) && (*val & 0x1))
1130 as_bad_where (fix->fx_file, fix->fx_line,
1131 _("This immediate requires 0 MOD 2 alignment"));
1132 else if ((fup & OP_ALIGN4) && (*val & 0x3))
1133 as_bad_where (fix->fx_file, fix->fx_line,
1134 _("This immediate requires 0 MOD 4 alignment"));
1135 else if ((fup & OP_ALIGN8) && (*val & 0x7))
1136 as_bad_where (fix->fx_file, fix->fx_line,
1137 _("This immediate requires 0 MOD 8 alignment"));
1138 else if ((fup & OP_ALIGN16) && (*val & 0xf))
1139 as_bad_where (fix->fx_file, fix->fx_line,
1140 _("This immediate requires 0 MOD 16 alignment"));
1141
1142 if (fup & OP_SEL_HA)
1143 {
1144 *val = (*val >> 16) + (*val & 0x8000 ? 1 : 0);
1145 reloc = BFD_RELOC_860_HIGHADJ;
1146 }
1147 else if (fup & OP_SEL_H)
1148 {
1149 *val >>= 16;
1150 reloc = BFD_RELOC_860_HIGH;
1151 }
1152 else if (fup & OP_SEL_L)
1153 {
1154 int num_encode;
1155 if (fup & OP_IMM_SPLIT16)
1156 {
1157 if (fup & OP_ENCODE1)
1158 {
1159 num_encode = 1;
1160 reloc = BFD_RELOC_860_SPLIT1;
1161 }
1162 else if (fup & OP_ENCODE2)
1163 {
1164 num_encode = 2;
1165 reloc = BFD_RELOC_860_SPLIT2;
1166 }
1167 else
1168 {
1169 num_encode = 0;
1170 reloc = BFD_RELOC_860_SPLIT0;
1171 }
1172 }
1173 else
1174 {
1175 if (fup & OP_ENCODE1)
1176 {
1177 num_encode = 1;
1178 reloc = BFD_RELOC_860_LOW1;
1179 }
1180 else if (fup & OP_ENCODE2)
1181 {
1182 num_encode = 2;
1183 reloc = BFD_RELOC_860_LOW2;
1184 }
1185 else if (fup & OP_ENCODE3)
1186 {
1187 num_encode = 3;
1188 reloc = BFD_RELOC_860_LOW3;
1189 }
1190 else
1191 {
1192 num_encode = 0;
1193 reloc = BFD_RELOC_860_LOW0;
1194 }
1195 }
1196
1197 /* Preserve size encode bits. */
1198 *val &= ~((1 << num_encode) - 1);
1199 }
1200 else
1201 {
1202 /* No selector. What reloc do we generate (???)? */
1203 reloc = BFD_RELOC_32;
1204 }
1205
1206 return reloc;
1207}
1208
1209/* Attempt to simplify or eliminate a fixup. To indicate that a fixup
1210 has been eliminated, set fix->fx_done. If fix->fx_addsy is non-NULL,
1211 we will have to generate a reloc entry. */
1212
1213void
1214md_apply_fix3 (fix, valP, seg)
1215 fixS * fix;
1216 valueT * valP;
1217 segT seg ATTRIBUTE_UNUSED;
1218{
1219 char *buf;
1220 long val = *valP;
1221 unsigned long insn;
1222 valueT fup;
1223
1224 buf = fix->fx_frag->fr_literal + fix->fx_where;
1225
1226 /* Recall that earlier we stored the opcode little-endian. */
1227 insn = bfd_getl32 (buf);
1228
1229 /* We stored a fix-up in this oddly-named scratch field. */
1230 fup = fix->fx_addnumber;
1231
1232 /* Determine the necessary relocations as well as inserting an
1233 immediate into the instruction. */
1234 if (fup == OP_IMM_U5)
1235 {
1236 if (val & ~0x1f)
1237 as_bad_where (fix->fx_file, fix->fx_line,
1238 _("5-bit immediate too large"));
1239 if (fix->fx_addsy)
1240 as_bad_where (fix->fx_file, fix->fx_line,
1241 _("5-bit field must be absolute"));
1242
1243 insn |= (val & 0x1f) << 11;
1244 bfd_putl32 (insn, buf);
1245 fix->fx_r_type = BFD_RELOC_NONE;
1246 fix->fx_done = 1;
1247 }
1248 else if (fup & OP_IMM_S16)
1249 {
1250 fix->fx_r_type = obtain_reloc_for_imm16 (fix, &val);
1251
1252 /* Insert the immediate. */
1253 if (fix->fx_addsy)
1254 fix->fx_done = 0;
1255 else
1256 {
1257 insn |= val & 0xffff;
1258 bfd_putl32 (insn, buf);
1259 fix->fx_r_type = BFD_RELOC_NONE;
1260 fix->fx_done = 1;
1261 }
1262 }
1263 else if (fup & OP_IMM_U16)
1264 abort ();
1265
1266 else if (fup & OP_IMM_SPLIT16)
1267 {
1268 fix->fx_r_type = obtain_reloc_for_imm16 (fix, &val);
1269
1270 /* Insert the immediate. */
1271 if (fix->fx_addsy)
1272 fix->fx_done = 0;
1273 else
1274 {
1275 insn |= val & 0x7ff;
1276 insn |= (val & 0xf800) << 5;
1277 bfd_putl32 (insn, buf);
1278 fix->fx_r_type = BFD_RELOC_NONE;
1279 fix->fx_done = 1;
1280 }
1281 }
1282 else if (fup & OP_IMM_BR16)
1283 {
1284 if (val & 0x3)
1285 as_bad_where (fix->fx_file, fix->fx_line,
1286 _("A branch offset requires 0 MOD 4 alignment"));
1287
1288 val = val >> 2;
1289
1290 /* Insert the immediate. */
1291 if (fix->fx_addsy)
1292 {
1293 fix->fx_done = 0;
1294 fix->fx_r_type = BFD_RELOC_860_PC16;
1295 }
1296 else
1297 {
1298 insn |= (val & 0x7ff);
1299 insn |= ((val & 0xf800) << 5);
1300 bfd_putl32 (insn, buf);
1301 fix->fx_r_type = BFD_RELOC_NONE;
1302 fix->fx_done = 1;
1303 }
1304 }
1305 else if (fup & OP_IMM_BR26)
1306 {
1307 if (val & 0x3)
1308 as_bad_where (fix->fx_file, fix->fx_line,
1309 _("A branch offset requires 0 MOD 4 alignment"));
1310
1311 val >>= 2;
1312
1313 /* Insert the immediate. */
1314 if (fix->fx_addsy)
1315 {
1316 fix->fx_r_type = BFD_RELOC_860_PC26;
1317 fix->fx_done = 0;
1318 }
1319 else
1320 {
1321 insn |= (val & 0x3ffffff);
1322 bfd_putl32 (insn, buf);
1323 fix->fx_r_type = BFD_RELOC_NONE;
1324 fix->fx_done = 1;
1325 }
1326 }
1327 else if (fup != OP_NONE)
1328 {
1329 as_bad_where (fix->fx_file, fix->fx_line,
1330 _("Unrecognized fix-up (0x%08lx)"), (unsigned long) fup);
1331 abort ();
1332 }
1333 else
1334 {
1335 /* I believe only fix-ups such as ".long .ep.main-main+0xc8000000"
1336 reach here (???). */
1337 if (fix->fx_addsy)
1338 {
1339 fix->fx_r_type = BFD_RELOC_32;
1340 fix->fx_done = 0;
1341 }
1342 else
1343 {
1344 insn |= (val & 0xffffffff);
1345 bfd_putl32 (insn, buf);
1346 fix->fx_r_type = BFD_RELOC_NONE;
1347 fix->fx_done = 1;
1348 }
1349 }
1350}
1351
1352/* Generate a machine dependent reloc from a fixup. */
1353arelent*
1354tc_gen_reloc (section, fixp)
1355 asection *section ATTRIBUTE_UNUSED;
1356 fixS *fixp;
1357{
1358 arelent *reloc;
1359
1360 reloc = xmalloc (sizeof (*reloc));
1361 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1362 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1363 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1364 reloc->addend = fixp->fx_offset;
1365 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1366
1367 if (! reloc->howto)
1368 {
1369 as_bad_where (fixp->fx_file, fixp->fx_line,
1370 "Cannot represent %s relocation in object file",
1371 bfd_get_reloc_code_name (fixp->fx_r_type));
1372 }
1373 return reloc;
1374}
Note: See TracBrowser for help on using the repository browser.