Home | History | Annotate | Line # | Download | only in config
      1   1.1  christos /* tc-dlx.c -- Assemble for the DLX
      2  1.10  christos    Copyright (C) 2002-2025 Free Software Foundation, Inc.
      3   1.1  christos 
      4   1.1  christos    This file is part of GAS, the GNU Assembler.
      5   1.1  christos 
      6   1.1  christos    GAS is free software; you can redistribute it and/or modify
      7   1.1  christos    it under the terms of the GNU General Public License as published by
      8   1.1  christos    the Free Software Foundation; either version 3, or (at your option)
      9   1.1  christos    any later version.
     10   1.1  christos 
     11   1.1  christos    GAS is distributed in the hope that it will be useful,
     12   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14   1.1  christos    GNU General Public License for more details.
     15   1.1  christos 
     16   1.1  christos    You should have received a copy of the GNU General Public License
     17   1.1  christos    along with GAS; see the file COPYING.  If not, write to the Free
     18   1.1  christos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     19   1.1  christos    02110-1301, USA.  */
     20   1.1  christos 
     21   1.1  christos /* Initially created by Kuang Hwa Lin, 3/20/2002.  */
     22   1.1  christos 
     23   1.1  christos #include "as.h"
     24   1.1  christos #include "safe-ctype.h"
     25   1.1  christos #include "tc-dlx.h"
     26   1.1  christos #include "opcode/dlx.h"
     27   1.5  christos #include "elf/dlx.h"
     28   1.5  christos #include "bfd/elf32-dlx.h"
     29   1.1  christos 
     30   1.1  christos /* Make it easier to clone this machine desc into another one.  */
     31   1.1  christos #define	machine_opcode      dlx_opcode
     32   1.1  christos #define	machine_opcodes     dlx_opcodes
     33   1.1  christos #define	machine_ip          dlx_ip
     34   1.1  christos #define	machine_it          dlx_it
     35   1.1  christos 
     36   1.1  christos #define NO_RELOC            BFD_RELOC_NONE
     37   1.1  christos #define RELOC_DLX_REL26     BFD_RELOC_DLX_JMP26
     38   1.1  christos #define RELOC_DLX_16        BFD_RELOC_16
     39   1.1  christos #define RELOC_DLX_REL16     BFD_RELOC_16_PCREL_S2
     40   1.1  christos #define RELOC_DLX_HI16      BFD_RELOC_HI16_S
     41   1.1  christos #define RELOC_DLX_LO16      BFD_RELOC_LO16
     42   1.1  christos #define RELOC_DLX_VTINHERIT BFD_RELOC_VTABLE_INHERIT
     43   1.1  christos #define RELOC_DLX_VTENTRY   BFD_RELOC_VTABLE_ENTRY
     44   1.1  christos 
     45   1.1  christos /* handle of the OPCODE hash table */
     46   1.8  christos static htab_t op_hash = NULL;
     47   1.1  christos 
     48   1.1  christos struct machine_it
     49   1.1  christos {
     50   1.1  christos   char *error;
     51   1.1  christos   unsigned long opcode;
     52   1.1  christos   struct nlist *nlistp;
     53   1.1  christos   expressionS exp;
     54   1.1  christos   int pcrel;
     55   1.1  christos   int size;
     56   1.1  christos   int reloc_offset;		/* Offset of reloc within insn.  */
     57   1.5  christos   bfd_reloc_code_real_type reloc;
     58   1.1  christos   int HI;
     59   1.1  christos   int LO;
     60   1.1  christos }
     61   1.1  christos the_insn;
     62   1.1  christos 
     63   1.1  christos /* This array holds the chars that always start a comment.  If the
     64   1.1  christos    pre-processor is disabled, these aren't very useful.  */
     65   1.1  christos const char comment_chars[] = ";";
     66   1.1  christos 
     67   1.1  christos /* This array holds the chars that only start a comment at the beginning of
     68   1.1  christos    a line.  If the line seems to have the form '# 123 filename'
     69   1.1  christos    .line and .file directives will appear in the pre-processed output.  */
     70   1.1  christos /* Note that input_file.c hand checks for '#' at the beginning of the
     71   1.1  christos    first line of the input file.  This is because the compiler outputs
     72   1.1  christos    #NO_APP at the beginning of its output.  */
     73   1.1  christos /* Also note that comments like this one will always work.  */
     74   1.1  christos const char line_comment_chars[] = "#";
     75   1.1  christos 
     76   1.1  christos /* We needed an unused char for line separation to work around the
     77   1.1  christos    lack of macros, using sed and such.  */
     78   1.1  christos const char line_separator_chars[] = "@";
     79   1.1  christos 
     80   1.1  christos /* Chars that can be used to separate mant from exp in floating point nums.  */
     81   1.1  christos const char EXP_CHARS[] = "eE";
     82   1.1  christos 
     83   1.1  christos /* Chars that mean this number is a floating point constant.
     84   1.1  christos    As in 0f12.456
     85   1.1  christos    or    0d1.2345e12.  */
     86   1.1  christos const char FLT_CHARS[] = "rRsSfFdDxXpP";
     87   1.1  christos 
     88   1.1  christos static void
     89   1.5  christos insert_sreg (const char *regname, int regnum)
     90   1.1  christos {
     91   1.1  christos   /* Must be large enough to hold the names of the special registers.  */
     92   1.1  christos   char buf[80];
     93   1.1  christos   int i;
     94   1.1  christos 
     95   1.8  christos   symbol_table_insert (symbol_new (regname, reg_section,
     96   1.8  christos 				   &zero_address_frag, regnum));
     97   1.1  christos   for (i = 0; regname[i]; i++)
     98   1.1  christos     buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i];
     99   1.1  christos   buf[i] = '\0';
    100   1.1  christos 
    101   1.8  christos   symbol_table_insert (symbol_new (buf, reg_section,
    102   1.8  christos 				   &zero_address_frag, regnum));
    103   1.1  christos }
    104   1.1  christos 
    105   1.1  christos /* Install symbol definitions for assorted special registers.
    106   1.1  christos    See MIPS Assembly Language Programmer's Guide page 1-4   */
    107   1.1  christos 
    108   1.1  christos static void
    109   1.1  christos define_some_regs (void)
    110   1.1  christos {
    111   1.1  christos   /* Software representation.  */
    112   1.1  christos   insert_sreg ("zero",  0);
    113   1.1  christos   insert_sreg ("at",    1);
    114   1.1  christos   insert_sreg ("v0",    2);
    115   1.1  christos   insert_sreg ("v1",    3);
    116   1.1  christos   insert_sreg ("a0",    4);
    117   1.1  christos   insert_sreg ("a1",    5);
    118   1.1  christos   insert_sreg ("a2",    6);
    119   1.1  christos   insert_sreg ("a3",    7);
    120   1.1  christos   insert_sreg ("t0",    8);
    121   1.1  christos   insert_sreg ("t1",    9);
    122   1.1  christos   insert_sreg ("t2",    10);
    123   1.1  christos   insert_sreg ("t3",    11);
    124   1.1  christos   insert_sreg ("t4",    12);
    125   1.1  christos   insert_sreg ("t5",    13);
    126   1.1  christos   insert_sreg ("t6",    14);
    127   1.1  christos   insert_sreg ("t7",    15);
    128   1.1  christos   insert_sreg ("s0",    16);
    129   1.1  christos   insert_sreg ("s1",    17);
    130   1.1  christos   insert_sreg ("s2",    18);
    131   1.1  christos   insert_sreg ("s3",    19);
    132   1.1  christos   insert_sreg ("s4",    20);
    133   1.1  christos   insert_sreg ("s5",    21);
    134   1.1  christos   insert_sreg ("s6",    22);
    135   1.1  christos   insert_sreg ("s7",    23);
    136   1.1  christos   insert_sreg ("t8",    24);
    137   1.1  christos   insert_sreg ("t9",    25);
    138   1.1  christos   insert_sreg ("k0",    26);
    139   1.1  christos   insert_sreg ("k1",    27);
    140   1.1  christos   insert_sreg ("gp",    28);
    141   1.1  christos   insert_sreg ("sp",    29);
    142   1.1  christos   insert_sreg ("fp",    30);
    143   1.1  christos   insert_sreg ("ra",    31);
    144   1.1  christos   /* Special registers.  */
    145   1.1  christos   insert_sreg ("pc",    0);
    146   1.1  christos   insert_sreg ("npc",   1);
    147   1.1  christos   insert_sreg ("iad",   2);
    148   1.1  christos }
    149   1.1  christos 
    150   1.1  christos /* Subroutine check the string to match an register.  */
    151   1.1  christos 
    152   1.1  christos static int
    153   1.1  christos match_sft_register (char *name)
    154   1.1  christos {
    155   1.1  christos #define MAX_REG_NO  35
    156   1.1  christos /* Currently we have 35 software registers defined -
    157   1.1  christos    we borrowed from MIPS.   */
    158   1.5  christos   static const char *soft_reg[] =
    159   1.1  christos     {
    160   1.1  christos       "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
    161   1.1  christos       "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9",
    162   1.1  christos       "s0", "s1", "s2", "s3", "s4", "s5", "s7", "k0", "k1",
    163   1.1  christos       "gp", "sp", "fp", "ra", "pc", "npc", "iad",
    164   1.1  christos       "EndofTab"  /* End of the Table indicator */
    165   1.1  christos     };
    166   1.1  christos   char low_name[21], *ptr;
    167   1.1  christos   int idx;
    168   1.1  christos 
    169   1.1  christos   for (ptr = name,idx = 0; *ptr != '\0'; ptr++)
    170   1.1  christos     low_name[idx++] = TOLOWER (*ptr);
    171   1.1  christos 
    172   1.1  christos   low_name[idx] = '\0';
    173   1.1  christos   idx = 0;
    174   1.1  christos 
    175   1.1  christos   while (idx < MAX_REG_NO && strcmp (soft_reg[idx], & low_name [0]))
    176   1.1  christos     idx += 1;
    177   1.1  christos 
    178   1.1  christos   return idx < MAX_REG_NO;
    179   1.1  christos }
    180   1.1  christos 
    181   1.1  christos /* Subroutine check the string to match an register.  */
    182   1.1  christos 
    183   1.1  christos static int
    184   1.1  christos is_ldst_registers (char *name)
    185   1.1  christos {
    186   1.1  christos   char *ptr = name;
    187   1.1  christos 
    188   1.1  christos   /* The first character of the register name got to be either %, $, r of R.  */
    189   1.1  christos   if ((ptr[0] == '%' || ptr[0] == '$' || ptr[0] == 'r' || ptr[0] == 'R')
    190  1.10  christos       && ISDIGIT (ptr[1]))
    191   1.1  christos     return 1;
    192   1.1  christos 
    193   1.1  christos   /* Now check the software register representation.  */
    194   1.1  christos   return match_sft_register (ptr);
    195   1.1  christos }
    196   1.1  christos 
    197   1.1  christos /* Subroutine of s_proc so targets can choose a different default prefix.
    198   1.1  christos    If DEFAULT_PREFIX is NULL, use the target's "leading char".  */
    199   1.1  christos 
    200   1.1  christos static void
    201   1.1  christos s_proc (int end_p)
    202   1.1  christos {
    203   1.1  christos   /* Record the current function so that we can issue an error message for
    204   1.1  christos      misplaced .func,.endfunc, and also so that .endfunc needs no
    205   1.1  christos      arguments.  */
    206   1.1  christos   static char *current_name;
    207   1.1  christos   static char *current_label;
    208   1.1  christos 
    209   1.1  christos   if (end_p)
    210   1.1  christos     {
    211   1.1  christos       if (current_name == NULL)
    212   1.1  christos 	{
    213   1.1  christos 	  as_bad (_("missing .proc"));
    214   1.1  christos 	  ignore_rest_of_line ();
    215   1.1  christos 	  return;
    216   1.1  christos 	}
    217   1.1  christos 
    218   1.1  christos       current_name = current_label = NULL;
    219   1.1  christos       SKIP_WHITESPACE ();
    220  1.10  christos       while (!is_end_of_stmt (*input_line_pointer))
    221   1.1  christos         input_line_pointer++;
    222   1.1  christos     }
    223   1.1  christos   else
    224   1.1  christos     {
    225   1.1  christos       char *name, *label;
    226   1.1  christos       char delim1, delim2;
    227   1.1  christos 
    228   1.1  christos       if (current_name != NULL)
    229   1.1  christos 	{
    230   1.1  christos 	  as_bad (_(".endfunc missing for previous .proc"));
    231   1.1  christos 	  ignore_rest_of_line ();
    232   1.1  christos 	  return;
    233   1.1  christos 	}
    234   1.1  christos 
    235   1.3  christos       delim1 = get_symbol_name (&name);
    236   1.1  christos       name = xstrdup (name);
    237  1.10  christos       restore_line_pointer (delim1);
    238  1.10  christos       SKIP_WHITESPACE ();
    239   1.1  christos 
    240   1.1  christos       if (*input_line_pointer != ',')
    241   1.1  christos 	{
    242   1.1  christos 	  char leading_char = 0;
    243   1.1  christos 
    244   1.1  christos 	  leading_char = bfd_get_symbol_leading_char (stdoutput);
    245   1.1  christos 	  /* Missing entry point, use function's name with the leading
    246   1.1  christos 	     char prepended.  */
    247   1.1  christos 	  if (leading_char)
    248   1.1  christos 	    {
    249   1.1  christos 	      unsigned len = strlen (name) + 1;
    250   1.5  christos 	      label = XNEWVEC (char, len + 1);
    251   1.1  christos 	      label[0] = leading_char;
    252   1.1  christos 	      memcpy (label + 1, name, len);
    253   1.1  christos 	    }
    254   1.1  christos 	  else
    255   1.1  christos 	    label = name;
    256   1.1  christos 	}
    257   1.1  christos       else
    258   1.1  christos 	{
    259   1.1  christos 	  ++input_line_pointer;
    260   1.1  christos 	  SKIP_WHITESPACE ();
    261   1.3  christos 	  delim2 = get_symbol_name (&label);
    262   1.1  christos 	  label = xstrdup (label);
    263   1.3  christos 	  (void) restore_line_pointer (delim2);
    264   1.1  christos 	}
    265   1.1  christos 
    266   1.1  christos       current_name = name;
    267   1.1  christos       current_label = label;
    268   1.1  christos     }
    269   1.1  christos   demand_empty_rest_of_line ();
    270   1.1  christos }
    271   1.1  christos 
    272   1.1  christos /* This function is called once, at assembler startup time.  It should
    273   1.1  christos    set up all the tables, etc., that the MD part of the assembler will
    274   1.1  christos    need.  */
    275   1.1  christos 
    276   1.1  christos void
    277   1.1  christos md_begin (void)
    278   1.1  christos {
    279   1.1  christos   unsigned int i;
    280   1.1  christos 
    281   1.1  christos   /* Create a new hash table.  */
    282   1.8  christos   op_hash = str_htab_create ();
    283   1.1  christos 
    284   1.1  christos   /* Hash up all the opcodes for fast use later.  */
    285   1.1  christos   for (i = 0; i < num_dlx_opcodes; i++)
    286   1.1  christos     {
    287   1.1  christos       const char *name = machine_opcodes[i].name;
    288   1.8  christos       if (str_hash_insert (op_hash, name, &machine_opcodes[i], 0) != NULL)
    289   1.8  christos 	as_fatal (_("duplicate %s"), name);
    290   1.1  christos     }
    291   1.1  christos 
    292   1.1  christos   define_some_regs ();
    293   1.1  christos }
    294   1.1  christos 
    295   1.1  christos /* This function will check the opcode and return 1 if the opcode is one
    296   1.1  christos    of the load/store instruction, and it will fix the operand string to
    297   1.1  christos    the standard form so we can use the standard parse_operand routine.  */
    298   1.1  christos 
    299   1.1  christos #define READ_OP     0x100
    300   1.1  christos #define WRITE_OP    0x200
    301   1.1  christos static char iBuf[81];
    302   1.1  christos 
    303   1.1  christos static char *
    304   1.1  christos dlx_parse_loadop (char * str)
    305   1.1  christos {
    306   1.1  christos   char *ptr = str;
    307   1.1  christos   int   idx = 0;
    308   1.1  christos 
    309   1.1  christos   /* The last pair of ()/[] is the register, all other are the
    310   1.1  christos      reloc displacement, and if there is a register then it ought
    311   1.1  christos      to have a pair of ()/[]
    312   1.1  christos      This is not necessarily true, what if the load instruction come
    313   1.1  christos      without the register and with %hi/%lo modifier?  */
    314   1.1  christos   for (idx = 0; idx < 72 && ptr[idx] != '\0'; idx++)
    315   1.1  christos     ;
    316   1.1  christos 
    317   1.1  christos   if (idx == 72)
    318   1.1  christos     {
    319   1.1  christos     badoperand_load:
    320   1.1  christos       as_bad (_("Bad operand for a load instruction: <%s>"), str);
    321   1.1  christos       return NULL;
    322   1.1  christos     }
    323   1.1  christos   else
    324   1.1  christos     {
    325   1.1  christos       int i, pb = 0;
    326   1.1  christos       int m2 = 0;
    327   1.1  christos       char rs1[7], rd[7], endm, match = '0';
    328   1.1  christos       char imm[72];
    329   1.1  christos 
    330   1.1  christos       idx -= 1;
    331   1.1  christos       switch (str[idx])
    332   1.1  christos 	{
    333   1.1  christos 	case ')':
    334   1.1  christos 	  match = '(';
    335   1.1  christos 	  endm  = ')';
    336   1.1  christos 	  break;
    337   1.1  christos 	case ']':
    338   1.1  christos 	  match = '[';
    339   1.1  christos 	  endm  = ']';
    340   1.1  christos 	  break;
    341   1.1  christos 	default:
    342   1.1  christos 	  /* No register indicated, fill in zero.  */
    343   1.1  christos 	  rs1[0] = 'r';
    344   1.1  christos 	  rs1[1] = '0';
    345   1.1  christos 	  rs1[2] = '\0';
    346   1.1  christos 	  match  = 0;
    347   1.1  christos 	  endm = 0;
    348   1.1  christos 	  m2 = 1;
    349   1.1  christos 	}
    350   1.1  christos 
    351   1.1  christos       if (!m2)
    352   1.1  christos 	{
    353   1.1  christos 	  /* Searching for (/[ which will match the ]/).  */
    354   1.1  christos 	  for (pb = idx - 1; str[pb] != match; pb -= 1)
    355   1.1  christos 	    /* Match can only be either '[' or '(', if it is
    356   1.1  christos 	       '(' then this can be a normal expression, we'll treat
    357   1.1  christos 	       it as an operand.  */
    358   1.1  christos 	    if (str[pb] == endm || pb < (idx - 5))
    359   1.1  christos 	      goto load_no_rs1;
    360   1.1  christos 	  pb += 1;
    361   1.1  christos 
    362   1.1  christos 	  for (i = 0; (pb + i) < idx; i++)
    363   1.1  christos 	    rs1[i] = str[pb+i];
    364   1.1  christos 
    365   1.1  christos 	  rs1[i] = '\0';
    366   1.1  christos 
    367   1.1  christos 	  if (is_ldst_registers (& rs1[0]))
    368   1.1  christos 	    /* Point to the last character of the imm.  */
    369   1.1  christos 	    pb -= 1;
    370   1.1  christos 	  else
    371   1.1  christos 	    {
    372   1.1  christos 	    load_no_rs1:
    373   1.1  christos 	      if (match == '[')
    374   1.1  christos 		goto badoperand_load;
    375   1.1  christos 	      /* No register indicated, fill in zero and restore the imm.  */
    376   1.1  christos 	      rs1[0] = 'r';
    377   1.1  christos 	      rs1[1] = '0';
    378   1.1  christos 	      rs1[2] = '\0';
    379   1.1  christos 	      m2 = 1;
    380   1.1  christos 	    }
    381   1.1  christos 	}
    382   1.1  christos 
    383   1.1  christos       /* Duplicate the first register.  */
    384   1.1  christos       for (i = 0; i < 7 && str[i] != ','; i++)
    385   1.1  christos 	rd[i] = ptr[i];
    386   1.1  christos 
    387   1.1  christos       if (str[i] != ',')
    388   1.1  christos 	goto badoperand_load;
    389   1.1  christos       else
    390   1.1  christos 	rd[i] = '\0';
    391   1.1  christos 
    392   1.1  christos       /* Copy the immd.  */
    393   1.1  christos       if (m2)
    394   1.1  christos 	/* Put the '\0' back in.  */
    395   1.1  christos 	pb = idx + 1;
    396   1.1  christos 
    397   1.1  christos       for (i++, m2 = 0; i < pb; m2++,i++)
    398   1.1  christos 	imm[m2] = ptr[i];
    399   1.1  christos 
    400   1.1  christos       imm[m2] = '\0';
    401   1.1  christos 
    402   1.1  christos       /* Assemble the instruction to gas internal format.  */
    403   1.1  christos       for (i = 0; rd[i] != '\0'; i++)
    404   1.1  christos 	iBuf[i] = rd[i];
    405   1.1  christos 
    406   1.1  christos       iBuf[i++] = ',';
    407   1.1  christos 
    408   1.1  christos       for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
    409   1.1  christos 	iBuf[i] = rs1[pb];
    410   1.1  christos 
    411   1.1  christos       iBuf[i++] = ',';
    412   1.1  christos 
    413   1.1  christos       for (pb = 0; imm[pb] != '\0'; i++, pb++)
    414   1.1  christos 	iBuf[i] = imm[pb];
    415   1.1  christos 
    416   1.1  christos       iBuf[i] = '\0';
    417   1.1  christos       return iBuf;
    418   1.1  christos     }
    419   1.1  christos }
    420   1.1  christos 
    421   1.1  christos static char *
    422   1.1  christos dlx_parse_storeop (char * str)
    423   1.1  christos {
    424   1.1  christos   char *ptr = str;
    425   1.1  christos   int   idx = 0;
    426   1.1  christos 
    427   1.1  christos   /* Search for the ','.  */
    428   1.1  christos   for (idx = 0; idx < 72 && ptr[idx] != ','; idx++)
    429   1.1  christos     ;
    430   1.1  christos 
    431   1.1  christos   if (idx == 72)
    432   1.1  christos     {
    433   1.1  christos     badoperand_store:
    434   1.1  christos       as_bad (_("Bad operand for a store instruction: <%s>"), str);
    435   1.1  christos       return NULL;
    436   1.1  christos     }
    437   1.1  christos   else
    438   1.1  christos     {
    439   1.1  christos       /* idx now points to the ','.  */
    440   1.1  christos       int i, pb = 0;
    441   1.1  christos       int comma = idx;
    442   1.1  christos       int m2 = 0;
    443   1.1  christos       char rs1[7], rd[7], endm, match = '0';
    444   1.1  christos       char imm[72];
    445   1.1  christos 
    446   1.1  christos       /* Now parse the '(' and ')', and make idx point to ')'.  */
    447   1.1  christos       idx -= 1;
    448   1.1  christos       switch (str[idx])
    449   1.1  christos 	{
    450   1.1  christos 	case ')':
    451   1.1  christos 	  match = '(';
    452   1.1  christos 	  endm  = ')';
    453   1.1  christos 	  break;
    454   1.1  christos 	case ']':
    455   1.1  christos 	  match = '[';
    456   1.1  christos 	  endm  = ']';
    457   1.1  christos 	  break;
    458   1.1  christos 	default:
    459   1.1  christos 	  /* No register indicated, fill in zero.  */
    460   1.1  christos 	  rs1[0] = 'r';
    461   1.1  christos 	  rs1[1] = '0';
    462   1.1  christos 	  rs1[2] = '\0';
    463   1.1  christos 	  match  = 0;
    464   1.1  christos 	  endm = 0;
    465   1.1  christos 	  m2 = 1;
    466   1.1  christos 	}
    467   1.1  christos 
    468   1.1  christos       if (!m2)
    469   1.1  christos 	{
    470   1.1  christos 	  /* Searching for (/[ which will match the ]/).  */
    471   1.1  christos 	  for (pb = idx - 1; str[pb] != match; pb -= 1)
    472   1.1  christos 	    if (pb < (idx - 5) || str[pb] == endm)
    473   1.1  christos 	      goto store_no_rs1;
    474   1.1  christos 	  pb += 1;
    475   1.1  christos 
    476   1.1  christos 	  for (i = 0; (pb + i) < idx; i++)
    477   1.1  christos 	    rs1[i] = str[pb + i];
    478   1.1  christos 
    479   1.1  christos 	  rs1[i] = '\0';
    480   1.1  christos 
    481   1.1  christos 	  if (is_ldst_registers (& rs1[0]))
    482   1.1  christos 	    /* Point to the last character of the imm.  */
    483   1.1  christos 	    pb -= 1;
    484   1.1  christos 	  else
    485   1.1  christos 	    {
    486   1.1  christos 	    store_no_rs1:
    487   1.1  christos 	      if (match == '[')
    488   1.1  christos 		goto badoperand_store;
    489   1.1  christos 
    490   1.1  christos 	      /* No register indicated, fill in zero and restore the imm.  */
    491   1.1  christos 	      rs1[0] = 'r';
    492   1.1  christos 	      rs1[1] = '0';
    493   1.1  christos 	      rs1[2] = '\0';
    494   1.1  christos 	      pb = comma;
    495   1.1  christos 	    }
    496   1.1  christos 	}
    497   1.1  christos       else
    498   1.1  christos 	/* No register was specified.  */
    499   1.1  christos 	pb = comma;
    500   1.1  christos 
    501   1.1  christos       /* Duplicate the first register.  */
    502  1.10  christos       for (i = comma + 1; is_whitespace (str[i]); i++)
    503   1.1  christos 	;
    504   1.1  christos 
    505   1.1  christos       for (m2 = 0; (m2 < 7 && str[i] != '\0'); i++, m2++)
    506   1.1  christos 	{
    507  1.10  christos 	  if (!is_whitespace (str[i]))
    508   1.1  christos 	    rd[m2] = str[i];
    509   1.1  christos 	  else
    510   1.1  christos 	    goto badoperand_store;
    511   1.1  christos 	}
    512   1.1  christos 
    513   1.1  christos       if (str[i] != '\0')
    514   1.1  christos 	goto badoperand_store;
    515   1.1  christos       else
    516   1.1  christos 	rd[m2] = '\0';
    517   1.1  christos 
    518   1.1  christos       /* Copy the immd.  */
    519   1.1  christos       for (i = 0; i < pb; i++)
    520   1.1  christos 	imm[i] = ptr[i];
    521   1.1  christos 
    522   1.1  christos       imm[i] = '\0';
    523   1.1  christos 
    524   1.1  christos       /* Assemble the instruction to gas internal format.  */
    525   1.1  christos       for (i = 0; rd[i] != '\0'; i++)
    526   1.1  christos 	iBuf[i] = rd[i];
    527   1.1  christos       iBuf[i++] = ',';
    528   1.1  christos       for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
    529   1.1  christos 	iBuf[i] = rs1[pb];
    530   1.1  christos       iBuf[i++] = ',';
    531   1.1  christos       for (pb = 0; imm[pb] != '\0'; i++, pb++)
    532   1.1  christos 	iBuf[i] = imm[pb];
    533   1.1  christos       iBuf[i] = '\0';
    534   1.1  christos       return iBuf;
    535   1.1  christos     }
    536   1.1  christos }
    537   1.1  christos 
    538   1.1  christos static char *
    539   1.1  christos fix_ld_st_operand (unsigned long opcode, char* str)
    540   1.1  christos {
    541   1.1  christos   /* Check the opcode.  */
    542  1.10  christos   switch (opcode)
    543   1.1  christos     {
    544   1.1  christos     case  LBOP:
    545   1.1  christos     case  LBUOP:
    546   1.1  christos     case  LSBUOP:
    547   1.1  christos     case  LHOP:
    548   1.1  christos     case  LHUOP:
    549   1.1  christos     case  LSHUOP:
    550   1.1  christos     case  LWOP:
    551   1.1  christos     case  LSWOP:
    552   1.1  christos       return dlx_parse_loadop (str);
    553   1.1  christos     case  SBOP:
    554   1.1  christos     case  SHOP:
    555   1.1  christos     case  SWOP:
    556   1.1  christos       return dlx_parse_storeop (str);
    557   1.1  christos     default:
    558   1.1  christos       return str;
    559   1.1  christos     }
    560   1.1  christos }
    561   1.1  christos 
    562   1.1  christos static int
    563   1.1  christos hilo_modifier_ok (char *s)
    564   1.1  christos {
    565   1.1  christos   char *ptr = s;
    566   1.1  christos   int   idx, count = 1;
    567   1.1  christos 
    568   1.1  christos   if (*ptr != '(')
    569   1.1  christos     return 1;
    570   1.1  christos 
    571   1.1  christos   for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1)
    572   1.1  christos     {
    573   1.1  christos       if (count == 0)
    574   1.1  christos 	return count;
    575   1.1  christos 
    576   1.1  christos       if (ptr[idx] == '(')
    577   1.1  christos 	count += 1;
    578   1.1  christos 
    579   1.1  christos       if (ptr[idx] == ')')
    580   1.1  christos 	count -= 1;
    581   1.1  christos     }
    582   1.1  christos 
    583   1.1  christos   return (count == 0) ? 1:0;
    584   1.1  christos }
    585   1.1  christos 
    586   1.1  christos static char *
    587   1.1  christos parse_operand (char *s, expressionS *operandp)
    588   1.1  christos {
    589   1.1  christos   char *save = input_line_pointer;
    590   1.1  christos   char *new_pos;
    591   1.1  christos 
    592   1.1  christos   the_insn.HI = the_insn.LO = 0;
    593   1.1  christos 
    594   1.1  christos   /* Search for %hi and %lo, make a mark and skip it.  */
    595   1.8  christos   if (startswith (s, "%hi"))
    596   1.1  christos     {
    597   1.1  christos       s += 3;
    598   1.1  christos       the_insn.HI = 1;
    599   1.1  christos     }
    600   1.1  christos   else
    601   1.1  christos     {
    602   1.8  christos       if (startswith (s, "%lo"))
    603   1.1  christos 	{
    604   1.1  christos 	  s += 3;
    605   1.1  christos 	  the_insn.LO = 1;
    606   1.1  christos 	}
    607   1.1  christos       else
    608   1.1  christos 	the_insn.LO = 0;
    609   1.1  christos     }
    610   1.1  christos 
    611   1.1  christos   if (the_insn.HI || the_insn.LO)
    612   1.1  christos     {
    613   1.1  christos       if (!hilo_modifier_ok (s))
    614   1.1  christos 	as_bad (_("Expression Error for operand modifier %%hi/%%lo\n"));
    615   1.1  christos     }
    616   1.1  christos 
    617   1.1  christos   /* Check for the % and $ register representation    */
    618   1.1  christos   if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R')
    619  1.10  christos       && ISDIGIT (s[1]))
    620   1.1  christos     {
    621   1.1  christos       /* We have a numeric register expression.  No biggy.  */
    622   1.1  christos       s += 1;
    623   1.1  christos       input_line_pointer = s;
    624   1.1  christos       (void) expression (operandp);
    625   1.1  christos       if (operandp->X_op != O_constant
    626   1.1  christos 	  || operandp->X_add_number > 31)
    627   1.1  christos 	as_bad (_("Invalid expression after %%%%\n"));
    628   1.1  christos       operandp->X_op = O_register;
    629   1.1  christos     }
    630   1.1  christos   else
    631   1.1  christos     {
    632   1.1  christos       /* Normal operand parsing.  */
    633   1.1  christos       input_line_pointer = s;
    634   1.1  christos       (void) expression (operandp);
    635   1.9  christos       resolve_register (operandp);
    636   1.1  christos     }
    637   1.1  christos 
    638   1.1  christos   new_pos = input_line_pointer;
    639   1.1  christos   input_line_pointer = save;
    640   1.1  christos   return new_pos;
    641   1.1  christos }
    642   1.1  christos 
    643   1.1  christos /* Instruction parsing.  Takes a string containing the opcode.
    644   1.1  christos    Operands are at input_line_pointer.  Output is in the_insn.
    645   1.1  christos    Warnings or errors are generated.  */
    646   1.1  christos 
    647   1.1  christos static void
    648   1.1  christos machine_ip (char *str)
    649   1.1  christos {
    650   1.1  christos   char *s;
    651   1.1  christos   const char *args;
    652   1.1  christos   struct machine_opcode *insn;
    653   1.1  christos   unsigned long opcode;
    654   1.1  christos   expressionS the_operand;
    655   1.1  christos   expressionS *operand = &the_operand;
    656   1.1  christos   unsigned int reg, reg_shift = 0;
    657   1.1  christos 
    658   1.3  christos   memset (&the_insn, '\0', sizeof (the_insn));
    659   1.3  christos   the_insn.reloc = NO_RELOC;
    660   1.3  christos 
    661   1.1  christos   /* Fixup the opcode string to all lower cases, and also
    662   1.1  christos      allow numerical digits.  */
    663   1.1  christos   s = str;
    664   1.1  christos 
    665   1.1  christos   if (ISALPHA (*s))
    666   1.1  christos     for (; ISALNUM (*s); ++s)
    667   1.1  christos       if (ISUPPER (*s))
    668   1.1  christos 	*s = TOLOWER (*s);
    669   1.1  christos 
    670   1.1  christos   switch (*s)
    671   1.1  christos     {
    672   1.1  christos     case '\0':
    673   1.1  christos       break;
    674   1.1  christos 
    675   1.1  christos     default:
    676  1.10  christos       if (is_whitespace (*s))
    677  1.10  christos 	{
    678  1.10  christos 	  *s++ = '\0';
    679  1.10  christos 	  break;
    680  1.10  christos 	}
    681   1.1  christos       as_bad (_("Unknown opcode: `%s'"), str);
    682   1.1  christos       return;
    683   1.1  christos     }
    684   1.1  christos 
    685   1.3  christos   /* Hash the opcode, insn will have the string from opcode table.  */
    686  1.10  christos   if ((insn = str_hash_find (op_hash, str)) == NULL)
    687   1.1  christos     {
    688   1.1  christos       /* Handle the ret and return macro here.  */
    689   1.1  christos       if ((strcmp (str, "ret") == 0) || (strcmp (str, "return") == 0))
    690   1.3  christos 	the_insn.opcode = JROP | 0x03e00000;    /* 0x03e00000 = r31 << 21 */
    691   1.1  christos       else
    692   1.1  christos 	as_bad (_("Unknown opcode `%s'."), str);
    693   1.1  christos 
    694   1.1  christos       return;
    695   1.1  christos     }
    696   1.1  christos 
    697   1.1  christos   opcode = insn->opcode;
    698   1.1  christos 
    699   1.1  christos   /* Set the sip reloc HI16 flag.  */
    700   1.1  christos   if (!set_dlx_skip_hi16_flag (1))
    701   1.1  christos     as_bad (_("Can not set dlx_skip_hi16_flag"));
    702   1.1  christos 
    703   1.1  christos   /* Fix the operand string if it is one of load store instructions.  */
    704   1.1  christos   s = fix_ld_st_operand (opcode, s);
    705   1.1  christos 
    706   1.1  christos   /* Build the opcode, checking as we go to make sure that the
    707   1.1  christos      operands match.
    708   1.1  christos      If an operand matches, we modify the_insn or opcode appropriately,
    709   1.1  christos      and do a "continue".  If an operand fails to match, we "break".  */
    710   1.1  christos   if (insn->args[0] != '\0' && insn->args[0] != 'N')
    711   1.1  christos     {
    712   1.1  christos       /* Prime the pump.  */
    713   1.1  christos       if (*s == '\0')
    714   1.1  christos 	{
    715   1.1  christos 	  as_bad (_("Missing arguments for opcode <%s>."), str);
    716   1.1  christos 	  return;
    717   1.1  christos 	}
    718   1.1  christos       else
    719   1.1  christos 	s = parse_operand (s, operand);
    720   1.1  christos     }
    721   1.1  christos   else if (insn->args[0] == 'N')
    722   1.1  christos     {
    723   1.1  christos       /* Clean up the insn and done!  */
    724   1.1  christos       the_insn.opcode = opcode;
    725   1.1  christos       return;
    726   1.1  christos     }
    727   1.1  christos 
    728   1.1  christos   /* Parse through the args (this is from opcode table), *s point to
    729   1.1  christos      the current character of the instruction stream.  */
    730   1.1  christos   for (args = insn->args;; ++args)
    731   1.1  christos     {
    732   1.1  christos       switch (*args)
    733   1.1  christos 	{
    734   1.1  christos 	  /* End of Line.  */
    735   1.1  christos 	case '\0':
    736   1.1  christos 	  /* End of args.  */
    737   1.1  christos 	  if (*s == '\0')
    738   1.1  christos 	    {
    739   1.1  christos 	      /* We are truly done.  */
    740   1.1  christos 	      the_insn.opcode = opcode;
    741   1.1  christos 	      /* Clean up the HI and LO mark.  */
    742   1.1  christos 	      the_insn.HI = 0;
    743   1.1  christos 	      the_insn.LO = 0;
    744   1.1  christos 	      return;
    745   1.1  christos 	    }
    746   1.1  christos 
    747   1.1  christos 	  the_insn.HI = 0;
    748   1.1  christos 	  the_insn.LO = 0;
    749   1.1  christos 	  as_bad (_("Too many operands: %s"), s);
    750   1.1  christos 	  break;
    751   1.1  christos 
    752   1.1  christos 	  /* ',' Args separator */
    753   1.1  christos 	case ',':
    754   1.1  christos 	  /* Must match a comma.  */
    755   1.1  christos 	  if (*s++ == ',')
    756   1.1  christos 	    {
    757   1.1  christos 	      /* Parse next operand.  */
    758   1.1  christos 	      s = parse_operand (s, operand);
    759   1.1  christos 	      continue;
    760   1.1  christos 	    }
    761   1.1  christos 	  break;
    762   1.1  christos 
    763   1.1  christos 	  /* It can be a 'a' register or 'i' operand.  */
    764   1.1  christos 	case 'P':
    765   1.1  christos 	  /* Macro move operand/reg.  */
    766   1.1  christos 	  if (operand->X_op == O_register)
    767   1.1  christos 	    {
    768   1.6  christos 	      /* It's a register.  */
    769   1.1  christos 	      reg_shift = 21;
    770   1.1  christos 	      goto general_reg;
    771   1.1  christos 	    }
    772   1.6  christos 	  /* Fall through.  */
    773   1.1  christos 
    774   1.1  christos 	  /* The immediate 16 bits literal, bit 0-15.  */
    775   1.1  christos 	case 'i':
    776   1.1  christos 	  /* offset, unsigned.  */
    777   1.1  christos 	case 'I':
    778   1.1  christos 	  /* offset, signed.  */
    779   1.1  christos 	  if (operand->X_op == O_constant)
    780   1.1  christos 	    {
    781   1.1  christos 	      if (the_insn.HI)
    782   1.1  christos 		operand->X_add_number >>= 16;
    783   1.1  christos 
    784   1.1  christos 	      opcode |= operand->X_add_number & 0xFFFF;
    785   1.1  christos 
    786   1.1  christos 	      if (the_insn.HI && the_insn.LO)
    787   1.1  christos 		as_bad (_("Both the_insn.HI and the_insn.LO are set : %s"), s);
    788   1.1  christos 	      else
    789   1.1  christos 		{
    790   1.1  christos 		  the_insn.HI = 0;
    791   1.1  christos 		  the_insn.LO = 0;
    792   1.1  christos 		}
    793   1.1  christos 	      continue;
    794   1.1  christos 	    }
    795   1.1  christos 
    796   1.3  christos 	  the_insn.reloc        = (the_insn.HI) ? RELOC_DLX_HI16
    797   1.1  christos 	    : (the_insn.LO ? RELOC_DLX_LO16 : RELOC_DLX_16);
    798   1.1  christos 	  the_insn.reloc_offset = 2;
    799   1.1  christos 	  the_insn.size         = 2;
    800   1.1  christos 	  the_insn.pcrel        = 0;
    801   1.1  christos 	  the_insn.exp          = * operand;
    802   1.1  christos 	  the_insn.HI           = 0;
    803   1.1  christos 	  the_insn.LO           = 0;
    804   1.1  christos 	  continue;
    805   1.1  christos 
    806   1.1  christos 	case 'd':
    807   1.1  christos 	  /* offset, signed.  */
    808   1.1  christos 	  if (operand->X_op == O_constant)
    809   1.1  christos 	    {
    810   1.1  christos 	      opcode |= operand->X_add_number & 0xFFFF;
    811   1.1  christos 	      continue;
    812   1.1  christos 	    }
    813   1.1  christos 	  the_insn.reloc        = RELOC_DLX_REL16;
    814   1.1  christos 	  the_insn.reloc_offset = 0;    /* BIG-ENDIAN Byte 3 of insn.  */
    815   1.1  christos 	  the_insn.size         = 4;
    816   1.1  christos 	  the_insn.pcrel        = 1;
    817   1.1  christos 	  the_insn.exp          = *operand;
    818   1.1  christos 	  continue;
    819   1.1  christos 
    820   1.1  christos 	  /* The immediate 26 bits literal, bit 0-25.  */
    821   1.1  christos 	case 'D':
    822   1.1  christos 	  /* offset, signed.  */
    823   1.1  christos 	  if (operand->X_op == O_constant)
    824   1.1  christos 	    {
    825   1.1  christos 	      opcode |= operand->X_add_number & 0x3FFFFFF;
    826   1.1  christos 	      continue;
    827   1.1  christos 	    }
    828   1.1  christos 	  the_insn.reloc = RELOC_DLX_REL26;
    829   1.1  christos 	  the_insn.reloc_offset = 0;    /* BIG-ENDIAN Byte 3 of insn.  */
    830   1.1  christos 	  the_insn.size  = 4;
    831   1.1  christos 	  the_insn.pcrel = 1;
    832   1.1  christos 	  the_insn.exp = *operand;
    833   1.1  christos 	  continue;
    834   1.1  christos 
    835   1.1  christos 	  /* Type 'a' Register.  */
    836   1.1  christos 	case 'a':
    837   1.1  christos 	  /* A general register at bits 21-25, rs1.  */
    838   1.1  christos 	  reg_shift = 21;
    839   1.1  christos 	  goto general_reg;
    840   1.1  christos 
    841   1.1  christos 	  /* Type 'b' Register.  */
    842   1.1  christos 	case 'b':
    843   1.1  christos 	  /* A general register at bits 16-20, rs2/rd.  */
    844   1.1  christos 	  reg_shift = 16;
    845   1.1  christos 	  goto general_reg;
    846   1.1  christos 
    847   1.1  christos 	  /* Type 'c' Register.  */
    848   1.1  christos 	case 'c':
    849   1.1  christos 	  /* A general register at bits 11-15, rd.  */
    850   1.1  christos 	  reg_shift = 11;
    851   1.1  christos 
    852   1.1  christos 	general_reg:
    853   1.1  christos 	  know (operand->X_add_symbol == 0);
    854   1.1  christos 	  know (operand->X_op_symbol == 0);
    855   1.1  christos 	  reg = operand->X_add_number;
    856   1.1  christos 	  if (reg & 0xffffffe0)
    857   1.1  christos 	    as_fatal (_("failed regnum sanity check."));
    858   1.1  christos 	  else
    859   1.1  christos 	    /* Got the register, now figure out where it goes in the opcode.  */
    860   1.1  christos 	    opcode |= reg << reg_shift;
    861   1.1  christos 
    862   1.1  christos 	  switch (*args)
    863   1.1  christos 	    {
    864   1.1  christos 	    case 'a':
    865   1.1  christos 	    case 'b':
    866   1.1  christos 	    case 'c':
    867   1.1  christos 	    case 'P':
    868   1.1  christos 	      continue;
    869   1.1  christos 	    }
    870   1.1  christos 	  as_fatal (_("failed general register sanity check."));
    871   1.1  christos 	  break;
    872   1.1  christos 
    873   1.1  christos 	default:
    874   1.1  christos 	  BAD_CASE (*args);
    875   1.1  christos 	}
    876   1.1  christos 
    877   1.1  christos       /* Types or values of args don't match.  */
    878   1.1  christos       as_bad (_("Invalid operands"));
    879   1.1  christos       return;
    880   1.1  christos     }
    881   1.1  christos }
    882   1.1  christos 
    883   1.1  christos /* Assemble a single instruction.  Its label has already been handled
    884   1.1  christos    by the generic front end.  We just parse opcode and operands, and
    885   1.1  christos    produce the bytes of data and relocation.  */
    886   1.1  christos 
    887   1.1  christos void
    888   1.1  christos md_assemble (char *str)
    889   1.1  christos {
    890   1.1  christos   char *toP;
    891   1.1  christos   fixS *fixP;
    892   1.1  christos   bit_fixS *bitP;
    893   1.1  christos 
    894   1.1  christos   know (str);
    895   1.1  christos   machine_ip (str);
    896   1.1  christos   toP = frag_more (4);
    897   1.1  christos   dwarf2_emit_insn (4);
    898   1.1  christos 
    899   1.1  christos   /* Put out the opcode.  */
    900   1.1  christos   md_number_to_chars (toP, the_insn.opcode, 4);
    901   1.1  christos 
    902   1.1  christos   /* Put out the symbol-dependent stuff.  */
    903   1.1  christos   if (the_insn.reloc != NO_RELOC)
    904   1.1  christos     {
    905   1.1  christos       fixP = fix_new_exp (frag_now,
    906   1.1  christos 			  (toP - frag_now->fr_literal + the_insn.reloc_offset),
    907   1.1  christos 			  the_insn.size, & the_insn.exp, the_insn.pcrel,
    908   1.1  christos 			  the_insn.reloc);
    909   1.1  christos 
    910   1.1  christos       /* Turn off complaints that the addend is
    911   1.1  christos 	 too large for things like foo+100000@ha.  */
    912   1.1  christos       switch (the_insn.reloc)
    913   1.1  christos 	{
    914   1.1  christos 	case RELOC_DLX_HI16:
    915   1.1  christos 	case RELOC_DLX_LO16:
    916   1.1  christos 	  fixP->fx_no_overflow = 1;
    917   1.1  christos 	  break;
    918   1.1  christos 	default:
    919   1.1  christos 	  break;
    920   1.1  christos 	}
    921   1.1  christos 
    922   1.1  christos       switch (fixP->fx_r_type)
    923   1.1  christos 	{
    924   1.1  christos 	case RELOC_DLX_REL26:
    925   1.5  christos 	  bitP = XNEW (bit_fixS);
    926   1.1  christos 	  bitP->fx_bit_size = 26;
    927   1.1  christos 	  bitP->fx_bit_offset = 25;
    928   1.1  christos 	  bitP->fx_bit_base = the_insn.opcode & 0xFC000000;
    929   1.1  christos 	  bitP->fx_bit_base_adj = 0;
    930   1.1  christos 	  bitP->fx_bit_max = 0;
    931   1.1  christos 	  bitP->fx_bit_min = 0;
    932   1.1  christos 	  bitP->fx_bit_add = 0x03FFFFFF;
    933   1.1  christos 	  fixP->fx_bit_fixP = bitP;
    934   1.1  christos 	  break;
    935   1.1  christos 	case RELOC_DLX_LO16:
    936   1.1  christos 	case RELOC_DLX_REL16:
    937   1.5  christos 	  bitP = XNEW (bit_fixS);
    938   1.1  christos 	  bitP->fx_bit_size = 16;
    939   1.1  christos 	  bitP->fx_bit_offset = 15;
    940   1.1  christos 	  bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
    941   1.1  christos 	  bitP->fx_bit_base_adj = 0;
    942   1.1  christos 	  bitP->fx_bit_max = 0;
    943   1.1  christos 	  bitP->fx_bit_min = 0;
    944   1.1  christos 	  bitP->fx_bit_add = 0x0000FFFF;
    945   1.1  christos 	  fixP->fx_bit_fixP = bitP;
    946   1.1  christos 	  break;
    947   1.1  christos 	case RELOC_DLX_HI16:
    948   1.5  christos 	  bitP = XNEW (bit_fixS);
    949   1.1  christos 	  bitP->fx_bit_size = 16;
    950   1.1  christos 	  bitP->fx_bit_offset = 15;
    951   1.1  christos 	  bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
    952   1.1  christos 	  bitP->fx_bit_base_adj = 0;
    953   1.1  christos 	  bitP->fx_bit_max = 0;
    954   1.1  christos 	  bitP->fx_bit_min = 0;
    955   1.1  christos 	  bitP->fx_bit_add = 0x0000FFFF;
    956   1.1  christos 	  fixP->fx_bit_fixP = bitP;
    957   1.1  christos 	  break;
    958   1.1  christos 	default:
    959   1.1  christos 	  fixP->fx_bit_fixP = NULL;
    960   1.1  christos 	  break;
    961   1.1  christos 	}
    962   1.1  christos     }
    963   1.1  christos }
    964   1.1  christos 
    965   1.1  christos /* This is identical to the md_atof in m68k.c.  I think this is right,
    966   1.1  christos    but I'm not sure.  Dlx will not use it anyway, so I just leave it
    967   1.1  christos    here for now.  */
    968   1.1  christos 
    969   1.5  christos const char *
    970   1.1  christos md_atof (int type, char *litP, int *sizeP)
    971   1.1  christos {
    972   1.8  christos   return ieee_md_atof (type, litP, sizeP, true);
    973   1.1  christos }
    974   1.1  christos 
    975   1.1  christos /* Write out big-endian.  */
    976   1.1  christos void
    977   1.1  christos md_number_to_chars (char *buf, valueT val, int n)
    978   1.1  christos {
    979   1.1  christos   number_to_chars_bigendian (buf, val, n);
    980   1.1  christos }
    981   1.1  christos 
    982   1.8  christos bool
    983   1.1  christos md_dlx_fix_adjustable (fixS *fixP)
    984   1.1  christos {
    985   1.1  christos   /* We need the symbol name for the VTABLE entries.  */
    986   1.1  christos   return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT
    987   1.1  christos           && fixP->fx_r_type != BFD_RELOC_VTABLE_ENTRY);
    988   1.1  christos }
    989   1.1  christos 
    990   1.1  christos void
    991   1.1  christos md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
    992   1.1  christos {
    993   1.1  christos   long val = *valP;
    994   1.1  christos   char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
    995   1.1  christos 
    996   1.1  christos   switch (fixP->fx_r_type)
    997   1.1  christos     {
    998   1.1  christos     case RELOC_DLX_LO16:
    999   1.1  christos     case RELOC_DLX_REL16:
   1000   1.1  christos       if (fixP->fx_bit_fixP != NULL)
   1001   1.1  christos 	{
   1002   1.1  christos 	  val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base;
   1003   1.1  christos 	  free (fixP->fx_bit_fixP);
   1004   1.1  christos 	  fixP->fx_bit_fixP = NULL;
   1005   1.1  christos 	}
   1006   1.1  christos       break;
   1007   1.1  christos 
   1008   1.1  christos     case RELOC_DLX_HI16:
   1009   1.1  christos       if (fixP->fx_bit_fixP != NULL)
   1010   1.1  christos 	{
   1011   1.1  christos 	  val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base;
   1012   1.1  christos 	  free (fixP->fx_bit_fixP);
   1013   1.1  christos 	  fixP->fx_bit_fixP = NULL;
   1014   1.1  christos 	}
   1015   1.1  christos       break;
   1016   1.1  christos 
   1017   1.1  christos     case RELOC_DLX_REL26:
   1018   1.1  christos       if (fixP->fx_bit_fixP != NULL)
   1019   1.1  christos 	{
   1020   1.1  christos 	  val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base;
   1021   1.1  christos 	  free (fixP->fx_bit_fixP);
   1022   1.1  christos 	  fixP->fx_bit_fixP = NULL;
   1023   1.1  christos 	}
   1024   1.1  christos       break;
   1025   1.1  christos 
   1026   1.1  christos     case BFD_RELOC_VTABLE_INHERIT:
   1027   1.1  christos       /* This borrowed from tc-ppc.c on a whim.  */
   1028   1.1  christos       fixP->fx_done = 0;
   1029   1.1  christos       if (fixP->fx_addsy
   1030   1.1  christos 	  && !S_IS_DEFINED (fixP->fx_addsy)
   1031   1.1  christos 	  && !S_IS_WEAK (fixP->fx_addsy))
   1032   1.1  christos 	S_SET_WEAK (fixP->fx_addsy);
   1033   1.1  christos       return;
   1034   1.1  christos 
   1035   1.1  christos     case BFD_RELOC_VTABLE_ENTRY:
   1036   1.1  christos       fixP->fx_done = 0;
   1037   1.1  christos       return;
   1038   1.1  christos 
   1039   1.1  christos     default:
   1040   1.1  christos       break;
   1041   1.1  christos     }
   1042   1.1  christos 
   1043   1.1  christos   number_to_chars_bigendian (place, val, fixP->fx_size);
   1044   1.1  christos   if (fixP->fx_addsy == NULL)
   1045   1.1  christos     fixP->fx_done = 1;
   1046   1.7  christos   if (fixP->fx_bit_fixP != NULL)
   1047   1.7  christos     fixP->fx_no_overflow = 1;
   1048   1.1  christos }
   1049   1.1  christos 
   1050  1.10  christos const char md_shortopts[] = "";
   1051   1.1  christos 
   1052  1.10  christos const struct option md_longopts[] =
   1053   1.1  christos   {
   1054   1.1  christos     {NULL, no_argument, NULL, 0}
   1055   1.1  christos   };
   1056   1.1  christos 
   1057  1.10  christos const size_t md_longopts_size = sizeof (md_longopts);
   1058   1.1  christos 
   1059   1.1  christos int
   1060   1.1  christos md_parse_option (int c     ATTRIBUTE_UNUSED,
   1061   1.5  christos 		 const char *arg ATTRIBUTE_UNUSED)
   1062   1.1  christos {
   1063   1.1  christos   return 0;
   1064   1.1  christos }
   1065   1.1  christos 
   1066   1.1  christos void
   1067   1.1  christos md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
   1068   1.1  christos {
   1069   1.1  christos }
   1070   1.1  christos 
   1071   1.1  christos /* This is called when a line is unrecognized.  */
   1072   1.1  christos 
   1073   1.1  christos int
   1074   1.1  christos dlx_unrecognized_line (int c)
   1075   1.1  christos {
   1076   1.1  christos   int lab;
   1077   1.1  christos   char *s;
   1078   1.1  christos 
   1079   1.1  christos   if (c != '$' || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
   1080   1.1  christos     return 0;
   1081   1.1  christos 
   1082   1.1  christos   s = input_line_pointer;
   1083   1.1  christos 
   1084   1.1  christos   lab = 0;
   1085   1.1  christos   while (ISDIGIT ((unsigned char) *s))
   1086   1.1  christos     {
   1087   1.1  christos       lab = lab * 10 + *s - '0';
   1088   1.1  christos       ++s;
   1089   1.1  christos     }
   1090   1.1  christos 
   1091   1.1  christos   if (*s != ':')
   1092   1.1  christos     /* Not a label definition.  */
   1093   1.1  christos     return 0;
   1094   1.1  christos 
   1095   1.1  christos   if (dollar_label_defined (lab))
   1096   1.1  christos     {
   1097   1.1  christos       as_bad (_("label \"$%d\" redefined"), lab);
   1098   1.1  christos       return 0;
   1099   1.1  christos     }
   1100   1.1  christos 
   1101   1.1  christos   define_dollar_label (lab);
   1102   1.1  christos   colon (dollar_label_name (lab, 0));
   1103   1.1  christos   input_line_pointer = s + 1;
   1104   1.1  christos 
   1105   1.1  christos   return 1;
   1106   1.1  christos }
   1107   1.1  christos 
   1108   1.1  christos /* Default the values of symbols known that should be "predefined".  We
   1109   1.1  christos    don't bother to predefine them unless you actually use one, since there
   1110   1.1  christos    are a lot of them.  */
   1111   1.1  christos 
   1112   1.1  christos symbolS *
   1113   1.1  christos md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
   1114   1.1  christos {
   1115   1.1  christos   return NULL;
   1116   1.1  christos }
   1117   1.1  christos 
   1118   1.1  christos /* Parse an operand that is machine-specific, the function was called
   1119   1.1  christos    in expr.c by operand() function, when everything failed before it
   1120   1.1  christos    call a quit.  */
   1121   1.1  christos 
   1122   1.1  christos void
   1123   1.1  christos md_operand (expressionS* expressionP)
   1124   1.1  christos {
   1125   1.1  christos   /* Check for the #number representation    */
   1126   1.1  christos   if (input_line_pointer[0] == '#' &&
   1127  1.10  christos       ISDIGIT (input_line_pointer[1]))
   1128   1.1  christos     {
   1129   1.1  christos       /* We have a numeric number expression.  No biggy.  */
   1130   1.1  christos       input_line_pointer += 1;	/* Skip # */
   1131   1.1  christos 
   1132   1.1  christos       (void) expression (expressionP);
   1133   1.1  christos 
   1134   1.1  christos       if (expressionP->X_op != O_constant)
   1135   1.1  christos 	as_bad (_("Invalid expression after # number\n"));
   1136   1.1  christos     }
   1137   1.1  christos 
   1138   1.1  christos   return;
   1139   1.1  christos }
   1140   1.1  christos 
   1141   1.1  christos /* Round up a section size to the appropriate boundary.  */
   1142   1.1  christos 
   1143   1.1  christos valueT
   1144   1.1  christos md_section_align (segT segment ATTRIBUTE_UNUSED,
   1145   1.1  christos 		  valueT size)
   1146   1.1  christos {
   1147   1.1  christos   /* Byte alignment is fine.  */
   1148   1.1  christos   return size;
   1149   1.1  christos }
   1150   1.1  christos 
   1151   1.1  christos /* Exactly what point is a PC-relative offset relative TO?
   1152   1.1  christos    On the 29000, they're relative to the address of the instruction,
   1153   1.1  christos    which we have set up as the address of the fixup too.  */
   1154   1.1  christos 
   1155   1.1  christos long
   1156   1.1  christos md_pcrel_from (fixS* fixP)
   1157   1.1  christos {
   1158   1.1  christos   return 4 + fixP->fx_where + fixP->fx_frag->fr_address;
   1159   1.1  christos }
   1160   1.1  christos 
   1161   1.1  christos /* Translate internal representation of relocation info to BFD target
   1162   1.1  christos    format.
   1163   1.1  christos    FIXME: To what extent can we get all relevant targets to use this?
   1164   1.1  christos    The above FIXME is from a29k, but I think it is also needed here.    */
   1165   1.1  christos 
   1166   1.1  christos arelent *
   1167   1.1  christos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
   1168   1.1  christos 	      fixS *fixP)
   1169   1.1  christos {
   1170   1.1  christos   arelent * reloc;
   1171   1.1  christos 
   1172  1.10  christos   reloc = notes_alloc (sizeof (arelent));
   1173  1.10  christos   reloc->sym_ptr_ptr = notes_alloc (sizeof (asymbol *));
   1174  1.10  christos   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
   1175  1.10  christos 
   1176   1.1  christos   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
   1177   1.1  christos   if (reloc->howto == NULL)
   1178   1.1  christos     {
   1179   1.1  christos       as_bad_where (fixP->fx_file, fixP->fx_line,
   1180   1.1  christos 		    _("internal error: can't export reloc type %d (`%s')"),
   1181   1.1  christos 		    fixP->fx_r_type,
   1182   1.1  christos 		    bfd_get_reloc_code_name (fixP->fx_r_type));
   1183   1.1  christos       return NULL;
   1184   1.1  christos     }
   1185   1.1  christos 
   1186   1.1  christos   gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
   1187   1.1  christos 
   1188   1.1  christos   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
   1189   1.1  christos 
   1190   1.1  christos   if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
   1191   1.1  christos     reloc->address = fixP->fx_offset;
   1192   1.1  christos   reloc->addend = 0;
   1193   1.1  christos 
   1194   1.1  christos   return reloc;
   1195   1.1  christos }
   1196   1.1  christos 
   1197   1.1  christos const pseudo_typeS
   1198   1.1  christos dlx_pseudo_table[] =
   1199   1.1  christos {
   1200   1.1  christos   /* Some additional ops that are used by gcc-dlx.  */
   1201   1.1  christos   {"asciiz", stringer, 8 + 1},
   1202   1.1  christos   {"half", cons, 2},
   1203   1.1  christos   {"dword", cons, 8},
   1204   1.1  christos   {"word", cons, 4},
   1205   1.1  christos   {"proc", s_proc, 0},
   1206   1.1  christos   {"endproc", s_proc, 1},
   1207   1.1  christos   {NULL, NULL, 0}
   1208   1.1  christos };
   1209   1.1  christos 
   1210   1.1  christos void
   1211   1.1  christos dlx_pop_insert (void)
   1212   1.1  christos {
   1213   1.1  christos   pop_insert (dlx_pseudo_table);
   1214   1.1  christos   return ;
   1215   1.1  christos }
   1216