[PATCH] [POWERPC] Emulate isel (Integer Select) instruction

Kumar Gala galak at kernel.crashing.org
Thu Nov 22 01:22:24 EST 2007


On Nov 21, 2007, at 7:09 AM, Geert Uytterhoeven wrote:

> On Tue, 20 Nov 2007, Kumar Gala wrote:
>> On Nov 20, 2007, at 11:54 AM, Scott Wood wrote:
>>> On Mon, Nov 19, 2007 at 09:36:57PM -0600, Kumar Gala wrote:
>>>> isel (Integer Select) is a new user space instruction in the
>>>> PowerISA 2.04 spec.  Not all processors implement it so lets  
>>>> emulate
>>>> to ensure code built with isel will run everywhere.
>>>
>>> Given that the instruction is meant to be a performance enhancement,
>>> we should probably warn the first few times it's emulated, so the  
>>> user
>>> knows they should change their toolchain setup if possible.
>>
>> The same is true of mcrxr, popcntb, and possibly string ld/st.
>>
>> Feel free to submit a patch that warns about their usage.
>
> Something like this?
>
> Probably we also want it for:
>
>  - arch/powerpc/kernel/align.c
>      o emulate_dcbz()
>      o emulate_multiple()
>      o emulate_fp_pair()
>      o emulate_spe()
>
>  - arch/powerpc/kernel/softemu8xx.c
>      o Soft_emulate_8xx()
>
>  - arch/powerpc/kernel/traps.c
>      o SoftwareEmulation()

You missed math_emu.

>   - arch/powerpc/kernel/vecemu.c
>      o emulate_altivec()

I'm not sure I would concern this one emulation, there isn't much you  
can do about the denorm fixup.

How about some per processor counters in sysfs under the processor.

> Question: do we want it for emulate_single_step(), too?

What do you mean, we should could the emulation, the emulate single  
step just is for handling if you are doing debug while hitting an  
emulated insn.

> So far my Debian userland didn't trigger any of them on the PS3, I  
> had to
> write an explicit test ;-)
> ---
> arch/powerpc/kernel/traps.c |   19 +++++++++++++++++--
> 1 files changed, 17 insertions(+), 2 deletions(-)
>
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -707,6 +707,14 @@ static int emulate_popcntb_inst(struct p
> 	return 0;
> }
>
> +#define WARN_EMULATE(type)						\
> +	do {								\
> +	    static unsigned int count;					\
> +	    if (count++ < 10)						\
> +		    pr_warning("%s used emulated %s instruction\n",	\
> +			       current->comm, type);			\
> +	} while (0)
> +
> static int emulate_instruction(struct pt_regs *regs)
> {
> 	u32 instword;
> @@ -721,31 +729,38 @@ static int emulate_instruction(struct pt
>
> 	/* Emulate the mfspr rD, PVR. */
> 	if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
> +		WARN_EMULATE("mfpvr");
> 		rd = (instword >> 21) & 0x1f;
> 		regs->gpr[rd] = mfspr(SPRN_PVR);
> 		return 0;
> 	}
>
> 	/* Emulating the dcba insn is just a no-op.  */
> -	if ((instword & INST_DCBA_MASK) == INST_DCBA)
> +	if ((instword & INST_DCBA_MASK) == INST_DCBA) {
> +		WARN_EMULATE("dcba");
> 		return 0;
> +	}
>
> 	/* Emulate the mcrxr insn.  */
> 	if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
> 		int shift = (instword >> 21) & 0x1c;
> 		unsigned long msk = 0xf0000000UL >> shift;
>
> +		WARN_EMULATE("mcrxr");
> 		regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
> 		regs->xer &= ~0xf0000000UL;
> 		return 0;
> 	}
>
> 	/* Emulate load/store string insn. */
> -	if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
> +	if ((instword & INST_STRING_GEN_MASK) == INST_STRING) {
> +		WARN_EMULATE("string");
> 		return emulate_string_inst(regs, instword);
> +	}
>
> 	/* Emulate the popcntb (Population Count Bytes) instruction. */
> 	if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) {
> +		WARN_EMULATE("popcntb");
> 		return emulate_popcntb_inst(regs, instword);
> 	}
>

This looks good as a start.

- k




More information about the Linuxppc-dev mailing list