root / target-lm32 / helper.c @ 7267c094
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 "host-utils.h" |
27 | 17c0fa3d | Michael Walle | |
28 | 17c0fa3d | Michael Walle | int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw, |
29 | 97b348e7 | Blue Swirl | int mmu_idx)
|
30 | 17c0fa3d | Michael Walle | { |
31 | 17c0fa3d | Michael Walle | int prot;
|
32 | 17c0fa3d | Michael Walle | |
33 | 17c0fa3d | Michael Walle | address &= TARGET_PAGE_MASK; |
34 | 17c0fa3d | Michael Walle | prot = PAGE_BITS; |
35 | 17c0fa3d | Michael Walle | if (env->flags & LM32_FLAG_IGNORE_MSB) {
|
36 | 17c0fa3d | Michael Walle | tlb_set_page(env, address, address & 0x7fffffff, prot, mmu_idx,
|
37 | 17c0fa3d | Michael Walle | TARGET_PAGE_SIZE); |
38 | 17c0fa3d | Michael Walle | } else {
|
39 | 17c0fa3d | Michael Walle | tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); |
40 | 17c0fa3d | Michael Walle | } |
41 | 17c0fa3d | Michael Walle | |
42 | 17c0fa3d | Michael Walle | return 0; |
43 | 17c0fa3d | Michael Walle | } |
44 | 17c0fa3d | Michael Walle | |
45 | 17c0fa3d | Michael Walle | target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
46 | 17c0fa3d | Michael Walle | { |
47 | 17c0fa3d | Michael Walle | return addr & TARGET_PAGE_MASK;
|
48 | 17c0fa3d | Michael Walle | } |
49 | 17c0fa3d | Michael Walle | |
50 | 17c0fa3d | Michael Walle | void do_interrupt(CPUState *env)
|
51 | 17c0fa3d | Michael Walle | { |
52 | 17c0fa3d | Michael Walle | qemu_log_mask(CPU_LOG_INT, |
53 | 17c0fa3d | Michael Walle | "exception at pc=%x type=%x\n", env->pc, env->exception_index);
|
54 | 17c0fa3d | Michael Walle | |
55 | 17c0fa3d | Michael Walle | switch (env->exception_index) {
|
56 | 17c0fa3d | Michael Walle | case EXCP_INSN_BUS_ERROR:
|
57 | 17c0fa3d | Michael Walle | case EXCP_DATA_BUS_ERROR:
|
58 | 17c0fa3d | Michael Walle | case EXCP_DIVIDE_BY_ZERO:
|
59 | 17c0fa3d | Michael Walle | case EXCP_IRQ:
|
60 | 17c0fa3d | Michael Walle | case EXCP_SYSTEMCALL:
|
61 | 17c0fa3d | Michael Walle | /* non-debug exceptions */
|
62 | 17c0fa3d | Michael Walle | env->regs[R_EA] = env->pc; |
63 | 17c0fa3d | Michael Walle | env->ie |= (env->ie & IE_IE) ? IE_EIE : 0;
|
64 | 17c0fa3d | Michael Walle | env->ie &= ~IE_IE; |
65 | 17c0fa3d | Michael Walle | if (env->dc & DC_RE) {
|
66 | 17c0fa3d | Michael Walle | env->pc = env->deba + (env->exception_index * 32);
|
67 | 17c0fa3d | Michael Walle | } else {
|
68 | 17c0fa3d | Michael Walle | env->pc = env->eba + (env->exception_index * 32);
|
69 | 17c0fa3d | Michael Walle | } |
70 | 17c0fa3d | Michael Walle | log_cpu_state_mask(CPU_LOG_INT, env, 0);
|
71 | 17c0fa3d | Michael Walle | break;
|
72 | 17c0fa3d | Michael Walle | case EXCP_BREAKPOINT:
|
73 | 17c0fa3d | Michael Walle | case EXCP_WATCHPOINT:
|
74 | 17c0fa3d | Michael Walle | /* debug exceptions */
|
75 | 17c0fa3d | Michael Walle | env->regs[R_BA] = env->pc; |
76 | 17c0fa3d | Michael Walle | env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
|
77 | 17c0fa3d | Michael Walle | env->ie &= ~IE_IE; |
78 | ecbe1de8 | Michael Walle | env->pc = env->deba + (env->exception_index * 32);
|
79 | 17c0fa3d | Michael Walle | log_cpu_state_mask(CPU_LOG_INT, env, 0);
|
80 | 17c0fa3d | Michael Walle | break;
|
81 | 17c0fa3d | Michael Walle | default:
|
82 | 17c0fa3d | Michael Walle | cpu_abort(env, "unhandled exception type=%d\n",
|
83 | 17c0fa3d | Michael Walle | env->exception_index); |
84 | 17c0fa3d | Michael Walle | break;
|
85 | 17c0fa3d | Michael Walle | } |
86 | 17c0fa3d | Michael Walle | } |
87 | 17c0fa3d | Michael Walle | |
88 | 17c0fa3d | Michael Walle | typedef struct { |
89 | 17c0fa3d | Michael Walle | const char *name; |
90 | 17c0fa3d | Michael Walle | uint32_t revision; |
91 | 17c0fa3d | Michael Walle | uint8_t num_interrupts; |
92 | 17c0fa3d | Michael Walle | uint8_t num_breakpoints; |
93 | 17c0fa3d | Michael Walle | uint8_t num_watchpoints; |
94 | 17c0fa3d | Michael Walle | uint32_t features; |
95 | 17c0fa3d | Michael Walle | } LM32Def; |
96 | 17c0fa3d | Michael Walle | |
97 | 17c0fa3d | Michael Walle | static const LM32Def lm32_defs[] = { |
98 | 17c0fa3d | Michael Walle | { |
99 | 17c0fa3d | Michael Walle | .name = "lm32-basic",
|
100 | 17c0fa3d | Michael Walle | .revision = 3,
|
101 | 17c0fa3d | Michael Walle | .num_interrupts = 32,
|
102 | 17c0fa3d | Michael Walle | .num_breakpoints = 4,
|
103 | 17c0fa3d | Michael Walle | .num_watchpoints = 4,
|
104 | 17c0fa3d | Michael Walle | .features = (LM32_FEATURE_SHIFT |
105 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SIGN_EXTEND |
106 | 17c0fa3d | Michael Walle | | LM32_FEATURE_CYCLE_COUNT), |
107 | 17c0fa3d | Michael Walle | }, |
108 | 17c0fa3d | Michael Walle | { |
109 | 17c0fa3d | Michael Walle | .name = "lm32-standard",
|
110 | 17c0fa3d | Michael Walle | .revision = 3,
|
111 | 17c0fa3d | Michael Walle | .num_interrupts = 32,
|
112 | 17c0fa3d | Michael Walle | .num_breakpoints = 4,
|
113 | 17c0fa3d | Michael Walle | .num_watchpoints = 4,
|
114 | 17c0fa3d | Michael Walle | .features = (LM32_FEATURE_MULTIPLY |
115 | 17c0fa3d | Michael Walle | | LM32_FEATURE_DIVIDE |
116 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SHIFT |
117 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SIGN_EXTEND |
118 | 17c0fa3d | Michael Walle | | LM32_FEATURE_I_CACHE |
119 | 17c0fa3d | Michael Walle | | LM32_FEATURE_CYCLE_COUNT), |
120 | 17c0fa3d | Michael Walle | }, |
121 | 17c0fa3d | Michael Walle | { |
122 | 17c0fa3d | Michael Walle | .name = "lm32-full",
|
123 | 17c0fa3d | Michael Walle | .revision = 3,
|
124 | 17c0fa3d | Michael Walle | .num_interrupts = 32,
|
125 | 17c0fa3d | Michael Walle | .num_breakpoints = 4,
|
126 | 17c0fa3d | Michael Walle | .num_watchpoints = 4,
|
127 | 17c0fa3d | Michael Walle | .features = (LM32_FEATURE_MULTIPLY |
128 | 17c0fa3d | Michael Walle | | LM32_FEATURE_DIVIDE |
129 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SHIFT |
130 | 17c0fa3d | Michael Walle | | LM32_FEATURE_SIGN_EXTEND |
131 | 17c0fa3d | Michael Walle | | LM32_FEATURE_I_CACHE |
132 | 17c0fa3d | Michael Walle | | LM32_FEATURE_D_CACHE |
133 | 17c0fa3d | Michael Walle | | LM32_FEATURE_CYCLE_COUNT), |
134 | 17c0fa3d | Michael Walle | } |
135 | 17c0fa3d | Michael Walle | }; |
136 | 17c0fa3d | Michael Walle | |
137 | 17c0fa3d | Michael Walle | void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf)
|
138 | 17c0fa3d | Michael Walle | { |
139 | 17c0fa3d | Michael Walle | int i;
|
140 | 17c0fa3d | Michael Walle | |
141 | 17c0fa3d | Michael Walle | cpu_fprintf(f, "Available CPUs:\n");
|
142 | 17c0fa3d | Michael Walle | for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) { |
143 | 17c0fa3d | Michael Walle | cpu_fprintf(f, " %s\n", lm32_defs[i].name);
|
144 | 17c0fa3d | Michael Walle | } |
145 | 17c0fa3d | Michael Walle | } |
146 | 17c0fa3d | Michael Walle | |
147 | 17c0fa3d | Michael Walle | static const LM32Def *cpu_lm32_find_by_name(const char *name) |
148 | 17c0fa3d | Michael Walle | { |
149 | 17c0fa3d | Michael Walle | int i;
|
150 | 17c0fa3d | Michael Walle | |
151 | 17c0fa3d | Michael Walle | for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) { |
152 | 17c0fa3d | Michael Walle | if (strcasecmp(name, lm32_defs[i].name) == 0) { |
153 | 17c0fa3d | Michael Walle | return &lm32_defs[i];
|
154 | 17c0fa3d | Michael Walle | } |
155 | 17c0fa3d | Michael Walle | } |
156 | 17c0fa3d | Michael Walle | |
157 | 17c0fa3d | Michael Walle | return NULL; |
158 | 17c0fa3d | Michael Walle | } |
159 | 17c0fa3d | Michael Walle | |
160 | 17c0fa3d | Michael Walle | static uint32_t cfg_by_def(const LM32Def *def) |
161 | 17c0fa3d | Michael Walle | { |
162 | 17c0fa3d | Michael Walle | uint32_t cfg = 0;
|
163 | 17c0fa3d | Michael Walle | |
164 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_MULTIPLY) {
|
165 | 17c0fa3d | Michael Walle | cfg |= CFG_M; |
166 | 17c0fa3d | Michael Walle | } |
167 | 17c0fa3d | Michael Walle | |
168 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_DIVIDE) {
|
169 | 17c0fa3d | Michael Walle | cfg |= CFG_D; |
170 | 17c0fa3d | Michael Walle | } |
171 | 17c0fa3d | Michael Walle | |
172 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_SHIFT) {
|
173 | 17c0fa3d | Michael Walle | cfg |= CFG_S; |
174 | 17c0fa3d | Michael Walle | } |
175 | 17c0fa3d | Michael Walle | |
176 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_SIGN_EXTEND) {
|
177 | 17c0fa3d | Michael Walle | cfg |= CFG_X; |
178 | 17c0fa3d | Michael Walle | } |
179 | 17c0fa3d | Michael Walle | |
180 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_I_CACHE) {
|
181 | 17c0fa3d | Michael Walle | cfg |= CFG_IC; |
182 | 17c0fa3d | Michael Walle | } |
183 | 17c0fa3d | Michael Walle | |
184 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_D_CACHE) {
|
185 | 17c0fa3d | Michael Walle | cfg |= CFG_DC; |
186 | 17c0fa3d | Michael Walle | } |
187 | 17c0fa3d | Michael Walle | |
188 | 17c0fa3d | Michael Walle | if (def->features & LM32_FEATURE_CYCLE_COUNT) {
|
189 | 17c0fa3d | Michael Walle | cfg |= CFG_CC; |
190 | 17c0fa3d | Michael Walle | } |
191 | 17c0fa3d | Michael Walle | |
192 | 17c0fa3d | Michael Walle | cfg |= (def->num_interrupts << CFG_INT_SHIFT); |
193 | 17c0fa3d | Michael Walle | cfg |= (def->num_breakpoints << CFG_BP_SHIFT); |
194 | 17c0fa3d | Michael Walle | cfg |= (def->num_watchpoints << CFG_WP_SHIFT); |
195 | 17c0fa3d | Michael Walle | cfg |= (def->revision << CFG_REV_SHIFT); |
196 | 17c0fa3d | Michael Walle | |
197 | 17c0fa3d | Michael Walle | return cfg;
|
198 | 17c0fa3d | Michael Walle | } |
199 | 17c0fa3d | Michael Walle | |
200 | 17c0fa3d | Michael Walle | CPUState *cpu_lm32_init(const char *cpu_model) |
201 | 17c0fa3d | Michael Walle | { |
202 | 17c0fa3d | Michael Walle | CPUState *env; |
203 | 17c0fa3d | Michael Walle | const LM32Def *def;
|
204 | 17c0fa3d | Michael Walle | static int tcg_initialized; |
205 | 17c0fa3d | Michael Walle | |
206 | 17c0fa3d | Michael Walle | def = cpu_lm32_find_by_name(cpu_model); |
207 | 17c0fa3d | Michael Walle | if (!def) {
|
208 | 17c0fa3d | Michael Walle | return NULL; |
209 | 17c0fa3d | Michael Walle | } |
210 | 17c0fa3d | Michael Walle | |
211 | 7267c094 | Anthony Liguori | env = g_malloc0(sizeof(CPUState));
|
212 | 17c0fa3d | Michael Walle | |
213 | 17c0fa3d | Michael Walle | env->features = def->features; |
214 | 17c0fa3d | Michael Walle | env->num_bps = def->num_breakpoints; |
215 | 17c0fa3d | Michael Walle | env->num_wps = def->num_watchpoints; |
216 | 17c0fa3d | Michael Walle | env->cfg = cfg_by_def(def); |
217 | 17c0fa3d | Michael Walle | env->flags = 0;
|
218 | 17c0fa3d | Michael Walle | |
219 | 17c0fa3d | Michael Walle | cpu_exec_init(env); |
220 | 17c0fa3d | Michael Walle | cpu_reset(env); |
221 | 17c0fa3d | Michael Walle | |
222 | 17c0fa3d | Michael Walle | if (!tcg_initialized) {
|
223 | 17c0fa3d | Michael Walle | tcg_initialized = 1;
|
224 | 17c0fa3d | Michael Walle | lm32_translate_init(); |
225 | 17c0fa3d | Michael Walle | } |
226 | 17c0fa3d | Michael Walle | |
227 | 17c0fa3d | Michael Walle | return env;
|
228 | 17c0fa3d | Michael Walle | } |
229 | 17c0fa3d | Michael Walle | |
230 | 17c0fa3d | Michael Walle | /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
|
231 | 17c0fa3d | Michael Walle | * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
|
232 | 17c0fa3d | Michael Walle | * 0x80000000-0xffffffff is not cached and used to access IO devices. */
|
233 | 17c0fa3d | Michael Walle | void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value) |
234 | 17c0fa3d | Michael Walle | { |
235 | 17c0fa3d | Michael Walle | if (value) {
|
236 | 17c0fa3d | Michael Walle | env->flags |= LM32_FLAG_IGNORE_MSB; |
237 | 17c0fa3d | Michael Walle | } else {
|
238 | 17c0fa3d | Michael Walle | env->flags &= ~LM32_FLAG_IGNORE_MSB; |
239 | 17c0fa3d | Michael Walle | } |
240 | 17c0fa3d | Michael Walle | } |
241 | 17c0fa3d | Michael Walle | |
242 | 17c0fa3d | Michael Walle | void cpu_reset(CPUState *env)
|
243 | 17c0fa3d | Michael Walle | { |
244 | 17c0fa3d | Michael Walle | if (qemu_loglevel_mask(CPU_LOG_RESET)) {
|
245 | 17c0fa3d | Michael Walle | qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
|
246 | 17c0fa3d | Michael Walle | log_cpu_state(env, 0);
|
247 | 17c0fa3d | Michael Walle | } |
248 | 17c0fa3d | Michael Walle | |
249 | 17c0fa3d | Michael Walle | tlb_flush(env, 1);
|
250 | 17c0fa3d | Michael Walle | |
251 | 17c0fa3d | Michael Walle | /* reset cpu state */
|
252 | 17c0fa3d | Michael Walle | memset(env, 0, offsetof(CPULM32State, breakpoints));
|
253 | 17c0fa3d | Michael Walle | } |