1 /* Assembly backend for the OpenRISC 1000.
2    Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
3    Contributed by Damjan Lampret <lampret@opencores.org>.
4    Modified bu Johan Rydberg, <johan.rydberg@netinsight.se>.
5    Based upon a29k port.
6 
7    This file is part of GAS, the GNU Assembler.
8 
9    GAS is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2, or (at your option)
12    any later version.
13 
14    GAS is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with GAS; see the file COPYING.  If not, write to
21    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
22    Boston, MA 02110-1301, USA.  */
23 
24 /* tc-a29k.c used as a template.  */
25 
26 #include "safe-ctype.h"
27 #include "as.h"
28 #include "opcode/or32.h"
29 #include "elf/or32.h"
30 
31 #define DEBUG 0
32 
33 #ifndef REGISTER_PREFIX
34 #define REGISTER_PREFIX   '%'
35 #endif
36 
37 /* Make it easier to clone this machine desc into another one.  */
38 #define machine_opcode  or32_opcode
39 #define machine_opcodes or32_opcodes
40 #define machine_ip      or32_ip
41 #define machine_it      or32_it
42 
43 /* Handle of the OPCODE hash table.  */
44 static struct hash_control *op_hash = NULL;
45 
46 struct machine_it
47 {
48   char *          error;
49   unsigned long   opcode;
50   struct nlist *  nlistp;
51   expressionS     exp;
52   int             pcrel;
53   int             reloc_offset;   /* Offset of reloc within insn.  */
54   int             reloc;
55 }
56 the_insn;
57 
58 const pseudo_typeS md_pseudo_table[] =
59 {
60   {"align",   s_align_bytes,  4 },
61   {"space",   s_space,        0 },
62   {"cputype", s_ignore,       0 },
63   {"reg",     s_lsym,         0 },  /* Register equate, same as equ.  */
64   {"sect",    s_ignore,       0 },  /* Creation of coff sections.  */
65   {"proc",    s_ignore,       0 },  /* Start of a function.  */
66   {"endproc", s_ignore,       0 },  /* Function end.  */
67   {"word",    cons,           4 },
68   {NULL,      0,              0 },
69 };
70 
71 int md_short_jump_size  = 4;
72 int md_long_jump_size   = 4;
73 
74 /* This array holds the chars that always start a comment.
75    If the pre-processor is disabled, these aren't very useful.  */
76 const char comment_chars[] = "#";
77 
78 /* This array holds the chars that only start a comment at the beginning of
79    a line.  If the line seems to have the form '# 123 filename'
80    .line and .file directives will appear in the pre-processed output.  */
81 /* Note that input_file.c hand checks for '#' at the beginning of the
82    first line of the input file.  This is because the compiler outputs
83    #NO_APP at the beginning of its output.  */
84 /* Also note that comments like this one will always work.  */
85 const char line_comment_chars[] = "#";
86 
87 /* We needed an unused char for line separation to work around the
88    lack of macros, using sed and such.  */
89 const char line_separator_chars[] = ";";
90 
91 /* Chars that can be used to separate mant from exp in floating point nums.  */
92 const char EXP_CHARS[] = "eE";
93 
94 /* Chars that mean this number is a floating point constant.
95    As in 0f12.456
96    or    0d1.2345e12.  */
97 const char FLT_CHARS[] = "rRsSfFdDxXpP";
98 
99 /* "l.jalr r9" precalculated opcode.  */
100 static unsigned long jalr_r9_opcode;
101 
102 static void machine_ip (char *);
103 
104 
105 /* Set bits in machine opcode according to insn->encoding
106    description and passed operand.  */
107 
108 static void
encode(const struct machine_opcode * insn,unsigned long * opcode,signed long param_val,char param_ch)109 encode (const struct machine_opcode *insn,
110 	unsigned long *opcode,
111 	signed long param_val,
112 	char param_ch)
113 {
114   int opc_pos = 0;
115   int param_pos = 0;
116   char *enc;
117 
118 #if DEBUG
119   printf ("    encode:  opcode=%.8lx  param_val=%.8lx abs=%.8lx param_ch=%c\n",
120 	  *opcode, param_val, abs (param_val), param_ch);
121 #endif
122   for (enc = insn->encoding; *enc != '\0'; enc++)
123     if (*enc == param_ch)
124       {
125 	if (enc - 2 >= insn->encoding && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
126 	  continue;
127 	else
128 	  param_pos ++;
129       }
130 
131   opc_pos = 32;
132 
133   for (enc = insn->encoding; *enc != '\0';)
134     {
135       if ((*enc == '0') && (*(enc + 1) == 'x'))
136 	{
137 	  int tmp = strtol (enc, NULL, 16);
138 
139 	  opc_pos -= 4;
140 	  *opcode |= tmp << opc_pos;
141 	  enc += 3;
142 	}
143       else if ((*enc == '0') || (*enc == '-'))
144 	{
145 	  opc_pos--;
146 	  enc++;
147 	}
148       else if (*enc == '1')
149 	{
150 	  opc_pos--;
151 	  *opcode |= 1 << opc_pos;
152 	  enc++;
153 	}
154       else if (*enc == param_ch)
155 	{
156 	  opc_pos--;
157 	  param_pos--;
158 	  *opcode |= ((param_val >> param_pos) & 0x1) << opc_pos;
159 	  enc++;
160 	}
161       else if (ISALPHA (*enc))
162 	{
163 	  opc_pos--;
164 	  enc++;
165 	}
166       else
167 	enc++;
168     }
169 
170 #if DEBUG
171   printf ("    opcode=%.8lx\n", *opcode);
172 #endif
173 }
174 
175 /* This function is called once, at assembler startup time.  It should
176    set up all the tables, etc., that the MD part of the assembler will
177    need.  */
178 
179 void
md_begin(void)180 md_begin (void)
181 {
182   const char *retval = NULL;
183   int lose = 0;
184   int skipnext = 0;
185   unsigned int i;
186 
187   /* Hash up all the opcodes for fast use later.  */
188   op_hash = hash_new ();
189 
190   for (i = 0; i < or32_num_opcodes; i++)
191     {
192       const char *name = machine_opcodes[i].name;
193 
194       if (skipnext)
195         {
196           skipnext = 0;
197           continue;
198         }
199 
200       retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]);
201       if (retval != NULL)
202         {
203           fprintf (stderr, "internal error: can't hash `%s': %s\n",
204                    machine_opcodes[i].name, retval);
205           lose = 1;
206         }
207     }
208 
209   if (lose)
210     as_fatal (_("Broken assembler.  No assembly attempted."));
211 
212   encode (&machine_opcodes[insn_index ("l.jalr")], &jalr_r9_opcode, 9, 'B');
213 }
214 
215 /* Returns non zero if instruction is to be used.  */
216 
217 static int
check_invalid_opcode(unsigned long opcode)218 check_invalid_opcode (unsigned long opcode)
219 {
220   return opcode == jalr_r9_opcode;
221 }
222 
223 /* Assemble a single instruction.  Its label has already been handled
224    by the generic front end.  We just parse opcode and operands, and
225    produce the bytes of data and relocation.  */
226 
227 void
md_assemble(char * str)228 md_assemble (char *str)
229 {
230   char *toP;
231 
232 #if DEBUG
233   printf ("NEW INSTRUCTION\n");
234 #endif
235 
236   know (str);
237   machine_ip (str);
238   toP = frag_more (4);
239 
240   /* Put out the opcode.  */
241   md_number_to_chars (toP, the_insn.opcode, 4);
242 
243   /* Put out the symbol-dependent stuff.  */
244   if (the_insn.reloc != BFD_RELOC_NONE)
245     {
246       fix_new_exp (frag_now,
247                    (toP - frag_now->fr_literal + the_insn.reloc_offset),
248                    4,   /* size */
249                    &the_insn.exp,
250                    the_insn.pcrel,
251                    the_insn.reloc);
252     }
253 }
254 
255 /* This is true of the we have issued a "lo(" or "hi"(.  */
256 static int waiting_for_shift = 0;
257 
258 static int mask_or_shift = 0;
259 
260 static char *
parse_operand(char * s,expressionS * operandp,int opt)261 parse_operand (char *s, expressionS *operandp, int opt)
262 {
263   char *save = input_line_pointer;
264   char *new;
265 
266 #if DEBUG
267   printf ("  PROCESS NEW OPERAND(%s) == %c (%d)\n", s, opt ? opt : '!', opt);
268 #endif
269 
270   input_line_pointer = s;
271 
272   if (strncasecmp (s, "HI(", 3) == 0)
273     {
274       waiting_for_shift = 1;
275       mask_or_shift = BFD_RELOC_HI16;
276 
277       input_line_pointer += 3;
278     }
279   else if (strncasecmp (s, "LO(", 3) == 0)
280     {
281       mask_or_shift = BFD_RELOC_LO16;
282 
283       input_line_pointer += 3;
284     }
285   else
286     mask_or_shift = 0;
287 
288   if ((*s == '(') && (*(s+1) == 'r'))
289     s++;
290 
291   if ((*s == 'r') && ISDIGIT (*(s + 1)))
292     {
293       operandp->X_add_number = strtol (s + 1, NULL, 10);
294       operandp->X_op = O_register;
295       for (; (*s != ',') && (*s != '\0');)
296         s++;
297       input_line_pointer = save;
298       return s;
299     }
300 
301   expression (operandp);
302 
303   if (operandp->X_op == O_absent)
304     {
305       if (! opt)
306         as_bad (_("missing operand"));
307       else
308         {
309           operandp->X_add_number = 0;
310           operandp->X_op = O_constant;
311         }
312     }
313 
314   new = input_line_pointer;
315   input_line_pointer = save;
316 
317 #if DEBUG
318   printf ("  %s=parse_operand(%s): operandp->X_op = %u\n", new, s, operandp->X_op);
319 #endif
320 
321   return new;
322 }
323 
324 /* Instruction parsing.  Takes a string containing the opcode.
325    Operands are at input_line_pointer.  Output is in the_insn.
326    Warnings or errors are generated.  */
327 
328 static void
machine_ip(char * str)329 machine_ip (char *str)
330 {
331   char *s;
332   const char *args;
333   const struct machine_opcode *insn;
334   char *argsStart;
335   unsigned long opcode;
336   expressionS the_operand;
337   expressionS *operand = &the_operand;
338   unsigned int regno;
339   int reloc = BFD_RELOC_NONE;
340 
341 #if DEBUG
342   printf ("machine_ip(%s)\n", str);
343 #endif
344 
345   s = str;
346   for (; ISALNUM (*s) || *s == '.'; ++s)
347     if (ISUPPER (*s))
348       *s = TOLOWER (*s);
349 
350   switch (*s)
351     {
352     case '\0':
353       break;
354 
355     case ' ':     /* FIXME-SOMEDAY more whitespace.  */
356       *s++ = '\0';
357       break;
358 
359     default:
360       as_bad (_("unknown opcode1: `%s'"), str);
361       return;
362     }
363 
364   if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
365     {
366       as_bad (_("unknown opcode2 `%s'."), str);
367       return;
368     }
369 
370   argsStart = s;
371   opcode = 0;
372   memset (&the_insn, '\0', sizeof (the_insn));
373   the_insn.reloc = BFD_RELOC_NONE;
374 
375   reloc = BFD_RELOC_NONE;
376 
377   /* Build the opcode, checking as we go to make sure that the
378      operands match.
379 
380      If an operand matches, we modify the_insn or opcode appropriately,
381      and do a "continue".  If an operand fails to match, we "break".  */
382   if (insn->args[0] != '\0')
383     /* Prime the pump.  */
384     s = parse_operand (s, operand, insn->args[0] == 'I');
385 
386   for (args = insn->args;; ++args)
387     {
388 #if DEBUG
389       printf ("  args = %s\n", args);
390 #endif
391       switch (*args)
392         {
393         case '\0':    /* End of args.  */
394           /* We have have 0 args, do the bazoooka!  */
395           if (args == insn->args)
396 	    encode (insn, &opcode, 0, 0);
397 
398           if (*s == '\0')
399             {
400               /* We are truly done.  */
401               the_insn.opcode = opcode;
402               if (check_invalid_opcode (opcode))
403                 as_bad (_("instruction not allowed: %s"), str);
404               return;
405             }
406           as_bad (_("too many operands: %s"), s);
407           break;
408 
409         case ',':   /* Must match a comma.  */
410           if (*s++ == ',')
411             {
412               reloc = BFD_RELOC_NONE;
413 
414               /* Parse next operand.  */
415               s = parse_operand (s, operand, args[1] == 'I');
416 #if DEBUG
417 	      printf ("    ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n",
418 		      operand->X_add_number, args, s);
419 #endif
420               continue;
421             }
422           break;
423 
424         case '(':   /* Must match a (.  */
425           s = parse_operand (s, operand, args[1] == 'I');
426           continue;
427 
428         case ')':   /* Must match a ).  */
429           continue;
430 
431         case 'r':   /* A general register.  */
432           args++;
433 
434           if (operand->X_op != O_register)
435             break;    /* Only registers.  */
436 
437           know (operand->X_add_symbol == 0);
438           know (operand->X_op_symbol == 0);
439           regno = operand->X_add_number;
440           encode (insn, &opcode, regno, *args);
441 #if DEBUG
442           printf ("    r: operand->X_op = %d\n", operand->X_op);
443 #endif
444           continue;
445 
446         default:
447           /* if (! ISALPHA (*args))
448                break;  */   /* Only immediate values.  */
449 
450           if (mask_or_shift)
451 	    {
452 #if DEBUG
453 	      printf ("mask_or_shift = %d\n", mask_or_shift);
454 #endif
455 	      reloc = mask_or_shift;
456 	    }
457           mask_or_shift = 0;
458 
459           if (strncasecmp (args, "LO(", 3) == 0)
460             {
461 #if DEBUG
462               printf ("reloc_const\n");
463 #endif
464               reloc = BFD_RELOC_LO16;
465             }
466           else if (strncasecmp (args, "HI(", 3) == 0)
467             {
468 #if DEBUG
469               printf ("reloc_consth\n");
470 #endif
471               reloc = BFD_RELOC_HI16;
472             }
473 
474           if (*s == '(')
475 	    operand->X_op = O_constant;
476           else if (*s == ')')
477             s += 1;
478 #if DEBUG
479           printf ("    default case: operand->X_add_number = %d, *args = %s, *s = %s\n", operand->X_add_number, args, s);
480 #endif
481           if (operand->X_op == O_constant)
482             {
483 	      if (reloc == BFD_RELOC_NONE)
484 		{
485 		  bfd_vma v, mask;
486 
487 		  mask = 0x3ffffff;
488 		  v = abs (operand->X_add_number) & ~ mask;
489 		  if (v)
490 		    as_bad (_("call/jmp target out of range (1)"));
491 		}
492 
493               if (reloc == BFD_RELOC_HI16)
494 		operand->X_add_number = ((operand->X_add_number >> 16) & 0xffff);
495 
496               the_insn.pcrel = 0;
497               encode (insn, &opcode, operand->X_add_number, *args);
498  /*             the_insn.reloc = BFD_RELOC_NONE; */
499               continue;
500             }
501 
502           if (reloc == BFD_RELOC_NONE)
503             the_insn.reloc = BFD_RELOC_32_GOT_PCREL;
504           else
505             the_insn.reloc = reloc;
506 
507           /* the_insn.reloc = insn->reloc;  */
508 #if DEBUG
509           printf ("    reloc sym=%d\n", the_insn.reloc);
510           printf ("    BFD_RELOC_NONE=%d\n", BFD_RELOC_NONE);
511 #endif
512           the_insn.exp = *operand;
513 
514           /*  the_insn.reloc_offset = 1;  */
515           the_insn.pcrel = 1; /* Assume PC-relative jump.  */
516 
517           /* FIXME-SOON, Do we figure out whether abs later, after
518              know sym val?  */
519           if (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_HI16)
520             the_insn.pcrel = 0;
521 
522           encode (insn, &opcode, operand->X_add_number, *args);
523           continue;
524         }
525 
526       /* Types or values of args don't match.  */
527       as_bad (_("invalid operands"));
528       return;
529     }
530 }
531 
532 /* This is identical to the md_atof in m68k.c.  I think this is right,
533    but I'm not sure.
534 
535    Turn a string in input_line_pointer into a floating point constant
536    of type type, and store the appropriate bytes in *litP.  The number
537    of LITTLENUMS emitted is stored in *sizeP .  An error message is
538    returned, or NULL on OK.  */
539 
540 /* Equal to MAX_PRECISION in atof-ieee.c.  */
541 #define MAX_LITTLENUMS 6
542 
543 char *
md_atof(int type,char * litP,int * sizeP)544 md_atof (int type, char * litP, int *  sizeP)
545 {
546   int prec;
547   LITTLENUM_TYPE words[MAX_LITTLENUMS];
548   LITTLENUM_TYPE *wordP;
549   char *t;
550 
551   switch (type)
552     {
553     case 'f':
554     case 'F':
555     case 's':
556     case 'S':
557       prec = 2;
558       break;
559 
560     case 'd':
561     case 'D':
562     case 'r':
563     case 'R':
564       prec = 4;
565       break;
566 
567     case 'x':
568     case 'X':
569       prec = 6;
570       break;
571 
572     case 'p':
573     case 'P':
574       prec = 6;
575       break;
576 
577     default:
578       *sizeP = 0;
579       return _("Bad call to MD_ATOF()");
580     }
581 
582   t = atof_ieee (input_line_pointer, type, words);
583   if (t)
584     input_line_pointer = t;
585 
586   *sizeP = prec * sizeof (LITTLENUM_TYPE);
587 
588   for (wordP = words; prec--;)
589     {
590       md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
591       litP += sizeof (LITTLENUM_TYPE);
592     }
593 
594   return NULL;
595 }
596 
597 /* Write out big-endian.  */
598 
599 void
md_number_to_chars(char * buf,valueT val,int n)600 md_number_to_chars (char *buf, valueT val, int n)
601 {
602   number_to_chars_bigendian (buf, val, n);
603 }
604 
605 void
md_apply_fix(fixS * fixP,valueT * val,segT seg ATTRIBUTE_UNUSED)606 md_apply_fix (fixS * fixP, valueT * val, segT seg ATTRIBUTE_UNUSED)
607 {
608   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
609   long t_val;
610 
611   t_val = (long) *val;
612 
613 #if DEBUG
614   printf ("md_apply_fix val:%x\n", t_val);
615 #endif
616 
617   fixP->fx_addnumber = t_val; /* Remember value for emit_reloc.  */
618 
619   know (fixP->fx_size == 4);
620   know (fixP->fx_r_type < BFD_RELOC_NONE);
621 
622   switch (fixP->fx_r_type)
623     {
624     case BFD_RELOC_32:      /* XXXXXXXX pattern in a word.  */
625 #if DEBUG
626       printf ("reloc_const: val=%x\n", t_val);
627 #endif
628       buf[0] = t_val >> 24;
629       buf[1] = t_val >> 16;
630       buf[2] = t_val >> 8;
631       buf[3] = t_val;
632       break;
633 
634     case BFD_RELOC_16:      /* XXXX0000 pattern in a word.  */
635 #if DEBUG
636       printf ("reloc_const: val=%x\n", t_val);
637 #endif
638       buf[0] = t_val >> 8;
639       buf[1] = t_val;
640       break;
641 
642     case BFD_RELOC_8:      /* XX000000 pattern in a word.  */
643 #if DEBUG
644       printf ("reloc_const: val=%x\n", t_val);
645 #endif
646       buf[0] = t_val;
647       break;
648 
649     case BFD_RELOC_LO16:      /* 0000XXXX pattern in a word.  */
650 #if DEBUG
651       printf ("reloc_const: val=%x\n", t_val);
652 #endif
653       buf[2] = t_val >> 8;  /* Holds bits 0000XXXX.  */
654       buf[3] = t_val;
655       break;
656 
657     case BFD_RELOC_HI16:    /* 0000XXXX pattern in a word.  */
658 #if DEBUG
659       printf ("reloc_consth: val=%x\n", t_val);
660 #endif
661       buf[2] = t_val >> 24; /* Holds bits XXXX0000.  */
662       buf[3] = t_val >> 16;
663       break;
664 
665     case BFD_RELOC_32_GOT_PCREL:  /* 0000XXXX pattern in a word.  */
666       if (!fixP->fx_done)
667         ;
668       else if (fixP->fx_pcrel)
669         {
670           long v = t_val >> 28;
671 
672           if (v != 0 && v != -1)
673             as_bad_where (fixP->fx_file, fixP->fx_line,
674                           _("call/jmp target out of range (2)"));
675         }
676       else
677         /* This case was supposed to be handled in machine_ip.  */
678         abort ();
679 
680       buf[0] |= (t_val >> 26) & 0x03; /* Holds bits 0FFFFFFC of address.  */
681       buf[1] = t_val >> 18;
682       buf[2] = t_val >> 10;
683       buf[3] = t_val >> 2;
684       break;
685 
686     case BFD_RELOC_VTABLE_INHERIT:
687     case BFD_RELOC_VTABLE_ENTRY:
688       fixP->fx_done = 0;
689       break;
690 
691     case BFD_RELOC_NONE:
692     default:
693       as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type);
694       break;
695     }
696 
697   if (fixP->fx_addsy == (symbolS *) NULL)
698     fixP->fx_done = 1;
699 }
700 
701 /* Should never be called for or32.  */
702 
703 void
md_create_short_jump(char * ptr ATTRIBUTE_UNUSED,addressT from_addr ATTRIBUTE_UNUSED,addressT to_addr ATTRIBUTE_UNUSED,fragS * frag ATTRIBUTE_UNUSED,symbolS * to_symbol ATTRIBUTE_UNUSED)704 md_create_short_jump (char *    ptr       ATTRIBUTE_UNUSED,
705 		      addressT  from_addr ATTRIBUTE_UNUSED,
706 		      addressT  to_addr   ATTRIBUTE_UNUSED,
707 		      fragS *   frag      ATTRIBUTE_UNUSED,
708 		      symbolS * to_symbol ATTRIBUTE_UNUSED)
709 {
710   as_fatal ("or32_create_short_jmp\n");
711 }
712 
713 /* Should never be called for or32.  */
714 
715 void
md_convert_frag(bfd * headers ATTRIBUTE_UNUSED,segT seg ATTRIBUTE_UNUSED,fragS * fragP ATTRIBUTE_UNUSED)716 md_convert_frag (bfd *   headers ATTRIBUTE_UNUSED,
717 		 segT    seg     ATTRIBUTE_UNUSED,
718 		 fragS * fragP   ATTRIBUTE_UNUSED)
719 {
720   as_fatal ("or32_convert_frag\n");
721 }
722 
723 /* Should never be called for or32.  */
724 
725 void
md_create_long_jump(char * ptr ATTRIBUTE_UNUSED,addressT from_addr ATTRIBUTE_UNUSED,addressT to_addr ATTRIBUTE_UNUSED,fragS * frag ATTRIBUTE_UNUSED,symbolS * to_symbol ATTRIBUTE_UNUSED)726 md_create_long_jump (char *    ptr       ATTRIBUTE_UNUSED,
727 		     addressT  from_addr ATTRIBUTE_UNUSED,
728 		     addressT  to_addr   ATTRIBUTE_UNUSED,
729 		     fragS *   frag      ATTRIBUTE_UNUSED,
730 		     symbolS * to_symbol ATTRIBUTE_UNUSED)
731 {
732   as_fatal ("or32_create_long_jump\n");
733 }
734 
735 /* Should never be called for or32.  */
736 
737 int
md_estimate_size_before_relax(fragS * fragP ATTRIBUTE_UNUSED,segT segtype ATTRIBUTE_UNUSED)738 md_estimate_size_before_relax (fragS * fragP   ATTRIBUTE_UNUSED,
739 			       segT    segtype ATTRIBUTE_UNUSED)
740 {
741   as_fatal ("or32_estimate_size_before_relax\n");
742   return 0;
743 }
744 
745 /* Translate internal representation of relocation info to target format.
746 
747    On sparc/29k: first 4 bytes are normal unsigned long address, next three
748    bytes are index, most sig. byte first.  Byte 7 is broken up with
749    bit 7 as external, bits 6 & 5 unused, and the lower
750    five bits as relocation type.  Next 4 bytes are long addend.  */
751 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com.  */
752 
753 #ifdef OBJ_AOUT
754 void
tc_aout_fix_to_chars(char * where,fixS * fixP,relax_addressT segment_address_in_file)755 tc_aout_fix_to_chars (char *where,
756 		      fixS *fixP,
757 		      relax_addressT segment_address_in_file)
758 {
759   long r_symbolnum;
760 
761 #if DEBUG
762   printf ("tc_aout_fix_to_chars\n");
763 #endif
764 
765   know (fixP->fx_r_type < BFD_RELOC_NONE);
766   know (fixP->fx_addsy != NULL);
767 
768   md_number_to_chars
769     (where,
770      fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
771      4);
772 
773   r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
774      ? S_GET_TYPE (fixP->fx_addsy)
775      : fixP->fx_addsy->sy_number);
776 
777   where[4] = (r_symbolnum >> 16) & 0x0ff;
778   where[5] = (r_symbolnum >> 8) & 0x0ff;
779   where[6] = r_symbolnum & 0x0ff;
780   where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
781 
782   /* Also easy.  */
783   md_number_to_chars (&where[8], fixP->fx_addnumber, 4);
784 }
785 
786 #endif /* OBJ_AOUT */
787 
788 const char *md_shortopts = "";
789 
790 struct option md_longopts[] =
791 {
792   { NULL, no_argument, NULL, 0 }
793 };
794 size_t md_longopts_size = sizeof (md_longopts);
795 
796 int
md_parse_option(int c ATTRIBUTE_UNUSED,char * arg ATTRIBUTE_UNUSED)797 md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
798 {
799   return 0;
800 }
801 
802 void
md_show_usage(FILE * stream ATTRIBUTE_UNUSED)803 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
804 {
805 }
806 
807 /* This is called when a line is unrecognized.  This is used to handle
808    definitions of or32 style local labels.  */
809 
810 int
or32_unrecognized_line(int c)811 or32_unrecognized_line (int c)
812 {
813   int lab;
814   char *s;
815 
816   if (c != '$'
817       || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
818     return 0;
819 
820   s = input_line_pointer;
821 
822   lab = 0;
823   while (ISDIGIT ((unsigned char) *s))
824     {
825       lab = lab * 10 + *s - '0';
826       ++s;
827     }
828 
829   if (*s != ':')
830     /* Not a label definition.  */
831     return 0;
832 
833   if (dollar_label_defined (lab))
834     {
835       as_bad (_("label \"$%d\" redefined"), lab);
836       return 0;
837     }
838 
839   define_dollar_label (lab);
840   colon (dollar_label_name (lab, 0));
841   input_line_pointer = s + 1;
842 
843   return 1;
844 }
845 
846 /* Default the values of symbols known that should be "predefined".  We
847    don't bother to predefine them unless you actually use one, since there
848    are a lot of them.  */
849 
850 symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)851 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
852 {
853   return NULL;
854 }
855 
856 /* Parse an operand that is machine-specific.  */
857 
858 void
md_operand(expressionS * expressionP)859 md_operand (expressionS *expressionP)
860 {
861 #if DEBUG
862   printf ("  md_operand(input_line_pointer = %s)\n", input_line_pointer);
863 #endif
864 
865   if (input_line_pointer[0] == REGISTER_PREFIX && input_line_pointer[1] == 'r')
866     {
867       /* We have a numeric register expression.  No biggy.  */
868       input_line_pointer += 2;  /* Skip %r */
869       (void) expression (expressionP);
870 
871       if (expressionP->X_op != O_constant
872           || expressionP->X_add_number > 255)
873         as_bad (_("Invalid expression after %%%%\n"));
874       expressionP->X_op = O_register;
875     }
876   else if (input_line_pointer[0] == '&')
877     {
878       /* We are taking the 'address' of a register...this one is not
879          in the manual, but it *is* in traps/fpsymbol.h!  What they
880          seem to want is the register number, as an absolute number.  */
881       input_line_pointer++; /* Skip & */
882       (void) expression (expressionP);
883 
884       if (expressionP->X_op != O_register)
885         as_bad (_("invalid register in & expression"));
886       else
887         expressionP->X_op = O_constant;
888     }
889   else if (input_line_pointer[0] == '$'
890            && ISDIGIT ((unsigned char) input_line_pointer[1]))
891     {
892       long lab;
893       char *name;
894       symbolS *sym;
895 
896       /* This is a local label.  */
897       ++input_line_pointer;
898       lab = (long) get_absolute_expression ();
899 
900       if (dollar_label_defined (lab))
901         {
902           name = dollar_label_name (lab, 0);
903           sym = symbol_find (name);
904         }
905       else
906         {
907           name = dollar_label_name (lab, 1);
908           sym = symbol_find_or_make (name);
909         }
910 
911       expressionP->X_op = O_symbol;
912       expressionP->X_add_symbol = sym;
913       expressionP->X_add_number = 0;
914     }
915   else if (input_line_pointer[0] == '$')
916     {
917       char *s;
918       char type;
919       int fieldnum, fieldlimit;
920       LITTLENUM_TYPE floatbuf[8];
921 
922       /* $float(), $doubleN(), or $extendN() convert floating values
923          to integers.  */
924       s = input_line_pointer;
925 
926       ++s;
927 
928       fieldnum = 0;
929       if (strncmp (s, "double", sizeof "double" - 1) == 0)
930         {
931           s += sizeof "double" - 1;
932           type = 'd';
933           fieldlimit = 2;
934         }
935       else if (strncmp (s, "float", sizeof "float" - 1) == 0)
936         {
937           s += sizeof "float" - 1;
938           type = 'f';
939           fieldlimit = 1;
940         }
941       else if (strncmp (s, "extend", sizeof "extend" - 1) == 0)
942         {
943           s += sizeof "extend" - 1;
944           type = 'x';
945           fieldlimit = 4;
946         }
947       else
948 	return;
949 
950       if (ISDIGIT (*s))
951         {
952           fieldnum = *s - '0';
953           ++s;
954         }
955       if (fieldnum >= fieldlimit)
956         return;
957 
958       SKIP_WHITESPACE ();
959       if (*s != '(')
960         return;
961       ++s;
962       SKIP_WHITESPACE ();
963 
964       s = atof_ieee (s, type, floatbuf);
965       if (s == NULL)
966         return;
967       s = s;
968 
969       SKIP_WHITESPACE ();
970       if (*s != ')')
971         return;
972       ++s;
973       SKIP_WHITESPACE ();
974 
975       input_line_pointer = s;
976       expressionP->X_op = O_constant;
977       expressionP->X_unsigned = 1;
978       expressionP->X_add_number = ((floatbuf[fieldnum * 2]
979                                     << LITTLENUM_NUMBER_OF_BITS)
980                                    + floatbuf[fieldnum * 2 + 1]);
981     }
982 }
983 
984 /* Round up a section size to the appropriate boundary.  */
985 
986 valueT
md_section_align(segT segment ATTRIBUTE_UNUSED,valueT size ATTRIBUTE_UNUSED)987 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size ATTRIBUTE_UNUSED)
988 {
989   return size;      /* Byte alignment is fine.  */
990 }
991 
992 /* Exactly what point is a PC-relative offset relative TO?
993    On the 29000, they're relative to the address of the instruction,
994    which we have set up as the address of the fixup too.  */
995 
996 long
md_pcrel_from(fixS * fixP)997 md_pcrel_from (fixS *fixP)
998 {
999   return fixP->fx_where + fixP->fx_frag->fr_address;
1000 }
1001 
1002 /* Generate a reloc for a fixup.  */
1003 
1004 arelent *
tc_gen_reloc(asection * seg ATTRIBUTE_UNUSED,fixS * fixp)1005 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
1006 {
1007   arelent *reloc;
1008 
1009   reloc = xmalloc (sizeof (arelent));
1010   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
1011   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1012   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1013   /*  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where + fixp->fx_addnumber;*/
1014   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1015 
1016   if (reloc->howto == (reloc_howto_type *) NULL)
1017     {
1018       as_bad_where (fixp->fx_file, fixp->fx_line,
1019 		    _("reloc %d not supported by object file format"),
1020 		    (int) fixp->fx_r_type);
1021       return NULL;
1022     }
1023 
1024   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1025     reloc->address = fixp->fx_offset;
1026 
1027   reloc->addend = fixp->fx_addnumber;
1028   return reloc;
1029 }
1030