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