This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]