[PATCH] powerpc: emulate power5 popcntb instruction

Subsystems: linux for powerpc (32-bit and 64-bit), the rest

STALE7280d

18 messages, 7 authors, 2006-08-30 · open the first message on its own page

[PATCH] powerpc: emulate power5 popcntb instruction

From: Will Schmidt <hidden>
Date: 2006-08-17 18:54:14

In an attempt to make it easier for a power5 optimized app to run on a 
power4 or a 970 or random earlier machine, this provides emulation of the popcntb 
instruction. 

tested on power4 and 970.  

Signed-off-by: Will Schmidt <redacted>

---
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 2105767..3e5ed30 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -588,6 +588,8 @@ #define INST_LSWX		0x7c00042a
 #define INST_STSWI		0x7c0005aa
 #define INST_STSWX		0x7c00052a
 
+#define INST_POPCNTB		0x7c0000f4
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
 	u8 rT = (instword >> 21) & 0x1f;
@@ -656,6 +658,26 @@ static int emulate_string_inst(struct pt
 	return 0;
 }
 
+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+	u32 ra,rs;
+	u32 countreg,tmp;
+	u32 x,y;
+
+	ra = (instword >> 16) & 0x1f;
+	rs = (instword >> 21) & 0x1f;
+	countreg = regs->gpr[rs];
+	regs->gpr[ra] = 0;
+
+	/* y=4 bytes, x=8 bits/byte */
+	for (y = 0; y < 4; y++) {
+		for (tmp = 0, x = 0; x < 8; x++)
+			if (countreg & (0x1 << (x + 8 * y))) tmp++;
+		regs->gpr[ra] += (tmp <<  8 * y );
+	}
+	return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
@@ -693,6 +715,11 @@ static int emulate_instruction(struct pt
 	if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
 		return emulate_string_inst(regs, instword);
 
+	/* Emulate the popcntb (Population Count Bytes) instruction. */
+	if ((instword & INST_POPCNTB) == INST_POPCNTB) {
+		return emulate_popcntb_inst(regs, instword);
+	}
+
 	return -EINVAL;
 }
 

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Segher Boessenkool <hidden>
Date: 2006-08-17 19:24:57

+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+	u32 ra,rs;
+	u32 countreg,tmp;
+	u32 x,y;
+
+	ra = (instword >> 16) & 0x1f;
+	rs = (instword >> 21) & 0x1f;
+	countreg = regs->gpr[rs];
+	regs->gpr[ra] = 0;
+
+	/* y=4 bytes, x=8 bits/byte */
+	for (y = 0; y < 4; y++) {
+		for (tmp = 0, x = 0; x < 8; x++)
+			if (countreg & (0x1 << (x + 8 * y))) tmp++;
+		regs->gpr[ra] += (tmp <<  8 * y );
+	}
+	return 0;
+}
x in, x out:

	x -= (x >> 1) & 0x5555555555555555;
	x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
	x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;

(Your code only runs on 4 bytes; shouldn't it be 8?)


Segher

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Will Schmidt <hidden>
Date: 2006-08-18 18:11:53

In an attempt to make it easier for a power5 optimized app to run on a 
power4 or a 970 or random earlier machine, this provides emulation of
the popcntb instruction.    Rewritten to use a slicker algorithm as
suggested by Segher.   I left a 'tmp' variable in play, as it seemed
cleaner to use tmp than referring to regs->gpr[rs] and [ra] multiple
times within the magic algorithm.  

Also tested on power4 with both 32 and 64 userspace this time.
*blush*.  :-) 


Signed-off-by: Will Schmidt <redacted>

---
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 2105767..a0e80dd 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -588,6 +588,8 @@ #define INST_LSWX		0x7c00042a
 #define INST_STSWI		0x7c0005aa
 #define INST_STSWX		0x7c00052a
 
+#define INST_POPCNTB		0x7c0000f4
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
 	u8 rT = (instword >> 21) & 0x1f;
@@ -656,6 +658,23 @@ static int emulate_string_inst(struct pt
 	return 0;
 }
 
+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+	u32 ra,rs;
+	unsigned long tmp;
+
+	ra = (instword >> 16) & 0x1f;
+	rs = (instword >> 21) & 0x1f;
+
+	tmp = regs->gpr[rs];
+	tmp = tmp - ((tmp >> 1) & 0x5555555555555555);
+	tmp = (tmp & 0x3333333333333333) + ((tmp >> 2) & 0x3333333333333333);
+	tmp = (tmp + (tmp >> 4)) & 0x0f0f0f0f0f0f0f0f;
+	regs->gpr[ra] = tmp;
+
+	return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
@@ -693,6 +712,11 @@ static int emulate_instruction(struct pt
 	if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
 		return emulate_string_inst(regs, instword);
 
+	/* Emulate the popcntb (Population Count Bytes) instruction. */
+	if ((instword & INST_POPCNTB) == INST_POPCNTB) {
+		return emulate_popcntb_inst(regs, instword);
+	}
+
 	return -EINVAL;
 }
 

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Arnd Bergmann <arnd@arndb.de>
Date: 2006-08-18 19:05:55

On Friday 18 August 2006 20:11, Will Schmidt wrote:
+#define INST_POPCNTB           0x7c0000f4
+
+=A0=A0=A0=A0=A0=A0=A0/* Emulate the popcntb (Population Count Bytes) ins=
truction. */
+=A0=A0=A0=A0=A0=A0=A0if ((instword & INST_POPCNTB) =3D=3D INST_POPCNTB) {
+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return emulate_popcntb_inst=
(regs, instword);
+=A0=A0=A0=A0=A0=A0=A0}
+
Is that the right check? The other similar traps check against a
mask of 0x7c0007fe.

	Arnd <><

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Kumar Gala <hidden>
Date: 2006-08-18 19:30:09

On Aug 18, 2006, at 2:05 PM, Arnd Bergmann wrote:
On Friday 18 August 2006 20:11, Will Schmidt wrote:
quoted
+#define INST_POPCNTB           0x7c0000f4
+
quoted
+       /* Emulate the popcntb (Population Count Bytes)  
instruction. */
+       if ((instword & INST_POPCNTB) == INST_POPCNTB) {
+               return emulate_popcntb_inst(regs, instword);
+       }
+
Is that the right check? The other similar traps check against a
mask of 0x7c0007fe.
I agree with Arnd here, its better to check with a larger mask to  
ensure that bits that should be '0' in the minor opcode are.

For example, if you had an instruction that was 0x7c0000f7 it would  
match.

- kumar

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Kumar Gala <hidden>
Date: 2006-08-18 19:42:19

+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+	u32 ra,rs;
+	unsigned long tmp;
+
+	ra = (instword >> 16) & 0x1f;
+	rs = (instword >> 21) & 0x1f;
+
+	tmp = regs->gpr[rs];
+	tmp = tmp - ((tmp >> 1) & 0x5555555555555555);
+	tmp = (tmp & 0x3333333333333333) + ((tmp >> 2) &  
0x3333333333333333);
+	tmp = (tmp + (tmp >> 4)) & 0x0f0f0f0f0f0f0f0f;
+	regs->gpr[ra] = tmp;
+
+	return 0;
+}
This is going to give warnings on ppc32 kernel compiles, maybe  
something like:

(unsigned long) 0x5555555555555555ull

- kumar

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: <hidden>
Date: 2006-08-19 18:56:46

quoted
+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+	u32 ra,rs;
+	unsigned long tmp;
+
+	ra = (instword >> 16) & 0x1f;
+	rs = (instword >> 21) & 0x1f;
+
+	tmp = regs->gpr[rs];
+	tmp = tmp - ((tmp >> 1) & 0x5555555555555555);
+	tmp = (tmp & 0x3333333333333333) + ((tmp >> 2) &
0x3333333333333333);
+	tmp = (tmp + (tmp >> 4)) & 0x0f0f0f0f0f0f0f0f;
+	regs->gpr[ra] = tmp;
+
+	return 0;
+}
This is going to give warnings on ppc32 kernel compiles, maybe
something like:

(unsigned long) 0x5555555555555555ull
Nah, just make "tmp" an u64.  And/or don't do this emulation on
32-bit machines at all.

And if the compiler warns about the non-qualified constants --
well, we should compile with -std=gnu99 anyway, eh?


Segher

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: <hidden>
Date: 2006-08-19 18:57:59

quoted
+#define INST_POPCNTB           0x7c0000f4
+
quoted
+       /* Emulate the popcntb (Population Count Bytes) instruction.
*/ +       if ((instword & INST_POPCNTB) == INST_POPCNTB) {
+               return emulate_popcntb_inst(regs, instword);
+       }
+
Is that the right check? The other similar traps check against a
mask of 0x7c0007fe.
I hope you mean 0xfc0007fe?


Segher

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Arnd Bergmann <arnd@arndb.de>
Date: 2006-08-19 20:19:14

T24gU2F0dXJkYXkgMTkgQXVndXN0IDIwMDYgMjE6MTAsIHNlZ2hlckBnYXRlLmNyYXNoaW5nLm9y
ZyB3cm90ZToKPiA+IElzIHRoYXQgdGhlIHJpZ2h0IGNoZWNrPyBUaGUgb3RoZXIgc2ltaWxhciB0
cmFwcyBjaGVjayBhZ2FpbnN0IGEKPiA+IG1hc2sgb2YgMHg3YzAwMDdmZS4KPiAKPiBJIGhvcGUg
eW91IG1lYW4gMHhmYzAwMDdmZT8KPiAKCk5vLCB0aGUgY29kZSBpbiBxdWVzdGlvbiBpcyAKCiNk
ZWZpbmUgSU5TVF9NRlNQUl9QVlKtt623t7e3t7e3MHg3YzFmNDJhNgojZGVmaW5lIElOU1RfTUZT
UFJfUFZSX01BU0utt7e3tzB4ZmMxZmZmZmYKCiNkZWZpbmUgSU5TVF9EQ0JBrbe3t7e3t623t7e3
t7e3MHg3YzAwMDVlYwojZGVmaW5lIElOU1RfRENCQV9NQVNLrbett7e3t7e3tzB4N2MwMDA3ZmUK
CiNkZWZpbmUgSU5TVF9NQ1JYUq23t7e3t623t7e3t7e3MHg3YzAwMDQwMAojZGVmaW5lIElOU1Rf
TUNSWFJfTUFTS62tt7e3t7e3tzB4N2MwMDA3ZmUKCiNkZWZpbmUgSU5TVF9TVFJJTkett7e3t623
t7e3t7e3MHg3YzAwMDQyYQojZGVmaW5lIElOU1RfU1RSSU5HX01BU0utt7e3t7e3tzB4N2MwMDA3
ZmUKI2RlZmluZSBJTlNUX1NUUklOR19HRU5fTUFTS623t7cweDdjMDAwNjdlCiNkZWZpbmUgSU5T
VF9MU1dJrbe3t7e3t623t7e3t7e3MHg3YzAwMDRhYQojZGVmaW5lIElOU1RfTFNXWK23t7e3t7et
t7e3t7e3tzB4N2MwMDA0MmEKI2RlZmluZSBJTlNUX1NUU1dJrbe3t7e3rbe3t7e3t7cweDdjMDAw
NWFhCiNkZWZpbmUgSU5TVF9TVFNXWK23t7e3t623t7e3t7e3MHg3YzAwMDUyYQoKV2hhdCBkb2Vz
IHRoZSBNU0IgZG8gaW4gb3VyIGluc3RydWN0aW9ucz8KCglBcm5kIDw+PAo=

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: <hidden>
Date: 2006-08-19 23:20:42

quoted
quoted
Is that the right check? The other similar traps check against a
mask of 0x7c0007fe.

I hope you mean 0xfc0007fe?
No, the code in question is

#define INST_MFSPR_PVR­·­·······0x7c1f42a6
#define INST_MFSPR_PVR_MASK­····0xfc1fffff

#define INST_DCBA­······­·······0x7c0005ec
#define INST_DCBA_MASK­·­·······0x7c0007fe

#define INST_MCRXR­·····­·······0x7c000400
#define INST_MCRXR_MASK­­·······0x7c0007fe

#define INST_STRING­····­·······0x7c00042a
#define INST_STRING_MASK­·······0x7c0007fe
#define INST_STRING_GEN_MASK­···0x7c00067e
#define INST_LSWI­······­·······0x7c0004aa
#define INST_LSWX­······­·······0x7c00042a
#define INST_STSWI­·····­·······0x7c0005aa
#define INST_STSWX­·····­·······0x7c00052a

What does the MSB do in our instructions?
Bits 0..5 are the primary opcode, for all insns;
bits 21..30 are the secondary opcode, for insns that
have one (all in primary opcode 31 do).

So we have a bug here; could you take care of it please
Arnd?


Segher

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Will Schmidt <hidden>
Date: 2006-08-21 20:10:04

On Sat, 2006-19-08 at 18:32 -0500, segher@gate.crashing.org wrote:
quoted
quoted
quoted
Is that the right check? The other similar traps check against a
mask of 0x7c0007fe.
So we have a bug here; could you take care of it please
Arnd?
I'm not Arnd :-) , but since I'm poking at it anyways,.. how about
this? 



In an attempt to make it easier for a power5 optimized app to run on a 
power4 or a 970 or random earlier machine, this provides emulation of
the popcntb instruction.
This version incorporates the suggestions from Arnd, Kumar and Segher;
including using a better MASK for popcntb, updating the existing masks
to include the msb for the instruction primary opcode. 

Signed-off-by: Will Schmidt <redacted>

diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 2105767..caba187 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -575,19 +575,22 @@ #define INST_MFSPR_PVR		0x7c1f42a6
 #define INST_MFSPR_PVR_MASK	0xfc1fffff
 
 #define INST_DCBA		0x7c0005ec
-#define INST_DCBA_MASK		0x7c0007fe
+#define INST_DCBA_MASK		0xfc0007fe
 
 #define INST_MCRXR		0x7c000400
-#define INST_MCRXR_MASK		0x7c0007fe
+#define INST_MCRXR_MASK		0xfc0007fe
 
 #define INST_STRING		0x7c00042a
-#define INST_STRING_MASK	0x7c0007fe
-#define INST_STRING_GEN_MASK	0x7c00067e
+#define INST_STRING_MASK	0xfc0007fe
+#define INST_STRING_GEN_MASK	0xfc00067e
 #define INST_LSWI		0x7c0004aa
 #define INST_LSWX		0x7c00042a
 #define INST_STSWI		0x7c0005aa
 #define INST_STSWX		0x7c00052a
 
+#define INST_POPCNTB		0x7c0000f4
+#define INST_POPCNTB_MASK	0xfc0007fe
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
 	u8 rT = (instword >> 21) & 0x1f;
@@ -656,6 +659,23 @@ static int emulate_string_inst(struct pt
 	return 0;
 }
 
+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+	u32 ra,rs;
+	u64 tmp;
+
+	ra = (instword >> 16) & 0x1f;
+	rs = (instword >> 21) & 0x1f;
+
+	tmp = regs->gpr[rs];
+	tmp = tmp - ((tmp >> 1) & 0x5555555555555555);
+	tmp = (tmp & 0x3333333333333333) + ((tmp >> 2) & 0x3333333333333333);
+	tmp = (tmp + (tmp >> 4)) & 0x0f0f0f0f0f0f0f0f;
+	regs->gpr[ra] = tmp;
+
+	return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
@@ -693,6 +713,11 @@ static int emulate_instruction(struct pt
 	if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
 		return emulate_string_inst(regs, instword);
 
+	/* Emulate the popcntb (Population Count Bytes) instruction. */
+	if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) {
+		return emulate_popcntb_inst(regs, instword);
+	}
+
 	return -EINVAL;
 }
 

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Paul Mackerras <hidden>
Date: 2006-08-24 06:36:07

Will Schmidt writes:
I'm not Arnd :-) , but since I'm poking at it anyways,.. how about
this? 
I just did a patch to fix the existing masks.  Could you do a new
version of this patch that doesn't include the unrelated mask fixes
please?  Also it would be really nice if you could figure out a way to
avoid doing the unnecessary 64-bit logical operations on 32-bit
machines - i.e. using an unsigned long for tmp, but then the constants
become problematic.  Maybe you need something like

#define LCONST(x)	((unsigned long)(x##ULL))

Thanks,
Paul.

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Segher Boessenkool <hidden>
Date: 2006-08-24 15:54:10

Also it would be really nice if you could figure out a way to
avoid doing the unnecessary 64-bit logical operations on 32-bit
machines
Like I asked before -- should we run this emulation on 32-bit
machines at all?  The instruction only exists in the 64-bit
architecture after all.


Segher

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Gabriel Paubert <hidden>
Date: 2006-08-25 09:59:53

On Thu, Aug 24, 2006 at 05:53:56PM +0200, Segher Boessenkool wrote:
quoted
Also it would be really nice if you could figure out a way to
avoid doing the unnecessary 64-bit logical operations on 32-bit
machines
Like I asked before -- should we run this emulation on 32-bit
machines at all?  The instruction only exists in the 64-bit
architecture after all.
It's useless for now, but I would not be surprised if someone 
creates a new 32 bit processor which includes this instruction.

	Gabriel

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Paul Mackerras <hidden>
Date: 2006-08-25 12:57:28

Segher Boessenkool writes:
Like I asked before -- should we run this emulation on 32-bit
machines at all?  The instruction only exists in the 64-bit
architecture after all.
It could be argued either way, but on the whole I would prefer to
minimize the number of things which could cause a 32-bit program that
runs quite happily on a 64-bit CPU to fail on a 32-bit CPU...

Paul.

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Willschm <hidden>
Date: 2006-08-28 18:03:54

On Thu, 2006-24-08 at 16:36 +1000, Paul Mackerras wrote:
Will Schmidt writes:

I just did a patch to fix the existing masks.  Could you do a new
version of this patch that doesn't include the unrelated mask fixes
please?  Also it would be really nice if you could figure out a way to
avoid doing the unnecessary 64-bit logical operations on 32-bit
machines - i.e. using an unsigned long for tmp, but then the constants
become problematic.  Maybe you need something like

#define LCONST(x)	((unsigned long)(x##ULL))
Ok, how about this..

In an attempt to make it easier for a power5 optimized app to run on a 
power4 or a 970 or random earlier machine, this provides emulation of
the popcntb instruction.

Signed-off-by: Will Schmidt <redacted>

---
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 2105767..f85a3af 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -588,6 +588,9 @@ #define INST_LSWX		0x7c00042a
 #define INST_STSWI		0x7c0005aa
 #define INST_STSWX		0x7c00052a
 
+#define INST_POPCNTB		0x7c0000f4
+#define INST_POPCNTB_MASK	0xfc0007fe
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
 	u8 rT = (instword >> 21) & 0x1f;
@@ -656,6 +659,25 @@ static int emulate_string_inst(struct pt
 	return 0;
 }
 
+#define LCONST(x)	((unsigned long)(x##ULL))
+
+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+	u32 ra,rs;
+	u64 tmp;
+
+	ra = (instword >> 16) & 0x1f;
+	rs = (instword >> 21) & 0x1f;
+
+	tmp = regs->gpr[rs];
+	tmp = tmp - ((tmp >> 1) & LCONST(0x5555555555555555));
+	tmp = (tmp & LCONST(0x3333333333333333)) + ((tmp >> 2) & LCONST(0x3333333333333333));
+	tmp = (tmp + (tmp >> 4)) & LCONST(0x0f0f0f0f0f0f0f0f);
+	regs->gpr[ra] = tmp;
+
+	return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
@@ -693,6 +715,11 @@ static int emulate_instruction(struct pt
 	if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
 		return emulate_string_inst(regs, instword);
 
+	/* Emulate the popcntb (Population Count Bytes) instruction. */
+	if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) {
+		return emulate_popcntb_inst(regs, instword);
+	}
+
 	return -EINVAL;
 }
 

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Segher Boessenkool <hidden>
Date: 2006-08-29 06:43:49

quoted
I just did a patch to fix the existing masks.
Thanks Paul.
quoted
Could you do a new
version of this patch that doesn't include the unrelated mask fixes
please?  Also it would be really nice if you could figure out a  
way to
avoid doing the unnecessary 64-bit logical operations on 32-bit
machines - i.e. using an unsigned long for tmp, but then the  
constants
become problematic.  Maybe you need something like

#define LCONST(x)	((unsigned long)(x##ULL))
Ok, how about this..
Hrm.  The LCONST() thing is butt ugly though; you can just write
0x3333333333333333ULL etc. and GCC will do the right thing (i.e.
efficient code), and not warn (don't need the "ULL" even when in
C99/gnu99 mode, as we should be but aren't, heh).

You want to make tmp and unsigned long instead of an u64...


Segher

Re: [PATCH] powerpc: emulate power5 popcntb instruction

From: Will Schmidt <hidden>
Date: 2006-08-30 18:11:51

On Tue, 2006-29-08 at 08:43 +0200, Segher Boessenkool wrote:
quoted
quoted
I just did a patch to fix the existing masks.
Thanks Paul.
quoted
quoted
Could you do a new
version of this patch that doesn't include the unrelated mask fixes
please?  Also it would be really nice if you could figure out a  
way to
avoid doing the unnecessary 64-bit logical operations on 32-bit
machines - i.e. using an unsigned long for tmp, but then the  
constants
become problematic.  Maybe you need something like

#define LCONST(x)	((unsigned long)(x##ULL))
Ok, how about this..
Hrm.  The LCONST() thing is butt ugly though; you can just write
0x3333333333333333ULL etc. and GCC will do the right thing (i.e.
efficient code), and not warn (don't need the "ULL" even when in
C99/gnu99 mode, as we should be but aren't, heh).

You want to make tmp and unsigned long instead of an u64...
Ok, so back to unsigned-long to let the 32-bit stuff be happy..

Now a bit of a tangent question:  As far as just 64-bit is concerned, is
there actually any difference between u64 and unsigned long?   Am
wondering why you suggested that change to u64 from unsigned long
earlier in the thread.


this version looks to build clean with arch=ppc (32-bit). 

This provides emulation of the power5 instruction popcntb.

Signed-off-by: Will Schmidt <redacted>


---
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 2105767..4014d71 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -588,6 +588,9 @@ #define INST_LSWX		0x7c00042a
 #define INST_STSWI		0x7c0005aa
 #define INST_STSWX		0x7c00052a
 
+#define INST_POPCNTB		0x7c0000f4
+#define INST_POPCNTB_MASK	0xfc0007fe
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
 	u8 rT = (instword >> 21) & 0x1f;
@@ -656,6 +659,23 @@ static int emulate_string_inst(struct pt
 	return 0;
 }
 
+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+	u32 ra,rs;
+	unsigned long tmp;
+
+	ra = (instword >> 16) & 0x1f;
+	rs = (instword >> 21) & 0x1f;
+
+	tmp = regs->gpr[rs];
+	tmp = tmp - ((tmp >> 1) & 0x5555555555555555ULL);
+	tmp = (tmp & 0x3333333333333333ULL) + ((tmp >> 2) & 0x3333333333333333ULL);
+	tmp = (tmp + (tmp >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
+	regs->gpr[ra] = tmp;
+
+	return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
@@ -693,6 +713,11 @@ static int emulate_instruction(struct pt
 	if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
 		return emulate_string_inst(regs, instword);
 
+	/* Emulate the popcntb (Population Count Bytes) instruction. */
+	if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) {
+		return emulate_popcntb_inst(regs, instword);
+	}
+
 	return -EINVAL;
 }
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help