Peter Maydell | ea99dde | 2016-01-26 18:16:57 +0000 | [diff] [blame] | 1 | #include "qemu/osdep.h" |
Blue Swirl | 3e45717 | 2011-07-13 12:44:15 +0000 | [diff] [blame] | 2 | #include "cpu.h" |
Richard Henderson | 2ef6175 | 2014-04-07 22:31:41 -0700 | [diff] [blame] | 3 | #include "exec/helper-proto.h" |
Paolo Bonzini | 1de7afc | 2012-12-17 18:20:00 +0100 | [diff] [blame] | 4 | #include "qemu/host-utils.h" |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 5 | |
Paolo Bonzini | 0d09e41 | 2013-02-05 17:06:20 +0100 | [diff] [blame] | 6 | #include "hw/lm32/lm32_pic.h" |
Andreas Färber | 0ee1024 | 2013-07-24 22:49:02 +0200 | [diff] [blame] | 7 | #include "hw/char/lm32_juart.h" |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 8 | |
Paolo Bonzini | 63c9155 | 2016-03-15 13:18:37 +0100 | [diff] [blame] | 9 | #include "exec/exec-all.h" |
Paolo Bonzini | f08b617 | 2014-03-28 19:42:10 +0100 | [diff] [blame] | 10 | #include "exec/cpu_ldst.h" |
Richard Henderson | b1669e5 | 2013-08-27 13:03:27 -0700 | [diff] [blame] | 11 | |
Michael Walle | 667ff96 | 2013-09-23 20:47:33 +0200 | [diff] [blame] | 12 | #ifndef CONFIG_USER_ONLY |
| 13 | #include "sysemu/sysemu.h" |
| 14 | #endif |
| 15 | |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 16 | #if !defined(CONFIG_USER_ONLY) |
Michael Walle | 3dd3a2b | 2013-09-18 19:10:45 +0200 | [diff] [blame] | 17 | void raise_exception(CPULM32State *env, int index) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 18 | { |
Andreas Färber | 2710342 | 2013-08-26 08:31:06 +0200 | [diff] [blame] | 19 | CPUState *cs = CPU(lm32_env_get_cpu(env)); |
| 20 | |
| 21 | cs->exception_index = index; |
Andreas Färber | 5638d18 | 2013-08-27 17:52:12 +0200 | [diff] [blame] | 22 | cpu_loop_exit(cs); |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 23 | } |
| 24 | |
Michael Walle | 3dd3a2b | 2013-09-18 19:10:45 +0200 | [diff] [blame] | 25 | void HELPER(raise_exception)(CPULM32State *env, uint32_t index) |
| 26 | { |
| 27 | raise_exception(env, index); |
| 28 | } |
| 29 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 30 | void HELPER(hlt)(CPULM32State *env) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 31 | { |
Andreas Färber | 259186a | 2013-01-17 18:51:17 +0100 | [diff] [blame] | 32 | CPUState *cs = CPU(lm32_env_get_cpu(env)); |
| 33 | |
| 34 | cs->halted = 1; |
Andreas Färber | 2710342 | 2013-08-26 08:31:06 +0200 | [diff] [blame] | 35 | cs->exception_index = EXCP_HLT; |
Andreas Färber | 5638d18 | 2013-08-27 17:52:12 +0200 | [diff] [blame] | 36 | cpu_loop_exit(cs); |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 37 | } |
| 38 | |
Michael Walle | 667ff96 | 2013-09-23 20:47:33 +0200 | [diff] [blame] | 39 | void HELPER(ill)(CPULM32State *env) |
| 40 | { |
| 41 | #ifndef CONFIG_USER_ONLY |
| 42 | CPUState *cs = CPU(lm32_env_get_cpu(env)); |
| 43 | fprintf(stderr, "VM paused due to illegal instruction. " |
| 44 | "Connect a debugger or switch to the monitor console " |
| 45 | "to find out more.\n"); |
Paolo Bonzini | 74892d2 | 2014-06-05 14:53:58 +0200 | [diff] [blame] | 46 | vm_stop(RUN_STATE_PAUSED); |
Michael Walle | 667ff96 | 2013-09-23 20:47:33 +0200 | [diff] [blame] | 47 | cs->halted = 1; |
| 48 | raise_exception(env, EXCP_HALTED); |
| 49 | #endif |
| 50 | } |
| 51 | |
Michael Walle | 3dd3a2b | 2013-09-18 19:10:45 +0200 | [diff] [blame] | 52 | void HELPER(wcsr_bp)(CPULM32State *env, uint32_t bp, uint32_t idx) |
| 53 | { |
| 54 | uint32_t addr = bp & ~1; |
| 55 | |
| 56 | assert(idx < 4); |
| 57 | |
| 58 | env->bp[idx] = bp; |
| 59 | lm32_breakpoint_remove(env, idx); |
| 60 | if (bp & 1) { |
| 61 | lm32_breakpoint_insert(env, idx, addr); |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | void HELPER(wcsr_wp)(CPULM32State *env, uint32_t wp, uint32_t idx) |
| 66 | { |
| 67 | lm32_wp_t wp_type; |
| 68 | |
| 69 | assert(idx < 4); |
| 70 | |
| 71 | env->wp[idx] = wp; |
| 72 | |
| 73 | wp_type = lm32_wp_type(env->dc, idx); |
| 74 | lm32_watchpoint_remove(env, idx); |
| 75 | if (wp_type != LM32_WP_DISABLED) { |
| 76 | lm32_watchpoint_insert(env, idx, wp, wp_type); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | void HELPER(wcsr_dc)(CPULM32State *env, uint32_t dc) |
| 81 | { |
| 82 | uint32_t old_dc; |
| 83 | int i; |
| 84 | lm32_wp_t old_type; |
| 85 | lm32_wp_t new_type; |
| 86 | |
| 87 | old_dc = env->dc; |
| 88 | env->dc = dc; |
| 89 | |
| 90 | for (i = 0; i < 4; i++) { |
| 91 | old_type = lm32_wp_type(old_dc, i); |
| 92 | new_type = lm32_wp_type(dc, i); |
| 93 | |
| 94 | if (old_type != new_type) { |
| 95 | lm32_watchpoint_remove(env, i); |
| 96 | if (new_type != LM32_WP_DISABLED) { |
| 97 | lm32_watchpoint_insert(env, i, env->wp[i], new_type); |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 103 | void HELPER(wcsr_im)(CPULM32State *env, uint32_t im) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 104 | { |
| 105 | lm32_pic_set_im(env->pic_state, im); |
| 106 | } |
| 107 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 108 | void HELPER(wcsr_ip)(CPULM32State *env, uint32_t im) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 109 | { |
| 110 | lm32_pic_set_ip(env->pic_state, im); |
| 111 | } |
| 112 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 113 | void HELPER(wcsr_jtx)(CPULM32State *env, uint32_t jtx) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 114 | { |
| 115 | lm32_juart_set_jtx(env->juart_state, jtx); |
| 116 | } |
| 117 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 118 | void HELPER(wcsr_jrx)(CPULM32State *env, uint32_t jrx) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 119 | { |
| 120 | lm32_juart_set_jrx(env->juart_state, jrx); |
| 121 | } |
| 122 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 123 | uint32_t HELPER(rcsr_im)(CPULM32State *env) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 124 | { |
| 125 | return lm32_pic_get_im(env->pic_state); |
| 126 | } |
| 127 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 128 | uint32_t HELPER(rcsr_ip)(CPULM32State *env) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 129 | { |
| 130 | return lm32_pic_get_ip(env->pic_state); |
| 131 | } |
| 132 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 133 | uint32_t HELPER(rcsr_jtx)(CPULM32State *env) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 134 | { |
| 135 | return lm32_juart_get_jtx(env->juart_state); |
| 136 | } |
| 137 | |
Michael Walle | 6635075 | 2013-03-03 23:17:48 +0100 | [diff] [blame] | 138 | uint32_t HELPER(rcsr_jrx)(CPULM32State *env) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 139 | { |
| 140 | return lm32_juart_get_jrx(env->juart_state); |
| 141 | } |
| 142 | |
| 143 | /* Try to fill the TLB and return an exception if error. If retaddr is |
Andreas Färber | d5a11fe | 2013-08-27 00:28:06 +0200 | [diff] [blame] | 144 | * NULL, it means that the function was called in C code (i.e. not |
| 145 | * from generated code or from helper.c) |
| 146 | */ |
Sergey Sorokin | b35399b | 2016-06-14 15:26:17 +0300 | [diff] [blame] | 147 | void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, |
| 148 | int mmu_idx, uintptr_t retaddr) |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 149 | { |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 150 | int ret; |
| 151 | |
Sergey Sorokin | b35399b | 2016-06-14 15:26:17 +0300 | [diff] [blame] | 152 | ret = lm32_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx); |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 153 | if (unlikely(ret)) { |
| 154 | if (retaddr) { |
| 155 | /* now we have a real cpu fault */ |
Andreas Färber | 3f38f30 | 2013-09-01 16:51:34 +0200 | [diff] [blame] | 156 | cpu_restore_state(cs, retaddr); |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 157 | } |
Andreas Färber | 5638d18 | 2013-08-27 17:52:12 +0200 | [diff] [blame] | 158 | cpu_loop_exit(cs); |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 159 | } |
Michael Walle | 143e895 | 2011-02-17 23:45:04 +0100 | [diff] [blame] | 160 | } |
| 161 | #endif |
| 162 | |