PowerPC: Support for Prefixed Add Immediate Shifted Instruction (RFC02686)

Message ID eaecf5a2-4726-41ac-9454-c52ea1afb95a@linux.ibm.com
State New
Headers
Series PowerPC: Support for Prefixed Add Immediate Shifted Instruction (RFC02686) |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Surya Kumari Jangala March 5, 2025, 5:24 p.m. UTC
  PowerPC: Support for Prefixed Add Immediate Shifted Instruction (RFC02686)

opcodes/
	* ppc-opc.c (insert_si32, extract_si32, insert_nsi32,
	extract_nsi32): New functions.
	(SI32, NSI32, P_D_SI32_MASK, P_DRAPCREL_SI32_MASK): New macros.
	(IM32): Update for new macros.
	(powerpc_opcodes): Add plis, paddis, psubis.

gas/
	* testsuite/gas/ppc/future.s: New test.
	* testsuite/gas/ppc/future.d: Likewise.
---
 gas/testsuite/gas/ppc/future.d | 23 ++++++++++++
 gas/testsuite/gas/ppc/future.s | 13 +++++++
 opcodes/ppc-opc.c              | 69 +++++++++++++++++++++++++++++++++-
 3 files changed, 104 insertions(+), 1 deletion(-)
  

Comments

Jan Beulich March 6, 2025, 1:25 p.m. UTC | #1
On 05.03.2025 18:24, Surya Kumari Jangala wrote:
> PowerPC: Support for Prefixed Add Immediate Shifted Instruction (RFC02686)

Is there any (public) reference to the rfc you could add? From just the patch
I can't deduce what is being shifted here in which way.

> @@ -4031,9 +4087,15 @@ const unsigned int num_powerpc_operands = ARRAY_SIZE (powerpc_operands);
>  /* An 8-byte D form prefix instruction.  */
>  #define P_D_MASK (((-1ULL << 50) & ~PCREL_MASK) | OP_MASK)
>  
> +/* An 8-byte D form prefix instruction with 32bit SI field.  */
> +#define P_D_SI32_MASK (((-1ULL << 48) & ~PCREL_MASK) | OP_MASK)
> +
>  /* The same as P_D_MASK, but with the RA and PCREL fields specified.  */
>  #define P_DRAPCREL_MASK (P_D_MASK | PCREL_MASK | RA_MASK)
>  
> +/* The same as P_D_MASK, but with the RA and PCREL fields specified.  */
> +#define P_DRAPCREL_SI32_MASK (P_D_SI32_MASK | PCREL_MASK | RA_MASK)

Does this define's comment perhaps mean to reference P_D_SI32_MASK?

Jan
  
Peter Bergner March 6, 2025, 4:08 p.m. UTC | #2
On 3/6/25 7:25 AM, Jan Beulich wrote:
> On 05.03.2025 18:24, Surya Kumari Jangala wrote:
>> PowerPC: Support for Prefixed Add Immediate Shifted Instruction (RFC02686)
> 
> Is there any (public) reference to the rfc you could add? From just the patch
> I can't deduce what is being shifted here in which way.

So they're available thru the OpenPower foundation, but IIRC, only to members,
so not available (yet) to the public.  Sorry.




>> +/* The same as P_D_MASK, but with the RA and PCREL fields specified.  */
>> +#define P_DRAPCREL_SI32_MASK (P_D_SI32_MASK | PCREL_MASK | RA_MASK)
> 
> Does this define's comment perhaps mean to reference P_D_SI32_MASK?

Agreed.

Peter
  
Jan Beulich March 11, 2025, 7:43 a.m. UTC | #3
On 05.03.2025 18:24, Surya Kumari Jangala wrote:
> @@ -9863,6 +9925,11 @@ const struct powerpc_opcode prefix_opcodes[] = {
>  {"pla",		  PMLS|OP(14),	       P_D_MASK,	POWER10, EXT,	{RT, D34, PRA0, PCREL1}},
>  {"paddi",	  PMLS|OP(14),	       P_D_MASK,	POWER10, 0,	{RT, RA0, SI34, PCREL}},
>  {"psubi",	  PMLS|OP(14),	       P_D_MASK,	POWER10, EXT,	{RT, RA0, NSI34, PCREL}},
> +
> +{"plis",	  PMLS|OP(15),	       P_DRAPCREL_SI32_MASK,	FUTURE,  EXT,	{RT, SI32}},
> +{"paddis",	  PMLS|OP(15),	       P_D_SI32_MASK,		FUTURE,  0,	{RT, RA0, SI32, PCREL}},
> +{"psubis",	  PMLS|OP(15),	       P_D_SI32_MASK,		FUTURE,  EXT,	{RT, RA0, NSI32, PCREL}},

Since, unlike for e.g. PADDI, these are 32-bit fields, and these are shifted
immediates, don't we need one or more new relocation types to express these
immediate operands when they're not plain constants?

Jan
  
Surya Kumari Jangala March 12, 2025, 3:43 a.m. UTC | #4
Hi Jan,

On 06/03/25 6:55 pm, Jan Beulich wrote:
>> @@ -4031,9 +4087,15 @@ const unsigned int num_powerpc_operands = ARRAY_SIZE (powerpc_operands);
>>  /* An 8-byte D form prefix instruction.  */
>>  #define P_D_MASK (((-1ULL << 50) & ~PCREL_MASK) | OP_MASK)
>>  
>> +/* An 8-byte D form prefix instruction with 32bit SI field.  */
>> +#define P_D_SI32_MASK (((-1ULL << 48) & ~PCREL_MASK) | OP_MASK)
>> +
>>  /* The same as P_D_MASK, but with the RA and PCREL fields specified.  */
>>  #define P_DRAPCREL_MASK (P_D_MASK | PCREL_MASK | RA_MASK)
>>  
>> +/* The same as P_D_MASK, but with the RA and PCREL fields specified.  */
>> +#define P_DRAPCREL_SI32_MASK (P_D_SI32_MASK | PCREL_MASK | RA_MASK)
> 
> Does this define's comment perhaps mean to reference P_D_SI32_MASK?

Yes, the comment should refer to P_D_SI32_MASK. Thanks for catching it!

> 
> Jan
  
Peter Bergner March 13, 2025, 11:57 p.m. UTC | #5
On 3/11/25 2:43 AM, Jan Beulich wrote:
> On 05.03.2025 18:24, Surya Kumari Jangala wrote:
>> @@ -9863,6 +9925,11 @@ const struct powerpc_opcode prefix_opcodes[] = {
>>  {"pla",		  PMLS|OP(14),	       P_D_MASK,	POWER10, EXT,	{RT, D34, PRA0, PCREL1}},
>>  {"paddi",	  PMLS|OP(14),	       P_D_MASK,	POWER10, 0,	{RT, RA0, SI34, PCREL}},
>>  {"psubi",	  PMLS|OP(14),	       P_D_MASK,	POWER10, EXT,	{RT, RA0, NSI34, PCREL}},
>> +
>> +{"plis",	  PMLS|OP(15),	       P_DRAPCREL_SI32_MASK,	FUTURE,  EXT,	{RT, SI32}},
>> +{"paddis",	  PMLS|OP(15),	       P_D_SI32_MASK,		FUTURE,  0,	{RT, RA0, SI32, PCREL}},
>> +{"psubis",	  PMLS|OP(15),	       P_D_SI32_MASK,		FUTURE,  EXT,	{RT, RA0, NSI32, PCREL}},
> 
> Since, unlike for e.g. PADDI, these are 32-bit fields, and these are shifted
> immediates, don't we need one or more new relocation types to express these
> immediate operands when they're not plain constants?

Currently, our GCC patches don't emit paddis yet for -mcmodel=large, just for
constant generation at the moment, but yes, once we tackle that, we will need
some new linker relocations.  That will be a follow-on patch.

Peter
  

Patch

diff --git a/gas/testsuite/gas/ppc/future.d b/gas/testsuite/gas/ppc/future.d
index 76a30a50316..e825cb6127b 100644
--- a/gas/testsuite/gas/ppc/future.d
+++ b/gas/testsuite/gas/ppc/future.d
@@ -57,4 +57,27 @@  Disassembly of section \.text:
 .*:	(d0 1e 22 f0|f0 22 1e d0) 	xxgfmul128gcm vs1,vs2,vs3
 .*:	(d6 0f e0 f3|f3 e0 0f d6) 	xxgfmul128xts vs31,vs32,vs33
 .*:	(d6 0f e0 f3|f3 e0 0f d6) 	xxgfmul128xts vs31,vs32,vs33
+.*:	(06 00 00 00|00 00 00 06) 	paddis  r12,r9,15
+.*:	(3d 89 00 0f|0f 00 89 3d) 
+.*:	(06 00 ff ff|ff ff 00 06) 	paddis  r12,r9,-32769
+.*:	(3d 89 7f ff|ff 7f 89 3d) 
+.*:	(06 10 00 00|00 00 10 06) 	paddis  r9,0,25,1	# d4
+.*:	(3d 20 00 19|19 00 20 3d) 
+.*:	(06 00 7f ff|ff 7f 00 06) 	paddis  r24,0,2147483647
+.*:	(3f 00 ff ff|ff ff 00 3f) 
+.*:	(06 00 7f ff|ff 7f 00 06) 	paddis  r24,0,2147483647
+.*:	(3f 00 ff ff|ff ff 00 3f) 
+.*:	(06 00 80 00|00 80 00 06) 	paddis  r30,r10,-2147483648
+.*:	(3f ca 00 00|00 00 ca 3f) 
+.*:	(06 00 80 00|00 80 00 06) 	paddis  r30,r10,-2147483648
+.*:	(3f ca 00 00|00 00 ca 3f) 
+.*:	(60 00 00 00|00 00 00 60) 	nop
+.*:	(06 00 7f ff|ff 7f 00 06) 	paddis  r30,r10,2147483647
+.*:	(3f ca ff ff|ff ff ca 3f) 
+.*:	(06 00 7f ff|ff 7f 00 06) 	paddis  r30,r10,2147483647
+.*:	(3f ca ff ff|ff ff ca 3f) 
+.*:	(06 10 7f ff|ff 7f 10 06) 	paddis  r15,0,2147483647,1	# 110
+.*	(3d e0 ff ff|ff ff e0 3d) 
+.*:	(06 10 7f ff|ff 7f 10 06) 	paddis  r15,0,2147483647,1	# 118
+.*	(3d e0 ff ff|ff ff e0 3d) 
 #pass
diff --git a/gas/testsuite/gas/ppc/future.s b/gas/testsuite/gas/ppc/future.s
index fec99e348bf..90e5e894bc1 100644
--- a/gas/testsuite/gas/ppc/future.s
+++ b/gas/testsuite/gas/ppc/future.s
@@ -49,3 +49,16 @@  _start:
 	xxgfmul128gcm 1, 2, 3
 	xxgfmul128 31, 32, 33, 1
 	xxgfmul128xts 31, 32, 33
+	paddis 12, 9, 15, 0
+	paddis 12, 9, ~(1<<15), 0
+	paddis 9, 0, 25, 1
+	paddis 24, 0, 2147483647, 0
+	plis 24, 2147483647
+	paddis 30, 10, -2147483648, 0
+	psubis 30, 10, 2147483648, 0
+	nop
+	paddis 30, 10, 2147483647, 0
+	psubis 30, 10, -2147483647, 0
+	paddis 15, 0, 2147483647, 1
+	psubis 15, 0, -2147483647, 1
+
diff --git a/opcodes/ppc-opc.c b/opcodes/ppc-opc.c
index ba93e569891..0476fb5a052 100644
--- a/opcodes/ppc-opc.c
+++ b/opcodes/ppc-opc.c
@@ -691,6 +691,52 @@  extract_imm32 (uint64_t insn,
   return (insn & 0xffff) | ((insn >> 16) & 0xffff0000);
 }
 
+/* The 32bit SI field in a 64-bit D form prefix instruction when the field is split
+   into separate SI0 and SI1 fields.  */
+
+static uint64_t
+insert_si32 (uint64_t insn,
+	     int64_t value,
+	     ppc_cpu_t dialect ATTRIBUTE_UNUSED,
+	     const char **errmsg ATTRIBUTE_UNUSED)
+{
+  return insn | ((value & 0xffff0000ULL) << 16) | (value & 0xffff);
+}
+
+static int64_t
+extract_si32 (uint64_t insn,
+	      ppc_cpu_t dialect ATTRIBUTE_UNUSED,
+	      int *invalid ATTRIBUTE_UNUSED)
+{
+  int64_t mask = 1ULL << 31;
+  int64_t value = ((insn >> 16) & 0xffff0000ULL) | (insn & 0xffff);
+  value = (value ^ mask) - mask;
+  return value;
+}
+
+/* The NSI32 field in an 8-byte D form prefix instruction.  This is the same
+   as the SI32 field, only negated.  The extraction function always marks it
+   as invalid, since we never want to recognize an instruction which uses
+   a field of this type.  */
+static uint64_t
+insert_nsi32 (uint64_t insn,
+	      int64_t value,
+	      ppc_cpu_t dialect,
+	      const char **errmsg)
+{
+  return insert_si32 (insn, -value, dialect, errmsg);
+}
+
+static int64_t
+extract_nsi32 (uint64_t insn,
+	       ppc_cpu_t dialect,
+	       int *invalid)
+{
+  int64_t value = extract_si32 (insn, dialect, invalid);
+  *invalid = 1;
+  return -value;
+}
+
 /* The R field in an 8-byte prefix instruction when there are restrictions
    between R's value and the RA value (ie, they cannot both be non zero).  */
 
@@ -3073,8 +3119,18 @@  const struct powerpc_operand powerpc_operands[] =
   { UINT64_C(0x3ffffffff), PPC_OPSHIFT_INV, insert_nsi34, extract_nsi34,
     PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED },
 
+  /* The 32bit SI field in an 8-byte D form prefix instruction.  */
+#define SI32 NSI34 + 1
+  { UINT64_C(0xffffffff), PPC_OPSHIFT_INV, insert_si32, extract_si32, PPC_OPERAND_SIGNED },
+
+  /* The NSI field in an 8-byte D form prefix instruction with 32bit SI field.  This is
+     the same as the SI32 field, only negated.  */
+#define NSI32 SI32 + 1
+  { UINT64_C(0xffffffff), PPC_OPSHIFT_INV, insert_nsi32, extract_nsi32,
+    PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED },
+
   /* The IMM32 field in a vector splat immediate prefix instruction.  */
-#define IMM32 NSI34 + 1
+#define IMM32 NSI32 + 1
   { 0xffffffff, PPC_OPSHIFT_INV, insert_imm32, extract_imm32, 0},
 
   /* The UIM field in a vector permute extended prefix instruction.  */
@@ -4031,9 +4087,15 @@  const unsigned int num_powerpc_operands = ARRAY_SIZE (powerpc_operands);
 /* An 8-byte D form prefix instruction.  */
 #define P_D_MASK (((-1ULL << 50) & ~PCREL_MASK) | OP_MASK)
 
+/* An 8-byte D form prefix instruction with 32bit SI field.  */
+#define P_D_SI32_MASK (((-1ULL << 48) & ~PCREL_MASK) | OP_MASK)
+
 /* The same as P_D_MASK, but with the RA and PCREL fields specified.  */
 #define P_DRAPCREL_MASK (P_D_MASK | PCREL_MASK | RA_MASK)
 
+/* The same as P_D_MASK, but with the RA and PCREL fields specified.  */
+#define P_DRAPCREL_SI32_MASK (P_D_SI32_MASK | PCREL_MASK | RA_MASK)
+
 /* Mask for prefix X form instructions.  */
 #define P_X_MASK (PREFIX_MASK | X_MASK)
 #define P_XX1_MASK (PREFIX_MASK | XX1_MASK)
@@ -9863,6 +9925,11 @@  const struct powerpc_opcode prefix_opcodes[] = {
 {"pla",		  PMLS|OP(14),	       P_D_MASK,	POWER10, EXT,	{RT, D34, PRA0, PCREL1}},
 {"paddi",	  PMLS|OP(14),	       P_D_MASK,	POWER10, 0,	{RT, RA0, SI34, PCREL}},
 {"psubi",	  PMLS|OP(14),	       P_D_MASK,	POWER10, EXT,	{RT, RA0, NSI34, PCREL}},
+
+{"plis",	  PMLS|OP(15),	       P_DRAPCREL_SI32_MASK,	FUTURE,  EXT,	{RT, SI32}},
+{"paddis",	  PMLS|OP(15),	       P_D_SI32_MASK,		FUTURE,  0,	{RT, RA0, SI32, PCREL}},
+{"psubis",	  PMLS|OP(15),	       P_D_SI32_MASK,		FUTURE,  EXT,	{RT, RA0, NSI32, PCREL}},
+
 {"xxsplti32dx",	  P8RR|VSOP(32,0),     P_VSI_MASK,	POWER10, 0,	{XTS, IX, IMM32}},
 {"xxspltidp",	  P8RR|VSOP(32,2),     P_VS_MASK,	POWER10, 0,	{XTS, IMM32}},
 {"xxspltiw",	  P8RR|VSOP(32,3),     P_VS_MASK,	POWER10, 0,	{XTS, IMM32}},