* config/tc-mips.c (NO_ISA_COP): New macro.
authorAdam Nemet <anemet@caviumnetworks.com>
Mon, 7 Jul 2008 19:16:23 +0000 (19:16 +0000)
committerAdam Nemet <anemet@caviumnetworks.com>
Mon, 7 Jul 2008 19:16:23 +0000 (19:16 +0000)
(COP_INSN): New macro.
(is_opcode_valid): Use them.
(macro) <ld_st>: Use them.  Don't accept coprocessor load store
insns based on the ISA if CPU is NO_ISA_COP.
<copz>: Likewise for coprocessor operations.

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

index 225b521a91b46f63718d63fb5f66184a8c7ce053..bb8218292b26caa48519b4d7a216cee4a757159a 100644 (file)
@@ -1,3 +1,12 @@
+2008-07-07  Adam Nemet  <anemet@caviumnetworks.com>
+
+       * config/tc-mips.c (NO_ISA_COP): New macro.
+       (COP_INSN): New macro.
+       (is_opcode_valid): Use them.
+       (macro) <ld_st>: Use them.  Don't accept coprocessor load store
+       insns based on the ISA if CPU is NO_ISA_COP.
+       <copz>: Likewise for coprocessor operations.
+
 2008-07-07  Paul Brook  <paul@codesourcery.com>
 
        * config/tc-arm.c (arm_fix_adjustable): Don't adjust MOVW/MOVT
index f544e6ae27c7094fea927904444267a39e49d489..d5ed84ceb2bedf9dc40125b65e54b2225c847dc5 100644 (file)
@@ -447,6 +447,11 @@ static int mips_32bitmode = 0;
 /* True if CPU has seq/sne and seqi/snei instructions.  */
 #define CPU_HAS_SEQ(CPU)       ((CPU) == CPU_OCTEON)
 
+/* True if CPU does not implement the all the coprocessor insns.  For these
+   CPUs only those COP insns are accepted that are explicitly marked to be
+   available on the CPU.  ISA membership for COP insns is ignored.  */
+#define NO_ISA_COP(CPU)                ((CPU) == CPU_OCTEON)
+
 /* True if mflo and mfhi can be immediately followed by instructions
    which write to the HI and LO registers.
 
@@ -504,7 +509,17 @@ static int mips_32bitmode = 0;
 
 /* Is this a mfhi or mflo instruction?  */
 #define MF_HILO_INSN(PINFO) \
-          ((PINFO & INSN_READ_HI) || (PINFO & INSN_READ_LO))
+  ((PINFO & INSN_READ_HI) || (PINFO & INSN_READ_LO))
+
+/* Returns true for a (non floating-point) coprocessor instruction.  Reading
+   or writing the condition code is only possible on the coprocessors and
+   these insns are not marked with INSN_COP.  Thus for these insns use the
+   condition-code flags unless this is the floating-point coprocessor.  */
+#define COP_INSN(PINFO)                                                        \
+  (PINFO != INSN_MACRO                                                 \
+   && (((PINFO) & INSN_COP)                                            \
+       || ((PINFO) & (INSN_READ_COND_CODE | INSN_WRITE_COND_CODE)      \
+          && ((PINFO) & (FP_S | FP_D)) == 0)))
 
 /* MIPS PIC level.  */
 
@@ -1803,6 +1818,12 @@ is_opcode_valid (const struct mips_opcode *mo, bfd_boolean expansionp)
   if (expansionp ? mips_opts.mips16 : file_ase_mips16)
     isa |= INSN_MIPS16;
 
+  /* Don't accept instructions based on the ISA if the CPU does not implement
+     all the coprocessor insns. */
+  if (NO_ISA_COP (mips_opts.arch)
+      && COP_INSN (mo->pinfo))
+    isa = 0;
+
   if (!OPCODE_IS_MEMBER (mo, isa, mips_opts.arch))
     return FALSE;
 
@@ -6312,6 +6333,15 @@ macro (struct mips_cl_insn *ip)
       tempreg = AT;
       used_at = 1;
     ld_st:
+      if (coproc
+         && NO_ISA_COP (mips_opts.arch)
+         && (ip->insn_mo->pinfo2 & (INSN2_M_FP_S | INSN2_M_FP_D)) == 0)
+       {
+         as_bad (_("opcode not supported on this processor: %s"),
+                 mips_cpu_info_from_arch (mips_opts.arch)->name);
+         break;
+       }
+
       /* Itbl support may require additional care here.  */
       if (mask == M_LWC1_AB
          || mask == M_SWC1_AB
@@ -7180,6 +7210,14 @@ macro (struct mips_cl_insn *ip)
     case M_COP3:
       s = "c3";
     copz:
+      if (NO_ISA_COP (mips_opts.arch)
+         && (ip->insn_mo->pinfo2 & INSN2_M_FP_S) == 0)
+       {
+         as_bad (_("opcode not supported on this processor: %s"),
+                 mips_cpu_info_from_arch (mips_opts.arch)->name);
+         break;
+       }
+
       /* For now we just do C (same as Cz).  The parameter will be
          stored in insn_opcode by mips_ip.  */
       macro_build (NULL, s, "C", ip->insn_opcode);