qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] MIPS64 user mode emulation Patch


From: Nathan Froyd
Subject: Re: [Qemu-devel] MIPS64 user mode emulation Patch
Date: Wed, 30 Mar 2011 09:38:51 -0700
User-agent: Mutt/1.5.17+20080114 (2008-01-14)

On Sat, Mar 26, 2011 at 11:58:37AM +0500, Khansa Butt wrote:
> Subject: [PATCH] MIPS64 user mode emulation in QEMU
>  This patch adds support for Cavium Network's
>  Octeon 57XX user mode instructions.  Octeon
>  57xx is based on MIPS64.  So this patch is
>  the first MIPS64 User Mode Emulation in QEMU
>  This is the team(Khansa Butt, Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed)
>  work of HPCNL Lab at KICS-UET Lahore.

Thanks for doing this.  As already noted, this patch should be split
into at least two patches: one to add Octeon-specific instructions in
target-mips/ and one adding the necessary linux-user bits.

> +extern int TARGET_OCTEON;

I don't think a global like this is the right way to go.  Perhaps the
elfload.c code should set a flag in image_info , which can then be used
to set a flag in CPUMIPSState later on.

If we must use a global variable, it should be declared in
target-mips/cpu.h.

> @@ -2013,7 +2024,8 @@ void cpu_loop(CPUMIPSState *env)
>                                   env->active_tc.gpr[5],
>                                   env->active_tc.gpr[6],
>                                   env->active_tc.gpr[7],
> -                                 arg5, arg6/*, arg7, arg8*/);
> +                                 env->active_tc.gpr[8],
> +                                 env->active_tc.gpr[9]/*, arg7, arg8*/);
>              }
>              if (ret == -TARGET_QEMU_ESIGRETURN) {
>                  /* Returning from a successful sigreturn syscall.

This change breaks O32 binaries; it needs to be done in a different way.

> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 499c4d7..47fef05 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -7195,6 +7195,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
> arg1,
>      case TARGET_NR_set_thread_area:
>  #if defined(TARGET_MIPS)
>        ((CPUMIPSState *) cpu_env)->tls_value = arg1;
> +       /*tls entry is moved to k0 so that this can be used later*/
> +      ((CPUMIPSState *) cpu_env)->active_tc.gpr[26] = arg1;
>        ret = 0;
>        break;
>  #elif defined(TARGET_CRIS)

I believe this is only correct for Octeon binaries; it's not how the
rest of the MIPS world works.  It therefore needs to be conditional on
Octeon-ness.

> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -140,6 +140,20 @@ typedef struct mips_def_t mips_def_t;
>  #define MIPS_FPU_MAX 1
>  #define MIPS_DSP_ACC 4
> 
> +typedef struct cavium_mul cavium_mul;
> +struct cavium_mul {
> + target_ulong MPL0;
> + target_ulong MPL1;
> + target_ulong MPL2;
> + target_ulong P0;
> + target_ulong P1;
> + target_ulong P2;
> +};
> +typedef struct cvmctl_register cvmctl_register;
> +struct cvmctl_register {
> + target_ulong cvmctl;
> +};

The indentation here needs to be fixed.  I don't think there's any
reason why these need to be defined outside TCState, either.

> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index cce77be..9c3d772 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -36,6 +36,15 @@
>  #define GEN_HELPER 1
>  #include "helper.h"
> 
> +int TARGET_OCTEON;
> +#if defined(TARGET_MIPS64)
> +/*Macros for setting values of cvmctl registers*/
> +#define FUSE_START_BIT(cvmctl)(cvmctl | 0x80000000)
> +#define KASUMI(cvmctl)(cvmctl | 0x20000000)
> +#define IPPCI(cvmctl)(cvmctl | 0x380)
> +#define IPTI(cvmctl)(cvmctl | 0x70)
> +#endif

Please follow existing style; spaces between the comment and comment
markers (many examples in translate.c, not just here) and spaces between
the macro argument list and definition.

> @@ -779,7 +818,9 @@ static inline void gen_op_addr_add (DisasContext *ctx,
> TCGv ret, TCGv arg0, TCGv
>         See the MIPS64 PRA manual, section 4.10. */
>      if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
>          !(ctx->hflags & MIPS_HFLAG_UX)) {
> -        tcg_gen_ext32s_i64(ret, ret);
> +        /*This function sign extend 32 bit value to 64 bit, was causing
> error
> +          when ld instruction came.Thats why it is commmented out*/
> +       /* tcg_gen_ext32s_i64(ret, ret);*/
>      }
>  #endif
>  }

Um, no.  If you needed to comment this out, you have a bug someplace
else.  Don't paper over the bug here.

> +        case OPC_VMULU:
> +        case OPC_V3MULU:

These two are large enough that they should be done as out-of-line
helpers.

Also, since all these new instructions are Octeon-specific, there should
be checks emitted to ensure that they produce appropriate errors when
non-Octeon hardware is being simulated, similar in style to
check_mips_64.

>  /* Arithmetic */
>  static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
>                         int rd, int rs, int rt)
>  {
>      const char *opn = "arith";
> 
> +    target_ulong mask = 0xFF;

I don't think it's really necessary to have this, but if you feel it's
necessary, please move the declaration closer to the point of use.

> +#if defined(TARGET_MIPS64)
> +static void gen_seqsne (DisasContext *ctx, uint32_t opc,
> +                        int rd, int rs, int rt)
> +{
> +    const char *opn = "seq/sne";
> +    TCGv t0, t1;
> +    t0 = tcg_temp_new();
> +    t1 = tcg_temp_new();
> +    switch (opc) {
> +    case OPC_SEQ:
> +        {
> +            tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +            gen_load_gpr(t0, rd);
> +            tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rd], t0, 1);
> +        }
> +        opn = "seq";
> +        break;

This looks like you are comparing rd with itself?

> +    case OPC_SNE:
> +        {
> +            tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +            gen_load_gpr(t0, rd);
> +            gen_load_gpr(t1, 0);
> +            tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t1, t0);

You could use setcondi here by reversing the condition.

> +#if defined(TARGET_MIPS64)
> +static void insn_opc_pop (DisasContext *ctx, CPUState *env, uint32_t opc,
> +                          int rd, int rs, int rt)
> +static void insn_opc_dpop (DisasContext *ctx, CPUState *env, uint32_t opc,
> +                           int rd, int rs, int rt)

These should also be done as out-of-line helpers.

> @@ -2983,7 +3408,44 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
>      tcg_temp_free(t0);
>      tcg_temp_free(t1);
>  }
> +/*For cavium specific extract instructions*/
> +#if defined(TARGET_MIPS64)
> +static void gen_exts (CPUState *env,DisasContext *ctx, uint32_t opc, int
> rt,
> +                      int rs, int lsb, int msb)
> +{
> +    TCGv t0 = tcg_temp_new();
> +    TCGv t1 = tcg_temp_new();
> +    target_ulong mask;
> +    gen_load_gpr(t1, rs);
> +    switch (opc) {
> +    case OPC_EXTS:
> +        tcg_gen_shri_tl(t0, t1, lsb);
> +        tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
> +        /* To sign extened the remaining bits according to
> +           the msb of the bit field */
> +        mask = 1ULL << msb;
> +        tcg_gen_andi_tl(t1, t0, mask);
> +        tcg_gen_addi_tl(t1, t1, -1);
> +        tcg_gen_not_i64(t1, t1);
> +        tcg_gen_or_tl(t0, t0, t1);

You can use tcg_gen_orc_tl here and elsewhere.

-Nathan



reply via email to

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