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: Khansa Butt
Subject: Re: [Qemu-devel] MIPS64 user mode emulation Patch
Date: Sat, 9 Apr 2011 14:57:35 +0500

Please see the online comments highlighted in red.
I'll be sending corrected Patches to the mailing list.

On Wed, Mar 30, 2011 at 9:38 PM, Nathan Froyd <address@hidden> wrote:
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.


A variable is declared in image_info to set a flag in CPUMIPSState and discarded a global variable
@@ -51,6 +51,7 @@ struct image_info {
         abi_ulong       arg_start;
         abi_ulong       arg_end;
  int personality;
+ int elf_arch;
 

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.


The above line has been changed with following code snippet
+#if defined(TARGET_MIPS64)
+                ret = do_syscall(env, env->active_tc.gpr[2],
+                                 env->active_tc.gpr[4],
+                                 env->active_tc.gpr[5],
+                                 env->active_tc.gpr[6],
+                                 env->active_tc.gpr[7],
+                                 env->active_tc.gpr[8],
+                                 env->active_tc.gpr[9]);
+#else
                 ret = do_syscall(env, env->active_tc.gpr[2],
                                  env->active_tc.gpr[4],
                                  env->active_tc.gpr[5],
                                  env->active_tc.gpr[6],
                                  env->active_tc.gpr[7],
                                  arg5, arg6/*, arg7, arg8*/);
+#endif 

 
> 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.

The above thing has been made octeon specific 
 
> --- 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.

Octeon register in TCState as follows
@@ -171,6 +176,15 @@ struct TCState {
     target_ulong CP0_TCSchedule;
     target_ulong CP0_TCScheFBack;
     int32_t CP0_Debug_tcstatus;
+    /* Multiplier registers for Octeon */
+    target_ulong MPL0;
+    target_ulong MPL1;
+    target_ulong MPL2;
+    target_ulong P0;
+    target_ulong P1;
+    target_ulong P2;
+    /* Octeon specific Coprocessor 0 register */
+    target_ulong cvmctl;
 };
 



> 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.


The above behavior when  ld instruction came was due to env->hflags had
 not been 'or' ed with mips64 user mode flag(MIPS_HFLAG_UX) so now following
line is added in translate.c: cpu_rest()
#ifdef TARGET_MIPS64
+    env->hflags |=  MIPS_HFLAG_UX;
     if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
         env->hflags |= MIPS_HFLAG_F64;
     }
   


> +        case OPC_VMULU:
> +        case OPC_V3MULU:

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

Out-of-line helper function has been implemented
 

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.

check for octeon specific instructions
static inline void check_octeon(DisasContext *ctx, CPUState *env)
+{
+    if (!env->TARGET_OCTEON)
+        generate_exception(ctx, EXCP_RI);
+}


 

>  /* 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?


t0 is actually compared with 1. if t0 <1 then rd =1 
for reference check slti instruction of mips64r2
switch (opc) {
    case OPC_SLTI:
        tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
        opn = "slti";



> +    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.


This is set if not equal instruction. if rs != rt, rd has some value greater than 1 (because of 
tcg_gen_xor_tl) so if t1 < t0(in  tcg_gen_setcond_tl) rd will be 1. that's wat we needed "set if not
equal"
 


> +#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]