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