* tc-pdp11.c: Use VAX float format support for PDP-11 target.
authorAlan Modra <amodra@gmail.com>
Tue, 5 Mar 2002 03:10:34 +0000 (03:10 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 5 Mar 2002 03:10:34 +0000 (03:10 +0000)
(parse_ac5): New function for parsing float regs in float operand.
(parse_expression): Remove attempt to make literals be octal.
(parse_op_no_deferred): Support float literals.
(parse_op): Reject attempts to refer to float regs.
(parse_fop): New function, like parse_op but for float operand.
(md_assemble): Add cases to parse float operands.  Also fix
IMM3, IMM6, IMM8 cases to pick up the operand from the right spot.

gas/ChangeLog
gas/config/tc-pdp11.c

index 221c592f3e45452eae027690a89e52692121e72e..80d2dae99bdfdc2bf1229339a2ad23be367dfa63 100644 (file)
@@ -1,3 +1,14 @@
+2002-03-05  Paul Koning  <pkoning@equallogic.com>
+
+       * tc-pdp11.c: Use VAX float format support for PDP-11 target.
+       (parse_ac5): New function for parsing float regs in float operand.
+       (parse_expression): Remove attempt to make literals be octal.
+       (parse_op_no_deferred): Support float literals.
+       (parse_op): Reject attempts to refer to float regs.
+       (parse_fop): New function, like parse_op but for float operand.
+       (md_assemble): Add cases to parse float operands.  Also fix 
+       IMM3, IMM6, IMM8 cases to pick up the operand from the right spot.
+
 2002-03-04  H.J. Lu <hjl@gnu.org>
 
        * config/obj-elf.c (special_section): Add .init_array,
index 4577d79632ea4c1c3a98e13b034e72073b158c16..0b59554ecd86118f46016d92da4e1e8a4b85f161 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-pdp11.c - pdp11-specific -
-   Copyright 2001 Free Software Foundation, Inc.
+   Copyright 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -33,6 +33,9 @@ static int set_option PARAMS ((char *arg));
 static int set_cpu_model PARAMS ((char *arg));
 static int set_machine_model PARAMS ((char *arg));
 
+extern int flonum_gen2vax PARAMS ((char format_letter, FLONUM_TYPE * f,
+                                   LITTLENUM_TYPE * words));
+
 #define TRUE 1
 #define FALSE 0
 
@@ -85,7 +88,7 @@ CONST char EXP_CHARS[] = "eE";
 /* Chars that mean this number is a floating point constant */
 /* as in 0f123.456 */
 /* or    0H1.234E-12 (see exp chars above) */
-CONST char FLT_CHARS[] = "dDfFgGhH";
+CONST char FLT_CHARS[] = "dDfF";
 
 void pseudo_even (int);
 void pseudo_bss (int);
@@ -298,7 +301,7 @@ parse_reg (char *str, struct pdp11_code *operand)
 }
 
 static char *
-parse_ac (char *str, struct pdp11_code *operand)
+parse_ac5 (char *str, struct pdp11_code *operand)
 {
   str = skip_whitespace (str);
   if (strncmp (str, "fr", 2) == 0 ||
@@ -310,6 +313,7 @@ parse_ac (char *str, struct pdp11_code *operand)
       switch (*str)
        {
        case '0': case '1': case '2': case '3':
+        case '4': case '5':
          operand->code = *str - '0';
          str++;
          break;
@@ -327,6 +331,19 @@ parse_ac (char *str, struct pdp11_code *operand)
   return str;
 }
 
+static char *
+parse_ac (char *str, struct pdp11_code *operand)
+{
+  str = parse_ac5 (str, operand);
+  if (!operand->error && operand->code > 3)
+    {
+         operand->error = "Bad register name";
+         return str - 3;
+    }
+
+  return str;
+}
+
 static char *
 parse_expression (char *str, struct pdp11_code *operand)
 {
@@ -348,6 +365,15 @@ parse_expression (char *str, struct pdp11_code *operand)
 
   operand->reloc.pc_rel = 0;
 
+#if 0
+  /* FIXME: what follows is broken badly.  You can't deal with differences
+     in radix conventions this way, because of symbolic constants, constant
+     expressions made up of pieces of differing radix, etc.  The only 
+     choices are to change ../expr.c to know about pdp11 conventions, or
+     to accept the fact that gas will use consistent conventions that differ
+     from those of traditional pdp11 assemblers.  For now, I've
+     chosen the latter.   paul koning, 12/23/2001
+  */
   if (operand->reloc.exp.X_op == O_constant)
     {
       if (*str == '.')
@@ -362,13 +388,15 @@ parse_expression (char *str, struct pdp11_code *operand)
          operand->reloc.exp.X_add_number = strtol (buf, &end, 8);
        }
     }
-
+#endif
   return str;
 }
 
 static char *
 parse_op_no_deferred (char *str, struct pdp11_code *operand)
 {
+  LITTLENUM_TYPE literal_float[2];
+
   str = skip_whitespace (str);
 
   switch (*str)
@@ -412,6 +440,19 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
          operand->reloc.type = BFD_RELOC_16;
          operand->reloc.pc_rel = 0;
          break;
+        case O_big:
+          if (operand->reloc.exp.X_add_number > 0)
+            {
+              operand->error = "Error in expression";
+              break;
+            }
+          /* it's a floating literal... */
+          know (operand->reloc.exp.X_add_number < 0);
+          flonum_gen2vax ('f', &generic_floating_point_number, literal_float);
+          operand->word = literal_float[0];
+          if (literal_float[1] != 0)
+            as_warn (_("Low order bits truncated in immediate float operand"));
+          break;
        default:
          operand->error = "Error in expression";
          break;
@@ -504,13 +545,9 @@ parse_op_no_deferred (char *str, struct pdp11_code *operand)
 }
 
 static char *
-parse_op (char *str, struct pdp11_code *operand)
+parse_op_noreg (char *str, struct pdp11_code *operand)
 {
   str = skip_whitespace (str);
-
-  str = parse_reg (str, operand);
-  if (!operand->error)
-    return str;
   operand->error = NULL;
 
   if (*str == '@' || *str == '*')
@@ -526,6 +563,46 @@ parse_op (char *str, struct pdp11_code *operand)
   return str;
 }
 
+static char *
+parse_op (char *str, struct pdp11_code *operand)
+{
+  str = skip_whitespace (str);
+
+  str = parse_reg (str, operand);
+  if (!operand->error)
+    return str;
+
+  operand->error = NULL;
+  parse_ac5 (str, operand);
+  if (!operand->error)
+    {
+      operand->error = "Float AC not legal as integer operand";
+      return str;
+    }
+  
+  return parse_op_noreg (str, operand);
+}
+
+static char *
+parse_fop (char *str, struct pdp11_code *operand)
+{
+  str = skip_whitespace (str);
+
+  str = parse_ac5 (str, operand);
+  if (!operand->error)
+    return str;
+
+  operand->error = NULL;
+  parse_reg (str, operand);
+  if (!operand->error)
+    {
+      operand->error = "General register not legal as float operand";
+      return str;
+    }
+
+  return parse_op_noreg (str, operand);
+}
+
 static char *
 parse_separator (char *str, int *error)
 {
@@ -585,7 +662,7 @@ md_assemble (instruction_string)
                       &insn.reloc.exp, insn.reloc.pc_rel, insn.reloc.type);
       }
 #else
-      as_warn ("Unknown instruction");
+      as_bad (_("Unknown instruction '%s'"), str);
 #endif
 
       return;
@@ -627,31 +704,36 @@ md_assemble (instruction_string)
       str = parse_expression (str, &op1);
       if (op1.error)
        break;
+      if (op1.reloc.exp.X_op != O_constant || op1.reloc.type != BFD_RELOC_NONE)
+       {
+         op1.error = "operand is not an absolute constant";
+         break;
+       }
       switch (op->type)
        {
        case PDP11_OPCODE_IMM3:
-         if (op1.code & ~7)
+         if (op1.reloc.exp.X_add_number & ~7)
            {
              op1.error = "3-bit immediate out of range";
              break;
            }
          break;
        case PDP11_OPCODE_IMM6:
-         if (op1.code & ~0x3f)
+         if (op1.reloc.exp.X_add_number & ~0x3f)
            {
              op1.error = "6-bit immediate out of range";
              break;
            }
          break;
        case PDP11_OPCODE_IMM8:
-         if (op1.code & ~0xff)
+         if (op1.reloc.exp.X_add_number & ~0xff)
            {
              op1.error = "8-bit immediate out of range";
              break;
            }
          break;
        }
-      insn.code |= op1.code;
+      insn.code |= op1.reloc.exp.X_add_number;
       break;
 
     case PDP11_OPCODE_DISPL:
@@ -693,6 +775,15 @@ md_assemble (instruction_string)
        size += 2;
       break;
 
+    case PDP11_OPCODE_FOP:
+      str = parse_fop (str, &op1);
+      if (op1.error)
+       break;
+      insn.code |= op1.code;
+      if (op1.additional)
+       size += 2;
+      break;
+
     case PDP11_OPCODE_REG_OP:
       str = parse_reg (str, &op2);
       if (op2.error)
@@ -731,6 +822,44 @@ md_assemble (instruction_string)
       insn.code |= op2.code << 6;
       break;
 
+    case PDP11_OPCODE_AC_FOP:
+      str = parse_ac (str, &op2);
+      if (op2.error)
+       break;
+      insn.code |= op2.code << 6;
+      str = parse_separator (str, &error);
+      if (error)
+       {
+         op1.error = "Missing ','";
+         break;
+       }
+      str = parse_fop (str, &op1);
+      if (op1.error)
+       break;
+      insn.code |= op1.code;
+      if (op1.additional)
+       size += 2;
+      break;
+
+    case PDP11_OPCODE_FOP_AC:
+      str = parse_fop (str, &op1);
+      if (op1.error)
+       break;
+      insn.code |= op1.code;
+      if (op1.additional)
+       size += 2;
+      str = parse_separator (str, &error);
+      if (error)
+       {
+         op1.error = "Missing ','";
+         break;
+       }
+      str = parse_ac (str, &op2);
+      if (op2.error)
+       break;
+      insn.code |= op2.code << 6;
+      break;
+
     case PDP11_OPCODE_AC_OP:
       str = parse_ac (str, &op2);
       if (op2.error)
@@ -750,6 +879,25 @@ md_assemble (instruction_string)
        size += 2;
       break;
 
+    case PDP11_OPCODE_OP_AC:
+      str = parse_op (str, &op1);
+      if (op1.error)
+       break;
+      insn.code |= op1.code;
+      if (op1.additional)
+       size += 2;
+      str = parse_separator (str, &error);
+      if (error)
+       {
+         op1.error = "Missing ','";
+         break;
+       }
+      str = parse_ac (str, &op2);
+      if (op2.error)
+       break;
+      insn.code |= op2.code << 6;
+      break;
+
     case PDP11_OPCODE_OP_OP:
       str = parse_op (str, &op1);
       if (op1.error)
This page took 0.030978 seconds and 4 git commands to generate.