qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 4/8] target-mips: microMIPS ASE support


From: Aurelien Jarno
Subject: Re: [Qemu-devel] [PATCH 4/8] target-mips: microMIPS ASE support
Date: Wed, 9 Jun 2010 16:08:40 +0200
User-agent: Mutt/1.5.18 (2008-05-17)

On Tue, Jun 08, 2010 at 01:29:59PM -0700, Nathan Froyd wrote:
> Add instruction decoding for the microMIPS ASE.  All we do is decode and
> then forward to the existing gen_* routines.
> 
> Signed-off-by: Nathan Froyd <address@hidden>
> ---
>  target-mips/helper.h    |    9 +
>  target-mips/mips-defs.h |    1 +
>  target-mips/op_helper.c |  136 +++
>  target-mips/translate.c | 2390 
> ++++++++++++++++++++++++++++++++++++++++++++++-
>  4 files changed, 2531 insertions(+), 5 deletions(-)
> 
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index ab47b1a..a6ba75d 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -160,6 +160,15 @@ DEF_HELPER_1(emt, tl, tl)
>  DEF_HELPER_1(dvpe, tl, tl)
>  DEF_HELPER_1(evpe, tl, tl)
>  #endif /* !CONFIG_USER_ONLY */
> +
> +/* microMIPS functions */
> +DEF_HELPER_3(lwm, void, tl, tl, i32);
> +DEF_HELPER_3(swm, void, tl, tl, i32);
> +#ifdef TARGET_MIPS64
> +DEF_HELPER_3(ldm, void, tl, tl, i32);
> +DEF_HELPER_3(sdm, void, tl, tl, i32);
> +#endif
> +
>  DEF_HELPER_2(fork, void, tl, tl)
>  DEF_HELPER_1(yield, tl, tl)
>  
> diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
> index c57de02..a7f4697 100644
> --- a/target-mips/mips-defs.h
> +++ b/target-mips/mips-defs.h
> @@ -38,6 +38,7 @@
>  #define              ASE_DSPR2       0x00010000
>  #define              ASE_MT          0x00020000
>  #define              ASE_SMARTMIPS   0x00040000
> +#define      ASE_MICROMIPS   0x00080000
>  
>  /* Chip specific instructions. */
>  #define              INSN_VR54XX     0x80000000
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index 2bfdd50..56c5e59 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -565,6 +565,142 @@ void helper_sdr(target_ulong arg1, target_ulong arg2, 
> int mem_idx)
>  }
>  #endif /* TARGET_MIPS64 */
>  
> +static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
> +
> +void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
> +{
> +    target_ulong base_reglist = reglist & 0xf;
> +    target_ulong do_r31 = reglist & 0x10;
> +#ifdef CONFIG_USER_ONLY
> +#undef ldfun
> +#define ldfun ldl_raw
> +#else
> +    uint32_t (*ldfun)(target_ulong);
> +
> +    switch (mem_idx)
> +    {
> +    case 0: ldfun = ldl_kernel; break;
> +    case 1: ldfun = ldl_super; break;
> +    default:
> +    case 2: ldfun = ldl_user; break;
> +    }
> +#endif
> +
> +    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
> +        target_ulong i;
> +
> +        for (i = 0; i < base_reglist; i++) {
> +            env->active_tc.gpr[multiple_regs[i]] = (target_long) ldfun(addr);
> +            addr += 4;
> +        }
> +    }
> +
> +    if (do_r31) {
> +        env->active_tc.gpr[31] = (target_long) ldfun(addr);
> +    }
> +}
> +
> +void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
> +{
> +    target_ulong base_reglist = reglist & 0xf;
> +    target_ulong do_r31 = reglist & 0x10;
> +#ifdef CONFIG_USER_ONLY
> +#undef stfun 
> +#define stfun stl_raw
> +#else
> +    void (*stfun)(target_ulong, uint32_t);
> +
> +    switch (mem_idx)
> +    {
> +    case 0: stfun = stl_kernel; break;
> +    case 1: stfun = stl_super; break;
> +     default:
> +    case 2: stfun = stl_user; break;
> +    }
> +#endif
> +
> +    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
> +        target_ulong i;
> +
> +        for (i = 0; i < base_reglist; i++) {
> +            stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
> +            addr += 4;
> +        }
> +    }
> +
> +    if (do_r31) {
> +        stfun(addr, env->active_tc.gpr[31]);
> +    }
> +}
> +
> +#if defined(TARGET_MIPS64)
> +void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
> +{
> +    target_ulong base_reglist = reglist & 0xf;
> +    target_ulong do_r31 = reglist & 0x10;
> +#ifdef CONFIG_USER_ONLY
> +#undef ldfun
> +#define ldfun ldq_raw
> +#else
> +    uint64_t (*ldfun)(target_ulong);
> +
> +    switch (mem_idx)
> +    {
> +    case 0: ldfun = ldq_kernel; break;
> +    case 1: ldfun = ldq_super; break;
> +    default:
> +    case 2: ldfun = ldq_user; break;
> +    }
> +#endif
> +
> +    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
> +        target_ulong i;
> +
> +        for (i = 0; i < base_reglist; i++) {
> +            env->active_tc.gpr[multiple_regs[i]] = ldfun(addr);
> +            addr += 8;
> +        }
> +    }
> +
> +    if (do_r31) {
> +        env->active_tc.gpr[31] = ldfun(addr);
> +    }
> +}
> +
> +void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
> +{
> +    target_ulong base_reglist = reglist & 0xf;
> +    target_ulong do_r31 = reglist & 0x10;
> +#ifdef CONFIG_USER_ONLY
> +#undef stfun
> +#define stfun stq_raw
> +#else
> +    void (*stfun)(target_ulong, uint64_t);
> +
> +    switch (mem_idx)
> +    {
> +    case 0: stfun = stq_kernel; break;
> +    case 1: stfun = stq_super; break;
> +     default:
> +    case 2: stfun = stq_user; break;
> +    }
> +#endif
> +
> +    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
> +        target_ulong i;
> +
> +        for (i = 0; i < base_reglist; i++) {
> +            stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
> +            addr += 8;
> +        }
> +    }
> +
> +    if (do_r31) {
> +        stfun(addr, env->active_tc.gpr[31]);
> +    }
> +}
> +#endif
> +
>  #ifndef CONFIG_USER_ONLY
>  /* CP0 helpers */
>  target_ulong helper_mfc0_mvpcontrol (void)

As the list of registers is included in the opcode, I do wonder if it
wouldn't be better to do this directly in translate.c as TCG code.


-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
address@hidden                 http://www.aurel32.net



reply via email to

[Prev in Thread] Current Thread [Next in Thread]