diff options
author | Guan Xuetao <gxt@mprc.pku.edu.cn> | 2012-08-10 14:42:22 +0800 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2012-08-11 09:36:56 +0000 |
commit | 527d9979b401fea5588b202fab930d1565f13bb1 (patch) | |
tree | df6539ea2d743210fe71eea49520d60005f65a4b /target-unicore32/helper.c | |
parent | 4f23a1e645d4bfba620a63ba2c54c1813bcbfb63 (diff) |
unicore32-softmmu: Add coprocessor 0(sysctrl) and 1(ocd) instruction support
Coprocessor 0 is system control coprocessor, and we need get/set its contents.
Also, all cache/tlb ops shoule be implemented here, but just ignored with no harm.
Coprocessor 1 is OCD (on-chip-debugger), which is used for faked console,
so we could output chars to this console without graphic card.
TODO: curses display should be added lator for screen output.
Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-unicore32/helper.c')
-rw-r--r-- | target-unicore32/helper.c | 185 |
1 files changed, 148 insertions, 37 deletions
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c index 9b8ff06d5c..f9f1960817 100644 --- a/target-unicore32/helper.c +++ b/target-unicore32/helper.c @@ -14,6 +14,14 @@ #include "helper.h" #include "host-utils.h" +#undef DEBUG_UC32 + +#ifdef DEBUG_UC32 +#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__) +#else +#define DPRINTF(fmt, ...) do {} while (0) +#endif + CPUUniCore32State *uc32_cpu_init(const char *cpu_model) { UniCore32CPU *cpu; @@ -45,6 +53,146 @@ uint32_t HELPER(clz)(uint32_t x) return clz32(x); } +#ifndef CONFIG_USER_ONLY +void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg, + uint32_t cop) +{ + /* + * movc pp.nn, rn, #imm9 + * rn: UCOP_REG_D + * nn: UCOP_REG_N + * 1: sys control reg. + * 2: page table base reg. + * 3: data fault status reg. + * 4: insn fault status reg. + * 5: cache op. reg. + * 6: tlb op. reg. + * imm9: split UCOP_IMM10 with bit5 is 0 + */ + switch (creg) { + case 1: + if (cop != 0) { + goto unrecognized; + } + env->cp0.c1_sys = val; + break; + case 2: + if (cop != 0) { + goto unrecognized; + } + env->cp0.c2_base = val; + break; + case 3: + if (cop != 0) { + goto unrecognized; + } + env->cp0.c3_faultstatus = val; + break; + case 4: + if (cop != 0) { + goto unrecognized; + } + env->cp0.c4_faultaddr = val; + break; + case 5: + switch (cop) { + case 28: + DPRINTF("Invalidate Entire I&D cache\n"); + return; + case 20: + DPRINTF("Invalidate Entire Icache\n"); + return; + case 12: + DPRINTF("Invalidate Entire Dcache\n"); + return; + case 10: + DPRINTF("Clean Entire Dcache\n"); + return; + case 14: + DPRINTF("Flush Entire Dcache\n"); + return; + case 13: + DPRINTF("Invalidate Dcache line\n"); + return; + case 11: + DPRINTF("Clean Dcache line\n"); + return; + case 15: + DPRINTF("Flush Dcache line\n"); + return; + } + break; + case 6: + if ((cop <= 6) && (cop >= 2)) { + /* invalid all tlb */ + tlb_flush(env, 1); + return; + } + break; + default: + goto unrecognized; + } + return; +unrecognized: + DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n", + creg, cop); +} + +uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop) +{ + /* + * movc rd, pp.nn, #imm9 + * rd: UCOP_REG_D + * nn: UCOP_REG_N + * 0: cpuid and cachetype + * 1: sys control reg. + * 2: page table base reg. + * 3: data fault status reg. + * 4: insn fault status reg. + * imm9: split UCOP_IMM10 with bit5 is 0 + */ + switch (creg) { + case 0: + switch (cop) { + case 0: + return env->cp0.c0_cpuid; + case 1: + return env->cp0.c0_cachetype; + } + break; + case 1: + if (cop == 0) { + return env->cp0.c1_sys; + } + break; + case 2: + if (cop == 0) { + return env->cp0.c2_base; + } + break; + case 3: + if (cop == 0) { + return env->cp0.c3_faultstatus; + } + break; + case 4: + if (cop == 0) { + return env->cp0.c4_faultaddr; + } + break; + } + DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n", + creg, cop); + return 0; +} + +void helper_cp1_putc(target_ulong x) +{ + /* TODO: curses display should be added here for screen output. */ + DPRINTF("%c", x); +} +#endif + #ifdef CONFIG_USER_ONLY void switch_mode(CPUUniCore32State *env, int mode) { @@ -66,43 +214,6 @@ int uc32_cpu_handle_mmu_fault(CPUUniCore32State *env, target_ulong address, } #endif -/* These should probably raise undefined insn exceptions. */ -void HELPER(set_cp)(CPUUniCore32State *env, uint32_t insn, uint32_t val) -{ - int op1 = (insn >> 8) & 0xf; - cpu_abort(env, "cp%i insn %08x\n", op1, insn); - return; -} - -uint32_t HELPER(get_cp)(CPUUniCore32State *env, uint32_t insn) -{ - int op1 = (insn >> 8) & 0xf; - cpu_abort(env, "cp%i insn %08x\n", op1, insn); - return 0; -} - -void HELPER(set_cp0)(CPUUniCore32State *env, uint32_t insn, uint32_t val) -{ - cpu_abort(env, "cp0 insn %08x\n", insn); -} - -uint32_t HELPER(get_cp0)(CPUUniCore32State *env, uint32_t insn) -{ - cpu_abort(env, "cp0 insn %08x\n", insn); - return 0; -} - -void HELPER(set_r29_banked)(CPUUniCore32State *env, uint32_t mode, uint32_t val) -{ - cpu_abort(env, "banked r29 write\n"); -} - -uint32_t HELPER(get_r29_banked)(CPUUniCore32State *env, uint32_t mode) -{ - cpu_abort(env, "banked r29 read\n"); - return 0; -} - /* UniCore-F64 support. We follow the convention used for F64 instrunctions: Single precition routines have a "s" suffix, double precision a "d" suffix. */ |