[PATCH v3 16/23] target/mips: Extract trap code into env->error_code

Richard Henderson posted 23 patches 4 years, 3 months ago
Maintainers: "Philippe Mathieu-Daudé" <f4bug@amsat.org>, Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>, Thomas Huth <thuth@redhat.com>, Jiaxun Yang <jiaxun.yang@flygoat.com>, Cornelia Huck <cohuck@redhat.com>, Aurelien Jarno <aurelien@aurel32.net>, Laurent Vivier <laurent@vivier.eu>
There is a newer version of this series
[PATCH v3 16/23] target/mips: Extract trap code into env->error_code
Posted by Richard Henderson 4 years, 3 months ago
Simplify cpu_loop by doing all of the decode in translate.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/mips/cpu_loop.c                | 41 +----------------------
 target/mips/tcg/translate.c               | 24 ++++++++++---
 target/mips/tcg/micromips_translate.c.inc |  4 +--
 target/mips/tcg/nanomips_translate.c.inc  |  4 +--
 4 files changed, 25 insertions(+), 48 deletions(-)

diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
index 8efb6d2a24..6079c2d600 100644
--- a/linux-user/mips/cpu_loop.c
+++ b/linux-user/mips/cpu_loop.c
@@ -197,51 +197,12 @@ done_syscall:
             do_tr_or_bp(env, code, false);
             break;
         case EXCP_TRAP:
-            {
-                abi_ulong trap_instr;
-                unsigned int code = 0;
-
-                /*
-                 * FIXME: It would be better to decode the trap number
-                 * during translate, and store it in error_code while
-                 * raising the exception.  We should not be re-reading
-                 * the opcode here.
-                 */
-
-                if (env->hflags & MIPS_HFLAG_M16) {
-                    /* microMIPS mode */
-                    abi_ulong instr[2];
-
-                    ret = get_user_u16(instr[0], env->active_tc.PC) ||
-                          get_user_u16(instr[1], env->active_tc.PC + 2);
-
-                    trap_instr = (instr[0] << 16) | instr[1];
-                } else {
-                    ret = get_user_u32(trap_instr, env->active_tc.PC);
-                }
-
-                if (ret != 0) {
-                    goto error;
-                }
-
-                /* The immediate versions don't provide a code.  */
-                if (!(trap_instr & 0xFC000000)) {
-                    if (env->hflags & MIPS_HFLAG_M16) {
-                        /* microMIPS mode */
-                        code = ((trap_instr >> 12) & ((1 << 4) - 1));
-                    } else {
-                        code = ((trap_instr >> 6) & ((1 << 10) - 1));
-                    }
-                }
-
-                do_tr_or_bp(env, code, true);
-            }
+            do_tr_or_bp(env, env->error_code, true);
             break;
         case EXCP_ATOMIC:
             cpu_exec_step_atomic(cs);
             break;
         default:
-error:
             EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
             abort();
         }
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index a42f507aed..98c0f1aab3 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -4733,7 +4733,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
 
 /* Traps */
 static void gen_trap(DisasContext *ctx, uint32_t opc,
-                     int rs, int rt, int16_t imm)
+                     int rs, int rt, int16_t imm, int code)
 {
     int cond;
     TCGv t0 = tcg_temp_new();
@@ -4778,6 +4778,11 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
         case OPC_TGEU:  /* rs >= rs unsigned */
         case OPC_TGEIU: /* r0 >= 0  unsigned */
             /* Always trap */
+#ifdef CONFIG_USER_ONLY
+            /* Pass the break code along to cpu_loop. */
+            tcg_gen_st_i32(tcg_constant_i32(code), cpu_env,
+                           offsetof(CPUMIPSState, error_code));
+#endif
             generate_exception_end(ctx, EXCP_TRAP);
             break;
         case OPC_TLT:   /* rs < rs           */
@@ -4818,6 +4823,18 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
             tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
             break;
         }
+#ifdef CONFIG_USER_ONLY
+        /* Pass the break code along to cpu_loop. */
+        tcg_gen_st_i32(tcg_constant_i32(code), cpu_env,
+                       offsetof(CPUMIPSState, error_code));
+#endif
+        /* Like save_cpu_state, only don't update saved values. */
+        if (ctx->base.pc_next != ctx->saved_pc) {
+            gen_save_pc(ctx->base.pc_next);
+        }
+        if (ctx->hflags != ctx->saved_hflags) {
+            tcg_gen_movi_i32(hflags, ctx->hflags);
+        }
         generate_exception(ctx, EXCP_TRAP);
         gen_set_label(l1);
     }
@@ -14155,7 +14172,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
     case OPC_TEQ:
     case OPC_TNE:
         check_insn(ctx, ISA_MIPS2);
-        gen_trap(ctx, op1, rs, rt, -1);
+        gen_trap(ctx, op1, rs, rt, -1, extract32(ctx->opcode, 6, 10));
         break;
     case OPC_PMON:
         /* Pmon entry point, also R4010 selsl */
@@ -15289,11 +15306,10 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
         case OPC_TLTI:
         case OPC_TLTIU:
         case OPC_TEQI:
-
         case OPC_TNEI:
             check_insn(ctx, ISA_MIPS2);
             check_insn_opc_removed(ctx, ISA_MIPS_R6);
-            gen_trap(ctx, op1, rs, -1, imm);
+            gen_trap(ctx, op1, rs, -1, imm, 0);
             break;
         case OPC_SIGRIE:
             check_insn(ctx, ISA_MIPS_R6);
diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc
index f91f7a96cd..7e7d26a91b 100644
--- a/target/mips/tcg/micromips_translate.c.inc
+++ b/target/mips/tcg/micromips_translate.c.inc
@@ -1047,7 +1047,7 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
     case TNE:
         mips32_op = OPC_TNE;
     do_trap:
-        gen_trap(ctx, mips32_op, rs, rt, -1);
+        gen_trap(ctx, mips32_op, rs, rt, -1, extract32(ctx->opcode, 12, 4));
         break;
 #ifndef CONFIG_USER_ONLY
     case MFC0:
@@ -2439,7 +2439,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
             check_insn_opc_removed(ctx, ISA_MIPS_R6);
             mips32_op = OPC_TEQI;
         do_trapi:
-            gen_trap(ctx, mips32_op, rs, -1, imm);
+            gen_trap(ctx, mips32_op, rs, -1, imm, 0);
             break;
 
         case BNEZC:
diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc
index 2c022a49f2..916cece4d2 100644
--- a/target/mips/tcg/nanomips_translate.c.inc
+++ b/target/mips/tcg/nanomips_translate.c.inc
@@ -1268,11 +1268,11 @@ static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
         switch (extract32(ctx->opcode, 10, 1)) {
         case NM_TEQ:
             check_nms(ctx);
-            gen_trap(ctx, OPC_TEQ, rs, rt, -1);
+            gen_trap(ctx, OPC_TEQ, rs, rt, -1, rd);
             break;
         case NM_TNE:
             check_nms(ctx);
-            gen_trap(ctx, OPC_TNE, rs, rt, -1);
+            gen_trap(ctx, OPC_TNE, rs, rt, -1, rd);
             break;
         }
         break;
-- 
2.25.1


Re: [PATCH v3 16/23] target/mips: Extract trap code into env->error_code
Posted by Philippe Mathieu-Daudé 4 years, 3 months ago
On 11/3/21 15:08, Richard Henderson wrote:
> Simplify cpu_loop by doing all of the decode in translate.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/mips/cpu_loop.c                | 41 +----------------------
>  target/mips/tcg/translate.c               | 24 ++++++++++---
>  target/mips/tcg/micromips_translate.c.inc |  4 +--
>  target/mips/tcg/nanomips_translate.c.inc  |  4 +--
>  4 files changed, 25 insertions(+), 48 deletions(-)

> diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc
> index f91f7a96cd..7e7d26a91b 100644
> --- a/target/mips/tcg/micromips_translate.c.inc
> +++ b/target/mips/tcg/micromips_translate.c.inc
> @@ -1047,7 +1047,7 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
>      case TNE:
>          mips32_op = OPC_TNE;
>      do_trap:
> -        gen_trap(ctx, mips32_op, rs, rt, -1);
> +        gen_trap(ctx, mips32_op, rs, rt, -1, extract32(ctx->opcode, 12, 4));
>          break;
>  #ifndef CONFIG_USER_ONLY
>      case MFC0:
> @@ -2439,7 +2439,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
>              check_insn_opc_removed(ctx, ISA_MIPS_R6);
>              mips32_op = OPC_TEQI;
>          do_trapi:
> -            gen_trap(ctx, mips32_op, rs, -1, imm);
> +            gen_trap(ctx, mips32_op, rs, -1, imm, 0);

IIUC the microMIPS manual (MD00594):

               gen_trap(ctx, mips32_op, rs, -1, imm,
                        extract32(ctx->opcode, 12, 4));

>              break;

Re: [PATCH v3 16/23] target/mips: Extract trap code into env->error_code
Posted by Richard Henderson 4 years, 3 months ago
On 11/3/21 11:21 AM, Philippe Mathieu-Daudé wrote:
>>       do_trap:
>> -        gen_trap(ctx, mips32_op, rs, rt, -1);
>> +        gen_trap(ctx, mips32_op, rs, rt, -1, extract32(ctx->opcode, 12, 4));
>>           break;
>>   #ifndef CONFIG_USER_ONLY
>>       case MFC0:
>> @@ -2439,7 +2439,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
>>               check_insn_opc_removed(ctx, ISA_MIPS_R6);
>>               mips32_op = OPC_TEQI;
>>           do_trapi:
>> -            gen_trap(ctx, mips32_op, rs, -1, imm);
>> +            gen_trap(ctx, mips32_op, rs, -1, imm, 0);
> 
> IIUC the microMIPS manual (MD00594):
> 
>                 gen_trap(ctx, mips32_op, rs, -1, imm,
>                          extract32(ctx->opcode, 12, 4));

No, there is no code for trap-immediate.
You can see the 12:4 code above for trap-register.

See the 3.05 revision of the manual, which still contains TEQI.  Note that all 
trap-immediate opcodes were removed for R6.


r~

Re: [PATCH v3 16/23] target/mips: Extract trap code into env->error_code
Posted by Philippe Mathieu-Daudé 4 years, 3 months ago
On 11/3/21 16:46, Richard Henderson wrote:
> On 11/3/21 11:21 AM, Philippe Mathieu-Daudé wrote:
>>>       do_trap:
>>> -        gen_trap(ctx, mips32_op, rs, rt, -1);
>>> +        gen_trap(ctx, mips32_op, rs, rt, -1, extract32(ctx->opcode,
>>> 12, 4));
>>>           break;
>>>   #ifndef CONFIG_USER_ONLY
>>>       case MFC0:
>>> @@ -2439,7 +2439,7 @@ static void decode_micromips32_opc(CPUMIPSState
>>> *env, DisasContext *ctx)
>>>               check_insn_opc_removed(ctx, ISA_MIPS_R6);
>>>               mips32_op = OPC_TEQI;
>>>           do_trapi:
>>> -            gen_trap(ctx, mips32_op, rs, -1, imm);
>>> +            gen_trap(ctx, mips32_op, rs, -1, imm, 0);
>>
>> IIUC the microMIPS manual (MD00594):
>>
>>                 gen_trap(ctx, mips32_op, rs, -1, imm,
>>                          extract32(ctx->opcode, 12, 4));
> 
> No, there is no code for trap-immediate.
> You can see the 12:4 code above for trap-register.
> 
> See the 3.05 revision of the manual, which still contains TEQI.  Note
> that all trap-immediate opcodes were removed for R6.

Oops indeed (checked 3.05 and 5.04).

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>