public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PowerPC se_rfmci and VLE, SPE2 and LSP insns with -many
@ 2022-10-16  4:42 Alan Modra
  0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2022-10-16  4:42 UTC (permalink / raw)
  To: binutils

I noticed recently that se_rfmci, a VLE mode instruction, was being
accepted by non-VLE cpus, and also that se_rfmci by itself in a
section did not cause SHF_PPC_VLE to be set.  ie. both testcases added
by this patch fail without the changes to tc-ppc.c here.

Also, VLE, SPE2 and LSP insns were not accepted by the assembler with
-many nor were SPE2 and LSP being disassembled with -Many.

gas/
	* config/tc-ppc.c (ppc_setup_opcodes): Wrap long lines.  Add
	vle_opcodes when PPC_OPCODE_VLE or PPC_OPCODE_ANY.  Simplify
	disassembler index segment checks.  Add LSP and SPE2 opcodes
	when PPC_OPCODE_ANY too.
	(md_assemble): Correct logic adding PPC_APUINFO_VLE and
	SHF_PPC_VLE.
	* testsuite/gas/ppc/se_rfmci.s
	* testsuite/gas/ppc/se_rfmci.d,
	* testsuite/gas/ppc/se_rfmci_bad.d: New tests.
	* testsuite/gas/ppc/ppc.exp: Run them.
opcodes/
	* ppc-dis.c (print_insn_powerpc): Disassemble SPE2 and LSP insn
	when -Many.
	* ppc-opc.c (vle_opcodes <se_rfmci>): Comment.

diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 5077e055401..97ad782012c 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -1694,10 +1694,12 @@ ppc_setup_opcodes (void)
 	  unsigned int new_opcode = PPC_OP (op[0].opcode);
 
 #ifdef PRINT_OPCODE_TABLE
-	  printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%llx\tmask: 0x%llx\tflags: 0x%llx\n",
+	  printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%llx"
+		  "\tmask: 0x%llx\tflags: 0x%llx\n",
 		  op->name, (unsigned int) (op - powerpc_opcodes),
 		  new_opcode, (unsigned long long) op->opcode,
-		  (unsigned long long) op->mask, (unsigned long long) op->flags);
+		  (unsigned long long) op->mask,
+		  (unsigned long long) op->flags);
 #endif
 
 	  /* The major opcodes had better be sorted.  Code in the disassembler
@@ -1745,10 +1747,12 @@ ppc_setup_opcodes (void)
 	  unsigned int new_opcode = PPC_PREFIX_SEG (op[0].opcode);
 
 #ifdef PRINT_OPCODE_TABLE
-	  printf ("%-14s\t#%04u\tmajor op/2: 0x%x\top: 0x%llx\tmask: 0x%llx\tflags: 0x%llx\n",
+	  printf ("%-14s\t#%04u\tmajor op/2: 0x%x\top: 0x%llx"
+		  "\tmask: 0x%llx\tflags: 0x%llx\n",
 		  op->name, (unsigned int) (op - prefix_opcodes),
 		  new_opcode, (unsigned long long) op->opcode,
-		  (unsigned long long) op->mask, (unsigned long long) op->flags);
+		  (unsigned long long) op->mask,
+		  (unsigned long long) op->flags);
 #endif
 
 	  /* The major opcodes had better be sorted.  Code in the disassembler
@@ -1775,43 +1779,42 @@ ppc_setup_opcodes (void)
     for (op = prefix_opcodes; op < op_end; op++)
       str_hash_insert (ppc_hash, op->name, op, 0);
 
-  op_end = vle_opcodes + vle_num_opcodes;
-  for (op = vle_opcodes; op < op_end; op++)
+  if ((ppc_cpu & (PPC_OPCODE_VLE | PPC_OPCODE_ANY)) != 0)
     {
-      if (ENABLE_CHECKING)
+      unsigned int prev_seg = 0;
+      unsigned int seg;
+
+      op_end = vle_opcodes + vle_num_opcodes;
+      for (op = vle_opcodes; op < op_end; op++)
 	{
-	  unsigned new_seg = VLE_OP_TO_SEG (VLE_OP (op[0].opcode, op[0].mask));
+	  if (ENABLE_CHECKING)
+	    {
+	      seg = VLE_OP_TO_SEG (VLE_OP (op[0].opcode, op[0].mask));
 
 #ifdef PRINT_OPCODE_TABLE
-	  printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%llx\tmask: 0x%llx\tflags: 0x%llx\n",
-		  op->name, (unsigned int) (op - vle_opcodes),
-		  (unsigned int) new_seg, (unsigned long long) op->opcode,
-		  (unsigned long long) op->mask, (unsigned long long) op->flags);
+	      printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%llx"
+		      "\tmask: 0x%llx\tflags: 0x%llx\n",
+		      op->name, (unsigned int) (op - vle_opcodes),
+		      (unsigned int) seg, (unsigned long long) op->opcode,
+		      (unsigned long long) op->mask,
+		      (unsigned long long) op->flags);
 #endif
 
-	  /* The major opcodes had better be sorted.  Code in the disassembler
-	     assumes the insns are sorted according to major opcode.  */
-	  if (op != vle_opcodes
-	      && new_seg < VLE_OP_TO_SEG (VLE_OP (op[-1].opcode, op[-1].mask)))
-	    {
-	      as_bad (_("major opcode is not sorted for %s"), op->name);
-	      bad_insn = true;
+	      if (seg < prev_seg)
+		{
+		  as_bad (_("major opcode is not sorted for %s"), op->name);
+		  bad_insn = true;
+		}
+	      prev_seg = seg;
+	      bad_insn |= insn_validate (op);
 	    }
 
-	  bad_insn |= insn_validate (op);
-	}
-
-      if ((ppc_cpu & op->flags) != 0
-	  && !(ppc_cpu & op->deprecated)
-	  && str_hash_insert (ppc_hash, op->name, op, 0) != NULL)
-	{
-	  as_bad (_("duplicate %s"), op->name);
-	  bad_insn = true;
+	  str_hash_insert (ppc_hash, op->name, op, 0);
 	}
     }
 
   /* LSP instructions */
-  if ((ppc_cpu & PPC_OPCODE_LSP) != 0)
+  if ((ppc_cpu & (PPC_OPCODE_LSP | PPC_OPCODE_ANY)) != 0)
     {
       unsigned int prev_seg = 0;
       unsigned int seg;
@@ -1835,46 +1838,27 @@ ppc_setup_opcodes (void)
     }
 
   /* SPE2 instructions */
-  if ((ppc_cpu & PPC_OPCODE_SPE2) == PPC_OPCODE_SPE2)
+  if ((ppc_cpu & (PPC_OPCODE_SPE2 | PPC_OPCODE_ANY)) != 0)
     {
+      unsigned int prev_seg = 0;
+      unsigned int seg;
       op_end = spe2_opcodes + spe2_num_opcodes;
       for (op = spe2_opcodes; op < op_end; op++)
 	{
 	  if (ENABLE_CHECKING)
 	    {
-	      if (op != spe2_opcodes)
+	      seg = VLE_OP_TO_SEG (VLE_OP (op[0].opcode, op[0].mask));
+	      if (seg < prev_seg)
 		{
-		unsigned old_seg, new_seg;
-
-		old_seg = VLE_OP (op[-1].opcode, op[-1].mask);
-		old_seg = VLE_OP_TO_SEG (old_seg);
-		new_seg = VLE_OP (op[0].opcode, op[0].mask);
-		new_seg = VLE_OP_TO_SEG (new_seg);
-
-		/* The major opcodes had better be sorted.  Code in the
-		    disassembler assumes the insns are sorted according to
-		    major opcode.  */
-		if (new_seg < old_seg)
-		  {
 		  as_bad (_("major opcode is not sorted for %s"), op->name);
 		  bad_insn = true;
-		  }
 		}
-
+	      prev_seg = seg;
 	      bad_insn |= insn_validate (op);
 	    }
 
-	  if ((ppc_cpu & op->flags) != 0
-	      && !(ppc_cpu & op->deprecated)
-	      && str_hash_insert (ppc_hash, op->name, op, 0) != NULL)
-	    {
-	      as_bad (_("duplicate %s"), op->name);
-	      bad_insn = true;
-	    }
+	  str_hash_insert (ppc_hash, op->name, op, 0);
 	}
-
-      for (op = spe2_opcodes; op < op_end; op++)
-	str_hash_insert (ppc_hash, op->name, op, 0);
     }
 
   if (bad_insn)
@@ -4035,7 +4019,7 @@ md_assemble (char *str)
          be set for VLE-only instructions or for VLE-only processors,
          however it'll remain clear for dual-mode instructions on
          dual-mode and, more importantly, standard-mode processors.  */
-      if ((ppc_cpu & opcode->flags) == PPC_OPCODE_VLE)
+      if (ppc_cpu & opcode->flags & PPC_OPCODE_VLE)
 	{
 	  ppc_apuinfo_section_add (PPC_APUINFO_VLE, 1);
 	  if (elf_section_data (now_seg) != NULL)
diff --git a/gas/testsuite/gas/ppc/ppc.exp b/gas/testsuite/gas/ppc/ppc.exp
index 1bfd375ccd6..ae8a7b61cde 100644
--- a/gas/testsuite/gas/ppc/ppc.exp
+++ b/gas/testsuite/gas/ppc/ppc.exp
@@ -87,6 +87,8 @@ run_dump_test "vle-simple-4"
 run_dump_test "vle-simple-5"
 run_dump_test "vle-simple-6"
 run_dump_test "vle-mult-ld-st-insns"
+run_dump_test "se_rfmci"
+run_dump_test "se_rfmci_bad"
 run_dump_test "lsp"
 run_dump_test "lsp-checks"
 run_dump_test "efs"
diff --git a/gas/testsuite/gas/ppc/se_rfmci.d b/gas/testsuite/gas/ppc/se_rfmci.d
new file mode 100644
index 00000000000..f43afe3061e
--- /dev/null
+++ b/gas/testsuite/gas/ppc/se_rfmci.d
@@ -0,0 +1,9 @@
+#as: -a32 -mbig -mvle
+#objdump: -d -Mvle
+
+.*: +file format elf.*-powerpc.*
+
+Disassembly of section \.text:
+
+0+00 <.*>:
+   0:	00 0b       	se_rfmci
diff --git a/gas/testsuite/gas/ppc/se_rfmci.s b/gas/testsuite/gas/ppc/se_rfmci.s
new file mode 100644
index 00000000000..fd8a479bce0
--- /dev/null
+++ b/gas/testsuite/gas/ppc/se_rfmci.s
@@ -0,0 +1 @@
+ se_rfmci
diff --git a/gas/testsuite/gas/ppc/se_rfmci_bad.d b/gas/testsuite/gas/ppc/se_rfmci_bad.d
new file mode 100644
index 00000000000..134f2d8a875
--- /dev/null
+++ b/gas/testsuite/gas/ppc/se_rfmci_bad.d
@@ -0,0 +1,3 @@
+#source: se_rfmci.s
+#as: -a32 -mbig -me500mc
+#error: .*unrecognized opcode.*
diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c
index cc9328c106a..33a96701ca8 100644
--- a/opcodes/ppc-dis.c
+++ b/opcodes/ppc-dis.c
@@ -1016,6 +1016,10 @@ print_insn_powerpc (bfd_vma memaddr,
 	opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
       if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
 	opcode = lookup_powerpc (insn, dialect);
+      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
+	opcode = lookup_spe2 (insn, dialect);
+      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
+	opcode = lookup_lsp (insn, dialect);
     }
 
   if (opcode != NULL)
diff --git a/opcodes/ppc-opc.c b/opcodes/ppc-opc.c
index e1b67647da6..b470ebd0aa9 100644
--- a/opcodes/ppc-opc.c
+++ b/opcodes/ppc-opc.c
@@ -9675,6 +9675,10 @@ const struct powerpc_opcode vle_opcodes[] = {
 {"se_rfi",	C(8),		C_MASK,		PPCVLE,	0,		{}},
 {"se_rfci",	C(9),		C_MASK,		PPCVLE,	0,		{}},
 {"se_rfdi",	C(10),		C_MASK,		PPCVLE,	0,		{}},
+/* PPCRFMCI in the following does not enable the instruction for any
+   PPC_OPCODE_RFMCI supporting cpu as vle_opcodes are all added to the
+   assembler hash table or searched by the disassembler under control
+   of PPC_OPCODE_VLE.  It's there to set apuinfo.  */
 {"se_rfmci",	C(11),		C_MASK, PPCRFMCI|PPCVLE, 0,		{}},
 {"se_rfgi",	C(12),		C_MASK,		PPCVLE,	0,		{}},
 {"se_not",	SE_R(0,2),	SE_R_MASK,	PPCVLE,	0,		{RX}},
@@ -9746,7 +9750,7 @@ const struct powerpc_opcode vle_opcodes[] = {
 {"e_ldmvdsrrw",	OPVUPRT(6,16,6),OPVUPRT_MASK,	PPCVLE,	0,		{D8, RA0}},
 {"e_stmvdsrrw",	OPVUPRT(6,17,6),OPVUPRT_MASK,	PPCVLE,	0,		{D8, RA0}},
 {"e_lmvmcsrrw",	OPVUPRT(6,16,7),OPVUPRT_MASK,	PPCVLE,	0,		{D8, RA0}},
-{"e_stmvmcsrrw",	OPVUPRT(6,17,7),OPVUPRT_MASK,	PPCVLE,	0,		{D8, RA0}},
+{"e_stmvmcsrrw",OPVUPRT(6,17,7),OPVUPRT_MASK,	PPCVLE,	0,		{D8, RA0}},
 {"e_add16i",	OP(7),		OP_MASK,	PPCVLE,	0,		{RT, RA, SI}},
 {"e_la",	OP(7),		OP_MASK,	PPCVLE,	EXT,		{RT, D, RA0}},
 {"e_sub16i",	OP(7),		OP_MASK,	PPCVLE,	EXT,		{RT, RA, NSI}},

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-10-16  4:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-16  4:42 PowerPC se_rfmci and VLE, SPE2 and LSP insns with -many Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).