summary refs log tree commit diff stats
path: root/target-unicore32/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-unicore32/translate.c')
-rw-r--r--target-unicore32/translate.c159
1 files changed, 130 insertions, 29 deletions
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 9793d14c1b..188bf8c52a 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1,7 +1,7 @@
 /*
  *  UniCore32 translation
  *
- * Copyright (C) 2010-2011 GUAN Xue-tao
+ * Copyright (C) 2010-2012 Guan Xuetao
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -33,9 +33,16 @@ typedef struct DisasContext {
     int condlabel;
     struct TranslationBlock *tb;
     int singlestep_enabled;
+#ifndef CONFIG_USER_ONLY
+    int user;
+#endif
 } DisasContext;
 
-#define IS_USER(s) 1
+#ifndef CONFIG_USER_ONLY
+#define IS_USER(s)      (s->user)
+#else
+#define IS_USER(s)      1
+#endif
 
 /* These instructions trap after executing, so defer them until after the
    conditional executions state has been updated.  */
@@ -176,6 +183,73 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
                         "Illegal UniCore32 instruction %x at line %d!", \
                         insn, __LINE__)
 
+#ifndef CONFIG_USER_ONLY
+static void disas_cp0_insn(CPUUniCore32State *env, DisasContext *s,
+        uint32_t insn)
+{
+    TCGv tmp, tmp2, tmp3;
+    if ((insn & 0xfe000000) == 0xe0000000) {
+        tmp2 = new_tmp();
+        tmp3 = new_tmp();
+        tcg_gen_movi_i32(tmp2, UCOP_REG_N);
+        tcg_gen_movi_i32(tmp3, UCOP_IMM10);
+        if (UCOP_SET_L) {
+            tmp = new_tmp();
+            gen_helper_cp0_get(tmp, cpu_env, tmp2, tmp3);
+            store_reg(s, UCOP_REG_D, tmp);
+        } else {
+            tmp = load_reg(s, UCOP_REG_D);
+            gen_helper_cp0_set(cpu_env, tmp, tmp2, tmp3);
+            dead_tmp(tmp);
+        }
+        dead_tmp(tmp2);
+        dead_tmp(tmp3);
+        return;
+    }
+    ILLEGAL;
+}
+
+static void disas_ocd_insn(CPUUniCore32State *env, DisasContext *s,
+        uint32_t insn)
+{
+    TCGv tmp;
+
+    if ((insn & 0xff003fff) == 0xe1000400) {
+        /*
+         * movc rd, pp.nn, #imm9
+         *      rd: UCOP_REG_D
+         *      nn: UCOP_REG_N (must be 0)
+         *      imm9: 0
+         */
+        if (UCOP_REG_N == 0) {
+            tmp = new_tmp();
+            tcg_gen_movi_i32(tmp, 0);
+            store_reg(s, UCOP_REG_D, tmp);
+            return;
+        } else {
+            ILLEGAL;
+        }
+    }
+    if ((insn & 0xff003fff) == 0xe0000401) {
+        /*
+         * movc pp.nn, rn, #imm9
+         *      rn: UCOP_REG_D
+         *      nn: UCOP_REG_N (must be 1)
+         *      imm9: 1
+         */
+        if (UCOP_REG_N == 1) {
+            tmp = load_reg(s, UCOP_REG_D);
+            gen_helper_cp1_putc(tmp);
+            dead_tmp(tmp);
+            return;
+        } else {
+            ILLEGAL;
+        }
+    }
+    ILLEGAL;
+}
+#endif
+
 static inline void gen_set_asr(TCGv var, uint32_t mask)
 {
     TCGv tmp_mask = tcg_const_i32(mask);
@@ -1124,9 +1198,18 @@ static void gen_exception_return(DisasContext *s, TCGv pc)
     s->is_jmp = DISAS_UPDATE;
 }
 
-static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
+static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s,
+        uint32_t insn)
 {
     switch (UCOP_CPNUM) {
+#ifndef CONFIG_USER_ONLY
+    case 0:
+        disas_cp0_insn(env, s, insn);
+        break;
+    case 1:
+        disas_ocd_insn(env, s, insn);
+        break;
+#endif
     case 2:
         disas_ucf64_insn(env, s, insn);
         break;
@@ -1478,12 +1561,12 @@ static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 /* load/store I_offset and R_offset */
 static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
-    unsigned int i;
+    unsigned int mmu_idx;
     TCGv tmp;
     TCGv tmp2;
 
     tmp2 = load_reg(s, UCOP_REG_N);
-    i = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
+    mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
 
     /* immediate */
     if (UCOP_SET_P) {
@@ -1493,17 +1576,17 @@ static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
     if (UCOP_SET_L) {
         /* load */
         if (UCOP_SET_B) {
-            tmp = gen_ld8u(tmp2, i);
+            tmp = gen_ld8u(tmp2, mmu_idx);
         } else {
-            tmp = gen_ld32(tmp2, i);
+            tmp = gen_ld32(tmp2, mmu_idx);
         }
     } else {
         /* store */
         tmp = load_reg(s, UCOP_REG_D);
         if (UCOP_SET_B) {
-            gen_st8(tmp, tmp2, i);
+            gen_st8(tmp, tmp2, mmu_idx);
         } else {
-            gen_st32(tmp, tmp2, i);
+            gen_st32(tmp, tmp2, mmu_idx);
         }
     }
     if (!UCOP_SET_P) {
@@ -1606,7 +1689,7 @@ static void do_ldst_hwsb(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 /* load/store multiple words */
 static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
-    unsigned int val, i;
+    unsigned int val, i, mmu_idx;
     int j, n, reg, user, loaded_base;
     TCGv tmp;
     TCGv tmp2;
@@ -1627,6 +1710,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
         }
     }
 
+    mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
     addr = load_reg(s, UCOP_REG_N);
 
     /* compute total size */
@@ -1671,7 +1755,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
         }
         if (UCOP_SET(i)) {
             if (UCOP_SET_L) { /* load */
-                tmp = gen_ld32(addr, IS_USER(s));
+                tmp = gen_ld32(addr, mmu_idx);
                 if (reg == 31) {
                     gen_bx(s, tmp);
                 } else if (user) {
@@ -1699,7 +1783,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
                 } else {
                     tmp = load_reg(s, reg);
                 }
-                gen_st32(tmp, addr, IS_USER(s));
+                gen_st32(tmp, addr, mmu_idx);
             }
             j++;
             /* no need to add after the last transfer */
@@ -1888,6 +1972,14 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
         max_insns = CF_COUNT_MASK;
     }
 
+#ifndef CONFIG_USER_ONLY
+    if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) {
+        dc->user = 1;
+    } else {
+        dc->user = 0;
+    }
+#endif
+
     gen_icount_start();
     do {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
@@ -2046,12 +2138,12 @@ static const char *cpu_mode_names[16] = {
     "UM18", "UM19", "UM1A", "EXTN", "UM1C", "UM1D", "UM1E", "SUSR"
 };
 
-#define UCF64_DUMP_STATE
-void cpu_dump_state(CPUUniCore32State *env, FILE *f, fprintf_function cpu_fprintf,
-        int flags)
+#undef UCF64_DUMP_STATE
+#ifdef UCF64_DUMP_STATE
+static void cpu_dump_state_ucf64(CPUUniCore32State *env, FILE *f,
+        fprintf_function cpu_fprintf, int flags)
 {
     int i;
-#ifdef UCF64_DUMP_STATE
     union {
         uint32_t i;
         float s;
@@ -2063,7 +2155,28 @@ void cpu_dump_state(CPUUniCore32State *env, FILE *f, fprintf_function cpu_fprint
         float64 f64;
         double d;
     } d0;
+
+    for (i = 0; i < 16; i++) {
+        d.d = env->ucf64.regs[i];
+        s0.i = d.l.lower;
+        s1.i = d.l.upper;
+        d0.f64 = d.d;
+        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g)",
+                    i * 2, (int)s0.i, s0.s,
+                    i * 2 + 1, (int)s1.i, s1.s);
+        cpu_fprintf(f, " d%02d=%" PRIx64 "(%8g)\n",
+                    i, (uint64_t)d0.f64, d0.d);
+    }
+    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->ucf64.xregs[UC32_UCF64_FPSCR]);
+}
+#else
+#define cpu_dump_state_ucf64(env, file, pr, flags)      do { } while (0)
 #endif
+
+void cpu_dump_state(CPUUniCore32State *env, FILE *f,
+        fprintf_function cpu_fprintf, int flags)
+{
+    int i;
     uint32_t psr;
 
     for (i = 0; i < 32; i++) {
@@ -2083,19 +2196,7 @@ void cpu_dump_state(CPUUniCore32State *env, FILE *f, fprintf_function cpu_fprint
                 psr & (1 << 28) ? 'V' : '-',
                 cpu_mode_names[psr & 0xf]);
 
-#ifdef UCF64_DUMP_STATE
-    for (i = 0; i < 16; i++) {
-        d.d = env->ucf64.regs[i];
-        s0.i = d.l.lower;
-        s1.i = d.l.upper;
-        d0.f64 = d.d;
-        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%" PRIx64 "(%8g)\n",
-                    i * 2, (int)s0.i, s0.s,
-                    i * 2 + 1, (int)s1.i, s1.s,
-                    i, (uint64_t)d0.f64, d0.d);
-    }
-    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->ucf64.xregs[UC32_UCF64_FPSCR]);
-#endif
+    cpu_dump_state_ucf64(env, f, cpu_fprintf, flags);
 }
 
 void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, int pc_pos)