root / target-lm32 / helper.c @ 36802b6b
History | View | Annotate | Download (6.5 kB)
1 | 17c0fa3d | Michael Walle | /*
|
---|---|---|---|
2 | 17c0fa3d | Michael Walle | * LatticeMico32 helper routines.
|
3 | 17c0fa3d | Michael Walle | *
|
4 | 17c0fa3d | Michael Walle | * Copyright (c) 2010 Michael Walle <michael@walle.cc>
|
5 | 17c0fa3d | Michael Walle | *
|
6 | 17c0fa3d | Michael Walle | * This library is free software; you can redistribute it and/or
|
7 | 17c0fa3d | Michael Walle | * modify it under the terms of the GNU Lesser General Public
|
8 | 17c0fa3d | Michael Walle | * License as published by the Free Software Foundation; either
|
9 | 17c0fa3d | Michael Walle | * version 2 of the License, or (at your option) any later version.
|
10 | 17c0fa3d | Michael Walle | *
|
11 | 17c0fa3d | Michael Walle | * This library is distributed in the hope that it will be useful,
|
12 | 17c0fa3d | Michael Walle | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | 17c0fa3d | Michael Walle | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | 17c0fa3d | Michael Walle | * Lesser General Public License for more details.
|
15 | 17c0fa3d | Michael Walle | *
|
16 | 17c0fa3d | Michael Walle | * You should have received a copy of the GNU Lesser General Public
|
17 | 17c0fa3d | Michael Walle | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
18 | 17c0fa3d | Michael Walle | */
|
19 | 17c0fa3d | Michael Walle | |
20 | 17c0fa3d | Michael Walle | #include <stdio.h> |
21 | 17c0fa3d | Michael Walle | #include <string.h> |
22 | 17c0fa3d | Michael Walle | #include <assert.h> |
23 | 17c0fa3d | Michael Walle | |
24 | 17c0fa3d | Michael Walle | #include "config.h" |
25 | 17c0fa3d | Michael Walle | #include "cpu.h" |
26 | 17c0fa3d | Michael Walle | #include "exec-all.h" |
27 | 17c0fa3d | Michael Walle | #include "host-utils.h" |
28 | 17c0fa3d | Michael Walle | |
29 | 17c0fa3d | Michael Walle | int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw, |
30 | 17c0fa3d | Michael Walle | int mmu_idx, int is_softmmu) |
31 | 17c0fa3d | Michael Walle | { |
32 | 17c0fa3d | Michael Walle | int prot;
|
33 | 17c0fa3d | Michael Walle | |
34 | 17c0fa3d | Michael Walle | address &= TARGET_PAGE_MASK; |
35 | 17c0fa3d | Michael Walle | prot = PAGE_BITS; |
36 | 17c0fa3d | Michael Walle | if (env->flags & LM32_FLAG_IGNORE_MSB) {
|
37 | 17c0fa3d | Michael Walle | tlb_set_page(env, address, address & 0x7fffffff, prot, mmu_idx,
|
38 | 17c0fa3d | Michael Walle | TARGET_PAGE_SIZE); |
39 | 17c0fa3d | Michael Walle | } else {
|
40 | 17c0fa3d | Michael Walle | tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); |
41 | 17c0fa3d | Michael Walle | } |
42 | 17c0fa3d | Michael Walle | |
43 | 17c0fa3d | Michael Walle | return 0; |
44 | 17c0fa3d | Michael Walle | } |
45 | 17c0fa3d | Michael Walle | |
46 | 17c0fa3d | Michael Walle | target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
47 | 17c0fa3d | Michael Walle | { |
48 | 17c0fa3d | Michael Walle | return addr & TARGET_PAGE_MASK;
|
49 | 17c0fa3d | Michael Walle | } |
50 | 17c0fa3d | Michael Walle | |
51 | 17c0fa3d | Michael Walle | void do_interrupt(CPUState *env)
|
52 | 17c0fa3d | Michael Walle | { |
53 | 17c0fa3d | Michael Walle | qemu_log_mask(CPU_LOG_INT, |
54 | 17c0fa3d | Michael Walle | "exception at pc=%x type=%x\n", env->pc, env->exception_index);
|
55 | 17c0fa3d | Michael Walle | |
56 | 17c0fa3d | Michael Walle | switch (env->exception_index) {
|
57 | 17c0fa3d | Michael Walle | case EXCP_INSN_BUS_ERROR:
|
58 | 17c0fa3d | Michael Walle | case EXCP_DATA_BUS_ERROR:
|
59 | 17c0fa3d | Michael Walle | case EXCP_DIVIDE_BY_ZERO:
|
60 | 17c0fa3d | Michael Walle | case EXCP_IRQ:
|
61 | 17c0fa3d | Michael Walle | case EXCP_SYSTEMCALL:
|
62 | 17c0fa3d | Michael Walle | /* non-debug exceptions */
|
63 | 17c0fa3d | Michael Walle | env->regs[R_EA] = env->pc; |
64 | 17c0fa3d | Michael Walle | env->ie |= (env->ie & IE_IE) ? IE_EIE : 0;
|
65 | 17c0fa3d | Michael Walle | env->ie &= ~IE_IE; |
66 | 17c0fa3d | Michael Walle | if (env->dc & DC_RE) {
|
67 | 17c0fa3d | Michael Walle | env->pc = env->deba + (env->exception_index * 32);
|
68 | 17c0fa3d | Michael Walle | } else {
|
69 | 17c0fa3d | Michael Walle | env->pc = env->eba + (env->exception_index * 32);
|
70 | 17c0fa3d | Michael Walle | } |
71 | 17c0fa3d | Michael Walle | log_cpu_state_mask(CPU_LOG_INT, env, 0);
|
72 | 17c0fa3d | Michael Walle | break;
|
73 | 17c0fa3d | Michael Walle | case EXCP_BREAKPOINT:
|
74 | 17c0fa3d | Michael Walle | case EXCP_WATCHPOINT:
|
75 | 17c0fa3d | Michael Walle | /* debug exceptions */
|
76 | 17c0fa3d | Michael Walle | env->regs[R_BA] = env->pc; |
77 | 17c0fa3d | Michael Walle | env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
|
78 | 17c0fa3d | Michael Walle | env->ie &= ~IE_IE; |
79 | ecbe1de8 | Michael Walle | env->pc = env->deba + (env->exception_index * 32);
|
80 | 17c0fa3d | Michael Walle | log_cpu_state_mask(CPU_LOG_INT, env, 0);
|
81 | 17c0fa3d | Michael Walle | break;
|
82 | 17c0fa3d | Michael Walle | default:
|
83 | 17c0fa3d | Michael Walle | cpu_abort(env, "unhandled exception type=%d\n",
|
84 | 17c0fa3d | Michael Walle | env->exception_index); |
85 | 17c0fa3d | Michael Walle | break;
|
86 | 17c0fa3d | Michael Walle | } |
87 | 17c0fa3d | Michael Walle | } |
88 | 17c0fa3d | Michael Walle | |
89 | 17c0fa3d | Michael Walle | typedef struct { |
90 | 17c0fa3d | Michael Walle | const char *name; |
91 | 17c0fa3d | Michael Walle | uint32_t revision; |
92 | 17c0fa3d | Michael Walle | uint8_t num_interrupts; |
93 | 17c0fa3d | Michael Walle | uint8_t num_breakpoints; |
94 | 17c0fa3d | Michael Walle | uint8_t num_watchpoints; |
95 | 17c0fa3d | Michael Walle | uint32_t features; |
96 | 17c0fa3d | Michael Walle | } LM32Def; |
97 | 17c0fa3d | Michael Walle | |
98 | 17c0fa3d | Michael Walle | static const LM32Def lm32_defs[] = { |
99 | 17c0fa3d | Michael Walle | { |
100 | 17c0fa3d | Michael Walle | .name = "lm32-basic",
|
101 | 17c0fa3d | Michael Walle | .revision = 3,
|
102 | 17c0fa3d | Michael Walle | .num_interrupts = 32,
|
103 | 17c0fa3d | Michael Walle | .num_breakpoints = 4,
|
104 | 17c0fa3d | Michael Walle | .num_watchpoints = 4,
|
105 | 17c0fa3d | Michael Walle | .features = (LM32_FEATURE_SHIFT |
106 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SIGN_EXTEND |
107 | 17c0fa3d | Michael Walle | | LM32_FEATURE_CYCLE_COUNT), |
108 | 17c0fa3d | Michael Walle | }, |
109 | 17c0fa3d | Michael Walle | { |
110 | 17c0fa3d | Michael Walle | .name = "lm32-standard",
|
111 | 17c0fa3d | Michael Walle | .revision = 3,
|
112 | 17c0fa3d | Michael Walle | .num_interrupts = 32,
|
113 | 17c0fa3d | Michael Walle | .num_breakpoints = 4,
|
114 | 17c0fa3d | Michael Walle | .num_watchpoints = 4,
|
115 | 17c0fa3d | Michael Walle | .features = (LM32_FEATURE_MULTIPLY |
116 | 17c0fa3d | Michael Walle | | LM32_FEATURE_DIVIDE |
117 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SHIFT |
118 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SIGN_EXTEND |
119 | 17c0fa3d | Michael Walle | | LM32_FEATURE_I_CACHE |
120 | 17c0fa3d | Michael Walle | | LM32_FEATURE_CYCLE_COUNT), |
121 | 17c0fa3d | Michael Walle | }, |
122 | 17c0fa3d | Michael Walle | { |
123 | 17c0fa3d | Michael Walle | .name = "lm32-full",
|
124 | 17c0fa3d | Michael Walle | .revision = 3,
|
125 | 17c0fa3d | Michael Walle | .num_interrupts = 32,
|
126 | 17c0fa3d | Michael Walle | .num_breakpoints = 4,
|
127 | 17c0fa3d | Michael Walle | .num_watchpoints = 4,
|
128 | 17c0fa3d | Michael Walle | .features = (LM32_FEATURE_MULTIPLY |
129 | 17c0fa3d | Michael Walle | | LM32_FEATURE_DIVIDE |
130 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SHIFT |
131 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SIGN_EXTEND |
132 | 17c0fa3d | Michael Walle | | LM32_FEATURE_I_CACHE |
133 | 17c0fa3d | Michael Walle | | LM32_FEATURE_D_CACHE |
134 | 17c0fa3d | Michael Walle | | LM32_FEATURE_CYCLE_COUNT), |
135 | 17c0fa3d | Michael Walle | } |
136 | 17c0fa3d | Michael Walle | }; |
137 | 17c0fa3d | Michael Walle | |
138 | 17c0fa3d | Michael Walle | void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf)
|
139 | 17c0fa3d | Michael Walle | { |
140 | 17c0fa3d | Michael Walle | int i;
|
141 | 17c0fa3d | Michael Walle | |
142 | 17c0fa3d | Michael Walle | cpu_fprintf(f, "Available CPUs:\n");
|
143 | 17c0fa3d | Michael Walle | for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) { |
144 | 17c0fa3d | Michael Walle | cpu_fprintf(f, " %s\n", lm32_defs[i].name);
|
145 | 17c0fa3d | Michael Walle | } |
146 | 17c0fa3d | Michael Walle | } |
147 | 17c0fa3d | Michael Walle | |
148 | 17c0fa3d | Michael Walle | static const LM32Def *cpu_lm32_find_by_name(const char *name) |
149 | 17c0fa3d | Michael Walle | { |
150 | 17c0fa3d | Michael Walle | int i;
|
151 | 17c0fa3d | Michael Walle | |
152 | 17c0fa3d | Michael Walle | for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) { |
153 | 17c0fa3d | Michael Walle | if (strcasecmp(name, lm32_defs[i].name) == 0) { |
154 | 17c0fa3d | Michael Walle | return &lm32_defs[i];
|
155 | 17c0fa3d | Michael Walle | } |
156 | 17c0fa3d | Michael Walle | } |
157 | 17c0fa3d | Michael Walle | |
158 | 17c0fa3d | Michael Walle | return NULL; |
159 | 17c0fa3d | Michael Walle | } |
160 | 17c0fa3d | Michael Walle | |
161 | 17c0fa3d | Michael Walle | static uint32_t cfg_by_def(const LM32Def *def) |
162 | 17c0fa3d | Michael Walle | { |
163 | 17c0fa3d | Michael Walle | uint32_t cfg = 0;
|
164 | 17c0fa3d | Michael Walle | |
165 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_MULTIPLY) {
|
166 | 17c0fa3d | Michael Walle | cfg |= CFG_M; |
167 | 17c0fa3d | Michael Walle | } |
168 | 17c0fa3d | Michael Walle | |
169 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_DIVIDE) {
|
170 | 17c0fa3d | Michael Walle | cfg |= CFG_D; |
171 | 17c0fa3d | Michael Walle | } |
172 | 17c0fa3d | Michael Walle | |
173 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_SHIFT) {
|
174 | 17c0fa3d | Michael Walle | cfg |= CFG_S; |
175 | 17c0fa3d | Michael Walle | } |
176 | 17c0fa3d | Michael Walle | |
177 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_SIGN_EXTEND) {
|
178 | 17c0fa3d | Michael Walle | cfg |= CFG_X; |
179 | 17c0fa3d | Michael Walle | } |
180 | 17c0fa3d | Michael Walle | |
181 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_I_CACHE) {
|
182 | 17c0fa3d | Michael Walle | cfg |= CFG_IC; |
183 | 17c0fa3d | Michael Walle | } |
184 | 17c0fa3d | Michael Walle | |
185 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_D_CACHE) {
|
186 | 17c0fa3d | Michael Walle | cfg |= CFG_DC; |
187 | 17c0fa3d | Michael Walle | } |
188 | 17c0fa3d | Michael Walle | |
189 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_CYCLE_COUNT) {
|
190 | 17c0fa3d | Michael Walle | cfg |= CFG_CC; |
191 | 17c0fa3d | Michael Walle | } |
192 | 17c0fa3d | Michael Walle | |
193 | 17c0fa3d | Michael Walle | cfg |= (def->num_interrupts << CFG_INT_SHIFT); |
194 | 17c0fa3d | Michael Walle | cfg |= (def->num_breakpoints << CFG_BP_SHIFT); |
195 | 17c0fa3d | Michael Walle | cfg |= (def->num_watchpoints << CFG_WP_SHIFT); |
196 | 17c0fa3d | Michael Walle | cfg |= (def->revision << CFG_REV_SHIFT); |
197 | 17c0fa3d | Michael Walle | |
198 | 17c0fa3d | Michael Walle | return cfg;
|
199 | 17c0fa3d | Michael Walle | } |
200 | 17c0fa3d | Michael Walle | |
201 | 17c0fa3d | Michael Walle | CPUState *cpu_lm32_init(const char *cpu_model) |
202 | 17c0fa3d | Michael Walle | { |
203 | 17c0fa3d | Michael Walle | CPUState *env; |
204 | 17c0fa3d | Michael Walle | const LM32Def *def;
|
205 | 17c0fa3d | Michael Walle | static int tcg_initialized; |
206 | 17c0fa3d | Michael Walle | |
207 | 17c0fa3d | Michael Walle | def = cpu_lm32_find_by_name(cpu_model); |
208 | 17c0fa3d | Michael Walle | if (!def) {
|
209 | 17c0fa3d | Michael Walle | return NULL; |
210 | 17c0fa3d | Michael Walle | } |
211 | 17c0fa3d | Michael Walle | |
212 | 17c0fa3d | Michael Walle | env = qemu_mallocz(sizeof(CPUState));
|
213 | 17c0fa3d | Michael Walle | |
214 | 17c0fa3d | Michael Walle | env->features = def->features; |
215 | 17c0fa3d | Michael Walle | env->num_bps = def->num_breakpoints; |
216 | 17c0fa3d | Michael Walle | env->num_wps = def->num_watchpoints; |
217 | 17c0fa3d | Michael Walle | env->cfg = cfg_by_def(def); |
218 | 17c0fa3d | Michael Walle | env->flags = 0;
|
219 | 17c0fa3d | Michael Walle | |
220 | 17c0fa3d | Michael Walle | cpu_exec_init(env); |
221 | 17c0fa3d | Michael Walle | cpu_reset(env); |
222 | 17c0fa3d | Michael Walle | |
223 | 17c0fa3d | Michael Walle | if (!tcg_initialized) {
|
224 | 17c0fa3d | Michael Walle | tcg_initialized = 1;
|
225 | 17c0fa3d | Michael Walle | lm32_translate_init(); |
226 | 17c0fa3d | Michael Walle | } |
227 | 17c0fa3d | Michael Walle | |
228 | 17c0fa3d | Michael Walle | return env;
|
229 | 17c0fa3d | Michael Walle | } |
230 | 17c0fa3d | Michael Walle | |
231 | 17c0fa3d | Michael Walle | /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
|
232 | 17c0fa3d | Michael Walle | * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
|
233 | 17c0fa3d | Michael Walle | * 0x80000000-0xffffffff is not cached and used to access IO devices. */
|
234 | 17c0fa3d | Michael Walle | void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value) |
235 | 17c0fa3d | Michael Walle | { |
236 | 17c0fa3d | Michael Walle | if (value) {
|
237 | 17c0fa3d | Michael Walle | env->flags |= LM32_FLAG_IGNORE_MSB; |
238 | 17c0fa3d | Michael Walle | } else {
|
239 | 17c0fa3d | Michael Walle | env->flags &= ~LM32_FLAG_IGNORE_MSB; |
240 | 17c0fa3d | Michael Walle | } |
241 | 17c0fa3d | Michael Walle | } |
242 | 17c0fa3d | Michael Walle | |
243 | 17c0fa3d | Michael Walle | void cpu_reset(CPUState *env)
|
244 | 17c0fa3d | Michael Walle | { |
245 | 17c0fa3d | Michael Walle | if (qemu_loglevel_mask(CPU_LOG_RESET)) {
|
246 | 17c0fa3d | Michael Walle | qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
|
247 | 17c0fa3d | Michael Walle | log_cpu_state(env, 0);
|
248 | 17c0fa3d | Michael Walle | } |
249 | 17c0fa3d | Michael Walle | |
250 | 17c0fa3d | Michael Walle | tlb_flush(env, 1);
|
251 | 17c0fa3d | Michael Walle | |
252 | 17c0fa3d | Michael Walle | /* reset cpu state */
|
253 | 17c0fa3d | Michael Walle | memset(env, 0, offsetof(CPULM32State, breakpoints));
|
254 | 17c0fa3d | Michael Walle | } |