qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 11/16 v1] target-tilegx: Add related feature to supp


From: Chen Gang
Subject: [Qemu-devel] [PATCH 11/16 v1] target-tilegx: Add related feature to support iret instruction
Date: Fri, 21 Aug 2015 05:44:27 +0800
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Thunderbird/31.7.0

In fact, iret itself needs nothing, but the related previous and next
instructions need to be implemented.

SPR_EX_CONTEXT_0_0 and SPR_EX_CONTEXT_0_1 are related with iret, so let
them in a patch.

Signed-off-by: Chen Gang <address@hidden>
---
 target-tilegx/cpu.h       |  2 ++
 target-tilegx/translate.c | 86 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h
index e404025..808f4e5 100644
--- a/target-tilegx/cpu.h
+++ b/target-tilegx/cpu.h
@@ -53,6 +53,8 @@ enum {
     TILEGX_SPR_CMPEXCH = 0,
     TILEGX_SPR_CRITICAL_SEC = 1,
     TILEGX_SPR_SIM_CONTROL = 2,
+    TILEGX_SPR_EX_CONTEXT_0_0 = 3,
+    TILEGX_SPR_EX_CONTEXT_0_1 = 4,
     TILEGX_SPR_COUNT
 };
 
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 1dd3a43..541d603 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -48,7 +48,7 @@ static const char * const reg_names[] = {
 };
 
 static const char * const spreg_names[] = {
-    "cmpexch", "criticalsec", "simcontrol"
+    "cmpexch", "criticalsec", "simcontrol", "excontext00", "excontext01"
 };
 
 /* It is for temporary registers */
@@ -174,6 +174,71 @@ static void gen_swint1(struct DisasContext *dc)
 }
 
 /*
+ * Description
+ *
+ * Returns from an interrupt. Transfers control flow to the program counter
+ * location and protection level contained in the current PL ’s EX_CONTEXT
+ * registers, and restores the interrupt critical section bit to the value
+ * contained in those registers.
+ *
+ * Functional Description
+ *
+ * setNextPC(sprf [EX_CONTEXT_SPRF_OFFSET +
+ *                 (getCurrentProtectionLevel() * EX_CONTEXT_SIZE) +
+ *                  PC_EX_CONTEXT_OFFSET]);
+ * branchPredictedIncorrect();
+ * setProtectionLevel(sprf [EX_CONTEXT_SPRF_OFFSET +
+ *                          (getCurrentProtectionLevel() * EX_CONTEXT_SIZE) +
+ *                           PROTECTION_LEVEL_EX_CONTEXT_OFFSET]);
+ * setInterruptCriticalSection(
+ *               sprf [EX_CONTEXT_SPRF_OFFSET +
+ *                     (getCurrentProtectionLevel() * EX_CONTEXT_SIZE) +
+ *                      INTERRUPT_CRITICAL_SECTION_EX_CONTEXT_OFFSET]);
+ *
+ * besides the PC we need to set our new protection level, and set the 
interrupt
+ * critical section bit atomically inside of this instruction
+ */
+static void gen_iret(struct DisasContext *dc)
+{
+    qemu_log_mask(CPU_LOG_TB_IN_ASM, "iret\n");
+    /*
+     * In user mode, all related things are already done by previous and next
+     * instructions, so just skip it. Can reference __longjmp code for it.
+     *
+     * ENTRY (__longjmp)
+     *         FEEDBACK_ENTER(__longjmp)
+     *
+     * #define RESTORE(r) { LD r, r0 ; ADDI_PTR r0, r0, REGSIZE }
+     *         FOR_EACH_CALLEE_SAVED_REG(RESTORE)
+     *
+     *         {
+     *          LD r2, r0       ; retrieve ICS bit from jmp_buf
+     *          movei r3, 1
+     *          CMPEQI r0, r1, 0
+     *         }
+     *
+     *         {
+     *          mtspr INTERRUPT_CRITICAL_SECTION, r3
+     *          shli r2, r2, SPR_EX_CONTEXT_0_1__ICS_SHIFT
+     *         }
+     *
+     *         {
+     *          mtspr EX_CONTEXT_0_0, lr
+     *          ori r2, r2, RETURN_PL
+     *         }
+     *
+     *         {
+     *          or r0, r1, r0
+     *          mtspr EX_CONTEXT_0_1, r2
+     *         }
+     *
+     *         iret
+     *
+     *         jrp lr
+     */
+}
+
+/*
  * Many SPR reads/writes have side effects and cannot be buffered. However, 
they
  * are all in the X1 pipe, which we are excuting last, therefore we need not do
  * additional buffering.
@@ -197,6 +262,12 @@ static void gen_mfspr(struct DisasContext *dc, uint8_t 
rdst, uint16_t imm14)
     case SPR_SIM_CONTROL:
         tcg_gen_mov_i64(cpu_regs[rdst], cpu_spregs[TILEGX_SPR_SIM_CONTROL]);
         return;
+    case SPR_EX_CONTEXT_0_0:
+        tcg_gen_mov_i64(cpu_regs[rdst], cpu_spregs[TILEGX_SPR_EX_CONTEXT_0_0]);
+        return;
+    case SPR_EX_CONTEXT_0_1:
+        tcg_gen_mov_i64(cpu_regs[rdst], cpu_spregs[TILEGX_SPR_EX_CONTEXT_0_1]);
+        return;
     default:
         qemu_log_mask(LOG_UNIMP, "UNIMP mfspr 0x%x.\n", imm14);
     }
@@ -218,6 +289,12 @@ static void gen_mtspr(struct DisasContext *dc, uint8_t 
rsrc, uint16_t imm14)
     case SPR_SIM_CONTROL:
         tcg_gen_mov_i64(cpu_spregs[TILEGX_SPR_SIM_CONTROL], load_gr(dc, rsrc));
         return;
+    case SPR_EX_CONTEXT_0_0:
+        tcg_gen_mov_i64(cpu_spregs[TILEGX_SPR_EX_CONTEXT_0_0], load_gr(dc, 
rsrc));
+        return;
+    case SPR_EX_CONTEXT_0_1:
+        tcg_gen_mov_i64(cpu_spregs[TILEGX_SPR_EX_CONTEXT_0_1], load_gr(dc, 
rsrc));
+        return;
     default:
         qemu_log_mask(LOG_UNIMP, "UNIMP mtspr 0x%x.\n", imm14);
     }
@@ -2257,6 +2334,12 @@ static void decode_u_opcode_ex_x1(struct DisasContext 
*dc,
             return;
         }
         break;
+    case IRET_UNARY_OPCODE_X1:
+        if (!rdst && !rsrc) {
+            gen_iret(dc);
+            return;
+        }
+        break;
     case SWINT1_UNARY_OPCODE_X1:
         if (!rsrc && !rdst) {
             gen_swint1(dc);
@@ -2277,7 +2360,6 @@ static void decode_u_opcode_ex_x1(struct DisasContext *dc,
     case ICOH_UNARY_OPCODE_X1:
     case ILL_UNARY_OPCODE_X1:
     case INV_UNARY_OPCODE_X1:
-    case IRET_UNARY_OPCODE_X1:
     case LDNT1S_UNARY_OPCODE_X1:
     case LDNT1U_UNARY_OPCODE_X1:
     case LDNT2S_UNARY_OPCODE_X1:
-- 
1.9.3



reply via email to

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