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.  */
47static struct hash_control *op_hash = NULL;
48
49struct 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  }
59the_insn;
60
61static void machine_ip PARAMS ((char *));
62
63const 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
76int md_short_jump_size  = 4;
77int md_long_jump_size   = 4;
78
79#if defined(BFD_HEADERS)
80#ifdef RELSZ
81const int md_reloc_size = RELSZ;  /* Coff headers.  */
82#else
83const int md_reloc_size = 12;   /* Something else headers.  */
84#endif
85#else
86const 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.  */
91const 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.  */
100const 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.  */
104const char line_separator_chars[] = ";";
105
106/* Chars that can be used to separate mant from exp in floating point nums.  */
107const 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.  */
112const char FLT_CHARS[] = "rRsSfFdDxXpP";
113
114/* "l.jalr r9" precalculated opcode.  */
115static unsigned long jalr_r9_opcode;
116
117
118static int check_invalid_opcode PARAMS ((unsigned long));
119static void encode PARAMS ((const struct machine_opcode *, unsigned long *, signed long, char));
120static char *parse_operand PARAMS ((char *, expressionS *, int));
121
122/* Set bits in machine opcode according to insn->encoding
123   description and passed operand.  */
124
125static void
126encode (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
197void
198md_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
235static int
236check_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
246void
247md_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"(.  */
280static int waiting_for_shift = 0;
281
282static int mask_or_shift = 0;
283
284#ifdef BFD_ASSEMBLER
285static char *
286parse_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
353static char *
354parse_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
432static void
433machine_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
647static void
648machine_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
871char *
872md_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
930void
931md_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
940void
941md_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
1052void
1053md_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
1188short
1189tc_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
1220void
1221md_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
1234void
1235md_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
1244void
1245md_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
1256void
1257md_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
1269int
1270md_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
1287void
1288tc_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
1322const char *md_shortopts = "";
1323
1324struct option md_longopts[] =
1325  {
1326    { NULL, no_argument, NULL, 0 }
1327  };
1328size_t md_longopts_size = sizeof (md_longopts);
1329
1330int
1331md_parse_option (c, arg)
1332     int    c   ATTRIBUTE_UNUSED;
1333     char * arg ATTRIBUTE_UNUSED;
1334{
1335  return 0;
1336}
1337
1338void
1339md_show_usage (stream)
1340     FILE * stream ATTRIBUTE_UNUSED;
1341{
1342}
1343
1344/* This is called when a line is unrecognized.  This is used to handle
1345   definitions of or32 style local labels.  */
1346
1347int
1348or32_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
1388or32_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}
1399void
1400tc_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
1413symbolS *
1414md_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
1450void
1451md_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
1579valueT
1580md_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
1591long
1592md_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
1601arelent *
1602tc_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
1631