aboutsummaryrefslogtreecommitdiff
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 9793d14..188bf8c 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)