qemu-devel
[Top][All Lists]
Advanced

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

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


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

Add instructions of SR opcode format.
Add micro-op generator functions for saturate and rsubi.
Add helper return from exception (rfe).

Signed-off-by: Bastian Koppelmann <address@hidden>
---
 target-tricore/helper.h    |   1 +
 target-tricore/op_helper.c |  58 ++++++++++++++++++
 target-tricore/translate.c | 144 +++++++++++++++++++++++++++++++++++++--------
 3 files changed, 180 insertions(+), 23 deletions(-)

diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index 8d70784..3595e38 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -22,3 +22,4 @@ DEF_HELPER_3(shac, i32, env, i32, i32)
 DEF_HELPER_3(call, void, env, i32, i32)
 DEF_HELPER_1(ret, void, env)
 DEF_HELPER_2(bisr, void, env, i32)
+DEF_HELPER_1(rfe, void, env)
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index 499697b..dc7b9b5 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -75,6 +75,27 @@ static int cdc_decrement(TCState *tc)
     return 0;
 }
 
+static bool cdc_zero(TCState *tc)
+{
+    int i;
+    int cdc = tc->PSW & MASK_PSW_CDC;
+    /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC ==
+       7'b1111111, otherwise returns FALSE. */
+    if (cdc == 0x7f) {
+        return true;
+    }
+    /* find CDC.COUNT */
+    for (i = 7; i > 0; i--) {
+        if ((cdc & (1 << i)) == 0) {
+            if ((cdc & ~(0x7f << i)) == 0) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
 static void save_context(CPUTRICOREState *env, int ea, int ul,
                          target_ulong *new_FCX)
 {
@@ -288,6 +309,43 @@ void helper_bisr(CPUTRICOREState *env, uint32_t const9)
     }
 }
 
+void helper_rfe(CPUTRICOREState *env)
+{
+    target_ulong ea;
+    target_ulong new_PCXI;
+    target_ulong new_PSW;
+    /* 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");
+    }
+    /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */
+    if (!cdc_zero(&env->active_tc) && (env->active_tc.PSW & MASK_PSW_CDE)) {
+        printf("MNG trap\n");
+    }
+    /* ICR.IE = PCXI.PIE; */
+    env->active_tc.ICR = (env->active_tc.ICR & ~MASK_ICR_IE) +
+                         ((env->active_tc.PCXI & MASK_PCXI_PIE) >> 15);
+    /* ICR.CCPN = PCXI.PCPN; */
+    env->active_tc.ICR = (env->active_tc.ICR & ~MASK_ICR_CCPN) +
+                         ((env->active_tc.PCXI & MASK_PCXI_PCPN) >> 24);
+    /*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, 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 628bd8b..44b9af6 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -156,6 +156,38 @@ OP_MEM_INDIRECT(st32)
 
 /* Functions for arithmetic instructions  */
 
+static void gen_saturate(TCGv ret, TCGv arg, int32_t up, int32_t low)
+{
+    TCGv sat_neg = tcg_const_i32(low);
+    int l1 = gen_new_label();
+    int l2 = gen_new_label();
+
+    /* sat_neg = (arg < low ) ? low : arg; */
+    tcg_gen_brcondi_tl(TCG_COND_LT, arg, low, l1);
+    tcg_gen_mov_tl(sat_neg, arg);
+    gen_set_label(l1);
+
+    /* ret = (sat_neg > up ) ? up  : sat_neg; */
+    tcg_gen_movi_tl(ret, up);
+    tcg_gen_brcondi_tl(TCG_COND_GT, sat_neg, up, l2);
+    tcg_gen_mov_tl(ret, sat_neg);
+    gen_set_label(l2);
+
+    tcg_temp_free(sat_neg);
+}
+
+static void gen_saturate_u(TCGv ret, TCGv arg, int32_t up)
+{
+    int l1 = gen_new_label();
+
+    /* sat_neg = (arg > up ) ? up : arg; */
+    tcg_gen_movi_tl(ret, up);
+    tcg_gen_brcondi_tl(TCG_COND_GTU, arg, up, l1);
+    tcg_gen_mov_tl(ret, arg);
+    gen_set_label(l1);
+
+}
+
 #define OP_COND(insn)\
 static inline void gen_cond_##insn(int cond, TCGv r1, TCGv r2, TCGv r3, \
                                    TCGv r4)                           \
@@ -205,6 +237,14 @@ static inline void gen_condi_mov(int cond, TCGv r1, 
int32_t r2, TCGv r3,
 OP_COND(add)
 OP_COND(sub)
 
+static void gen_rsubi(TCGv ret, int32_t cons, TCGv r2)
+{
+    TCGv temp = tcg_temp_new();
+    tcg_gen_movi_tl(temp, cons);
+    tcg_gen_sub_tl(ret, temp, r2);
+    tcg_temp_free(temp);
+}
+
 static void gen_sh(TCGv ret, TCGv r1, TCGv r2)
 {
     int label, label2;
@@ -384,6 +424,15 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t 
opc,
     case OPC1_16_SBR_LOOP:
         gen_loop(ctx, r1, 0xffffffe0+(offset<<1));
         break;
+/* SR-format jumps */
+    case OPC1_16_SR_JI:
+        tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], 0xffffffff);
+        tcg_gen_exit_tb(0);
+        break;
+    case OPC2_16_SR_RET:
+        gen_helper_ret(cpu_env);
+        tcg_gen_exit_tb(0);
+        break;
     default:
             printf("Branch Error at %x\n", ctx->pc);
     }
@@ -393,6 +442,63 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t 
opc,
 /*
  * Functions for decoding instructions
  */
+
+static void decode_sr_system(CPUTRICOREState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    op2 = MASK_OP_SR_OP2(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_16_SR_NOP:
+        printf("NOP Instruction at %08x\n", ctx->pc);
+        ctx->bstate = BS_STOP;
+        break;
+    case OPC2_16_SR_RET:
+        gen_compute_branch(ctx, op2, 0, 0, 0, 0);
+        break;
+    case OPC2_16_SR_RFE:
+        gen_helper_rfe(cpu_env);
+        break;
+    case OPC2_16_SR_DEBUG:
+        printf("DEBUG Instruction at %08x\n", ctx->pc);
+        ctx->bstate = BS_STOP;
+            break;
+    default:
+        printf("default sr_system Instruction at %08x\n", ctx->pc);
+    }
+}
+
+static void decode_sr_accu(CPUTRICOREState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    uint32_t r1;
+
+    r1 = MASK_OP_SR_S1D(ctx->opcode);
+    op2 = MASK_OP_SR_OP2(ctx->opcode);
+
+    switch (op2) {
+
+    case OPC2_16_SR_RSUB:
+        gen_rsubi(cpu_gpr_d[r1], 0, cpu_gpr_d[r1]);
+        break;
+    case OPC2_16_SR_SAT_B:
+        gen_saturate(cpu_gpr_d[r1], cpu_gpr_d[r1], 0x7f, -0x80);
+        break;
+    case OPC2_16_SR_SAT_BU:
+        gen_saturate_u(cpu_gpr_d[r1], cpu_gpr_d[r1], 0xff);
+        break;
+    case OPC2_16_SR_SAT_H:
+        gen_saturate(cpu_gpr_d[r1], cpu_gpr_d[r1], 0x7fff, -0x8000);
+        break;
+    case OPC2_16_SR_SAT_HU:
+        gen_saturate_u(cpu_gpr_d[r1], cpu_gpr_d[r1], 0xffff);
+        break;
+    default:
+        printf("default sr_accu Instruction at %08x\n", ctx->pc);
+        break;
+    }
+}
+
 static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx)
 {
     target_ulong op1;
@@ -905,32 +1011,24 @@ static void decode_16Bit_opc(CPUTRICOREState *env, 
DisasContext *ctx)
         const16 = MASK_OP_SSRO_OFF4(ctx->opcode);
         gen_indirect_st32(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4);
         break;
-/* SSRO-format */
-    case OPC1_16_SSRO_ST_A:
-        r1 = MASK_OP_SSRO_S1(ctx->opcode);
-        const16 = MASK_OP_SSRO_OFF4(ctx->opcode);
-        gen_indirect_st32(ctx, cpu_gpr_a[r1], cpu_gpr_a[15], const16 * 4);
+/* SR-format */
+    case OPCM_16_SR_SYSTEM:
+        decode_sr_system(env, ctx);
         break;
-    case OPC1_16_SSRO_ST_B:
-        r1 = MASK_OP_SSRO_S1(ctx->opcode);
-        const16 = MASK_OP_SSRO_OFF4(ctx->opcode);
-        temp = tcg_temp_new();
-        tcg_gen_andi_tl(temp, cpu_gpr_d[r1], 0xff);
-        gen_indirect_st8(ctx, temp, cpu_gpr_a[15], const16);
-        tcg_temp_free(temp);
+    case OPCM_16_SR_ACCU:
+        decode_sr_accu(env, ctx);
         break;
-    case OPC1_16_SSRO_ST_H:
-        r1 = MASK_OP_SSRO_S1(ctx->opcode);
-        const16 = MASK_OP_SSRO_OFF4(ctx->opcode);
-        temp = tcg_temp_new();
-        tcg_gen_andi_tl(temp, cpu_gpr_d[r1], 0xffff);
-        gen_indirect_st16(ctx, temp, cpu_gpr_a[15], const16 * 2);
-        tcg_temp_free(temp);
+    case OPC1_16_SR_JI:
+        r1 = MASK_OP_SR_S1D(ctx->opcode);
+        gen_compute_branch(ctx, op1, r1, 0, 0, 0);
         break;
-    case OPC1_16_SSRO_ST_W:
-        r1 = MASK_OP_SSRO_S1(ctx->opcode);
-        const16 = MASK_OP_SSRO_OFF4(ctx->opcode);
-        gen_indirect_st32(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4);
+    case OPC1_16_SR_NOT:
+        if (MASK_OP_SR_OP2(ctx->opcode) == 0x0) {
+            printf("Wrong OP2 at at %08x\n", ctx->pc);
+            break;
+        }
+        r1 = MASK_OP_SR_S1D(ctx->opcode);
+        tcg_gen_not_tl(cpu_gpr_d[r1], cpu_gpr_d[r1]);
         break;
     }
 }
-- 
2.0.1




reply via email to

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