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