Back to index

cell-binutils  2.17cvs20070401
tc-or32.c
Go to the documentation of this file.
00001 /* Assembly backend for the OpenRISC 1000.
00002    Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
00003    Contributed by Damjan Lampret <lampret@opencores.org>.
00004    Modified bu Johan Rydberg, <johan.rydberg@netinsight.se>.
00005    Based upon a29k port.
00006 
00007    This file is part of GAS, the GNU Assembler.
00008 
00009    GAS is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2, or (at your option)
00012    any later version.
00013 
00014    GAS is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with GAS; see the file COPYING.  If not, write to
00021    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
00022    Boston, MA 02110-1301, USA.  */
00023 
00024 /* tc-a29k.c used as a template.  */
00025 
00026 #include "safe-ctype.h"
00027 #include "as.h"
00028 #include "opcode/or32.h"
00029 #include "elf/or32.h"
00030 
00031 #define DEBUG 0
00032 
00033 #ifndef REGISTER_PREFIX
00034 #define REGISTER_PREFIX   '%'
00035 #endif
00036 
00037 /* Make it easier to clone this machine desc into another one.  */
00038 #define machine_opcode  or32_opcode
00039 #define machine_opcodes or32_opcodes
00040 #define machine_ip      or32_ip
00041 #define machine_it      or32_it
00042 
00043 /* Handle of the OPCODE hash table.  */
00044 static struct hash_control *op_hash = NULL;
00045 
00046 struct machine_it
00047 {
00048   char *          error;
00049   unsigned long   opcode;
00050   struct nlist *  nlistp;
00051   expressionS     exp;
00052   int             pcrel;
00053   int             reloc_offset;   /* Offset of reloc within insn.  */
00054   int             reloc;
00055 }
00056 the_insn;
00057 
00058 const pseudo_typeS md_pseudo_table[] =
00059 {
00060   {"align",   s_align_bytes,  4 },
00061   {"space",   s_space,        0 },
00062   {"cputype", s_ignore,       0 },
00063   {"reg",     s_lsym,         0 },  /* Register equate, same as equ.  */
00064   {"sect",    s_ignore,       0 },  /* Creation of coff sections.  */
00065   {"proc",    s_ignore,       0 },  /* Start of a function.  */
00066   {"endproc", s_ignore,       0 },  /* Function end.  */
00067   {"word",    cons,           4 },
00068   {NULL,      0,              0 },
00069 };
00070 
00071 int md_short_jump_size  = 4;
00072 int md_long_jump_size   = 4;
00073 
00074 /* This array holds the chars that always start a comment.
00075    If the pre-processor is disabled, these aren't very useful.  */
00076 const char comment_chars[] = "#";
00077 
00078 /* This array holds the chars that only start a comment at the beginning of
00079    a line.  If the line seems to have the form '# 123 filename'
00080    .line and .file directives will appear in the pre-processed output.  */
00081 /* Note that input_file.c hand checks for '#' at the beginning of the
00082    first line of the input file.  This is because the compiler outputs
00083    #NO_APP at the beginning of its output.  */
00084 /* Also note that comments like this one will always work.  */
00085 const char line_comment_chars[] = "#";
00086 
00087 /* We needed an unused char for line separation to work around the
00088    lack of macros, using sed and such.  */
00089 const char line_separator_chars[] = ";";
00090 
00091 /* Chars that can be used to separate mant from exp in floating point nums.  */
00092 const char EXP_CHARS[] = "eE";
00093 
00094 /* Chars that mean this number is a floating point constant.
00095    As in 0f12.456
00096    or    0d1.2345e12.  */
00097 const char FLT_CHARS[] = "rRsSfFdDxXpP";
00098 
00099 /* "l.jalr r9" precalculated opcode.  */
00100 static unsigned long jalr_r9_opcode;
00101 
00102 static void machine_ip (char *);
00103 
00104 
00105 /* Set bits in machine opcode according to insn->encoding
00106    description and passed operand.  */
00107 
00108 static void
00109 encode (const struct machine_opcode *insn,
00110        unsigned long *opcode,
00111        signed long param_val,
00112        char param_ch)
00113 {
00114   int opc_pos = 0;
00115   int param_pos = 0;
00116   char *enc;
00117 
00118 #if DEBUG
00119   printf ("    encode:  opcode=%.8lx  param_val=%.8lx abs=%.8lx param_ch=%c\n",
00120          *opcode, param_val, abs (param_val), param_ch);
00121 #endif
00122   for (enc = insn->encoding; *enc != '\0'; enc++)
00123     if (*enc == param_ch)
00124       {
00125        if (enc - 2 >= insn->encoding && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
00126          continue;
00127        else
00128          param_pos ++;
00129       }
00130 
00131   opc_pos = 32;
00132 
00133   for (enc = insn->encoding; *enc != '\0';)
00134     {
00135       if ((*enc == '0') && (*(enc + 1) == 'x'))
00136        {
00137          int tmp = strtol (enc, NULL, 16);
00138 
00139          opc_pos -= 4;
00140          *opcode |= tmp << opc_pos;
00141          enc += 3;
00142        }
00143       else if ((*enc == '0') || (*enc == '-'))
00144        {
00145          opc_pos--;
00146          enc++;
00147        }
00148       else if (*enc == '1')
00149        {
00150          opc_pos--;
00151          *opcode |= 1 << opc_pos;
00152          enc++;
00153        }
00154       else if (*enc == param_ch)
00155        {
00156          opc_pos--;
00157          param_pos--;
00158          *opcode |= ((param_val >> param_pos) & 0x1) << opc_pos;
00159          enc++;
00160        }
00161       else if (ISALPHA (*enc))
00162        {
00163          opc_pos--;
00164          enc++;
00165        }
00166       else
00167        enc++;
00168     }
00169 
00170 #if DEBUG
00171   printf ("    opcode=%.8lx\n", *opcode);
00172 #endif
00173 }
00174 
00175 /* This function is called once, at assembler startup time.  It should
00176    set up all the tables, etc., that the MD part of the assembler will
00177    need.  */
00178 
00179 void
00180 md_begin (void)
00181 {
00182   const char *retval = NULL;
00183   int lose = 0;
00184   int skipnext = 0;
00185   unsigned int i;
00186 
00187   /* Hash up all the opcodes for fast use later.  */
00188   op_hash = hash_new ();
00189 
00190   for (i = 0; i < or32_num_opcodes; i++)
00191     {
00192       const char *name = machine_opcodes[i].name;
00193 
00194       if (skipnext)
00195         {
00196           skipnext = 0;
00197           continue;
00198         }
00199 
00200       retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]);
00201       if (retval != NULL)
00202         {
00203           fprintf (stderr, "internal error: can't hash `%s': %s\n",
00204                    machine_opcodes[i].name, retval);
00205           lose = 1;
00206         }
00207     }
00208 
00209   if (lose)
00210     as_fatal (_("Broken assembler.  No assembly attempted."));
00211 
00212   encode (&machine_opcodes[insn_index ("l.jalr")], &jalr_r9_opcode, 9, 'B');
00213 }
00214 
00215 /* Returns non zero if instruction is to be used.  */
00216 
00217 static int
00218 check_invalid_opcode (unsigned long opcode)
00219 {
00220   return opcode == jalr_r9_opcode;
00221 }
00222 
00223 /* Assemble a single instruction.  Its label has already been handled
00224    by the generic front end.  We just parse opcode and operands, and
00225    produce the bytes of data and relocation.  */
00226 
00227 void
00228 md_assemble (char *str)
00229 {
00230   char *toP;
00231 
00232 #if DEBUG
00233   printf ("NEW INSTRUCTION\n");
00234 #endif
00235 
00236   know (str);
00237   machine_ip (str);
00238   toP = frag_more (4);
00239 
00240   /* Put out the opcode.  */
00241   md_number_to_chars (toP, the_insn.opcode, 4);
00242 
00243   /* Put out the symbol-dependent stuff.  */
00244   if (the_insn.reloc != BFD_RELOC_NONE)
00245     {
00246       fix_new_exp (frag_now,
00247                    (toP - frag_now->fr_literal + the_insn.reloc_offset),
00248                    4,   /* size */
00249                    &the_insn.exp,
00250                    the_insn.pcrel,
00251                    the_insn.reloc);
00252     }
00253 }
00254 
00255 /* This is true of the we have issued a "lo(" or "hi"(.  */
00256 static int waiting_for_shift = 0;
00257 
00258 static int mask_or_shift = 0;
00259 
00260 static char *
00261 parse_operand (char *s, expressionS *operandp, int opt)
00262 {
00263   char *save = input_line_pointer;
00264   char *new;
00265 
00266 #if DEBUG
00267   printf ("  PROCESS NEW OPERAND(%s) == %c (%d)\n", s, opt ? opt : '!', opt);
00268 #endif
00269 
00270   input_line_pointer = s;
00271 
00272   if (strncasecmp (s, "HI(", 3) == 0)
00273     {
00274       waiting_for_shift = 1;
00275       mask_or_shift = BFD_RELOC_HI16;
00276 
00277       input_line_pointer += 3;
00278     }
00279   else if (strncasecmp (s, "LO(", 3) == 0)
00280     {
00281       mask_or_shift = BFD_RELOC_LO16;
00282 
00283       input_line_pointer += 3;
00284     }
00285   else
00286     mask_or_shift = 0;
00287 
00288   if ((*s == '(') && (*(s+1) == 'r'))
00289     s++;
00290 
00291   if ((*s == 'r') && ISDIGIT (*(s + 1)))
00292     {
00293       operandp->X_add_number = strtol (s + 1, NULL, 10);
00294       operandp->X_op = O_register;
00295       for (; (*s != ',') && (*s != '\0');)
00296         s++;
00297       input_line_pointer = save;
00298       return s;
00299     }
00300 
00301   expression (operandp);
00302 
00303   if (operandp->X_op == O_absent)
00304     {
00305       if (! opt)
00306         as_bad (_("missing operand"));
00307       else
00308         {
00309           operandp->X_add_number = 0;
00310           operandp->X_op = O_constant;
00311         }
00312     }
00313 
00314   new = input_line_pointer;
00315   input_line_pointer = save;
00316 
00317 #if DEBUG
00318   printf ("  %s=parse_operand(%s): operandp->X_op = %u\n", new, s, operandp->X_op);
00319 #endif
00320 
00321   return new;
00322 }
00323 
00324 /* Instruction parsing.  Takes a string containing the opcode.
00325    Operands are at input_line_pointer.  Output is in the_insn.
00326    Warnings or errors are generated.  */
00327 
00328 static void
00329 machine_ip (char *str)
00330 {
00331   char *s;
00332   const char *args;
00333   const struct machine_opcode *insn;
00334   char *argsStart;
00335   unsigned long opcode;
00336   expressionS the_operand;
00337   expressionS *operand = &the_operand;
00338   unsigned int regno;
00339   int reloc = BFD_RELOC_NONE;
00340 
00341 #if DEBUG
00342   printf ("machine_ip(%s)\n", str);
00343 #endif
00344 
00345   s = str;
00346   for (; ISALNUM (*s) || *s == '.'; ++s)
00347     if (ISUPPER (*s))
00348       *s = TOLOWER (*s);
00349 
00350   switch (*s)
00351     {
00352     case '\0':
00353       break;
00354 
00355     case ' ':     /* FIXME-SOMEDAY more whitespace.  */
00356       *s++ = '\0';
00357       break;
00358 
00359     default:
00360       as_bad (_("unknown opcode1: `%s'"), str);
00361       return;
00362     }
00363 
00364   if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
00365     {
00366       as_bad (_("unknown opcode2 `%s'."), str);
00367       return;
00368     }
00369 
00370   argsStart = s;
00371   opcode = 0;
00372   memset (&the_insn, '\0', sizeof (the_insn));
00373   the_insn.reloc = BFD_RELOC_NONE;
00374 
00375   reloc = BFD_RELOC_NONE;
00376 
00377   /* Build the opcode, checking as we go to make sure that the
00378      operands match.
00379 
00380      If an operand matches, we modify the_insn or opcode appropriately,
00381      and do a "continue".  If an operand fails to match, we "break".  */
00382   if (insn->args[0] != '\0')
00383     /* Prime the pump.  */
00384     s = parse_operand (s, operand, insn->args[0] == 'I');
00385 
00386   for (args = insn->args;; ++args)
00387     {
00388 #if DEBUG
00389       printf ("  args = %s\n", args);
00390 #endif
00391       switch (*args)
00392         {
00393         case '\0':    /* End of args.  */
00394           /* We have have 0 args, do the bazoooka!  */
00395           if (args == insn->args)
00396            encode (insn, &opcode, 0, 0);
00397 
00398           if (*s == '\0')
00399             {
00400               /* We are truly done.  */
00401               the_insn.opcode = opcode;
00402               if (check_invalid_opcode (opcode))
00403                 as_bad (_("instruction not allowed: %s"), str);
00404               return;
00405             }
00406           as_bad (_("too many operands: %s"), s);
00407           break;
00408 
00409         case ',':   /* Must match a comma.  */
00410           if (*s++ == ',')
00411             {
00412               reloc = BFD_RELOC_NONE;
00413 
00414               /* Parse next operand.  */
00415               s = parse_operand (s, operand, args[1] == 'I');
00416 #if DEBUG
00417              printf ("    ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n",
00418                     operand->X_add_number, args, s);
00419 #endif
00420               continue;
00421             }
00422           break;
00423 
00424         case '(':   /* Must match a (.  */
00425           s = parse_operand (s, operand, args[1] == 'I');
00426           continue;
00427 
00428         case ')':   /* Must match a ).  */
00429           continue;
00430 
00431         case 'r':   /* A general register.  */
00432           args++;
00433 
00434           if (operand->X_op != O_register)
00435             break;    /* Only registers.  */
00436 
00437           know (operand->X_add_symbol == 0);
00438           know (operand->X_op_symbol == 0);
00439           regno = operand->X_add_number;
00440           encode (insn, &opcode, regno, *args);
00441 #if DEBUG
00442           printf ("    r: operand->X_op = %d\n", operand->X_op);
00443 #endif
00444           continue;
00445 
00446         default:
00447           /* if (! ISALPHA (*args))
00448                break;  */   /* Only immediate values.  */
00449 
00450           if (mask_or_shift)
00451            {
00452 #if DEBUG
00453              printf ("mask_or_shift = %d\n", mask_or_shift);
00454 #endif
00455              reloc = mask_or_shift;
00456            }
00457           mask_or_shift = 0;
00458 
00459           if (strncasecmp (args, "LO(", 3) == 0)
00460             {
00461 #if DEBUG
00462               printf ("reloc_const\n");
00463 #endif
00464               reloc = BFD_RELOC_LO16;
00465             }
00466           else if (strncasecmp (args, "HI(", 3) == 0)
00467             {
00468 #if DEBUG
00469               printf ("reloc_consth\n");
00470 #endif
00471               reloc = BFD_RELOC_HI16;
00472             }
00473 
00474           if (*s == '(')
00475            operand->X_op = O_constant;
00476           else if (*s == ')')
00477             s += 1;
00478 #if DEBUG
00479           printf ("    default case: operand->X_add_number = %d, *args = %s, *s = %s\n", operand->X_add_number, args, s);
00480 #endif
00481           if (operand->X_op == O_constant)
00482             {
00483              if (reloc == BFD_RELOC_NONE)
00484               {
00485                 bfd_vma v, mask;
00486 
00487                 mask = 0x3ffffff;
00488                 v = abs (operand->X_add_number) & ~ mask;
00489                 if (v)
00490                   as_bad (_("call/jmp target out of range (1)"));
00491               }
00492 
00493               if (reloc == BFD_RELOC_HI16)
00494               operand->X_add_number = ((operand->X_add_number >> 16) & 0xffff);
00495 
00496               the_insn.pcrel = 0;
00497               encode (insn, &opcode, operand->X_add_number, *args);
00498  /*             the_insn.reloc = BFD_RELOC_NONE; */
00499               continue;
00500             }
00501 
00502           if (reloc == BFD_RELOC_NONE)
00503             the_insn.reloc = BFD_RELOC_32_GOT_PCREL;
00504           else
00505             the_insn.reloc = reloc;
00506 
00507           /* the_insn.reloc = insn->reloc;  */
00508 #if DEBUG
00509           printf ("    reloc sym=%d\n", the_insn.reloc);
00510           printf ("    BFD_RELOC_NONE=%d\n", BFD_RELOC_NONE);
00511 #endif
00512           the_insn.exp = *operand;
00513 
00514           /*  the_insn.reloc_offset = 1;  */
00515           the_insn.pcrel = 1; /* Assume PC-relative jump.  */
00516 
00517           /* FIXME-SOON, Do we figure out whether abs later, after
00518              know sym val?  */
00519           if (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_HI16)
00520             the_insn.pcrel = 0;
00521 
00522           encode (insn, &opcode, operand->X_add_number, *args);
00523           continue;
00524         }
00525 
00526       /* Types or values of args don't match.  */
00527       as_bad (_("invalid operands"));
00528       return;
00529     }
00530 }
00531 
00532 /* This is identical to the md_atof in m68k.c.  I think this is right,
00533    but I'm not sure.
00534 
00535    Turn a string in input_line_pointer into a floating point constant
00536    of type type, and store the appropriate bytes in *litP.  The number
00537    of LITTLENUMS emitted is stored in *sizeP .  An error message is
00538    returned, or NULL on OK.  */
00539 
00540 /* Equal to MAX_PRECISION in atof-ieee.c.  */
00541 #define MAX_LITTLENUMS 6
00542 
00543 char *
00544 md_atof (int type, char * litP, int *  sizeP)
00545 {
00546   int prec;
00547   LITTLENUM_TYPE words[MAX_LITTLENUMS];
00548   LITTLENUM_TYPE *wordP;
00549   char *t;
00550 
00551   switch (type)
00552     {
00553     case 'f':
00554     case 'F':
00555     case 's':
00556     case 'S':
00557       prec = 2;
00558       break;
00559 
00560     case 'd':
00561     case 'D':
00562     case 'r':
00563     case 'R':
00564       prec = 4;
00565       break;
00566 
00567     case 'x':
00568     case 'X':
00569       prec = 6;
00570       break;
00571 
00572     case 'p':
00573     case 'P':
00574       prec = 6;
00575       break;
00576 
00577     default:
00578       *sizeP = 0;
00579       return _("Bad call to MD_ATOF()");
00580     }
00581 
00582   t = atof_ieee (input_line_pointer, type, words);
00583   if (t)
00584     input_line_pointer = t;
00585 
00586   *sizeP = prec * sizeof (LITTLENUM_TYPE);
00587 
00588   for (wordP = words; prec--;)
00589     {
00590       md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
00591       litP += sizeof (LITTLENUM_TYPE);
00592     }
00593 
00594   return NULL;
00595 }
00596 
00597 /* Write out big-endian.  */
00598 
00599 void
00600 md_number_to_chars (char *buf, valueT val, int n)
00601 {
00602   number_to_chars_bigendian (buf, val, n);
00603 }
00604 
00605 void
00606 md_apply_fix (fixS * fixP, valueT * val, segT seg ATTRIBUTE_UNUSED)
00607 {
00608   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
00609   long t_val;
00610 
00611   t_val = (long) *val;
00612 
00613 #if DEBUG
00614   printf ("md_apply_fix val:%x\n", t_val);
00615 #endif
00616 
00617   fixP->fx_addnumber = t_val; /* Remember value for emit_reloc.  */
00618 
00619   know (fixP->fx_size == 4);
00620   know (fixP->fx_r_type < BFD_RELOC_NONE);
00621 
00622   switch (fixP->fx_r_type)
00623     {
00624     case BFD_RELOC_32:      /* XXXXXXXX pattern in a word.  */
00625 #if DEBUG
00626       printf ("reloc_const: val=%x\n", t_val);
00627 #endif
00628       buf[0] = t_val >> 24;
00629       buf[1] = t_val >> 16;
00630       buf[2] = t_val >> 8;
00631       buf[3] = t_val;
00632       break;
00633 
00634     case BFD_RELOC_16:      /* XXXX0000 pattern in a word.  */
00635 #if DEBUG
00636       printf ("reloc_const: val=%x\n", t_val);
00637 #endif
00638       buf[0] = t_val >> 8;
00639       buf[1] = t_val;
00640       break;
00641 
00642     case BFD_RELOC_8:      /* XX000000 pattern in a word.  */
00643 #if DEBUG
00644       printf ("reloc_const: val=%x\n", t_val);
00645 #endif
00646       buf[0] = t_val;
00647       break;
00648 
00649     case BFD_RELOC_LO16:      /* 0000XXXX pattern in a word.  */
00650 #if DEBUG
00651       printf ("reloc_const: val=%x\n", t_val);
00652 #endif
00653       buf[2] = t_val >> 8;  /* Holds bits 0000XXXX.  */
00654       buf[3] = t_val;
00655       break;
00656 
00657     case BFD_RELOC_HI16:    /* 0000XXXX pattern in a word.  */
00658 #if DEBUG
00659       printf ("reloc_consth: val=%x\n", t_val);
00660 #endif
00661       buf[2] = t_val >> 24; /* Holds bits XXXX0000.  */
00662       buf[3] = t_val >> 16;
00663       break;
00664 
00665     case BFD_RELOC_32_GOT_PCREL:  /* 0000XXXX pattern in a word.  */
00666       if (!fixP->fx_done)
00667         ;
00668       else if (fixP->fx_pcrel)
00669         {
00670           long v = t_val >> 28;
00671 
00672           if (v != 0 && v != -1)
00673             as_bad_where (fixP->fx_file, fixP->fx_line,
00674                           _("call/jmp target out of range (2)"));
00675         }
00676       else
00677         /* This case was supposed to be handled in machine_ip.  */
00678         abort ();
00679 
00680       buf[0] |= (t_val >> 26) & 0x03; /* Holds bits 0FFFFFFC of address.  */
00681       buf[1] = t_val >> 18;
00682       buf[2] = t_val >> 10;
00683       buf[3] = t_val >> 2;
00684       break;
00685 
00686     case BFD_RELOC_VTABLE_INHERIT:
00687     case BFD_RELOC_VTABLE_ENTRY:
00688       fixP->fx_done = 0;
00689       break;
00690 
00691     case BFD_RELOC_NONE:
00692     default:
00693       as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type);
00694       break;
00695     }
00696 
00697   if (fixP->fx_addsy == (symbolS *) NULL)
00698     fixP->fx_done = 1;
00699 }
00700 
00701 /* Should never be called for or32.  */
00702 
00703 void
00704 md_create_short_jump (char *    ptr       ATTRIBUTE_UNUSED,
00705                     addressT  from_addr ATTRIBUTE_UNUSED,
00706                     addressT  to_addr   ATTRIBUTE_UNUSED,
00707                     fragS *   frag      ATTRIBUTE_UNUSED,
00708                     symbolS * to_symbol ATTRIBUTE_UNUSED)
00709 {
00710   as_fatal ("or32_create_short_jmp\n");
00711 }
00712 
00713 /* Should never be called for or32.  */
00714 
00715 void
00716 md_convert_frag (bfd *   headers ATTRIBUTE_UNUSED,
00717                segT    seg     ATTRIBUTE_UNUSED,
00718                fragS * fragP   ATTRIBUTE_UNUSED)
00719 {
00720   as_fatal ("or32_convert_frag\n");
00721 }
00722 
00723 /* Should never be called for or32.  */
00724 
00725 void
00726 md_create_long_jump (char *    ptr       ATTRIBUTE_UNUSED,
00727                    addressT  from_addr ATTRIBUTE_UNUSED,
00728                    addressT  to_addr   ATTRIBUTE_UNUSED,
00729                    fragS *   frag      ATTRIBUTE_UNUSED,
00730                    symbolS * to_symbol ATTRIBUTE_UNUSED)
00731 {
00732   as_fatal ("or32_create_long_jump\n");
00733 }
00734 
00735 /* Should never be called for or32.  */
00736 
00737 int
00738 md_estimate_size_before_relax (fragS * fragP   ATTRIBUTE_UNUSED,
00739                             segT    segtype ATTRIBUTE_UNUSED)
00740 {
00741   as_fatal ("or32_estimate_size_before_relax\n");
00742   return 0;
00743 }
00744 
00745 /* Translate internal representation of relocation info to target format.
00746 
00747    On sparc/29k: first 4 bytes are normal unsigned long address, next three
00748    bytes are index, most sig. byte first.  Byte 7 is broken up with
00749    bit 7 as external, bits 6 & 5 unused, and the lower
00750    five bits as relocation type.  Next 4 bytes are long addend.  */
00751 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com.  */
00752 
00753 #ifdef OBJ_AOUT
00754 void
00755 tc_aout_fix_to_chars (char *where,
00756                     fixS *fixP,
00757                     relax_addressT segment_address_in_file)
00758 {
00759   long r_symbolnum;
00760 
00761 #if DEBUG
00762   printf ("tc_aout_fix_to_chars\n");
00763 #endif
00764 
00765   know (fixP->fx_r_type < BFD_RELOC_NONE);
00766   know (fixP->fx_addsy != NULL);
00767 
00768   md_number_to_chars
00769     (where,
00770      fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
00771      4);
00772 
00773   r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
00774      ? S_GET_TYPE (fixP->fx_addsy)
00775      : fixP->fx_addsy->sy_number);
00776 
00777   where[4] = (r_symbolnum >> 16) & 0x0ff;
00778   where[5] = (r_symbolnum >> 8) & 0x0ff;
00779   where[6] = r_symbolnum & 0x0ff;
00780   where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
00781 
00782   /* Also easy.  */
00783   md_number_to_chars (&where[8], fixP->fx_addnumber, 4);
00784 }
00785 
00786 #endif /* OBJ_AOUT */
00787 
00788 const char *md_shortopts = "";
00789 
00790 struct option md_longopts[] =
00791 {
00792   { NULL, no_argument, NULL, 0 }
00793 };
00794 size_t md_longopts_size = sizeof (md_longopts);
00795 
00796 int
00797 md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
00798 {
00799   return 0;
00800 }
00801 
00802 void
00803 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
00804 {
00805 }
00806 
00807 /* This is called when a line is unrecognized.  This is used to handle
00808    definitions of or32 style local labels.  */
00809 
00810 int
00811 or32_unrecognized_line (int c)
00812 {
00813   int lab;
00814   char *s;
00815 
00816   if (c != '$'
00817       || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
00818     return 0;
00819 
00820   s = input_line_pointer;
00821 
00822   lab = 0;
00823   while (ISDIGIT ((unsigned char) *s))
00824     {
00825       lab = lab * 10 + *s - '0';
00826       ++s;
00827     }
00828 
00829   if (*s != ':')
00830     /* Not a label definition.  */
00831     return 0;
00832 
00833   if (dollar_label_defined (lab))
00834     {
00835       as_bad (_("label \"$%d\" redefined"), lab);
00836       return 0;
00837     }
00838 
00839   define_dollar_label (lab);
00840   colon (dollar_label_name (lab, 0));
00841   input_line_pointer = s + 1;
00842 
00843   return 1;
00844 }
00845 
00846 /* Default the values of symbols known that should be "predefined".  We
00847    don't bother to predefine them unless you actually use one, since there
00848    are a lot of them.  */
00849 
00850 symbolS *
00851 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
00852 {
00853   return NULL;
00854 }
00855 
00856 /* Parse an operand that is machine-specific.  */
00857 
00858 void
00859 md_operand (expressionS *expressionP)
00860 {
00861 #if DEBUG
00862   printf ("  md_operand(input_line_pointer = %s)\n", input_line_pointer);
00863 #endif
00864 
00865   if (input_line_pointer[0] == REGISTER_PREFIX && input_line_pointer[1] == 'r')
00866     {
00867       /* We have a numeric register expression.  No biggy.  */
00868       input_line_pointer += 2;  /* Skip %r */
00869       (void) expression (expressionP);
00870 
00871       if (expressionP->X_op != O_constant
00872           || expressionP->X_add_number > 255)
00873         as_bad (_("Invalid expression after %%%%\n"));
00874       expressionP->X_op = O_register;
00875     }
00876   else if (input_line_pointer[0] == '&')
00877     {
00878       /* We are taking the 'address' of a register...this one is not
00879          in the manual, but it *is* in traps/fpsymbol.h!  What they
00880          seem to want is the register number, as an absolute number.  */
00881       input_line_pointer++; /* Skip & */
00882       (void) expression (expressionP);
00883 
00884       if (expressionP->X_op != O_register)
00885         as_bad (_("invalid register in & expression"));
00886       else
00887         expressionP->X_op = O_constant;
00888     }
00889   else if (input_line_pointer[0] == '$'
00890            && ISDIGIT ((unsigned char) input_line_pointer[1]))
00891     {
00892       long lab;
00893       char *name;
00894       symbolS *sym;
00895 
00896       /* This is a local label.  */
00897       ++input_line_pointer;
00898       lab = (long) get_absolute_expression ();
00899 
00900       if (dollar_label_defined (lab))
00901         {
00902           name = dollar_label_name (lab, 0);
00903           sym = symbol_find (name);
00904         }
00905       else
00906         {
00907           name = dollar_label_name (lab, 1);
00908           sym = symbol_find_or_make (name);
00909         }
00910 
00911       expressionP->X_op = O_symbol;
00912       expressionP->X_add_symbol = sym;
00913       expressionP->X_add_number = 0;
00914     }
00915   else if (input_line_pointer[0] == '$')
00916     {
00917       char *s;
00918       char type;
00919       int fieldnum, fieldlimit;
00920       LITTLENUM_TYPE floatbuf[8];
00921 
00922       /* $float(), $doubleN(), or $extendN() convert floating values
00923          to integers.  */
00924       s = input_line_pointer;
00925 
00926       ++s;
00927 
00928       fieldnum = 0;
00929       if (strncmp (s, "double", sizeof "double" - 1) == 0)
00930         {
00931           s += sizeof "double" - 1;
00932           type = 'd';
00933           fieldlimit = 2;
00934         }
00935       else if (strncmp (s, "float", sizeof "float" - 1) == 0)
00936         {
00937           s += sizeof "float" - 1;
00938           type = 'f';
00939           fieldlimit = 1;
00940         }
00941       else if (strncmp (s, "extend", sizeof "extend" - 1) == 0)
00942         {
00943           s += sizeof "extend" - 1;
00944           type = 'x';
00945           fieldlimit = 4;
00946         }
00947       else
00948        return;
00949 
00950       if (ISDIGIT (*s))
00951         {
00952           fieldnum = *s - '0';
00953           ++s;
00954         }
00955       if (fieldnum >= fieldlimit)
00956         return;
00957 
00958       SKIP_WHITESPACE ();
00959       if (*s != '(')
00960         return;
00961       ++s;
00962       SKIP_WHITESPACE ();
00963 
00964       s = atof_ieee (s, type, floatbuf);
00965       if (s == NULL)
00966         return;
00967       s = s;
00968 
00969       SKIP_WHITESPACE ();
00970       if (*s != ')')
00971         return;
00972       ++s;
00973       SKIP_WHITESPACE ();
00974 
00975       input_line_pointer = s;
00976       expressionP->X_op = O_constant;
00977       expressionP->X_unsigned = 1;
00978       expressionP->X_add_number = ((floatbuf[fieldnum * 2]
00979                                     << LITTLENUM_NUMBER_OF_BITS)
00980                                    + floatbuf[fieldnum * 2 + 1]);
00981     }
00982 }
00983 
00984 /* Round up a section size to the appropriate boundary.  */
00985 
00986 valueT
00987 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size ATTRIBUTE_UNUSED)
00988 {
00989   return size;      /* Byte alignment is fine.  */
00990 }
00991 
00992 /* Exactly what point is a PC-relative offset relative TO?
00993    On the 29000, they're relative to the address of the instruction,
00994    which we have set up as the address of the fixup too.  */
00995 
00996 long
00997 md_pcrel_from (fixS *fixP)
00998 {
00999   return fixP->fx_where + fixP->fx_frag->fr_address;
01000 }
01001 
01002 /* Generate a reloc for a fixup.  */
01003 
01004 arelent *
01005 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
01006 {
01007   arelent *reloc;
01008 
01009   reloc = xmalloc (sizeof (arelent));
01010   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01011   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
01012   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
01013   /*  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where + fixp->fx_addnumber;*/
01014   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
01015 
01016   if (reloc->howto == (reloc_howto_type *) NULL)
01017     {
01018       as_bad_where (fixp->fx_file, fixp->fx_line,
01019                   _("reloc %d not supported by object file format"),
01020                   (int) fixp->fx_r_type);
01021       return NULL;
01022     }
01023 
01024   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
01025     reloc->address = fixp->fx_offset;
01026 
01027   reloc->addend = fixp->fx_addnumber;
01028   return reloc;
01029 }