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