Skip to content

Commit

Permalink
PowerPC se_rfmci and VLE, SPE2 and LSP insns with -many
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
amodra committed Oct 16, 2022
1 parent 206e979 commit 45685a2
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 57 deletions.
96 changes: 40 additions & 56 deletions gas/config/tc-ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions gas/testsuite/gas/ppc/ppc.exp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
9 changes: 9 additions & 0 deletions gas/testsuite/gas/ppc/se_rfmci.d
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions gas/testsuite/gas/ppc/se_rfmci.s
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
se_rfmci
3 changes: 3 additions & 0 deletions gas/testsuite/gas/ppc/se_rfmci_bad.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#source: se_rfmci.s
#as: -a32 -mbig -me500mc
#error: .*unrecognized opcode.*
4 changes: 4 additions & 0 deletions opcodes/ppc-dis.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion opcodes/ppc-opc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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}},
Expand Down Expand Up @@ -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}},
Expand Down

0 comments on commit 45685a2

Please sign in to comment.