]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gas/config/tc-or32.c
Import the binutils-2_15-branch from the sourceware CVS repository,
[FreeBSD/FreeBSD.git] / gas / config / tc-or32.c
1 /* Assembly backend for the OpenRISC 1000.
2    Copyright (C) 2002 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, 59 Temple Place - Suite 330,
22    Boston, MA 02111-1307, 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
30 #ifdef BFD_ASSEMBLER
31 #include "elf/or32.h"
32 #endif
33
34 #define DEBUG 0
35
36 #ifndef REGISTER_PREFIX
37 #define REGISTER_PREFIX   '%'
38 #endif
39
40 /* Make it easier to clone this machine desc into another one.  */
41 #define machine_opcode  or32_opcode
42 #define machine_opcodes or32_opcodes
43 #define machine_ip      or32_ip
44 #define machine_it      or32_it
45
46 /* Handle of the OPCODE hash table.  */
47 static struct hash_control *op_hash = NULL;
48
49 struct machine_it
50   {
51     char *          error;
52     unsigned long   opcode;
53     struct nlist *  nlistp;
54     expressionS     exp;
55     int             pcrel;
56     int             reloc_offset;   /* Offset of reloc within insn.  */
57     int             reloc;
58   }
59 the_insn;
60
61 static void machine_ip PARAMS ((char *));
62
63 const pseudo_typeS md_pseudo_table[] =
64   {
65     {"align",   s_align_bytes,  4 },
66     {"space",   s_space,        0 },
67     {"cputype", s_ignore,       0 },
68     {"reg",     s_lsym,         0 },  /* Register equate, same as equ.  */
69     {"sect",    s_ignore,       0 },  /* Creation of coff sections.  */
70     {"proc",    s_ignore,       0 },  /* Start of a function.  */
71     {"endproc", s_ignore,       0 },  /* Function end.  */
72     {"word",    cons,           4 },
73     {NULL,      0,              0 },
74   };
75
76 int md_short_jump_size  = 4;
77 int md_long_jump_size   = 4;
78
79 #if defined(BFD_HEADERS)
80 #ifdef RELSZ
81 const int md_reloc_size = RELSZ;  /* Coff headers.  */
82 #else
83 const int md_reloc_size = 12;   /* Something else headers.  */
84 #endif
85 #else
86 const int md_reloc_size = 12;   /* Not bfdized.  */
87 #endif
88
89 /* This array holds the chars that always start a comment.
90    If the pre-processor is disabled, these aren't very useful.  */
91 const char comment_chars[] = "#";
92
93 /* This array holds the chars that only start a comment at the beginning of
94    a line.  If the line seems to have the form '# 123 filename'
95    .line and .file directives will appear in the pre-processed output.  */
96 /* Note that input_file.c hand checks for '#' at the beginning of the
97    first line of the input file.  This is because the compiler outputs
98    #NO_APP at the beginning of its output.  */
99 /* Also note that comments like this one will always work.  */
100 const char line_comment_chars[] = "#";
101
102 /* We needed an unused char for line separation to work around the
103    lack of macros, using sed and such.  */
104 const char line_separator_chars[] = ";";
105
106 /* Chars that can be used to separate mant from exp in floating point nums.  */
107 const char EXP_CHARS[] = "eE";
108
109 /* Chars that mean this number is a floating point constant.
110    As in 0f12.456
111    or    0d1.2345e12.  */
112 const char FLT_CHARS[] = "rRsSfFdDxXpP";
113
114 /* "l.jalr r9" precalculated opcode.  */
115 static unsigned long jalr_r9_opcode;
116
117
118 static int check_invalid_opcode PARAMS ((unsigned long));
119 static void encode PARAMS ((const struct machine_opcode *, unsigned long *, signed long, char));
120 static char *parse_operand PARAMS ((char *, expressionS *, int));
121
122 /* Set bits in machine opcode according to insn->encoding
123    description and passed operand.  */
124
125 static void
126 encode (insn, opcode, param_val, param_ch)
127      const struct machine_opcode *insn;
128      unsigned long *opcode;
129      signed long param_val;
130      char param_ch;
131 {
132   int opc_pos = 0;
133   int param_pos = 0;
134   char *enc;
135
136 #if DEBUG
137   printf ("    encode:  opcode=%.8lx  param_val=%.8lx abs=%.8lx param_ch=%c\n",
138           *opcode, param_val, abs (param_val), param_ch);
139 #endif
140   for (enc = insn->encoding; *enc != '\0'; enc++)
141     if (*enc == param_ch)
142       {
143         if (enc - 2 >= insn->encoding && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
144           continue;
145         else
146           param_pos ++;
147       }
148
149   opc_pos = 32;
150
151   for (enc = insn->encoding; *enc != '\0';)
152     {
153       if ((*enc == '0') && (*(enc + 1) == 'x'))
154         {
155           int tmp = strtol (enc, NULL, 16);
156
157           opc_pos -= 4;
158           *opcode |= tmp << opc_pos;
159           enc += 3;
160         }
161       else if ((*enc == '0') || (*enc == '-'))
162         {
163           opc_pos--;
164           enc++;
165         }
166       else if (*enc == '1')
167         {
168           opc_pos--;
169           *opcode |= 1 << opc_pos;
170           enc++;
171         }
172       else if (*enc == param_ch)
173         {
174           opc_pos--;
175           param_pos--;
176           *opcode |= ((param_val >> param_pos) & 0x1) << opc_pos;
177           enc++;
178         }
179       else if (ISALPHA (*enc))
180         {
181           opc_pos--;
182           enc++;
183         }
184       else
185         enc++;
186     }
187
188 #if DEBUG
189   printf ("    opcode=%.8lx\n", *opcode);
190 #endif
191 }
192
193 /* This function is called once, at assembler startup time.  It should
194    set up all the tables, etc., that the MD part of the assembler will
195    need.  */
196
197 void
198 md_begin ()
199 {
200   const char *retval = NULL;
201   int lose = 0;
202   int skipnext = 0;
203   unsigned int i;
204
205   /* Hash up all the opcodes for fast use later.  */
206   op_hash = hash_new ();
207
208   for (i = 0; i < or32_num_opcodes; i++)
209     {
210       const char *name = machine_opcodes[i].name;
211
212       if (skipnext)
213         {
214           skipnext = 0;
215           continue;
216         }
217
218       retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]);
219       if (retval != NULL)
220         {
221           fprintf (stderr, "internal error: can't hash `%s': %s\n",
222                    machine_opcodes[i].name, retval);
223           lose = 1;
224         }
225     }
226
227   if (lose)
228     as_fatal (_("Broken assembler.  No assembly attempted."));
229
230   encode (&machine_opcodes[insn_index ("l.jalr")], &jalr_r9_opcode, 9, 'B');
231 }
232
233 /* Returns non zero if instruction is to be used.  */
234
235 static int
236 check_invalid_opcode (opcode)
237      unsigned long opcode;
238 {
239   return opcode == jalr_r9_opcode;
240 }
241
242 /* Assemble a single instruction.  Its label has already been handled
243    by the generic front end.  We just parse opcode and operands, and
244    produce the bytes of data and relocation.  */
245
246 void
247 md_assemble (str)
248      char *str;
249 {
250   char *toP;
251
252 #if DEBUG
253   printf ("NEW INSTRUCTION\n");
254 #endif
255
256   know (str);
257   machine_ip (str);
258   toP = frag_more (4);
259
260   /* Put out the opcode.  */
261   md_number_to_chars (toP, the_insn.opcode, 4);
262
263   /* Put out the symbol-dependent stuff.  */
264 #ifdef BFD_ASSEMBLER
265   if (the_insn.reloc != BFD_RELOC_NONE)
266 #else
267   if (the_insn.reloc != NO_RELOC)
268 #endif
269     {
270       fix_new_exp (frag_now,
271                    (toP - frag_now->fr_literal + the_insn.reloc_offset),
272                    4,   /* size */
273                    &the_insn.exp,
274                    the_insn.pcrel,
275                    the_insn.reloc);
276     }
277 }
278
279 /* This is true of the we have issued a "lo(" or "hi"(.  */
280 static int waiting_for_shift = 0;
281
282 static int mask_or_shift = 0;
283
284 #ifdef BFD_ASSEMBLER
285 static char *
286 parse_operand (s, operandp, opt)
287      char *s;
288      expressionS *operandp;
289      int opt;
290 {
291   char *save = input_line_pointer;
292   char *new;
293
294 #if DEBUG
295   printf ("  PROCESS NEW OPERAND(%s) == %c (%d)\n", s, opt ? opt : '!', opt);
296 #endif
297
298   input_line_pointer = s;
299
300   if (strncasecmp (s, "HI(", 3) == 0)
301     {
302       waiting_for_shift = 1;
303       mask_or_shift = BFD_RELOC_HI16;
304
305       input_line_pointer += 3;
306     }
307   else if (strncasecmp (s, "LO(", 3) == 0)
308     {
309       mask_or_shift = BFD_RELOC_LO16;
310
311       input_line_pointer += 3;
312     }
313   else
314     mask_or_shift = 0;
315
316   if ((*s == '(') && (*(s+1) == 'r'))
317     s++;
318
319   if ((*s == 'r') && ISDIGIT (*(s + 1)))
320     {
321       operandp->X_add_number = strtol (s + 1, NULL, 10);
322       operandp->X_op = O_register;
323       for (; (*s != ',') && (*s != '\0');)
324         s++;
325       input_line_pointer = save;
326       return s;
327     }
328
329   expression (operandp);
330
331   if (operandp->X_op == O_absent)
332     {
333       if (! opt)
334         as_bad (_("missing operand"));
335       else
336         {
337           operandp->X_add_number = 0;
338           operandp->X_op = O_constant;
339         }
340     }
341
342   new = input_line_pointer;
343   input_line_pointer = save;
344
345 #if DEBUG
346   printf ("  %s=parse_operand(%s): operandp->X_op = %u\n", new, s, operandp->X_op);
347 #endif
348
349   return new;
350 }
351 #else
352
353 static char *
354 parse_operand (s, operandp, opt)
355      char *s;
356      expressionS *operandp;
357      int opt;
358 {
359   char *save = input_line_pointer;
360   char *new;
361
362 #if DEBUG
363   printf ("  PROCESS NEW OPERAND(%s) == %c (%d)\n", s, opt ? opt : '!', opt);
364 #endif
365
366   input_line_pointer = s;
367
368   if (strncasecmp (s, "HI(", 3) == 0)
369     {
370       waiting_for_shift = 1;
371       mask_or_shift = RELOC_CONSTH;
372
373       input_line_pointer += 3;
374     }
375   else if (strncasecmp (s, "LO(", 3) == 0)
376     {
377       mask_or_shift = RELOC_CONST;
378
379       input_line_pointer += 3;
380     }
381   else
382     mask_or_shift = 0;
383
384
385   expression (operandp);
386
387   if (operandp->X_op == O_absent)
388     {
389       if (! opt)
390         as_bad (_("missing operand"));
391       else
392         {
393           operandp->X_add_number = 0;
394           operandp->X_op = O_constant;
395         }
396     }
397
398   new = input_line_pointer;
399   input_line_pointer = save;
400
401   if ((operandp->X_op == O_symbol) && (*s != '_'))
402     {
403 #if DEBUG
404       printf ("symbol: '%s'\n", save);
405 #endif
406
407       for (save = s; s < new; s++)
408         if ((*s == REGISTER_PREFIX) && (*(s + 1) == 'r')) /* Register prefix.  */
409           s++;
410
411         if ((*s == 'r') && ISDIGIT (*(s + 1)))
412           {
413             operandp->X_add_number = strtol (s + 1, NULL, 10);
414             operandp->X_op = O_register;
415           }
416       s = save;
417     }
418
419 #if DEBUG
420   printf ("  %s=parse_operand(%s): operandp->X_op = %u\n", new, s, operandp->X_op);
421 #endif
422
423   return new;
424 }
425 #endif
426
427 /* Instruction parsing.  Takes a string containing the opcode.
428    Operands are at input_line_pointer.  Output is in the_insn.
429    Warnings or errors are generated.  */
430
431 #ifdef BFD_ASSEMBLER
432 static void
433 machine_ip (str)
434      char *str;
435 {
436   char *s;
437   const char *args;
438   const struct machine_opcode *insn;
439   char *argsStart;
440   unsigned long opcode;
441   expressionS the_operand;
442   expressionS *operand = &the_operand;
443   unsigned int regno;
444   int reloc = BFD_RELOC_NONE;
445
446 #if DEBUG
447   printf ("machine_ip(%s)\n", str);
448 #endif
449
450   s = str;
451   for (; ISALNUM (*s) || *s == '.'; ++s)
452     if (ISUPPER (*s))
453       *s = TOLOWER (*s);
454
455   switch (*s)
456     {
457     case '\0':
458       break;
459
460     case ' ':     /* FIXME-SOMEDAY more whitespace.  */
461       *s++ = '\0';
462       break;
463
464     default:
465       as_bad (_("unknown opcode1: `%s'"), str);
466       return;
467     }
468
469   if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
470     {
471       as_bad (_("unknown opcode2 `%s'."), str);
472       return;
473     }
474
475   argsStart = s;
476   opcode = 0;
477   memset (&the_insn, '\0', sizeof (the_insn));
478   the_insn.reloc = BFD_RELOC_NONE;
479
480   reloc = BFD_RELOC_NONE;
481
482   /* Build the opcode, checking as we go to make sure that the
483      operands match.
484
485      If an operand matches, we modify the_insn or opcode appropriately,
486      and do a "continue".  If an operand fails to match, we "break".  */
487   if (insn->args[0] != '\0')
488     {
489       /* Prime the pump.  */
490       s = parse_operand (s, operand, insn->args[0] == 'I');
491     }
492
493   for (args = insn->args;; ++args)
494     {
495 #if DEBUG
496       printf ("  args = %s\n", args);
497 #endif
498       switch (*args)
499         {
500         case '\0':    /* End of args.  */
501           /* We have have 0 args, do the bazoooka!  */
502           if (args == insn->args)
503             encode (insn, &opcode, 0, 0);
504
505           if (*s == '\0')
506             {
507               /* We are truly done.  */
508               the_insn.opcode = opcode;
509               if (check_invalid_opcode (opcode))
510                 as_bad (_("instruction not allowed: %s"), str);
511               return;
512             }
513           as_bad (_("too many operands: %s"), s);
514           break;
515
516         case ',':   /* Must match a comma.  */
517           if (*s++ == ',')
518             {
519               reloc = BFD_RELOC_NONE;
520
521               /* Parse next operand.  */
522               s = parse_operand (s, operand, args[1] == 'I');
523 #if DEBUG
524               printf ("    ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n",
525                       operand->X_add_number, args, s);
526 #endif
527               continue;
528             }
529           break;
530
531         case '(':   /* Must match a (.  */
532           s = parse_operand (s, operand, args[1] == 'I');
533           continue;
534
535         case ')':   /* Must match a ).  */
536           continue;
537
538         case 'r':   /* A general register.  */
539           args++;
540
541           if (operand->X_op != O_register)
542             break;    /* Only registers.  */
543
544           know (operand->X_add_symbol == 0);
545           know (operand->X_op_symbol == 0);
546           regno = operand->X_add_number;
547           encode (insn, &opcode, regno, *args);
548 #if DEBUG
549           printf ("    r: operand->X_op = %d\n", operand->X_op);
550 #endif
551           continue;
552
553         default:
554           /* if (! ISALPHA (*args))
555                break;  */   /* Only immediate values.  */
556
557           if (mask_or_shift)
558             {
559 #if DEBUG
560               printf ("mask_or_shift = %d\n", mask_or_shift);
561 #endif
562               reloc = mask_or_shift;
563             }
564           mask_or_shift = 0;
565
566           if (strncasecmp (args, "LO(", 3) == 0)
567             {
568 #if DEBUG
569               printf ("reloc_const\n");
570 #endif
571               reloc = BFD_RELOC_LO16;
572             }
573           else if (strncasecmp (args, "HI(", 3) == 0)
574             {
575 #if DEBUG
576               printf ("reloc_consth\n");
577 #endif
578               reloc = BFD_RELOC_HI16;
579             }
580
581           if (*s == '(')
582             {
583               operand->X_op = O_constant;
584 #if 0
585               operand->X_add_number = 0; /* ??? if enabled load/store offsets
586                                             are zero.  */
587 #endif
588             }
589           else if (*s == ')')
590             s += 1;
591 #if DEBUG
592           printf ("    default case: operand->X_add_number = %d, *args = %s, *s = %s\n", operand->X_add_number, args, s);
593 #endif
594           if (operand->X_op == O_constant)
595             {
596               if (reloc == BFD_RELOC_NONE)
597                 {
598                   bfd_vma v, mask;
599
600                   mask = 0x3ffffff;
601                   v = abs (operand->X_add_number) & ~ mask;
602                   if (v)
603                     as_bad (_("call/jmp target out of range (1)"));
604                 }
605
606               if (reloc == BFD_RELOC_HI16)
607                 operand->X_add_number = ((operand->X_add_number >> 16) & 0xffff);
608
609               the_insn.pcrel = 0;
610               encode (insn, &opcode, operand->X_add_number, *args);
611  /*             the_insn.reloc = BFD_RELOC_NONE; */
612               continue;
613             }
614
615           if (reloc == BFD_RELOC_NONE)
616             the_insn.reloc = BFD_RELOC_32_GOT_PCREL;
617           else
618             the_insn.reloc = reloc;
619
620           /* the_insn.reloc = insn->reloc;  */
621 #if DEBUG
622           printf ("    reloc sym=%d\n", the_insn.reloc);
623           printf ("    BFD_RELOC_NONE=%d\n", BFD_RELOC_NONE);
624 #endif
625           the_insn.exp = *operand;
626
627           /*  the_insn.reloc_offset = 1;  */
628           the_insn.pcrel = 1; /* Assume PC-relative jump.  */
629
630           /* FIXME-SOON, Do we figure out whether abs later, after
631              know sym val?  */
632           if (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_HI16)
633             the_insn.pcrel = 0;
634
635           encode (insn, &opcode, operand->X_add_number, *args);
636           continue;
637         }
638
639       /* Types or values of args don't match.  */
640       as_bad (_("invalid operands"));
641       return;
642     }
643 }
644
645 #else
646
647 static void
648 machine_ip (str)
649      char *str;
650 {
651   char *s;
652   const char *args;
653   const struct machine_opcode *insn;
654   char *argsStart;
655   unsigned long opcode;
656   expressionS the_operand;
657   expressionS *operand = &the_operand;
658   unsigned int regno;
659   int reloc = NO_RELOC;
660
661 #if DEBUG
662   printf ("machine_ip(%s)\n", str);
663 #endif
664
665   s = str;
666   for (; ISALNUM (*s) || *s == '.'; ++s)
667     if (ISUPPER (*s))
668       *s = TOLOWER (*s);
669
670   switch (*s)
671     {
672     case '\0':
673       break;
674
675     case ' ':     /* FIXME-SOMEDAY more whitespace.  */
676       *s++ = '\0';
677       break;
678
679     default:
680       as_bad (_("unknown opcode1: `%s'"), str);
681       return;
682     }
683
684   if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
685     {
686       as_bad (_("unknown opcode2 `%s'."), str);
687       return;
688     }
689
690   argsStart = s;
691   opcode = 0;
692   memset (&the_insn, '\0', sizeof (the_insn));
693   the_insn.reloc = NO_RELOC;
694
695   reloc = NO_RELOC;
696
697   /* Build the opcode, checking as we go to make sure that the
698      operands match.
699
700      If an operand matches, we modify the_insn or opcode appropriately,
701      and do a "continue".  If an operand fails to match, we "break".  */
702   if (insn->args[0] != '\0')
703     /* Prime the pump.  */
704     s = parse_operand (s, operand,
705                        insn->args[0] == 'I'
706                        || strcmp (insn->name, "l.nop") == 0);
707
708   for (args = insn->args;; ++args)
709     {
710 #if DEBUG
711       printf ("  args = %s\n", args);
712 #endif
713       switch (*args)
714         {
715         case '\0':    /* End of args.  */
716           /* We have have 0 args, do the bazoooka!  */
717           if (args == insn->args)
718             encode (insn, &opcode, 0, 0);
719
720           if (*s == '\0')
721             {
722               /* We are truly done.  */
723               the_insn.opcode = opcode;
724               if (check_invalid_opcode (opcode))
725                 as_bad (_("instruction not allowed: %s"), str);
726               return;
727             }
728           as_bad (_("too many operands: %s"), s);
729           break;
730
731         case ',':   /* Must match a comma.  */
732           if (*s++ == ',')
733             {
734               reloc = NO_RELOC;
735
736               /* Parse next operand.  */
737               s = parse_operand (s, operand, args[1] == 'I');
738 #if DEBUG
739               printf ("    ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n",
740                       operand->X_add_number, args, s);
741 #endif
742               continue;
743             }
744           break;
745
746         case '(':   /* Must match a (.  */
747           s = parse_operand (s, operand, args[1] == 'I');
748           continue;
749
750         case ')':   /* Must match a ).  */
751           continue;
752
753         case 'r':   /* A general register.  */
754           args++;
755
756           if (operand->X_op != O_register)
757             break;    /* Only registers.  */
758
759           know (operand->X_add_symbol == 0);
760           know (operand->X_op_symbol == 0);
761           regno = operand->X_add_number;
762           encode (insn, &opcode, regno, *args);
763 #if DEBUG
764           printf ("    r: operand->X_op = %d\n", operand->X_op);
765 #endif
766           continue;
767
768         default:
769           /* if (! ISALPHA (*args))
770                break;  */   /* Only immediate values.  */
771
772           if (mask_or_shift)
773             {
774 #if DEBUG
775               printf ("mask_or_shift = %d\n", mask_or_shift);
776 #endif
777               reloc = mask_or_shift;
778             }
779           mask_or_shift = 0;
780
781           if (strncasecmp (args, "LO(", 3) == 0)
782             {
783 #if DEBUG
784               printf ("reloc_const\n");
785 #endif
786               reloc = RELOC_CONST;
787             }
788           else if (strncasecmp (args, "HI(", 3) == 0)
789             {
790 #if DEBUG
791               printf ("reloc_consth\n");
792 #endif
793               reloc = RELOC_CONSTH;
794             }
795
796           if (*s == '(')
797             {
798               operand->X_op = O_constant;
799 #if 0
800               operand->X_add_number = 0; /* ??? if enabled load/store offsets
801                                             are zero.  */
802 #endif
803             }
804           else if (*s == ')')
805             s += 1;
806 #if DEBUG
807           printf ("    default case: operand->X_add_number = %d, *args = %s, *s = %s\n",
808                   operand->X_add_number, args, s);
809 #endif
810           if (operand->X_op == O_constant)
811             {
812               if (reloc == NO_RELOC)
813                 {
814                   unsigned long v, mask;
815
816                   mask = 0x3ffffff;
817                   v = abs (operand->X_add_number) & ~ mask;
818                   if (v)
819                     as_bad (_("call/jmp target out of range (1)"));
820                 }
821
822               if (reloc == RELOC_CONSTH)
823                 operand->X_add_number = ((operand->X_add_number>>16) & 0xffff);
824
825               the_insn.pcrel = 0;
826               encode (insn, &opcode, operand->X_add_number, *args);
827               /* the_insn.reloc = NO_RELOC; */
828               continue;
829             }
830
831           if (reloc == NO_RELOC)
832             the_insn.reloc = RELOC_JUMPTARG;
833           else
834             the_insn.reloc = reloc;
835 #if DEBUG
836           printf ("    reloc sym=%d\n", the_insn.reloc);
837           printf ("    NO_RELOC=%d\n", NO_RELOC);
838 #endif
839           the_insn.exp = *operand;
840
841           /*  the_insn.reloc_offset = 1;  */
842           the_insn.pcrel = 1; /* Assume PC-relative jump.  */
843
844           /* FIXME-SOON, Do we figure out whether abs later, after
845              know sym val?  */
846           if (reloc == RELOC_CONST || reloc == RELOC_CONSTH)
847             the_insn.pcrel = 0;
848
849           encode (insn, &opcode, operand->X_add_number, *args);
850           continue;
851         }
852
853       /* Types or values of args don't match.  */
854       as_bad (_("invalid operands"));
855       return;
856     }
857 }
858 #endif
859
860 /* This is identical to the md_atof in m68k.c.  I think this is right,
861    but I'm not sure.
862
863    Turn a string in input_line_pointer into a floating point constant
864    of type type, and store the appropriate bytes in *litP.  The number
865    of LITTLENUMS emitted is stored in *sizeP .  An error message is
866    returned, or NULL on OK.  */
867
868 /* Equal to MAX_PRECISION in atof-ieee.c.  */
869 #define MAX_LITTLENUMS 6
870
871 char *
872 md_atof (type, litP, sizeP)
873      char   type;
874      char * litP;
875      int *  sizeP;
876 {
877   int prec;
878   LITTLENUM_TYPE words[MAX_LITTLENUMS];
879   LITTLENUM_TYPE *wordP;
880   char *t;
881
882   switch (type)
883     {
884     case 'f':
885     case 'F':
886     case 's':
887     case 'S':
888       prec = 2;
889       break;
890
891     case 'd':
892     case 'D':
893     case 'r':
894     case 'R':
895       prec = 4;
896       break;
897
898     case 'x':
899     case 'X':
900       prec = 6;
901       break;
902
903     case 'p':
904     case 'P':
905       prec = 6;
906       break;
907
908     default:
909       *sizeP = 0;
910       return _("Bad call to MD_ATOF()");
911     }
912
913   t = atof_ieee (input_line_pointer, type, words);
914   if (t)
915     input_line_pointer = t;
916
917   *sizeP = prec * sizeof (LITTLENUM_TYPE);
918
919   for (wordP = words; prec--;)
920     {
921       md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
922       litP += sizeof (LITTLENUM_TYPE);
923     }
924
925   return NULL;
926 }
927
928 /* Write out big-endian.  */
929
930 void
931 md_number_to_chars (buf, val, n)
932      char *buf;
933      valueT val;
934      int n;
935 {
936   number_to_chars_bigendian (buf, val, n);
937 }
938
939 #ifdef BFD_ASSEMBLER
940 void
941 md_apply_fix3 (fixP, val, seg)
942      fixS *   fixP;
943      valueT * val;
944      segT     seg ATTRIBUTE_UNUSED;
945 {
946   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
947   long t_val;
948
949   t_val = (long) *val;
950
951 #if DEBUG
952   printf ("md_apply_fix val:%x\n", t_val);
953 #endif
954
955   fixP->fx_addnumber = t_val; /* Remember value for emit_reloc.  */
956
957   know (fixP->fx_size == 4);
958   know (fixP->fx_r_type < BFD_RELOC_NONE);
959
960   switch (fixP->fx_r_type)
961     {
962     case BFD_RELOC_32:      /* XXXXXXXX pattern in a word.  */
963 #if DEBUG
964       printf ("reloc_const: val=%x\n", t_val);
965 #endif
966       buf[0] = t_val >> 24;
967       buf[1] = t_val >> 16;
968       buf[2] = t_val >> 8;
969       buf[3] = t_val;
970       break;
971
972     case BFD_RELOC_16:      /* XXXX0000 pattern in a word.  */
973 #if DEBUG
974       printf ("reloc_const: val=%x\n", t_val);
975 #endif
976       buf[0] = t_val >> 8;
977       buf[1] = t_val;
978       break;
979
980     case BFD_RELOC_8:      /* XX000000 pattern in a word.  */
981 #if DEBUG
982       printf ("reloc_const: val=%x\n", t_val);
983 #endif
984       buf[0] = t_val;
985       break;
986
987     case BFD_RELOC_LO16:      /* 0000XXXX pattern in a word.  */
988 #if DEBUG
989       printf ("reloc_const: val=%x\n", t_val);
990 #endif
991       buf[2] = t_val >> 8;  /* Holds bits 0000XXXX.  */
992       buf[3] = t_val;
993       break;
994
995     case BFD_RELOC_HI16:    /* 0000XXXX pattern in a word.  */
996 #if DEBUG
997       printf ("reloc_consth: val=%x\n", t_val);
998 #endif
999       buf[2] = t_val >> 24; /* Holds bits XXXX0000.  */
1000       buf[3] = t_val >> 16;
1001       break;
1002
1003     case BFD_RELOC_32_GOT_PCREL:  /* 0000XXXX pattern in a word.  */
1004       if (!fixP->fx_done)
1005         {
1006           /* The linker tries to support both AMD and old GNU style
1007              R_IREL relocs.  That means that if the addend is exactly
1008              the negative of the address within the section, the
1009              linker will not handle it correctly.  */
1010 #if 0
1011           if (fixP->fx_pcrel
1012               && t_val != 0
1013               && t_val == - (fixP->fx_frag->fr_address + fixP->fx_where))
1014             as_bad_where
1015               (fixP->fx_file, fixP->fx_line,
1016                _("the linker will not handle this relocation correctly (1)"));
1017 #endif
1018         }
1019       else if (fixP->fx_pcrel)
1020         {
1021           long v = t_val >> 28;
1022
1023           if (v != 0 && v != -1)
1024             as_bad_where (fixP->fx_file, fixP->fx_line,
1025                           _("call/jmp target out of range (2)"));
1026         }
1027       else
1028         /* This case was supposed to be handled in machine_ip.  */
1029         abort ();
1030
1031       buf[0] |= (t_val >> 26) & 0x03; /* Holds bits 0FFFFFFC of address.  */
1032       buf[1] = t_val >> 18;
1033       buf[2] = t_val >> 10;
1034       buf[3] = t_val >> 2;
1035       break;
1036
1037     case BFD_RELOC_VTABLE_INHERIT:
1038     case BFD_RELOC_VTABLE_ENTRY:
1039       fixP->fx_done = 0;
1040       break;
1041
1042     case BFD_RELOC_NONE:
1043     default:
1044       as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type);
1045       break;
1046     }
1047
1048   if (fixP->fx_addsy == (symbolS *) NULL)
1049     fixP->fx_done = 1;
1050 }
1051 #else
1052 void
1053 md_apply_fix3 (fixP, valP, seg)
1054      fixS *fixP;
1055      valueT *valP;
1056      segT seg ATTRIBUTE_UNUSED;
1057 {
1058   long val = *valP;
1059   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1060
1061 #if DEBUG
1062   printf ("md_apply_fix val:%x\n", val);
1063 #endif
1064
1065   fixP->fx_addnumber = val; /* Remember value for emit_reloc.  */
1066
1067   know (fixP->fx_size == 4);
1068   know (fixP->fx_r_type < NO_RELOC);
1069
1070   /* This is a hack.  There should be a better way to handle this.  */
1071   if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy)
1072     val += fixP->fx_where + fixP->fx_frag->fr_address;
1073
1074   switch (fixP->fx_r_type)
1075     {
1076     case RELOC_32:
1077       buf[0] = val >> 24;
1078       buf[1] = val >> 16;
1079       buf[2] = val >> 8;
1080       buf[3] = val;
1081       break;
1082
1083     case RELOC_8:
1084       buf[0] = val;
1085       break;
1086
1087     case RELOC_WDISP30:
1088       val = (val >> 2) + 1;
1089       buf[0] |= (val >> 24) & 0x3f;
1090       buf[1] = (val >> 16);
1091       buf[2] = val >> 8;
1092       buf[3] = val;
1093       break;
1094
1095     case RELOC_HI22:
1096       buf[1] |= (val >> 26) & 0x3f;
1097       buf[2] = val >> 18;
1098       buf[3] = val >> 10;
1099       break;
1100
1101     case RELOC_LO10:
1102       buf[2] |= (val >> 8) & 0x03;
1103       buf[3] = val;
1104       break;
1105
1106     case RELOC_BASE13:
1107       buf[2] |= (val >> 8) & 0x1f;
1108       buf[3] = val;
1109       break;
1110
1111     case RELOC_WDISP22:
1112       val = (val >> 2) + 1;
1113       /* FALLTHROUGH */
1114     case RELOC_BASE22:
1115       buf[1] |= (val >> 16) & 0x3f;
1116       buf[2] = val >> 8;
1117       buf[3] = val;
1118       break;
1119
1120     case RELOC_JUMPTARG:  /* 0000XXXX pattern in a word.  */
1121       if (!fixP->fx_done)
1122         {
1123           /* The linker tries to support both AMD and old GNU style
1124              R_IREL relocs.  That means that if the addend is exactly
1125              the negative of the address within the section, the
1126              linker will not handle it correctly.  */
1127 #if 0
1128           if (fixP->fx_pcrel
1129               && val != 0
1130               && val == - (fixP->fx_frag->fr_address + fixP->fx_where))
1131             as_bad_where
1132               (fixP->fx_file, fixP->fx_line,
1133                _("the linker will not handle this relocation correctly (1)"));
1134 #endif
1135         }
1136       else if (fixP->fx_pcrel)
1137         {
1138           long v = val >> 28;
1139 #if 1
1140           if (v != 0 && v != -1)
1141             as_bad_where (fixP->fx_file, fixP->fx_line,
1142                           _("call/jmp target out of range (2)"));
1143 #endif
1144         }
1145       else
1146         /* This case was supposed to be handled in machine_ip.  */
1147         abort ();
1148
1149       buf[0] |= (val >> 26) & 0x03; /* Holds bits 0FFFFFFC of address.  */
1150       buf[1] = val >> 18;
1151       buf[2] = val >> 10;
1152       buf[3] = val >> 2;
1153       break;
1154
1155     case RELOC_CONST:     /* 0000XXXX pattern in a word.  */
1156 #if DEBUG
1157       printf ("reloc_const: val=%x\n", val);
1158 #endif
1159       buf[2] = val >> 8;  /* Holds bits 0000XXXX.  */
1160       buf[3] = val;
1161       break;
1162
1163     case RELOC_CONSTH:    /* 0000XXXX pattern in a word.  */
1164 #if DEBUG
1165       printf ("reloc_consth: val=%x\n", val);
1166 #endif
1167       buf[2] = val >> 24; /* Holds bits XXXX0000.  */
1168       buf[3] = val >> 16;
1169       break;
1170
1171     case BFD_RELOC_VTABLE_INHERIT:
1172     case BFD_RELOC_VTABLE_ENTRY:
1173       fixP->fx_done = 0;
1174       break;
1175
1176     case NO_RELOC:
1177     default:
1178       as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type);
1179       break;
1180     }
1181
1182   if (fixP->fx_addsy == (symbolS *) NULL)
1183     fixP->fx_done = 1;
1184 }
1185 #endif
1186
1187 #ifdef OBJ_COFF
1188 short
1189 tc_coff_fix2rtype (fixP)
1190      fixS *fixP;
1191 {
1192 #if DEBUG
1193   printf ("tc_coff_fix2rtype\n");
1194 #endif
1195
1196   switch (fixP->fx_r_type)
1197     {
1198     case RELOC_32:
1199       return (R_WORD);
1200     case RELOC_8:
1201       return (R_BYTE);
1202     case RELOC_CONST:
1203       return (R_ILOHALF);
1204     case RELOC_CONSTH:
1205       return (R_IHIHALF);
1206     case RELOC_JUMPTARG:
1207       return (R_IREL);
1208     default:
1209       printf ("need %d\n", fixP->fx_r_type);
1210       abort ();
1211     }
1212
1213   return 0;
1214 }
1215
1216 #endif /* OBJ_COFF */
1217
1218 /* Should never be called for or32.  */
1219
1220 void
1221 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
1222      char *    ptr       ATTRIBUTE_UNUSED;
1223      addressT  from_addr ATTRIBUTE_UNUSED;
1224      addressT  to_addr   ATTRIBUTE_UNUSED;
1225      fragS *   frag      ATTRIBUTE_UNUSED;
1226      symbolS * to_symbol ATTRIBUTE_UNUSED;
1227 {
1228   as_fatal ("or32_create_short_jmp\n");
1229 }
1230
1231 /* Should never be called for or32.  */
1232
1233 #ifndef BFD_ASSEMBLER
1234 void
1235 md_convert_frag (headers, seg, fragP)
1236      object_headers * headers ATTRIBUTE_UNUSED;
1237      segT             seg     ATTRIBUTE_UNUSED;
1238      register fragS * fragP   ATTRIBUTE_UNUSED;
1239 {
1240   as_fatal ("or32_convert_frag\n");
1241 }
1242
1243 #else
1244 void
1245 md_convert_frag (headers, seg, fragP)
1246      bfd *   headers ATTRIBUTE_UNUSED;
1247      segT    seg     ATTRIBUTE_UNUSED;
1248      fragS * fragP   ATTRIBUTE_UNUSED;
1249 {
1250   as_fatal ("or32_convert_frag\n");
1251 }
1252 #endif
1253
1254 /* Should never be called for or32.  */
1255
1256 void
1257 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
1258      char *    ptr       ATTRIBUTE_UNUSED;
1259      addressT  from_addr ATTRIBUTE_UNUSED;
1260      addressT  to_addr   ATTRIBUTE_UNUSED;
1261      fragS *   frag      ATTRIBUTE_UNUSED;
1262      symbolS * to_symbol ATTRIBUTE_UNUSED;
1263 {
1264   as_fatal ("or32_create_long_jump\n");
1265 }
1266
1267 /* Should never be called for or32.  */
1268
1269 int
1270 md_estimate_size_before_relax (fragP, segtype)
1271      fragS * fragP   ATTRIBUTE_UNUSED;
1272      segT    segtype ATTRIBUTE_UNUSED;
1273 {
1274   as_fatal ("or32_estimate_size_before_relax\n");
1275   return 0;
1276 }
1277
1278 /* Translate internal representation of relocation info to target format.
1279
1280    On sparc/29k: first 4 bytes are normal unsigned long address, next three
1281    bytes are index, most sig. byte first.  Byte 7 is broken up with
1282    bit 7 as external, bits 6 & 5 unused, and the lower
1283    five bits as relocation type.  Next 4 bytes are long addend.  */
1284 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com.  */
1285
1286 #ifdef OBJ_AOUT
1287 void
1288 tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
1289      char *where;
1290      fixS *fixP;
1291      relax_addressT segment_address_in_file;
1292 {
1293   long r_symbolnum;
1294
1295 #if DEBUG
1296   printf ("tc_aout_fix_to_chars\n");
1297 #endif
1298
1299   know (fixP->fx_r_type < BFD_RELOC_NONE);
1300   know (fixP->fx_addsy != NULL);
1301
1302   md_number_to_chars
1303     (where,
1304      fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
1305      4);
1306
1307   r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
1308      ? S_GET_TYPE (fixP->fx_addsy)
1309      : fixP->fx_addsy->sy_number);
1310
1311   where[4] = (r_symbolnum >> 16) & 0x0ff;
1312   where[5] = (r_symbolnum >> 8) & 0x0ff;
1313   where[6] = r_symbolnum & 0x0ff;
1314   where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
1315
1316   /* Also easy.  */
1317   md_number_to_chars (&where[8], fixP->fx_addnumber, 4);
1318 }
1319
1320 #endif /* OBJ_AOUT */
1321 \f
1322 const char *md_shortopts = "";
1323
1324 struct option md_longopts[] =
1325   {
1326     { NULL, no_argument, NULL, 0 }
1327   };
1328 size_t md_longopts_size = sizeof (md_longopts);
1329
1330 int
1331 md_parse_option (c, arg)
1332      int    c   ATTRIBUTE_UNUSED;
1333      char * arg ATTRIBUTE_UNUSED;
1334 {
1335   return 0;
1336 }
1337
1338 void
1339 md_show_usage (stream)
1340      FILE * stream ATTRIBUTE_UNUSED;
1341 {
1342 }
1343 \f
1344 /* This is called when a line is unrecognized.  This is used to handle
1345    definitions of or32 style local labels.  */
1346
1347 int
1348 or32_unrecognized_line (c)
1349      int c;
1350 {
1351   int lab;
1352   char *s;
1353
1354   if (c != '$'
1355       || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
1356     return 0;
1357
1358   s = input_line_pointer;
1359
1360   lab = 0;
1361   while (ISDIGIT ((unsigned char) *s))
1362     {
1363       lab = lab * 10 + *s - '0';
1364       ++s;
1365     }
1366
1367   if (*s != ':')
1368     /* Not a label definition.  */
1369     return 0;
1370
1371   if (dollar_label_defined (lab))
1372     {
1373       as_bad (_("label \"$%d\" redefined"), lab);
1374       return 0;
1375     }
1376
1377   define_dollar_label (lab);
1378   colon (dollar_label_name (lab, 0));
1379   input_line_pointer = s + 1;
1380
1381   return 1;
1382 }
1383
1384 #ifndef BFD_ASSEMBLER
1385 /* Record a fixup for a cons expression.  */
1386 /*
1387   void
1388 or32_cons_fix_new (frag, where, nbytes, exp)
1389      fragS *frag;
1390      int where;
1391      int nbytes;
1392      expressionS *exp;
1393 {
1394   fix_new_exp (frag, where, nbytes, exp, 0,
1395                    nbytes == 5 ? RELOC_32
1396                    : nbytes == 2 ? RELOC_16
1397                    : RELOC_8);
1398 }
1399 void
1400 tc_aout_pre_write_hook ()
1401 {
1402 #if DEBUG
1403   printf ("In tc_aout_pre_write_hook()\n");
1404 #endif
1405 }
1406 */
1407 #endif
1408
1409 /* Default the values of symbols known that should be "predefined".  We
1410    don't bother to predefine them unless you actually use one, since there
1411    are a lot of them.  */
1412
1413 symbolS *
1414 md_undefined_symbol (name)
1415      char *name ATTRIBUTE_UNUSED;
1416 {
1417 #ifndef BFD_ASSEMBLER
1418   long regnum;
1419   char testbuf[5 + /*SLOP*/ 5];
1420
1421 #if DEBUG
1422   printf ("md_undefined_symbol(%s)\n", name);
1423 #endif
1424
1425   /* Register name.  */
1426   if (name[0] == 'r' || name[0] == 'R' || name[0] == 'a' || name[0] == 'b')
1427     {
1428       /* Parse the number, make sure it has no extra zeroes or
1429          trailing chars.  */
1430       regnum = atol (& name[1]);
1431
1432       if (regnum > 31)
1433         as_fatal (_("register out of range"));
1434
1435       sprintf (testbuf, "%ld", regnum);
1436
1437       if (strcmp (testbuf, &name[1]) != 0)
1438         return NULL;  /* gr007 or lr7foo or whatever.  */
1439
1440       /* We have a wiener!  Define and return a new symbol for it.  */
1441       return (symbol_new (name, SEG_REGISTER, (valueT) regnum,
1442                           &zero_address_frag));
1443     }
1444 #endif
1445   return NULL;
1446 }
1447
1448 /* Parse an operand that is machine-specific.  */
1449
1450 void
1451 md_operand (expressionP)
1452      expressionS *expressionP;
1453 {
1454 #if DEBUG
1455   printf ("  md_operand(input_line_pointer = %s)\n", input_line_pointer);
1456 #endif
1457
1458   if (input_line_pointer[0] == REGISTER_PREFIX && input_line_pointer[1] == 'r')
1459     {
1460       /* We have a numeric register expression.  No biggy.  */
1461       input_line_pointer += 2;  /* Skip %r */
1462       (void) expression (expressionP);
1463
1464       if (expressionP->X_op != O_constant
1465           || expressionP->X_add_number > 255)
1466         as_bad (_("Invalid expression after %%%%\n"));
1467       expressionP->X_op = O_register;
1468     }
1469   else if (input_line_pointer[0] == '&')
1470     {
1471       /* We are taking the 'address' of a register...this one is not
1472          in the manual, but it *is* in traps/fpsymbol.h!  What they
1473          seem to want is the register number, as an absolute number.  */
1474       input_line_pointer++; /* Skip & */
1475       (void) expression (expressionP);
1476
1477       if (expressionP->X_op != O_register)
1478         as_bad (_("invalid register in & expression"));
1479       else
1480         expressionP->X_op = O_constant;
1481     }
1482   else if (input_line_pointer[0] == '$'
1483            && ISDIGIT ((unsigned char) input_line_pointer[1]))
1484     {
1485       long lab;
1486       char *name;
1487       symbolS *sym;
1488
1489       /* This is a local label.  */
1490       ++input_line_pointer;
1491       lab = (long) get_absolute_expression ();
1492
1493       if (dollar_label_defined (lab))
1494         {
1495           name = dollar_label_name (lab, 0);
1496           sym = symbol_find (name);
1497         }
1498       else
1499         {
1500           name = dollar_label_name (lab, 1);
1501           sym = symbol_find_or_make (name);
1502         }
1503
1504       expressionP->X_op = O_symbol;
1505       expressionP->X_add_symbol = sym;
1506       expressionP->X_add_number = 0;
1507     }
1508   else if (input_line_pointer[0] == '$')
1509     {
1510       char *s;
1511       char type;
1512       int fieldnum, fieldlimit;
1513       LITTLENUM_TYPE floatbuf[8];
1514
1515       /* $float(), $doubleN(), or $extendN() convert floating values
1516          to integers.  */
1517       s = input_line_pointer;
1518
1519       ++s;
1520
1521       fieldnum = 0;
1522       if (strncmp (s, "double", sizeof "double" - 1) == 0)
1523         {
1524           s += sizeof "double" - 1;
1525           type = 'd';
1526           fieldlimit = 2;
1527         }
1528       else if (strncmp (s, "float", sizeof "float" - 1) == 0)
1529         {
1530           s += sizeof "float" - 1;
1531           type = 'f';
1532           fieldlimit = 1;
1533         }
1534       else if (strncmp (s, "extend", sizeof "extend" - 1) == 0)
1535         {
1536           s += sizeof "extend" - 1;
1537           type = 'x';
1538           fieldlimit = 4;
1539         }
1540       else
1541         return;
1542
1543       if (ISDIGIT (*s))
1544         {
1545           fieldnum = *s - '0';
1546           ++s;
1547         }
1548       if (fieldnum >= fieldlimit)
1549         return;
1550
1551       SKIP_WHITESPACE ();
1552       if (*s != '(')
1553         return;
1554       ++s;
1555       SKIP_WHITESPACE ();
1556
1557       s = atof_ieee (s, type, floatbuf);
1558       if (s == NULL)
1559         return;
1560       s = s;
1561
1562       SKIP_WHITESPACE ();
1563       if (*s != ')')
1564         return;
1565       ++s;
1566       SKIP_WHITESPACE ();
1567
1568       input_line_pointer = s;
1569       expressionP->X_op = O_constant;
1570       expressionP->X_unsigned = 1;
1571       expressionP->X_add_number = ((floatbuf[fieldnum * 2]
1572                                     << LITTLENUM_NUMBER_OF_BITS)
1573                                    + floatbuf[fieldnum * 2 + 1]);
1574     }
1575 }
1576
1577 /* Round up a section size to the appropriate boundary.  */
1578
1579 valueT
1580 md_section_align (segment, size)
1581      segT segment ATTRIBUTE_UNUSED;
1582      valueT size ATTRIBUTE_UNUSED;
1583 {
1584   return size;      /* Byte alignment is fine.  */
1585 }
1586
1587 /* Exactly what point is a PC-relative offset relative TO?
1588    On the 29000, they're relative to the address of the instruction,
1589    which we have set up as the address of the fixup too.  */
1590
1591 long
1592 md_pcrel_from (fixP)
1593      fixS *fixP;
1594 {
1595   return fixP->fx_where + fixP->fx_frag->fr_address;
1596 }
1597
1598 /* Generate a reloc for a fixup.  */
1599
1600 #ifdef BFD_ASSEMBLER
1601 arelent *
1602 tc_gen_reloc (seg, fixp)
1603      asection *seg ATTRIBUTE_UNUSED;
1604      fixS *fixp;
1605 {
1606   arelent *reloc;
1607
1608   reloc = (arelent *) xmalloc (sizeof (arelent));
1609   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1610   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1611   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1612   /*  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where + fixp->fx_addnumber;*/
1613   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1614
1615   if (reloc->howto == (reloc_howto_type *) NULL)
1616     {
1617       as_bad_where (fixp->fx_file, fixp->fx_line,
1618                     _("reloc %d not supported by object file format"),
1619                     (int) fixp->fx_r_type);
1620       return NULL;
1621     }
1622
1623   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1624     reloc->address = fixp->fx_offset;
1625
1626   reloc->addend = fixp->fx_addnumber;
1627   return reloc;
1628 }
1629 #endif
1630