diff options
Diffstat (limited to 'target-unicore32/translate.c')
-rw-r--r-- | target-unicore32/translate.c | 159 |
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) |