qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] tilegx: Generate ill related instructions according


From: gang . chen . 5i5j
Subject: [Qemu-devel] [PATCH] tilegx: Generate ill related instructions according to Linux kernel
Date: Sat, 26 Sep 2015 13:00:35 +0800

From: Chen Gang <address@hidden>

At present, tilegx qemu will abort for "setup_frame: not implemented",
when meet raise instruction.

Signed-off-by: Chen Gang <address@hidden>
---
 linux-user/main.c         | 14 ++++++++
 target-tilegx/cpu.h       |  3 ++
 target-tilegx/translate.c | 89 +++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 92 insertions(+), 14 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 782037d..7e49931 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3436,6 +3436,17 @@ static void gen_sigill_reg(CPUTLGState *env)
     queue_signal(env, info.si_signo, &info);
 }
 
+static void gen_sigill(CPUTLGState *env)
+{
+    target_siginfo_t info;
+
+    info.si_signo = env->signo;
+    info.si_errno = 0;
+    info.si_code = env->sigcode;
+    info._sifields._sigfault._addr = env->pc;
+    queue_signal(env, info.si_signo, &info);
+}
+
 static void set_regval(CPUTLGState *env, uint8_t reg, uint64_t val)
 {
     if (unlikely(reg >= TILEGX_R_COUNT)) {
@@ -3622,6 +3633,9 @@ void cpu_loop(CPUTLGState *env)
         case TILEGX_EXCP_OPCODE_FETCHOR4:
             do_fetch(env, trapnr, false);
             break;
+        case TILEGX_EXCP_OPCODE_ILL:
+            gen_sigill(env);
+            break;
         case TILEGX_EXCP_REG_IDN_ACCESS:
         case TILEGX_EXCP_REG_UDN_ACCESS:
             gen_sigill_reg(env);
diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h
index b9f5082..72a1878 100644
--- a/target-tilegx/cpu.h
+++ b/target-tilegx/cpu.h
@@ -75,6 +75,7 @@ typedef enum {
     TILEGX_EXCP_OPCODE_FETCHAND4 = 0x10c,
     TILEGX_EXCP_OPCODE_FETCHOR = 0x10d,
     TILEGX_EXCP_OPCODE_FETCHOR4 = 0x10e,
+    TILEGX_EXCP_OPCODE_ILL = 0x10f,
     TILEGX_EXCP_REG_IDN_ACCESS = 0x181,
     TILEGX_EXCP_REG_UDN_ACCESS = 0x182,
     TILEGX_EXCP_UNALIGNMENT = 0x201,
@@ -86,6 +87,8 @@ typedef struct CPUTLGState {
     uint64_t spregs[TILEGX_SPR_COUNT]; /* Special used registers by outside */
     uint64_t pc;                       /* Current pc */
 
+    uint64_t signo;                    /* Signal number */
+    uint64_t sigcode;                  /* Signal code */
 #if defined(CONFIG_USER_ONLY)
     uint64_t atomic_srca;              /* Arguments to atomic "exceptions" */
     uint64_t atomic_srcb;
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 6622aeb..969c66e 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -23,6 +23,8 @@
 #include "disas/disas.h"
 #include "tcg-op.h"
 #include "exec/cpu_ldst.h"
+#include "linux-user/syscall_defs.h"
+
 #include "opcode_tilegx.h"
 #include "spr_def_64.h"
 
@@ -378,8 +380,74 @@ static void gen_v4op(TCGv d64, TCGv a64, TCGv b64,
     tcg_temp_free_i32(bh);
 }
 
+static TileExcp gen_ill(DisasContext *dc, int signo, int sigcode,
+                        const char *mnemonic)
+{
+    TCGv t0 = tcg_const_tl(signo);
+    TCGv t1 = tcg_const_tl(sigcode);
+
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUTLGState, signo));
+    tcg_gen_st_tl(t1, cpu_env, offsetof(CPUTLGState, sigcode));
+
+    tcg_temp_free(t1);
+    tcg_temp_free(t0);
+
+    qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic);
+    return TILEGX_EXCP_OPCODE_ILL;
+}
+
+static int parse_from_addli(uint64_t bundle, int *signo, int *sigcode)
+{
+    if ((get_Opcode_X0(bundle) != ADDLI_OPCODE_X0)
+        || (get_Dest_X0(bundle) != TILEGX_R_ZERO)
+        || (get_SrcA_X0(bundle) != TILEGX_R_ZERO)) {
+        return 0;
+    }
+
+    *signo = get_Imm16_X0(bundle) & 0x3f;
+    *sigcode = (get_Imm16_X0(bundle) >> 6) & 0xf;
+
+    switch (*signo) {
+    case TARGET_SIGILL:
+        return *sigcode <= TARGET_NSIGILL;
+    case TARGET_SIGFPE:
+        return *sigcode <= TARGET_NSIGFPE;
+    case TARGET_SIGSEGV:
+        return *sigcode <= TARGET_NSIGSEGV;
+    case TARGET_SIGBUS:
+        return *sigcode <= TARGET_NSIGBUS;
+    case TARGET_SIGTRAP:
+        return *sigcode <= TARGET_NSIGTRAP;
+    default:
+        return 0;
+    }
+}
+
+static TileExcp gen_specill(DisasContext *dc, unsigned dest, unsigned srca,
+                            uint64_t bundle)
+{
+    const char *mnemonic;
+    int signo;
+    int sigcode;
+
+    if (dest == 0x1c && srca == 0x25) {
+        signo = TARGET_SIGTRAP;
+        sigcode = TARGET_TRAP_BRKPT;
+        mnemonic = "bpt";
+    } else if (dest == 0x1d && srca == 0x25
+               && parse_from_addli(bundle, &signo, &sigcode)) {
+        mnemonic = "raise";
+    } else {
+        signo = TARGET_SIGILL;
+        sigcode = TARGET_ILL_ILLOPC;
+        mnemonic = "ill";
+    }
+
+    return gen_ill(dc, signo, sigcode, mnemonic);
+}
+
 static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
-                              unsigned dest, unsigned srca)
+                              unsigned dest, unsigned srca, uint64_t bundle)
 {
     TCGv tdest, tsrca;
     const char *mnemonic;
@@ -407,16 +475,9 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned 
opext,
         mnemonic = "flushwb";
         goto done0;
     case OE_RR_X1(ILL):
-        if (dest == 0x1c && srca == 0x25) {
-            mnemonic = "bpt";
-            goto done2;
-        }
-        /* Fall through */
+        return gen_specill(dc, dest, srca, bundle);
     case OE_RR_Y1(ILL):
-        mnemonic = "ill";
-    done2:
-        qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic);
-        return TILEGX_EXCP_OPCODE_UNKNOWN;
+        return gen_ill(dc, TARGET_SIGILL, TARGET_ILL_ILLOPC, "ill");
     case OE_RR_X1(MF):
         mnemonic = "mf";
         goto done0;
@@ -1806,7 +1867,7 @@ static TileExcp decode_y0(DisasContext *dc, 
tilegx_bundle_bits bundle)
     case RRR_1_OPCODE_Y0:
         if (ext == UNARY_RRR_1_OPCODE_Y0) {
             ext = get_UnaryOpcodeExtension_Y0(bundle);
-            return gen_rr_opcode(dc, OE(opc, ext, Y0), dest, srca);
+            return gen_rr_opcode(dc, OE(opc, ext, Y0), dest, srca, bundle);
         }
         /* fallthru */
     case RRR_0_OPCODE_Y0:
@@ -1852,7 +1913,7 @@ static TileExcp decode_y1(DisasContext *dc, 
tilegx_bundle_bits bundle)
     case RRR_1_OPCODE_Y1:
         if (ext == UNARY_RRR_1_OPCODE_Y0) {
             ext = get_UnaryOpcodeExtension_Y1(bundle);
-            return gen_rr_opcode(dc, OE(opc, ext, Y1), dest, srca);
+            return gen_rr_opcode(dc, OE(opc, ext, Y1), dest, srca, bundle);
         }
         /* fallthru */
     case RRR_0_OPCODE_Y1:
@@ -1954,7 +2015,7 @@ static TileExcp decode_x0(DisasContext *dc, 
tilegx_bundle_bits bundle)
         ext = get_RRROpcodeExtension_X0(bundle);
         if (ext == UNARY_RRR_0_OPCODE_X0) {
             ext = get_UnaryOpcodeExtension_X0(bundle);
-            return gen_rr_opcode(dc, OE(opc, ext, X0), dest, srca);
+            return gen_rr_opcode(dc, OE(opc, ext, X0), dest, srca, bundle);
         }
         srcb = get_SrcB_X0(bundle);
         return gen_rrr_opcode(dc, OE(opc, ext, X0), dest, srca, srcb);
@@ -2001,7 +2062,7 @@ static TileExcp decode_x1(DisasContext *dc, 
tilegx_bundle_bits bundle)
         switch (ext) {
         case UNARY_RRR_0_OPCODE_X1:
             ext = get_UnaryOpcodeExtension_X1(bundle);
-            return gen_rr_opcode(dc, OE(opc, ext, X1), dest, srca);
+            return gen_rr_opcode(dc, OE(opc, ext, X1), dest, srca, bundle);
         case ST1_RRR_0_OPCODE_X1:
             return gen_st_opcode(dc, dest, srca, srcb, MO_UB, "st1");
         case ST2_RRR_0_OPCODE_X1:
-- 
1.9.3




reply via email to

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