This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: PowerPC gas -many
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: Nick Clifton <nickc at redhat dot com>
- Cc: binutils at sources dot redhat dot com, Anton Blanchard <anton at samba dot org>,Paul Mackerras <paulus at au1 dot ibm dot com>
- Date: Tue, 02 Sep 2003 17:26:00 +0930
- Subject: Re: PowerPC gas -many
- References: <20030902004925.GD1320@bubble.sa.bigpond.net.au><m3vfsbu0je.fsf@redhat.com>
On Tue, Sep 02, 2003 at 08:12:05AM +0100, Nick Clifton wrote:
> Wouldn't it be simpler to drop the "-many" switch since as you point
> out the correct choice of instruction coding cannot always be
> guaranteed. Instead you could have a pseudo op (eg ".machine") which
> could be used to select the desired architecture at the desired point
> in the source. ie:
That's actually more work, because the opcode table is currently set
at md_begin time. Here's what I'm playing with at the moment.
opcodes/ChangeLog
* ppc-opc.c (insert_fxm): Expand comment.
(PPC, PPCCOM, PPC32, PPC64, PPCVEC): Remove PPC_OPCODE_ANY.
(POWER, POWER2, PPCPWR2, POWER32, COM, COM32, M601, PWRCOM): Likewise.
(POWER4): Remove PPCCOM.
* ppc-dis.c (powerpc_dialect): Make static. Accept -Many in addition
to existing options.
(print_insn_big_powerpc, print_insn_little_powerpc): Formatting.
(print_insn_powerpc): Remove unnecessary efs/altivec check. Try harder
to disassemble if given -Many.
gas/ChangeLog
* config/tc-ppc.c (md_parse_option): Add PPC_OPCODE_ANY to existing
ppc_cpu selection rather than replacing.
(ppc_set_cpu): Ignore and preserve PPC_OPCODE_ANY in ppc_cpu.
(md_begin): When PPC_OPCODE_ANY, insert all opcodes in ppc_hash.
Index: opcodes/ppc-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/ppc-dis.c,v
retrieving revision 1.14
diff -u -p -r1.14 ppc-dis.c
--- opcodes/ppc-dis.c 2 Sep 2003 04:15:29 -0000 1.14
+++ opcodes/ppc-dis.c 2 Sep 2003 07:51:55 -0000
@@ -36,7 +36,7 @@ static int print_insn_powerpc (bfd_vma,
BookE. For convenience, also disassemble instructions supported
by the AltiVec vector unit. */
-int
+static int
powerpc_dialect (struct disassemble_info *info)
{
int dialect = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC;
@@ -45,40 +45,39 @@ powerpc_dialect (struct disassemble_info
dialect |= PPC_OPCODE_64;
if (info->disassembler_options
- && (strcmp (info->disassembler_options, "booke") == 0
- || strcmp (info->disassembler_options, "booke32") == 0
- || strcmp (info->disassembler_options, "booke64") == 0))
+ && strstr (info->disassembler_options, "booke") != NULL)
dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
- else
- if ((info->mach == bfd_mach_ppc_e500)
- || (info->disassembler_options
- && ( strcmp (info->disassembler_options, "e500") == 0
- || strcmp (info->disassembler_options, "e500x2") == 0)))
- {
- dialect |= PPC_OPCODE_BOOKE
- | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
- | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
- | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
- | PPC_OPCODE_RFMCI;
- /* efs* and AltiVec conflict. */
- dialect &= ~PPC_OPCODE_ALTIVEC;
- }
- else
- if (info->disassembler_options
- && (strcmp (info->disassembler_options, "efs") == 0))
- {
- dialect |= PPC_OPCODE_EFS;
- /* efs* and AltiVec conflict. */
- dialect &= ~PPC_OPCODE_ALTIVEC;
- }
+ else if ((info->mach == bfd_mach_ppc_e500)
+ || (info->disassembler_options
+ && strstr (info->disassembler_options, "e500") != NULL))
+ {
+ dialect |= PPC_OPCODE_BOOKE
+ | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
+ | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
+ | PPC_OPCODE_RFMCI;
+ /* efs* and AltiVec conflict. */
+ dialect &= ~PPC_OPCODE_ALTIVEC;
+ }
+ else if (info->disassembler_options
+ && strstr (info->disassembler_options, "efs") != NULL)
+ {
+ dialect |= PPC_OPCODE_EFS;
+ /* efs* and AltiVec conflict. */
+ dialect &= ~PPC_OPCODE_ALTIVEC;
+ }
else
dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
| PPC_OPCODE_COMMON);
if (info->disassembler_options
- && strcmp (info->disassembler_options, "power4") == 0)
+ && strstr (info->disassembler_options, "power4") != NULL)
dialect |= PPC_OPCODE_POWER4;
+ if (info->disassembler_options
+ && strstr (info->disassembler_options, "any") != NULL)
+ dialect |= PPC_OPCODE_ANY;
+
if (info->disassembler_options)
{
if (strstr (info->disassembler_options, "32") != NULL)
@@ -95,7 +94,7 @@ powerpc_dialect (struct disassemble_info
int
print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
{
- return print_insn_powerpc (memaddr, info, 1, powerpc_dialect(info));
+ return print_insn_powerpc (memaddr, info, 1, powerpc_dialect (info));
}
/* Print a little endian PowerPC instruction. */
@@ -103,7 +102,7 @@ print_insn_big_powerpc (bfd_vma memaddr,
int
print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
{
- return print_insn_powerpc (memaddr, info, 0, powerpc_dialect(info));
+ return print_insn_powerpc (memaddr, info, 0, powerpc_dialect (info));
}
/* Print a POWER (RS/6000) instruction. */
@@ -147,6 +146,7 @@ print_insn_powerpc (bfd_vma memaddr,
/* Find the first match in the opcode table. We could speed this up
a bit by doing a binary search on the major opcode. */
opcode_end = powerpc_opcodes + powerpc_num_opcodes;
+ again:
for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
{
unsigned long table_op;
@@ -166,9 +166,6 @@ print_insn_powerpc (bfd_vma memaddr,
|| (opcode->flags & dialect) == 0)
continue;
- if ((dialect & PPC_OPCODE_EFS) && (opcode->flags & PPC_OPCODE_ALTIVEC))
- continue;
-
/* Make two passes over the operands. First see if any of them
have extraction functions, and, if they do, make sure the
instruction is valid. */
@@ -275,6 +272,12 @@ print_insn_powerpc (bfd_vma memaddr,
/* We have found and printed an instruction; return. */
return 4;
+ }
+
+ if ((dialect & PPC_OPCODE_ANY) != 0)
+ {
+ dialect = ~PPC_OPCODE_ANY;
+ goto again;
}
/* We could not find a match. */
Index: opcodes/ppc-opc.c
===================================================================
RCS file: /cvs/src/src/opcodes/ppc-opc.c,v
retrieving revision 1.56
diff -u -p -r1.56 ppc-opc.c
--- opcodes/ppc-opc.c 2 Sep 2003 04:15:29 -0000 1.56
+++ opcodes/ppc-opc.c 2 Sep 2003 07:51:57 -0000
@@ -1001,7 +1001,8 @@ insert_fxm (unsigned long insn,
;
/* If only one bit of the FXM field is set, we can use the new form
- of the instruction, which is faster. */
+ of the instruction, which is faster. Unlike the Power4 branch hint
+ encoding, this is not backward compatible. */
else if ((dialect & PPC_OPCODE_POWER4) != 0 && (value & -value) == value)
insn |= 1 << 20;
@@ -1762,27 +1763,27 @@ extract_tbr (unsigned long insn,
/* Smaller names for the flags so each entry in the opcodes table will
fit on a single line. */
#undef PPC
-#define PPC PPC_OPCODE_PPC | PPC_OPCODE_ANY
-#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_ANY
+#define PPC PPC_OPCODE_PPC
+#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON
#define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM
-#define POWER4 PPC_OPCODE_POWER4 | PPCCOM
-#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC | PPC_OPCODE_ANY
-#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC | PPC_OPCODE_ANY
+#define POWER4 PPC_OPCODE_POWER4
+#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC
+#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC
#define PPCONLY PPC_OPCODE_PPC
#define PPC403 PPC_OPCODE_403
#define PPC405 PPC403
#define PPC440 PPC_OPCODE_440
#define PPC750 PPC
#define PPC860 PPC
-#define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_ANY | PPC_OPCODE_PPC
-#define POWER PPC_OPCODE_POWER | PPC_OPCODE_ANY
-#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_ANY
-#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_ANY
-#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_ANY | PPC_OPCODE_32
-#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_ANY
-#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_ANY | PPC_OPCODE_32
-#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_ANY
-#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON | PPC_OPCODE_ANY
+#define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_PPC
+#define POWER PPC_OPCODE_POWER
+#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2
+#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2
+#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_32
+#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON
+#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_32
+#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601
+#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON
#define MFDEC1 PPC_OPCODE_POWER
#define MFDEC2 PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_BOOKE
#define BOOKE PPC_OPCODE_BOOKE
Index: gas/config/tc-ppc.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ppc.c,v
retrieving revision 1.81
diff -u -p -r1.81 tc-ppc.c
--- gas/config/tc-ppc.c 19 Aug 2003 15:48:53 -0000 1.81
+++ gas/config/tc-ppc.c 2 Sep 2003 07:52:00 -0000
@@ -974,7 +974,7 @@ md_parse_option (c, arg)
ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
/* -many means to assemble for any architecture (PWR/PWRX/PPC). */
else if (strcmp (arg, "any") == 0)
- ppc_cpu = PPC_OPCODE_ANY | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_ANY;
else if (strcmp (arg, "regnames") == 0)
reg_names_p = TRUE;
@@ -1118,23 +1118,23 @@ ppc_set_cpu ()
const char *default_os = TARGET_OS;
const char *default_cpu = TARGET_CPU;
- if (ppc_cpu == 0)
+ if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0)
{
if (ppc_obj64)
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+ ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
else if (strncmp (default_os, "aix", 3) == 0
&& default_os[3] >= '4' && default_os[3] <= '9')
- ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_COMMON | PPC_OPCODE_32;
else if (strncmp (default_os, "aix3", 4) == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
else if (strcmp (default_cpu, "rs6000") == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
else if (strncmp (default_cpu, "powerpc", 7) == 0)
{
if (default_cpu[7] == '6' && default_cpu[8] == '4')
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+ ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
else
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
}
else
as_fatal (_("Unknown default cpu = %s, os = %s"),
@@ -1264,6 +1264,10 @@ md_begin ()
}
}
}
+
+ if ((ppc_cpu & PPC_OPCODE_ANY) != 0)
+ for (op = powerpc_opcodes; op < op_end; op++)
+ hash_insert (ppc_hash, op->name, (PTR) op);
/* Insert the macros into a hash table. */
ppc_macro_hash = hash_new ();
--
Alan Modra
IBM OzLabs - Linux Technology Centre