This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Handle extrdi and large register rotate values
- From: Peter Bergner <bergner at vnet dot ibm dot com>
- To: Alan Modra <amodra at bigpond dot net dot au>
- Cc: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Date: Thu, 27 Aug 2009 17:29:36 -0500
- Subject: Handle extrdi and large register rotate values
Alan,
Someone complained that the assembler rejects the following extended
mnemonic (whereas the AIX and iSeries assemblers accept):
extrdi rA,rS,6,58 (ie, rA = rS & 0x3f)
This is mapped to "rldicl rA,rS,58+6,64-6", which complains
that the SH value (58+6=64) is too large. Logically, the extrdi
use above makes sense, since it's saying we just want to grab 6
bits starting at bit position 58. It's just that the rldicl
handling doesn't accept SH values greater than the register
size. At first, I thought about doing something like:
-{"extrdi", 4, PPC64, "rldicl %0,%1,(%2)+(%3),64-(%2)"},
-{"extrdi.", 4, PPC64, "rldicl. %0,%1,(%2)+(%3),64-(%2)"},
+{"extrdi", 4, PPC64, "rldicl %0,%1,((%2)+(%3))&0x3f,64-(%2)"},
+{"extrdi.", 4, PPC64, "rldicl. %0,%1,((%2)+(%3))&0x3f,64-(%2)"},
but that would mean updating quite a few other ops similarly. Is the
following patch acceptable to catch them all in one shot or do you
prefer a change like the above?
Peter
Index: include/opcode/ppc.h
===================================================================
--- include/opcode/ppc.h (revision 521)
+++ include/opcode/ppc.h (working copy)
@@ -329,6 +329,13 @@ extern const unsigned int num_powerpc_op
/* This operand names a vector-scalar unit register. The disassembler
prints these with a leading 'vs'. */
#define PPC_OPERAND_VSR (0x100000)
+
+/* This operand's value should be truncated to fit within the
+ range specified by its bitmask. Namely:
+ op &= o->bitm;
+ This can be used to handle register rotate bit shift values that
+ exceed the register size and convert them to their logical equivalents. */
+#define PPC_OPERAND_TRUNCATE (0x200000)
/* The POWER and PowerPC assemblers use a few macros. We keep them
with the operands table for simplicity. The macro table is an
Index: gas/config/tc-ppc.c
===================================================================
--- gas/config/tc-ppc.c (revision 521)
+++ gas/config/tc-ppc.c (working copy)
@@ -1629,6 +1629,9 @@ ppc_insert_operand (unsigned long insn,
{
long min, max, right;
+ if ((operand->flags & PPC_OPERAND_TRUNCATE) != 0)
+ val &= operand->bitm;
+
max = operand->bitm;
right = max & -max;
min = 0;
Index: opcodes/ppc-opc.c
===================================================================
--- opcodes/ppc-opc.c (revision 521)
+++ opcodes/ppc-opc.c (working copy)
@@ -418,14 +418,16 @@ const struct powerpc_operand powerpc_ope
/* The SH field in an X or M form instruction. */
#define SH RSO + 1
#define SH_MASK (0x1f << 11)
+ { 0x1f, 11, NULL, NULL, PPC_OPERAND_TRUNCATE },
+
/* The other UIMM field in a EVX form instruction. */
-#define EVUIMM SH
+#define EVUIMM SH + 1
{ 0x1f, 11, NULL, NULL, 0 },
/* The SH field in an MD form instruction. This is split. */
-#define SH6 SH + 1
+#define SH6 EVUIMM + 1
#define SH6_MASK ((0x1f << 11) | (1 << 1))
- { 0x3f, -1, insert_sh6, extract_sh6, 0 },
+ { 0x3f, -1, insert_sh6, extract_sh6, PPC_OPERAND_TRUNCATE },
/* The SH field of the tlbwe instruction, which is optional. */
#define SHO SH6 + 1