summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-10-14 12:28:33 +1030
committerAlan Modra <amodra@gmail.com>2022-10-16 13:54:50 +1030
commit45685a2fd86073e76a772c5b677f14f8465a5040 (patch)
treef7ddbaca363370fcdec5448d01896bcc744958e4 /gas
parent206e9791cb09459bf92603428370c16bfde282ac (diff)
downloadbinutils-gdb-45685a2fd86073e76a772c5b677f14f8465a5040.tar.gz
PowerPC se_rfmci and VLE, SPE2 and LSP insns with -many
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.
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-ppc.c96
-rw-r--r--gas/testsuite/gas/ppc/ppc.exp2
-rw-r--r--gas/testsuite/gas/ppc/se_rfmci.d9
-rw-r--r--gas/testsuite/gas/ppc/se_rfmci.s1
-rw-r--r--gas/testsuite/gas/ppc/se_rfmci_bad.d3
5 files changed, 55 insertions, 56 deletions
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.*