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