]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gas/config/tc-pdp11.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gas / config / tc-pdp11.c
index cf103df929595a0d7f37a8e9abd5428fc41fbf2a..2b01fbc5836bb2998924045da498c8a157334e00 100644 (file)
@@ -1,11 +1,11 @@
 /* tc-pdp11.c - pdp11-specific -
-   Copyright 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -15,7 +15,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "as.h"
 #include "safe-ctype.h"
@@ -29,7 +30,7 @@ extern int flonum_gen2vax (int, FLONUM_TYPE * f, LITTLENUM_TYPE *);
 /* A representation for PDP-11 machine code.  */
 struct pdp11_code
 {
-  char *error;
+  const char *error;
   int code;
   int additional;      /* Is there an additional word?  */
   int word;            /* Additional word, if any.  */
@@ -81,10 +82,10 @@ const pseudo_typeS md_pseudo_table[] =
   { 0, 0, 0 },
 };
 
-static struct hash_control *insn_hash = NULL;
+static htab_t insn_hash = NULL;
 \f
 static int
-set_option (char *arg)
+set_option (const char *arg)
 {
   int yes = 1;
 
@@ -108,7 +109,7 @@ set_option (char *arg)
       arg += 3;
     }
 
-  /* Commersial instructions.  */
+  /* Commercial instructions.  */
   if (strcmp (arg, "cis") == 0)
     pdp11_extension[PDP11_CIS] = yes;
   /* Call supervisor mode.  */
@@ -187,14 +188,12 @@ md_begin (void)
 
   init_defaults ();
 
-  insn_hash = hash_new ();
-  if (insn_hash == NULL)
-    as_fatal ("Virtual memory exhausted");
+  insn_hash = str_htab_create ();
 
   for (i = 0; i < pdp11_num_opcodes; i++)
-    hash_insert (insn_hash, pdp11_opcodes[i].name, (void *) (pdp11_opcodes + i));
+    str_hash_insert (insn_hash, pdp11_opcodes[i].name, pdp11_opcodes + i, 0);
   for (i = 0; i < pdp11_num_aliases; i++)
-    hash_insert (insn_hash, pdp11_aliases[i].name, (void *) (pdp11_aliases + i));
+    str_hash_insert (insn_hash, pdp11_aliases[i].name, pdp11_aliases + i, 0);
 }
 
 void
@@ -202,7 +201,7 @@ md_number_to_chars (char con[], valueT value, int nbytes)
 {
   /* On a PDP-11, 0x1234 is stored as "\x12\x34", and
      0x12345678 is stored as "\x56\x78\x12\x34". It's
-     anyones guess what 0x123456 would be stored like.  */
+     anyone's guess what 0x123456 would be stored like.  */
 
   switch (nbytes)
     {
@@ -221,6 +220,18 @@ md_number_to_chars (char con[], valueT value, int nbytes)
       con[2] =  value        & 0xff;
       con[3] = (value >>  8) & 0xff;
       break;
+#ifdef BFD64
+    case 8:
+      con[0] = (value >> 48) & 0xff;
+      con[1] = (value >> 56) & 0xff;
+      con[2] = (value >> 32) & 0xff;
+      con[3] = (value >> 40) & 0xff;
+      con[4] = (value >> 16) & 0xff;
+      con[5] = (value >> 24) & 0xff;
+      con[6] =  value        & 0xff;
+      con[7] = (value >>  8) & 0xff;
+      break;
+#endif
     default:
       BAD_CASE (nbytes);
     }
@@ -247,11 +258,19 @@ md_apply_fix (fixS *fixP,
 
   switch (fixP->fx_r_type)
     {
+    case BFD_RELOC_8:
+      mask = 0xff;
+      shift = 0;
+      break;
     case BFD_RELOC_16:
     case BFD_RELOC_16_PCREL:
       mask = 0xffff;
       shift = 0;
       break;
+    case BFD_RELOC_32:
+      mask = 0xffffffff;
+      shift = 0;
+      break;
     case BFD_RELOC_PDP11_DISP_8_PCREL:
       mask = 0x00ff;
       shift = 1;
@@ -278,13 +297,11 @@ md_apply_fix (fixS *fixP,
 }
 
 long
-md_chars_to_number (con, nbytes)
-     unsigned char con[];      /* Low order byte 1st.  */
-     int nbytes;               /* Number of bytes in the input.  */
+md_chars_to_number (unsigned char *con, int nbytes)
 {
   /* On a PDP-11, 0x1234 is stored as "\x12\x34", and
      0x12345678 is stored as "\x56\x78\x12\x34". It's
-     anyones guess what 0x123456 would be stored like.  */
+     anyone's guess what 0x123456 would be stored like.  */
   switch (nbytes)
     {
     case 0:
@@ -334,7 +351,7 @@ parse_reg (char *str, struct pdp11_code *operand)
          str++;
          break;
        default:
-         operand->error = "Bad register name";
+         operand->error = _("Bad register name");
          return str - 1;
        }
     }
@@ -352,10 +369,16 @@ parse_reg (char *str, struct pdp11_code *operand)
     }
   else
     {
-      operand->error = "Bad register name";
+      operand->error = _("Bad register name");
       return str;
     }
 
+  if (ISALNUM (*str) || *str == '_' || *str == '.')
+    {
+      operand->error = _("Bad register name");
+      str -= 2;
+    }
+  
   return str;
 }
 
@@ -377,13 +400,13 @@ parse_ac5 (char *str, struct pdp11_code *operand)
          str++;
          break;
        default:
-         operand->error = "Bad register name";
+         operand->error = _("Bad register name");
          return str - 2;
        }
     }
   else
     {
-      operand->error = "Bad register name";
+      operand->error = _("Bad register name");
       return str;
     }
 
@@ -396,7 +419,7 @@ parse_ac (char *str, struct pdp11_code *operand)
   str = parse_ac5 (str, operand);
   if (!operand->error && operand->code > 3)
     {
-         operand->error = "Bad register name";
+      operand->error = _("Bad register name");
          return str - 3;
     }
 
@@ -415,7 +438,7 @@ parse_expression (char *str, struct pdp11_code *operand)
   if (seg == NULL)
     {
       input_line_pointer = save_input_line_pointer;
-      operand->error = "Error in expression";
+      operand->error = _("Error in expression");
       return str;
     }
 
@@ -443,7 +466,7 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
       str = skip_whitespace (str);
       if (*str != ')')
        {
-         operand->error = "Missing ')'";
+         operand->error = _("Missing ')'");
          return str;
        }
       str++;
@@ -479,7 +502,7 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
         case O_big:
           if (operand->reloc.exp.X_add_number > 0)
             {
-              operand->error = "Error in expression";
+              operand->error = _("Error in expression");
               break;
             }
           /* It's a floating literal...  */
@@ -490,7 +513,7 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
             as_warn (_("Low order bits truncated in immediate float operand"));
           break;
        default:
-         operand->error = "Error in expression";
+         operand->error = _("Error in expression");
          break;
        }
       operand->code = 027;
@@ -499,8 +522,6 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
       /* label, d(rn), -(rn)  */
     default:
       {
-       char *old = str;
-
        if (strncmp (str, "-(", 2) == 0)        /* -(rn) */
          {
            str = parse_reg (str + 2, operand);
@@ -509,7 +530,7 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
            str = skip_whitespace (str);
            if (*str != ')')
              {
-               operand->error = "Missing ')'";
+               operand->error = _("Missing ')'");
                return str;
              }
            operand->code |= 040;
@@ -525,11 +546,6 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
 
        if (*str != '(')
          {
-           if (operand->reloc.exp.X_op != O_symbol)
-             {
-               operand->error = "Label expected";
-               return old;
-             }
            operand->code = 067;
            operand->additional = 1;
            operand->word = 0;
@@ -548,7 +564,7 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
 
        if (*str != ')')
          {
-           operand->error = "Missing ')'";
+           operand->error = _("Missing ')'");
            return str;
          }
 
@@ -558,8 +574,8 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
        switch (operand->reloc.exp.X_op)
          {
          case O_symbol:
-           operand->word = 0;
-           operand->reloc.pc_rel = 1;
+           operand->reloc.type = BFD_RELOC_16;
+           operand->reloc.pc_rel = 0;
            break;
          case O_constant:
            if ((operand->code & 7) == 7)
@@ -589,9 +605,34 @@ parse_op_noreg (char *str, struct pdp11_code *operand)
 
   if (*str == '@' || *str == '*')
     {
-      str = parse_op_no_deferred (str + 1, operand);
+      /* @(Rn) == @0(Rn): Mode 7, Indexed deferred.
+        Check for auto-increment deferred.  */
+      if (str[1] == '('
+         && str[2] != 0
+         && str[3] != 0
+         && str[4] != 0
+         && str[5] != '+')
+        {
+         /* Change implied to explicit index deferred.  */
+          *str = '0';
+          str = parse_op_no_deferred (str, operand);
+        }
+      else
+        {
+          /* @Rn == (Rn): Register deferred.  */
+          str = parse_reg (str + 1, operand);
+         
+          /* Not @Rn */
+          if (operand->error)
+           {
+             operand->error = NULL;
+             str = parse_op_no_deferred (str, operand);
+           }
+        }
+
       if (operand->error)
        return str;
+
       operand->code |= 010;
     }
   else
@@ -613,7 +654,7 @@ parse_op (char *str, struct pdp11_code *operand)
   parse_ac5 (str, operand);
   if (!operand->error)
     {
-      operand->error = "Float AC not legal as integer operand";
+      operand->error = _("Float AC not legal as integer operand");
       return str;
     }
 
@@ -633,7 +674,7 @@ parse_fop (char *str, struct pdp11_code *operand)
   parse_reg (str, operand);
   if (!operand->error)
     {
-      operand->error = "General register not legal as float operand";
+      operand->error = _("General register not legal as float operand");
       return str;
     }
 
@@ -657,7 +698,7 @@ md_assemble (char *instruction_string)
   struct pdp11_code insn, op1, op2;
   int error;
   int size;
-  char *err = NULL;
+  const char *err = NULL;
   char *str;
   char *p;
   char c;
@@ -666,13 +707,13 @@ md_assemble (char *instruction_string)
   p = find_whitespace (str);
   if (p - str == 0)
     {
-      as_bad ("No instruction found");
+      as_bad (_("No instruction found"));
       return;
     }
 
   c = *p;
   *p = '\0';
-  op = (struct pdp11_opcode *)hash_find (insn_hash, str);
+  op = (struct pdp11_opcode *)str_hash_find (insn_hash, str);
   *p = c;
   if (op == 0)
     {
@@ -682,7 +723,7 @@ md_assemble (char *instruction_string)
 
   if (!pdp11_extension[op->extension])
     {
-      as_warn ("Unsupported instruction set extension: %s", op->name);
+      as_warn (_("Unsupported instruction set extension: %s"), op->name);
       return;
     }
 
@@ -703,8 +744,6 @@ md_assemble (char *instruction_string)
     {
     case PDP11_OPCODE_NO_OPS:
       str = skip_whitespace (str);
-      if (*str == 0)
-       str = "";
       break;
 
     case PDP11_OPCODE_IMM3:
@@ -718,7 +757,7 @@ md_assemble (char *instruction_string)
        break;
       if (op1.reloc.exp.X_op != O_constant || op1.reloc.type != BFD_RELOC_NONE)
        {
-         op1.error = "operand is not an absolute constant";
+         op1.error = _("operand is not an absolute constant");
          break;
        }
       switch (op->type)
@@ -726,21 +765,21 @@ md_assemble (char *instruction_string)
        case PDP11_OPCODE_IMM3:
          if (op1.reloc.exp.X_add_number & ~7)
            {
-             op1.error = "3-bit immediate out of range";
+             op1.error = _("3-bit immediate out of range");
              break;
            }
          break;
        case PDP11_OPCODE_IMM6:
          if (op1.reloc.exp.X_add_number & ~0x3f)
            {
-             op1.error = "6-bit immediate out of range";
+             op1.error = _("6-bit immediate out of range");
              break;
            }
          break;
        case PDP11_OPCODE_IMM8:
          if (op1.reloc.exp.X_add_number & ~0xff)
            {
-             op1.error = "8-bit immediate out of range";
+             op1.error = _("8-bit immediate out of range");
              break;
            }
          break;
@@ -750,22 +789,22 @@ md_assemble (char *instruction_string)
 
     case PDP11_OPCODE_DISPL:
       {
-       char *new;
-       new = parse_expression (str, &op1);
+       char *new_pointer;
+       new_pointer = parse_expression (str, &op1);
        op1.code = 0;
        op1.reloc.pc_rel = 1;
        op1.reloc.type = BFD_RELOC_PDP11_DISP_8_PCREL;
        if (op1.reloc.exp.X_op != O_symbol)
          {
-           op1.error = "Symbol expected";
+           op1.error = _("Symbol expected");
            break;
          }
        if (op1.code & ~0xff)
          {
-           err = "8-bit displacement out of range";
+           err = _("8-bit displacement out of range");
            break;
          }
-       str = new;
+       str = new_pointer;
        insn.code |= op1.code;
        insn.reloc = op1.reloc;
       }
@@ -804,7 +843,7 @@ md_assemble (char *instruction_string)
       str = parse_separator (str, &error);
       if (error)
        {
-         op2.error = "Missing ','";
+         op2.error = _("Missing ','");
          break;
        }
       str = parse_op (str, &op1);
@@ -825,7 +864,7 @@ md_assemble (char *instruction_string)
       str = parse_separator (str, &error);
       if (error)
        {
-         op2.error = "Missing ','";
+         op2.error = _("Missing ','");
          break;
        }
       str = parse_reg (str, &op2);
@@ -842,7 +881,7 @@ md_assemble (char *instruction_string)
       str = parse_separator (str, &error);
       if (error)
        {
-         op1.error = "Missing ','";
+         op1.error = _("Missing ','");
          break;
        }
       str = parse_fop (str, &op1);
@@ -863,7 +902,7 @@ md_assemble (char *instruction_string)
       str = parse_separator (str, &error);
       if (error)
        {
-         op1.error = "Missing ','";
+         op1.error = _("Missing ','");
          break;
        }
       str = parse_ac (str, &op2);
@@ -880,7 +919,7 @@ md_assemble (char *instruction_string)
       str = parse_separator (str, &error);
       if (error)
        {
-         op1.error = "Missing ','";
+         op1.error = _("Missing ','");
          break;
        }
       str = parse_op (str, &op1);
@@ -901,7 +940,7 @@ md_assemble (char *instruction_string)
       str = parse_separator (str, &error);
       if (error)
        {
-         op1.error = "Missing ','";
+         op1.error = _("Missing ','");
          break;
        }
       str = parse_ac (str, &op2);
@@ -920,7 +959,7 @@ md_assemble (char *instruction_string)
       str = parse_separator (str, &error);
       if (error)
        {
-         op2.error = "Missing ','";
+         op2.error = _("Missing ','");
          break;
        }
       str = parse_op (str, &op2);
@@ -933,7 +972,7 @@ md_assemble (char *instruction_string)
 
     case PDP11_OPCODE_REG_DISPL:
       {
-       char *new;
+       char *new_pointer;
        str = parse_reg (str, &op2);
        if (op2.error)
          break;
@@ -941,24 +980,24 @@ md_assemble (char *instruction_string)
        str = parse_separator (str, &error);
        if (error)
          {
-           op1.error = "Missing ','";
+           op1.error = _("Missing ','");
            break;
          }
-       new = parse_expression (str, &op1);
+       new_pointer = parse_expression (str, &op1);
        op1.code = 0;
        op1.reloc.pc_rel = 1;
        op1.reloc.type = BFD_RELOC_PDP11_DISP_6_PCREL;
        if (op1.reloc.exp.X_op != O_symbol)
          {
-           op1.error = "Symbol expected";
+           op1.error = _("Symbol expected");
            break;
          }
        if (op1.code & ~0x3f)
          {
-           err = "6-bit displacement out of range";
+           err = _("6-bit displacement out of range");
            break;
          }
-       str = new;
+       str = new_pointer;
        insn.code |= op1.code;
        insn.reloc = op1.reloc;
       }
@@ -976,7 +1015,7 @@ md_assemble (char *instruction_string)
     {
       str = skip_whitespace (str);
       if (*str)
-       err = "Too many operands";
+       err = _("Too many operands");
     }
 
   {
@@ -984,7 +1023,7 @@ md_assemble (char *instruction_string)
 
     if (err)
       {
-       as_bad (err);
+       as_bad ("%s", err);
        return;
       }
 
@@ -1051,7 +1090,7 @@ md_create_long_jump (char *ptr ATTRIBUTE_UNUSED,
 }
 
 static int
-set_cpu_model (char *arg)
+set_cpu_model (const char *arg)
 {
   char buf[4];
   char *model = buf;
@@ -1167,7 +1206,7 @@ set_cpu_model (char *arg)
 }
 
 static int
-set_machine_model (char *arg)
+set_machine_model (const char *arg)
 {
   if (strncmp (arg, "pdp-11/", 7) != 0
       && strncmp (arg, "pdp11/", 6) != 0
@@ -1254,7 +1293,7 @@ size_t md_longopts_size = sizeof (md_longopts);
    See if it's a processor-specific option.  */
 
 int
-md_parse_option (int c, char *arg)
+md_parse_option (int c, const char *arg)
 {
   init_defaults ();
 
@@ -1296,9 +1335,9 @@ md_show_usage (FILE *stream)
 {
   fprintf (stream, "\
 \n\
-PDP-11 instruction set extentions:\n\
+PDP-11 instruction set extensions:\n\
 \n\
--m(no-)cis             allow (disallow) commersial instruction set\n\
+-m(no-)cis             allow (disallow) commercial instruction set\n\
 -m(no-)csm             allow (disallow) CSM instruction\n\
 -m(no-)eis             allow (disallow) full extended instruction set\n\
 -m(no-)fis             allow (disallow) KEV11 floating-point instructions\n\
@@ -1312,8 +1351,8 @@ PDP-11 instruction set extentions:\n\
 -m(no-)ucode           allow (disallow) microcode instructions\n\
 -mall-extensions       allow all instruction set extensions\n\
                        (this is the default)\n\
--mno-extentions                disallow all instruction set extensions\n\
--pic                   generate position-indepenent code\n\
+-mno-extensions                disallow all instruction set extensions\n\
+-pic                   generate position-independent code\n\
 \n\
 PDP-11 CPU model options:\n\
 \n\
@@ -1394,31 +1433,31 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
   arelent *reloc;
   bfd_reloc_code_real_type code;
 
-  reloc = xmalloc (sizeof (* reloc));
+  reloc = XNEW (arelent);
 
-  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+  reloc->sym_ptr_ptr = XNEW (asymbol *);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
 
   /* This is taken account for in md_apply_fix().  */
   reloc->addend = -symbol_get_bfdsym (fixp->fx_addsy)->section->vma;
 
-  switch (fixp->fx_r_type)
+  code = fixp->fx_r_type;
+  if (fixp->fx_pcrel)
     {
-    case BFD_RELOC_16:
-      if (fixp->fx_pcrel)
-       code = BFD_RELOC_16_PCREL;
-      else
-       code = BFD_RELOC_16;
-      break;
+      switch (code)
+       {
+       case BFD_RELOC_16:
+         code = BFD_RELOC_16_PCREL;
+         break;
 
-    case BFD_RELOC_16_PCREL:
-      code = BFD_RELOC_16_PCREL;
-      break;
+       case BFD_RELOC_16_PCREL:
+         break;
 
-    default:
-      BAD_CASE (fixp->fx_r_type);
-      return NULL;
+       default:
+         BAD_CASE (code);
+         return NULL;
+       }
     }
 
   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
@@ -1426,7 +1465,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
   if (reloc->howto == NULL)
     {
       as_bad_where (fixp->fx_file, fixp->fx_line,
-                   "Can not represent %s relocation in this object file format",
+                   _("Can not represent %s relocation in this object file format"),
                    bfd_get_reloc_code_name (code));
       return NULL;
     }
@@ -1451,3 +1490,9 @@ pseudo_even (int c ATTRIBUTE_UNUSED)
   frag_align (alignment, 0, 1);
   record_alignment (now_seg, alignment);
 }
+
+const char *
+md_atof (int type, char * litP, int * sizeP)
+{
+  return vax_md_atof (type, litP, sizeP);
+}