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