powerpc/lib/sstep: Add cmpb instruction emulation
PATCH v4 1/5 powerpc/lib/sstep: Add cmpb instruction emulation
This patch adds emulation of the cmpb instruction, enabling xmon to emulate this instruction.
Tested for correctness against the cmpb asm instruction on ppc64le.
---
v2:
- fixed opcode
- fixed mask typecasting
--- arch/powerpc/lib/sstep.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
arch/powerpc/lib/sstep.c +20 -0
@@ -596,6 +596,22 @@ static nokprobe_inline void do_cmp_unsigned(struct pt_regs *regs, unsigned long regs->ccr = (regs->ccr & ~(0xf << shift)) | (crval << shift); } +static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1, +unsigned long v2,int rd) +{ +unsigned long long out_val, mask; +int i; + + out_val =0 ; +for (i =0 ; i <8 ; i++) { + mask =0xffUL << (i *8 ); +if ((v1 & mask) == (v2 & mask)) + out_val |= mask; + } + + regs->gpr[rd] = out_val; +} + static nokprobe_inline int trap_compare(long v1, long v2) {int ret =0 ;
@@ -1049,6 +1065,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,do_cmp_unsigned (regs, val, val2, rd >>2 ); goto instr_done; +case 508 :/* cmpb */ +do_cmpb (regs, regs->gpr[rd], regs->gpr[rb], ra); + goto instr_done; +/* * Arithmetic instructions */
Signature · 1 line
2.9.3
PATCH v4 2/5 powerpc/lib/sstep: Add popcnt instruction emulation
This adds emulations for the popcntb, popcntw, and popcntd instructions. Tested for correctness against the popcnt{b,w,d} instructions on ppc64le.
---
v4:
- change ifdef macro from __powerpc64__ to CONFIG_PPC64
- slight optimisations
(now identical to the popcntb implementation in kernel/traps.c)
v3:
- optimised using the Giles-Miller method of side-ways addition
v2:
- fixed opcodes
- fixed typecasting
- fixed bitshifting error for both 32 and 64bit arch
--- arch/powerpc/lib/sstep.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-)
arch/powerpc/lib/sstep.c +41 -1
@@ -612,6 +612,34 @@ static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1, regs->gpr[rd] = out_val; } +/* +* The size parameter is used to adjust the equivalent popcnt instruction. +* popcntb = 8, popcntw = 32, popcntd = 64 +*/ +static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1, +int size,int ra) +{ +unsigned long long out = v1; + + out -= (out >>1 ) &0x5555555555555555 ; + out = (0x3333333333333333 & out) + (0x3333333333333333 & (out >>2 )); + out = (out + (out >>4 )) &0x0f0f0f0f0f0f0f0f ; + +if (size ==8 ) {/* popcntb */ + regs->gpr[ra] = out; +return ; + } + out += out >>8 ; + out += out >>16 ; +if (size ==32 ) {/* popcntw */ + regs->gpr[ra] = out &0x0000003f0000003f ; +return ; + } + + out = (out + (out >>32 )) &0x7f ; + regs->gpr[ra] = out;/* popcntd */ +} + static nokprobe_inline int trap_compare(long v1, long v2) {int ret =0 ;
@@ -1194,6 +1222,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, regs->gpr[ra] = regs->gpr[rd] & ~regs->gpr[rb]; goto logical_done; +case 122 :/* popcntb */ +do_popcnt (regs, regs->gpr[rd],8 , ra); + goto logical_done; +case 124 :/* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done;
@@ -1206,6 +1238,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, regs->gpr[ra] = regs->gpr[rd] ^ regs->gpr[rb]; goto logical_done; +case 378 :/* popcntw */ +do_popcnt (regs, regs->gpr[rd],32 , ra); + goto logical_done; +case 412 :/* orc */ regs->gpr[ra] = regs->gpr[rd] | ~regs->gpr[rb]; goto logical_done;
@@ -1217,7 +1253,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,case 476 :/* nand */ regs->gpr[ra] = ~(regs->gpr[rd] & regs->gpr[rb]); goto logical_done; - +#ifdef CONFIG_PPC64 +case 506 :/* popcntd */ +do_popcnt (regs, regs->gpr[rd],64 , ra); + goto logical_done; +#endif case 922 :/* extsh */ regs->gpr[ra] = (signed short ) regs->gpr[rd]; goto logical_done;
Signature · 1 line
2.9.3
PATCH v4 3/5 powerpc/lib/sstep: Add bpermd instruction emulation
In reply to Matt BrownThis adds emulation for the bpermd instruction.
Tested for correctness against the bpermd instruction on ppc64le.
---
v4:
- change ifdef macro from __powerpc64__ to CONFIG_PPC64
v2:
- fixed opcode
- added ifdef tags to do_bpermd func
- fixed bitshifting errors
--- arch/powerpc/lib/sstep.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
arch/powerpc/lib/sstep.c +23 -1
@@ -640,6 +640,24 @@ static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1, regs->gpr[ra] = out;/* popcntd */ } +#ifdef CONFIG_PPC64 +static nokprobe_inline void do_bpermd(struct pt_regs *regs, unsigned long v1, +unsigned long v2,int ra) +{ +unsigned char perm, idx; +unsigned int i; + + perm =0 ; +for (i =0 ; i <8 ; i++) { + idx = (v1 >> (i *8 )) &0xff ; +if (idx <64 ) +if (v2 &PPC_BIT (idx)) + perm |=1 << i; + } + regs->gpr[ra] = perm; +} +#endif /* CONFIG_PPC64 */ + static nokprobe_inline int trap_compare(long v1, long v2) {int ret =0 ;
@@ -1229,7 +1247,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,case 124 :/* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done; - +#ifdef CONFIG_PPC64 +case 252 :/* bpermd */ +do_bpermd (regs, regs->gpr[rd], regs->gpr[rb], ra); + goto logical_done; +#endif case 284 :/* xor */ regs->gpr[ra] = ~(regs->gpr[rd] ^ regs->gpr[rb]); goto logical_done;
Signature · 1 line
2.9.3
PATCH v4 4/5 powerpc/lib/sstep: Add prty instruction emulation
In reply to Matt BrownThis adds emulation for the prtyw and prtyd instructions. Tested for logical correctness against the prtyw and prtyd instructions on ppc64le.
---
v4:
- use simpler xor method
v3:
- optimised using the Giles-Miller method of side-ways addition
v2:
- fixed opcodes
- fixed bitshifting and typecast errors
- merged do_prtyw and do_prtyd into single function
--- arch/powerpc/lib/sstep.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
arch/powerpc/lib/sstep.c +26 -0
@@ -657,6 +657,24 @@ static nokprobe_inline void do_bpermd(struct pt_regs *regs, unsigned long v1, regs->gpr[ra] = perm; }#endif /* CONFIG_PPC64 */ +/* +* The size parameter adjusts the equivalent prty instruction. +* prtyw = 32, prtyd = 64 +*/ +static nokprobe_inline void do_prty(struct pt_regs *regs, unsigned long v, +int size,int ra) +{ +unsigned long long res = v ^ (v >>8 ); + + res ^= res >>16 ; +if (size ==32 ) {/* prtyw */ + regs->gpr[ra] = res &0x0000000100000001 ; +return ; + } + + res ^= res >>32 ; + regs->gpr[ra] = res &1 ;/*prtyd */ +} static nokprobe_inline int trap_compare(long v1, long v2) {
@@ -1247,6 +1265,14 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,case 124 :/* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done; + +case 154 :/* prtyw */ +do_prty (regs, regs->gpr[rd],32 , ra); + goto logical_done; + +case 186 :/* prtyd */ +do_prty (regs, regs->gpr[rd],64 , ra); + goto logical_done;#ifdef CONFIG_PPC64 case 252 :/* bpermd */ do_bpermd (regs, regs->gpr[rd], regs->gpr[rb], ra);
Signature · 1 line
2.9.3
PATCH v4 5/5 powerpc/lib/sstep: Add isel instruction emulation
In reply to Matt BrownThis adds emulation for the isel instruction.
Tested for correctness against the isel instruction and its extended mnemonics (lt, gt, eq) on ppc64le.
---
v4:
- simplify if statement to ternary op
(same as isel emulation in kernel/traps.c)
v2:
- fixed opcode
- fixed definition to include the 'if RA=0, a=0' clause
- fixed ccr bitshifting error
--- arch/powerpc/lib/sstep.c | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/powerpc/lib/sstep.c +8 -0
@@ -1240,6 +1240,14 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,/* * Logical instructions */ +case 15 :/* isel */ + mb = (instr >>6 ) &0x1f ;/* bc */ + val = (regs->ccr >> (31 - mb)) &1 ; + val2 = (ra) ? regs->gpr[ra] :0 ; + + regs->gpr[rd] = (val) ? val2 : regs->gpr[rb]; + goto logical_done; +case 26 :/* cntlzw */ asm("cntlzw %0,%1" :"=r" (regs->gpr[ra]) :"r" (regs->gpr[rd]));
Signature · 1 line
2.9.3
Quoted 5 lines · Matt Brown
This patch adds emulation of the cmpb instruction, enabling xmon to emulate this instruction.
Tested for correctness against the cmpb asm instruction on ppc64le.Signed-off-by Matt Brown <[email protected]>
Quoted 46 lines
---
v2:
- fixed opcode
- fixed mask typecasting--- arch/powerpc/lib/sstep.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)arch/powerpc/lib/sstep.c +20
-0@@ -596,6 +596,22 @@ static nokprobe_inline void do_cmp_unsigned(struct pt_regs *regs, unsigned long regs->ccr = (regs->ccr & ~(0xf << shift)) | (crval << shift); } +static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1, +unsigned long v2,int rd) +{ +unsigned long long out_val, mask; +int i; + + out_val =0 ; +for (i =0 ; i <8 ; i++) { + mask =0xffUL << (i *8 ); +if ((v1 & mask) == (v2 & mask)) + out_val |= mask; + } + + regs->gpr[rd] = out_val; +} + static nokprobe_inline int trap_compare(long v1, long v2) {int ret =0 ;@@ -1049,6 +1065,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,do_cmp_unsigned (regs, val, val2, rd >>2 ); goto instr_done; +case 508 :/* cmpb */ +do_cmpb (regs, regs->gpr[rd], regs->gpr[rb], ra); + goto instr_done; +/* * Arithmetic instructions */
Re: [PATCH v4 3/5] powerpc/lib/sstep: Add bpermd instruction emulation
In reply to Matt BrownQuoted 4 lines · Matt Brown
This adds emulation for the bpermd instruction.
Tested for correctness against the bpermd instruction on ppc64le.Signed-off-by Matt Brown <[email protected]>
Quoted 53 lines
---
v4:
- change ifdef macro from__powerpc64__toCONFIG_PPC64
v2:
- fixed opcode
- added ifdef tags todo_bpermdfunc
- fixed bitshifting errors--- arch/powerpc/lib/sstep.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)arch/powerpc/lib/sstep.c +23
-1@@ -640,6 +640,24 @@ static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1, regs->gpr[ra] = out;/* popcntd */ } +#ifdef CONFIG_PPC64 +static nokprobe_inline void do_bpermd(struct pt_regs *regs, unsigned long v1, +unsigned long v2,int ra) +{ +unsigned char perm, idx; +unsigned int i; + + perm =0 ; +for (i =0 ; i <8 ; i++) { + idx = (v1 >> (i *8 )) &0xff ; +if (idx <64 ) +if (v2 &PPC_BIT (idx)) + perm |=1 << i; + } + regs->gpr[ra] = perm; +} +#endif /* CONFIG_PPC64 */ + static nokprobe_inline int trap_compare(long v1, long v2) {int ret =0 ;@@ -1229,7 +1247,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,case 124 :/* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done; - +#ifdef CONFIG_PPC64 +case 252 :/* bpermd */ +do_bpermd (regs, regs->gpr[rd], regs->gpr[rb], ra); + goto logical_done; +#endif case 284 :/* xor */ regs->gpr[ra] = ~(regs->gpr[rd] ^ regs->gpr[rb]); goto logical_done;
Re: [PATCH v4 4/5] powerpc/lib/sstep: Add prty instruction emulation
In reply to Matt BrownQuoted 5 lines · Matt Brown
This adds emulation for the prtyw and prtyd instructions. Tested for logical correctness against the prtyw and prtyd instructions on ppc64le.
Signed-off-by Matt Brown <[email protected]>
Quoted 57 lines
---
v4:
- use simpler xor method
v3:
- optimised using the Giles-Miller method of side-ways addition
v2:
- fixed opcodes
- fixed bitshifting and typecast errors
- mergeddo_prtywanddo_prtydinto single function--- arch/powerpc/lib/sstep.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)arch/powerpc/lib/sstep.c +26
-0@@ -657,6 +657,24 @@ static nokprobe_inline void do_bpermd(struct pt_regs *regs, unsigned long v1, regs->gpr[ra] = perm; }#endif /* CONFIG_PPC64 */ +/* +* The size parameter adjusts the equivalent prty instruction. +* prtyw = 32, prtyd = 64 +*/ +static nokprobe_inline void do_prty(struct pt_regs *regs, unsigned long v, +int size,int ra) +{ +unsigned long long res = v ^ (v >>8 ); + + res ^= res >>16 ; +if (size ==32 ) {/* prtyw */ + regs->gpr[ra] = res &0x0000000100000001 ; +return ; + } + + res ^= res >>32 ; + regs->gpr[ra] = res &1 ;/*prtyd */ +} static nokprobe_inline int trap_compare(long v1, long v2) {@@ -1247,6 +1265,14 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,case 124 :/* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done; + +case 154 :/* prtyw */ +do_prty (regs, regs->gpr[rd],32 , ra); + goto logical_done; + +case 186 :/* prtyd */ +do_prty (regs, regs->gpr[rd],64 , ra); + goto logical_done;#ifdef CONFIG_PPC64 case 252 :/* bpermd */ do_bpermd (regs, regs->gpr[rd], regs->gpr[rb], ra);
Re: [PATCH v4 5/5] powerpc/lib/sstep: Add isel instruction emulation
In reply to Matt BrownQuoted 5 lines · Matt Brown
This adds emulation for the isel instruction.
Tested for correctness against the isel instruction and its extended mnemonics (lt, gt, eq) on ppc64le.Signed-off-by Matt Brown <[email protected]>
Quoted 31 lines
---
v4:
- simplify if statement to ternary op
(same as isel emulation inkernel/traps.c)
v2:
- fixed opcode
- fixed definition to include the 'if RA=0, a=0' clause
- fixed ccr bitshifting error--- arch/powerpc/lib/sstep.c | 8 ++++++++ 1 file changed, 8 insertions(+)arch/powerpc/lib/sstep.c +8
-0@@ -1240,6 +1240,14 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,/* * Logical instructions */ +case 15 :/* isel */ + mb = (instr >>6 ) &0x1f ;/* bc */ + val = (regs->ccr >> (31 - mb)) &1 ; + val2 = (ra) ? regs->gpr[ra] :0 ; + + regs->gpr[rd] = (val) ? val2 : regs->gpr[rb]; + goto logical_done; +case 26 :/* cntlzw */ asm("cntlzw %0,%1" :"=r" (regs->gpr[ra]) :"r" (regs->gpr[rd]));
Re: [PATCH v4 2/5] powerpc/lib/sstep: Add popcnt instruction emulation
In reply to Matt BrownQuoted 4 lines · Matt Brown
This adds emulations for the popcntb, popcntw, and popcntd instructions. Tested for correctness against the popcnt{b,w,d} instructions on ppc64le.
Signed-off-by Matt Brown <[email protected]>
Unlike the rest of this series, it isn't immediately clear that it is correct, we're definitely on the other side of the optimisation vs readability line. It looks like it is, perhaps some comments to clarify.
Otherwise,
Quoted 89 lines
---
v4:
- change ifdef macro from__powerpc64__toCONFIG_PPC64
- slight optimisations
(now identical to the popcntb implementation inkernel/traps.c)
v3:
- optimised using the Giles-Miller method of side-ways addition
v2:
- fixed opcodes
- fixed typecasting
- fixed bitshifting error for both 32 and 64bit arch--- arch/powerpc/lib/sstep.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-)arch/powerpc/lib/sstep.c +41
-1@@ -612,6 +612,34 @@ static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1, regs->gpr[rd] = out_val; } +/* +* The size parameter is used to adjust the equivalent popcnt instruction. +* popcntb = 8, popcntw = 32, popcntd = 64 +*/ +static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1, +int size,int ra) +{ +unsigned long long out = v1; + + out -= (out >>1 ) &0x5555555555555555 ; + out = (0x3333333333333333 & out) + (0x3333333333333333 & (out >>2 )); + out = (out + (out >>4 )) &0x0f0f0f0f0f0f0f0f ; + +if (size ==8 ) {/* popcntb */ + regs->gpr[ra] = out; +return ; + } + out += out >>8 ; + out += out >>16 ; +if (size ==32 ) {/* popcntw */ + regs->gpr[ra] = out &0x0000003f0000003f ; +return ; + } + + out = (out + (out >>32 )) &0x7f ; + regs->gpr[ra] = out;/* popcntd */ +} + static nokprobe_inline int trap_compare(long v1, long v2) {int ret =0 ;@@ -1194,6 +1222,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, regs->gpr[ra] = regs->gpr[rd] & ~regs->gpr[rb]; goto logical_done; +case 122 :/* popcntb */ +do_popcnt (regs, regs->gpr[rd],8 , ra); + goto logical_done; +case 124 :/* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done;@@ -1206,6 +1238,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, regs->gpr[ra] = regs->gpr[rd] ^ regs->gpr[rb]; goto logical_done; +case 378 :/* popcntw */ +do_popcnt (regs, regs->gpr[rd],32 , ra); + goto logical_done; +case 412 :/* orc */ regs->gpr[ra] = regs->gpr[rd] | ~regs->gpr[rb]; goto logical_done;@@ -1217,7 +1253,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,case 476 :/* nand */ regs->gpr[ra] = ~(regs->gpr[rd] & regs->gpr[rb]); goto logical_done; - +#ifdef CONFIG_PPC64 +case 506 :/* popcntd */ +do_popcnt (regs, regs->gpr[rd],64 , ra); + goto logical_done; +#endif case 922 :/* extsh */ regs->gpr[ra] = (signed short ) regs->gpr[rd]; goto logical_done;
Hi!
arch/powerpc/lib/sstep.c int analyse_instr(struct instruction_op *op, struct pt_regs *regs, · line 1070
Quoted 7 lines · Matt Brown
arch/powerpc/lib/sstep.c +3
-0@@ -1049,6 +1065,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,do_cmp_unsigned (regs, val, val2, rd >>2 ); goto instr_done; +case 508 :/* cmpb */ +do_cmpb (regs, regs->gpr[rd], regs->gpr[rb], ra); + goto instr_done;
Should this then be under an ifdef for 64-bit?
Segher
Quoted 7 lines · Segher Boessenkool
Hi!
Quoted 4 lines · Matt Brown
arch/powerpc/lib/sstep.c +0
-0@@ -1049,6 +1065,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,do_cmp_unsigned (regs, val, val2, rd >>2 ); goto instr_done;
Quoted 5 lines
arch/powerpc/lib/sstep.c int analyse_instr(struct instruction_op *op, struct pt_regs *regs, · line 1070
Quoted 3 lines
arch/powerpc/lib/sstep.c +3
-0+case 508 :/* cmpb */ +do_cmpb (regs, regs->gpr[rd], regs->gpr[rb], ra); + goto instr_done;Should this then be under an ifdef for 64-bit?
I don't think so, the cmpb instruction should be 32 and 64-bit. It isn't listed under the '64-bit Fixed-point Logical Instructions' section in the ISA either.
Thanks,
Matt
Quoted 3 lines
Segher
Quoted 6 lines · Matt Brown
This patch adds emulation of the cmpb instruction, enabling xmon to emulate this instruction.
Tested for correctness against the cmpb asm instruction on ppc64le.Signed-off-by Matt Brown <[email protected]>Reviewed-by Cyril Bur <[email protected]>
Series applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/02c0f62a60b67d6c9bfe9429cbe3aa
cheers