qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 10/15] target-tricore: Add instructions of SB opcode


From: Bastian Koppelmann
Subject: [Qemu-devel] [PATCH 10/15] target-tricore: Add instructions of SB opcode format
Date: Mon, 7 Jul 2014 19:13:37 +0100

Add instructions of SB opcode format.
Add helper call/ret.
Add micro-op generator functions for branches.
Add makro to generate helper functions.

Signed-off-by: Bastian Koppelmann <address@hidden>
---
 target-tricore/helper.h    |   5 ++
 target-tricore/op_helper.c | 192 +++++++++++++++++++++++++++++++++++++++++++++
 target-tricore/translate.c |  85 ++++++++++++++++++++
 3 files changed, 282 insertions(+)

diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index acea104..0d79d1d 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -17,3 +17,8 @@
 
 /* Arithmetic */
 DEF_HELPER_3(shac, i32, env, i32, i32)
+
+/* CSA */
+DEF_HELPER_3(call, void, env, i32, i32)
+DEF_HELPER_1(ret, void, env)
+
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index b9fbfad..5267fd0 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -56,6 +56,198 @@ target_ulong helper_shac(CPUTRICOREState *env, target_ulong 
r1,
     return ret;
 }
 
+/* context save area (CSA) related helpers */
+
+enum {
+    CONTEXT_LOWER = 0,
+    CONTEXT_UPPER = 1,
+};
+
+static int cdc_increment(TCState *tc)
+{
+    tc->PSW++;
+    return 0;
+}
+
+static int cdc_decrement(TCState *tc)
+{
+    tc->PSW--;
+    return 0;
+}
+
+static void save_context(CPUTRICOREState *env, int ea, int ul,
+                         target_ulong *new_FCX)
+{
+    *new_FCX = cpu_ldl_data(env, ea);
+    cpu_stl_data(env, ea, env->active_tc.PCXI);
+    if (ul == CONTEXT_UPPER) {
+        cpu_stl_data(env, ea+4, env->active_tc.PSW);
+        cpu_stl_data(env, ea+8, env->active_tc.gpr_a[10]);
+        cpu_stl_data(env, ea+12, env->active_tc.gpr_a[11]);
+        cpu_stl_data(env, ea+16, env->active_tc.gpr_d[8]);
+        cpu_stl_data(env, ea+20, env->active_tc.gpr_d[9]);
+        cpu_stl_data(env, ea+24, env->active_tc.gpr_d[10]);
+        cpu_stl_data(env, ea+28, env->active_tc.gpr_d[11]);
+        cpu_stl_data(env, ea+32, env->active_tc.gpr_a[12]);
+        cpu_stl_data(env, ea+36, env->active_tc.gpr_a[13]);
+        cpu_stl_data(env, ea+40, env->active_tc.gpr_a[14]);
+        cpu_stl_data(env, ea+44, env->active_tc.gpr_a[15]);
+        cpu_stl_data(env, ea+48, env->active_tc.gpr_d[12]);
+        cpu_stl_data(env, ea+52, env->active_tc.gpr_d[13]);
+        cpu_stl_data(env, ea+56, env->active_tc.gpr_d[14]);
+        cpu_stl_data(env, ea+60, env->active_tc.gpr_d[15]);
+    } else {
+        cpu_stl_data(env, ea+4, env->active_tc.gpr_a[11]);
+        cpu_stl_data(env, ea+8, env->active_tc.gpr_a[2]);
+        cpu_stl_data(env, ea+12, env->active_tc.gpr_a[3]);
+        cpu_stl_data(env, ea+16, env->active_tc.gpr_d[0]);
+        cpu_stl_data(env, ea+20, env->active_tc.gpr_d[1]);
+        cpu_stl_data(env, ea+24, env->active_tc.gpr_d[2]);
+        cpu_stl_data(env, ea+28, env->active_tc.gpr_d[3]);
+        cpu_stl_data(env, ea+32, env->active_tc.gpr_a[4]);
+        cpu_stl_data(env, ea+36, env->active_tc.gpr_a[5]);
+        cpu_stl_data(env, ea+40, env->active_tc.gpr_a[6]);
+        cpu_stl_data(env, ea+44, env->active_tc.gpr_a[7]);
+        cpu_stl_data(env, ea+48, env->active_tc.gpr_d[4]);
+        cpu_stl_data(env, ea+52, env->active_tc.gpr_d[5]);
+        cpu_stl_data(env, ea+56, env->active_tc.gpr_d[6]);
+        cpu_stl_data(env, ea+60, env->active_tc.gpr_d[7]);
+    }
+}
+
+static void restore_context(CPUTRICOREState *env, int ea, int ul,
+                            target_ulong *new_PCXI, target_ulong *new_PSW)
+{
+    *new_PCXI = cpu_ldl_data(env, ea);
+    if (ul == CONTEXT_UPPER) {
+        *new_PSW = cpu_ldl_data(env, ea+4);
+        env->active_tc.gpr_a[10] = cpu_ldl_data(env, ea+8);
+        env->active_tc.gpr_a[11] = cpu_ldl_data(env, ea+12);
+        env->active_tc.gpr_d[8]  = cpu_ldl_data(env, ea+16);
+        env->active_tc.gpr_d[9]  = cpu_ldl_data(env, ea+20);
+        env->active_tc.gpr_d[10] = cpu_ldl_data(env, ea+24);
+        env->active_tc.gpr_d[11] = cpu_ldl_data(env, ea+28);
+        env->active_tc.gpr_a[12] = cpu_ldl_data(env, ea+32);
+        env->active_tc.gpr_a[13] = cpu_ldl_data(env, ea+36);
+        env->active_tc.gpr_a[14] = cpu_ldl_data(env, ea+40);
+        env->active_tc.gpr_a[15] = cpu_ldl_data(env, ea+44);
+        env->active_tc.gpr_d[12] = cpu_ldl_data(env, ea+48);
+        env->active_tc.gpr_d[13] = cpu_ldl_data(env, ea+52);
+        env->active_tc.gpr_d[14] = cpu_ldl_data(env, ea+56);
+        env->active_tc.gpr_d[15] = cpu_ldl_data(env, ea+60);
+    } else {
+        env->active_tc.gpr_a[11] = cpu_ldl_data(env, ea+4);
+        env->active_tc.gpr_a[2]  = cpu_ldl_data(env, ea+8);
+        env->active_tc.gpr_a[3]  = cpu_ldl_data(env, ea+12);
+        env->active_tc.gpr_d[0]  = cpu_ldl_data(env, ea+16);
+        env->active_tc.gpr_d[1]  = cpu_ldl_data(env, ea+20);
+        env->active_tc.gpr_d[2]  = cpu_ldl_data(env, ea+24);
+        env->active_tc.gpr_d[3]  = cpu_ldl_data(env, ea+28);
+        env->active_tc.gpr_a[4]  = cpu_ldl_data(env, ea+32);
+        env->active_tc.gpr_a[5]  = cpu_ldl_data(env, ea+36);
+        env->active_tc.gpr_a[6]  = cpu_ldl_data(env, ea+40);
+        env->active_tc.gpr_a[7]  = cpu_ldl_data(env, ea+44);
+        env->active_tc.gpr_d[4]  = cpu_ldl_data(env, ea+48);
+        env->active_tc.gpr_d[5]  = cpu_ldl_data(env, ea+52);
+        env->active_tc.gpr_d[6]  = cpu_ldl_data(env, ea+56);
+        env->active_tc.gpr_d[7]  = cpu_ldl_data(env, ea+60);
+    }
+    cpu_stl_data(env, ea, env->active_tc.FCX);
+}
+
+void helper_call(CPUTRICOREState *env, uint32_t pc,
+                               uint32_t insnsize)
+{
+    target_ulong ret_address;
+    target_ulong tmp_FCX;
+    target_ulong ea;
+    target_ulong new_FCX;
+
+    /* if (FCX == 0) trap(FCU); */
+    if (env->active_tc.FCX == 0) {
+        printf("FCU trap");
+    }
+    /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */
+    if (env->active_tc.PSW & MASK_PSW_CDE) {
+        if (cdc_increment(&(env->active_tc))) {
+            printf("CDO trap\n");
+        }
+    }
+    /* PSW.CDE = 1;*/
+    env->active_tc.PSW |= MASK_PSW_CDE;
+    /* ret_addr = PC + 4; */
+    ret_address = pc + insnsize;
+    /* tmp_FCX = FCX; */
+    tmp_FCX = env->active_tc.FCX;
+    /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */
+    ea = ((env->active_tc.FCX & MASK_FCX_FCXS) << 12) +
+         ((env->active_tc.FCX & MASK_FCX_FCXO) << 6);
+    /* new_FCX = M(EA, word);
+       M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11],
+                          A[12], A[13], A[14], A[15], D[12], D[13], D[14],
+                          D[15]}; */
+    save_context(env, ea, 1, &new_FCX);
+
+    /* PCXI.PCPN = ICR.CCPN; */
+    env->active_tc.PCXI = (env->active_tc.PCXI & 0xffffff) +
+              ((env->active_tc.ICR & MASK_ICR_CCPN) << 24);
+    /* PCXI.PIE = ICR.IE; */
+    env->active_tc.PCXI = ((env->active_tc.PCXI & ~MASK_PCXI_PIE) +
+                           ((env->active_tc.ICR & MASK_ICR_IE) << 15));
+    /* PCXI.UL = 1; */
+    env->active_tc.PCXI |= MASK_PCXI_UL;
+
+    /* PCXI[19: 0] = FCX[19: 0]; */
+    env->active_tc.PCXI = (env->active_tc.PCXI & 0xfff00000) +
+                          (env->active_tc.FCX & 0xfffff);
+    /* FCX[19: 0] = new_FCX[19: 0]; */
+    env->active_tc.FCX = (env->active_tc.FCX & 0xfff00000) +
+                         (new_FCX & 0xfffff);
+    /* A[11] = ret_addr[31: 0]; */
+    env->active_tc.gpr_a[11] = ret_address;
+
+    /* if (tmp_FCX == LCX) trap(FCD);*/
+    if (tmp_FCX == env->active_tc.LCX) {
+        printf("FCD trap\n");
+    }
+}
+
+void helper_ret(CPUTRICOREState *env)
+{
+    target_ulong ea;
+    target_ulong new_PCXI;
+    target_ulong new_PSW;
+     /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/
+    if (env->active_tc.PSW & MASK_PSW_CDE) {
+        if (cdc_decrement(&(env->active_tc))) {
+            printf("CDU trap\n");
+        }
+    }
+    /*   if (PCXI[19: 0] == 0) then trap(CSU); */
+    if ((env->active_tc.PCXI & 0xfffff) == 0) {
+        printf("CSU trap\n");
+    }
+    /* if (PCXI.UL == 0) then trap(CTYP); */
+    if ((env->active_tc.PCXI & MASK_PCXI_UL) == 0) {
+        printf("CTYP trap\n");
+    }
+    /* PC = {A11 [31: 1], 1’b0}; */
+    env->active_tc.PC = env->active_tc.gpr_a[11] & 0xfffffffe;
+
+    /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
+    ea = ((env->active_tc.PCXI & MASK_PCXI_PCXS) << 12) +
+         ((env->active_tc.PCXI & MASK_PCXI_PCXO) << 6);
+    /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12],
+        A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word);
+        M(EA, word) = FCX; */
+    restore_context(env, ea, CONTEXT_UPPER, &new_PCXI, &new_PSW);
+    /* FCX[19: 0] = PCXI[19: 0]; */
+    env->active_tc.FCX = (env->active_tc.FCX & 0xfff00000) +
+                         (env->active_tc.PCXI & 0x000fffff);
+    /* PCXI = new_PCXI; */
+    env->active_tc.PCXI = new_PCXI;
+}
+
 static inline void QEMU_NORETURN do_raise_exception_err(CPUTRICOREState *env,
                                                         uint32_t exception,
                                                         int error_code,
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 39f29bb..f32e1d1 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -117,6 +117,15 @@ static int sign_extend(uint32_t val, uint32_t width)
  * Functions to generate micro-ops
  */
 
+/* Makros for generating helpers */
+#define gen_helper_2arg(name, arg0, arg1) do {                    \
+    TCGv_i32 helper_tmp0 = tcg_const_i32(arg0);                   \
+    TCGv_i32 helper_tmp1 = tcg_const_i32(arg1);                   \
+    gen_helper_##name(cpu_env, helper_tmp0, helper_tmp1);         \
+    tcg_temp_free_i32(helper_tmp0);                               \
+    tcg_temp_free_i32(helper_tmp1);                               \
+    } while (0)
+
 /* Functions for load/save to/from memory */
 #define OP_MEM_INDIRECT(insn)                                             \
 static inline void gen_indirect_##insn(DisasContext *ctx, TCGv r1, TCGv r2, \
@@ -241,6 +250,64 @@ static inline void gen_ssov(TCGv ret, TCGv arg, int32_t 
cons)
     tcg_temp_free(temp);
 }
 
+/* helpers for generating program flow micro-ops */
+
+static inline void gen_save_pc(target_ulong pc)
+{
+    tcg_gen_movi_tl(cpu_PC, pc);
+}
+
+static inline void gen_branch_cond(DisasContext *ctx, int cond, TCGv r1,
+                                   TCGv r2, int16_t address)
+{
+    int jumpLabel;
+    jumpLabel = gen_new_label();
+    tcg_gen_brcond_tl(cond, r1, r2, jumpLabel);
+
+    gen_save_pc(ctx->pc + insn_bytes);
+    tcg_gen_exit_tb(0);
+
+    gen_set_label(jumpLabel);
+    gen_save_pc(ctx->pc + address * 2);
+    tcg_gen_exit_tb(0);
+
+}
+
+static inline void gen_branch_condi(DisasContext *ctx, int cond, TCGv r1,
+                                   int r2, int16_t address)
+{
+    TCGv temp = tcg_const_i32(r2);
+    gen_branch_cond(ctx, cond, r1, temp, address);
+    tcg_temp_free(temp);
+}
+
+static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
+                   int r1, int r2 , int32_t constant , int32_t offset)
+{
+
+    switch (opc) {
+/* SB-format jumps */
+    case OPC1_16_SB_J:
+    case OPC1_32_B_J:
+        gen_save_pc(ctx->pc+offset*2);
+        tcg_gen_exit_tb(0);
+        break;
+    case OPC1_16_SB_CALL:
+        gen_helper_2arg(call, ctx->pc, insn_bytes);
+        gen_save_pc(ctx->pc+sign_extend(offset, 7)*2);
+        tcg_gen_exit_tb(0);
+    case OPC1_16_SB_JZ:
+        gen_branch_condi(ctx, TCG_COND_EQ, cpu_gpr_d[15], 0, offset);
+        break;
+    case OPC1_16_SB_JNZ:
+        gen_branch_condi(ctx, TCG_COND_NE, cpu_gpr_d[15], 0, offset);
+        break;
+    default:
+            printf("Branch Error at %x\n", ctx->pc);
+    }
+    ctx->bstate = BS_BRANCH;
+}
+
 /*
  * Functions for decoding instructions
  */
@@ -249,6 +316,7 @@ static void decode_16Bit_opc(CPUTRICOREState *env, 
DisasContext *ctx)
     target_ulong op1;
     int r1, r2;
     uint16_t const16;
+    int32_t address;
     TCGv temp;
 
     op1 = MASK_OP_MAJOR(ctx->opcode);
@@ -541,6 +609,23 @@ static void decode_16Bit_opc(CPUTRICOREState *env, 
DisasContext *ctx)
         const16 = MASK_OP_SLRO_OFF4(ctx->opcode);
         gen_indirect_ld32s(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4);
         break;
+/* SB-format */
+    case OPC1_16_SB_CALL:
+        address = MASK_OP_SB_DISP8(ctx->opcode);
+        gen_compute_branch(ctx, op1, 0, 0, 0, address);
+        break;
+    case OPC1_16_SB_J:
+        address = MASK_OP_SB_DISP8(ctx->opcode);
+        gen_compute_branch(ctx, op1, 0, 0, 0, address);
+        break;
+    case OPC1_16_SB_JNZ:
+        address = sign_extend(MASK_OP_SB_DISP8(ctx->opcode), 7);
+        gen_compute_branch(ctx, op1, 0, 0, 0, address);
+        break;
+    case OPC1_16_SB_JZ:
+        address = sign_extend(MASK_OP_SB_DISP8(ctx->opcode), 7);
+        gen_compute_branch(ctx, op1, 0, 0, 0, address);
+        break;
     }
 }
 
-- 
2.0.1




reply via email to

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