]>
Commit | Line | Data |
---|---|---|
f1c671f9 MR |
1 | /* |
2 | * QEMU AVR CPU | |
3 | * | |
4 | * Copyright (c) 2019-2020 Michael Rolnik | |
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.1 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 | |
18 | * <http://www.gnu.org/licenses/lgpl-2.1.html> | |
19 | */ | |
20 | ||
21 | #include "qemu/osdep.h" | |
22 | #include "qapi/error.h" | |
23 | #include "qemu/qemu-print.h" | |
24 | #include "exec/exec-all.h" | |
25 | #include "cpu.h" | |
26 | #include "disas/dis-asm.h" | |
fafe0021 | 27 | #include "tcg/debug-assert.h" |
235948bf | 28 | #include "hw/qdev-properties.h" |
f1c671f9 MR |
29 | |
30 | static void avr_cpu_set_pc(CPUState *cs, vaddr value) | |
31 | { | |
32 | AVRCPU *cpu = AVR_CPU(cs); | |
33 | ||
34 | cpu->env.pc_w = value / 2; /* internally PC points to words */ | |
35 | } | |
36 | ||
e4fdf9df RH |
37 | static vaddr avr_cpu_get_pc(CPUState *cs) |
38 | { | |
39 | AVRCPU *cpu = AVR_CPU(cs); | |
40 | ||
41 | return cpu->env.pc_w * 2; | |
42 | } | |
43 | ||
f1c671f9 MR |
44 | static bool avr_cpu_has_work(CPUState *cs) |
45 | { | |
46 | AVRCPU *cpu = AVR_CPU(cs); | |
47 | CPUAVRState *env = &cpu->env; | |
48 | ||
49 | return (cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_RESET)) | |
50 | && cpu_interrupts_enabled(env); | |
51 | } | |
52 | ||
04a37d4c RH |
53 | static void avr_cpu_synchronize_from_tb(CPUState *cs, |
54 | const TranslationBlock *tb) | |
f1c671f9 MR |
55 | { |
56 | AVRCPU *cpu = AVR_CPU(cs); | |
57 | CPUAVRState *env = &cpu->env; | |
58 | ||
604b66ce AJ |
59 | tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL)); |
60 | env->pc_w = tb->pc / 2; /* internally PC points to words */ | |
f1c671f9 MR |
61 | } |
62 | ||
f06c1ad4 RH |
63 | static void avr_restore_state_to_opc(CPUState *cs, |
64 | const TranslationBlock *tb, | |
65 | const uint64_t *data) | |
66 | { | |
67 | AVRCPU *cpu = AVR_CPU(cs); | |
68 | CPUAVRState *env = &cpu->env; | |
69 | ||
70 | env->pc_w = data[0]; | |
71 | } | |
72 | ||
60578760 | 73 | static void avr_cpu_reset_hold(Object *obj) |
f1c671f9 | 74 | { |
60578760 | 75 | CPUState *cs = CPU(obj); |
f1c671f9 MR |
76 | AVRCPU *cpu = AVR_CPU(cs); |
77 | AVRCPUClass *mcc = AVR_CPU_GET_CLASS(cpu); | |
78 | CPUAVRState *env = &cpu->env; | |
79 | ||
60578760 PM |
80 | if (mcc->parent_phases.hold) { |
81 | mcc->parent_phases.hold(obj); | |
82 | } | |
f1c671f9 MR |
83 | |
84 | env->pc_w = 0; | |
85 | env->sregI = 1; | |
86 | env->sregC = 0; | |
87 | env->sregZ = 0; | |
88 | env->sregN = 0; | |
89 | env->sregV = 0; | |
90 | env->sregS = 0; | |
91 | env->sregH = 0; | |
92 | env->sregT = 0; | |
93 | ||
94 | env->rampD = 0; | |
95 | env->rampX = 0; | |
96 | env->rampY = 0; | |
97 | env->rampZ = 0; | |
98 | env->eind = 0; | |
235948bf | 99 | env->sp = cpu->init_sp; |
f1c671f9 MR |
100 | |
101 | env->skip = 0; | |
102 | ||
103 | memset(env->r, 0, sizeof(env->r)); | |
f1c671f9 MR |
104 | } |
105 | ||
106 | static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) | |
107 | { | |
108 | info->mach = bfd_arch_avr; | |
9d8caa67 | 109 | info->print_insn = avr_print_insn; |
f1c671f9 MR |
110 | } |
111 | ||
112 | static void avr_cpu_realizefn(DeviceState *dev, Error **errp) | |
113 | { | |
114 | CPUState *cs = CPU(dev); | |
115 | AVRCPUClass *mcc = AVR_CPU_GET_CLASS(dev); | |
116 | Error *local_err = NULL; | |
117 | ||
118 | cpu_exec_realizefn(cs, &local_err); | |
119 | if (local_err != NULL) { | |
120 | error_propagate(errp, local_err); | |
121 | return; | |
122 | } | |
123 | qemu_init_vcpu(cs); | |
124 | cpu_reset(cs); | |
125 | ||
126 | mcc->parent_realize(dev, errp); | |
127 | } | |
128 | ||
129 | static void avr_cpu_set_int(void *opaque, int irq, int level) | |
130 | { | |
131 | AVRCPU *cpu = opaque; | |
132 | CPUAVRState *env = &cpu->env; | |
133 | CPUState *cs = CPU(cpu); | |
134 | uint64_t mask = (1ull << irq); | |
135 | ||
136 | if (level) { | |
137 | env->intsrc |= mask; | |
138 | cpu_interrupt(cs, CPU_INTERRUPT_HARD); | |
139 | } else { | |
140 | env->intsrc &= ~mask; | |
141 | if (env->intsrc == 0) { | |
142 | cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); | |
143 | } | |
144 | } | |
145 | } | |
146 | ||
147 | static void avr_cpu_initfn(Object *obj) | |
148 | { | |
149 | AVRCPU *cpu = AVR_CPU(obj); | |
150 | ||
f1c671f9 MR |
151 | /* Set the number of interrupts supported by the CPU. */ |
152 | qdev_init_gpio_in(DEVICE(cpu), avr_cpu_set_int, | |
153 | sizeof(cpu->env.intsrc) * 8); | |
154 | } | |
155 | ||
235948bf GN |
156 | static Property avr_cpu_properties[] = { |
157 | DEFINE_PROP_UINT32("init-sp", AVRCPU, init_sp, 0), | |
158 | DEFINE_PROP_END_OF_LIST() | |
159 | }; | |
160 | ||
f1c671f9 MR |
161 | static ObjectClass *avr_cpu_class_by_name(const char *cpu_model) |
162 | { | |
d5be19f5 | 163 | return object_class_by_name(cpu_model); |
f1c671f9 MR |
164 | } |
165 | ||
166 | static void avr_cpu_dump_state(CPUState *cs, FILE *f, int flags) | |
167 | { | |
168 | AVRCPU *cpu = AVR_CPU(cs); | |
169 | CPUAVRState *env = &cpu->env; | |
170 | int i; | |
171 | ||
172 | qemu_fprintf(f, "\n"); | |
2e34e622 | 173 | qemu_fprintf(f, "PC: %06x\n", env->pc_w * 2); /* PC points to words */ |
f1c671f9 MR |
174 | qemu_fprintf(f, "SP: %04x\n", env->sp); |
175 | qemu_fprintf(f, "rampD: %02x\n", env->rampD >> 16); | |
176 | qemu_fprintf(f, "rampX: %02x\n", env->rampX >> 16); | |
177 | qemu_fprintf(f, "rampY: %02x\n", env->rampY >> 16); | |
178 | qemu_fprintf(f, "rampZ: %02x\n", env->rampZ >> 16); | |
179 | qemu_fprintf(f, "EIND: %02x\n", env->eind >> 16); | |
180 | qemu_fprintf(f, "X: %02x%02x\n", env->r[27], env->r[26]); | |
181 | qemu_fprintf(f, "Y: %02x%02x\n", env->r[29], env->r[28]); | |
182 | qemu_fprintf(f, "Z: %02x%02x\n", env->r[31], env->r[30]); | |
183 | qemu_fprintf(f, "SREG: [ %c %c %c %c %c %c %c %c ]\n", | |
184 | env->sregI ? 'I' : '-', | |
185 | env->sregT ? 'T' : '-', | |
186 | env->sregH ? 'H' : '-', | |
187 | env->sregS ? 'S' : '-', | |
188 | env->sregV ? 'V' : '-', | |
189 | env->sregN ? '-' : 'N', /* Zf has negative logic */ | |
190 | env->sregZ ? 'Z' : '-', | |
191 | env->sregC ? 'I' : '-'); | |
192 | qemu_fprintf(f, "SKIP: %02x\n", env->skip); | |
193 | ||
194 | qemu_fprintf(f, "\n"); | |
195 | for (i = 0; i < ARRAY_SIZE(env->r); i++) { | |
196 | qemu_fprintf(f, "R[%02d]: %02x ", i, env->r[i]); | |
197 | ||
198 | if ((i % 8) == 7) { | |
199 | qemu_fprintf(f, "\n"); | |
200 | } | |
201 | } | |
202 | qemu_fprintf(f, "\n"); | |
203 | } | |
204 | ||
8b80bd28 PMD |
205 | #include "hw/core/sysemu-cpu-ops.h" |
206 | ||
207 | static const struct SysemuCPUOps avr_sysemu_ops = { | |
08928c6d | 208 | .get_phys_page_debug = avr_cpu_get_phys_page_debug, |
8b80bd28 PMD |
209 | }; |
210 | ||
78271684 CF |
211 | #include "hw/core/tcg-cpu-ops.h" |
212 | ||
11906557 | 213 | static const struct TCGCPUOps avr_tcg_ops = { |
78271684 CF |
214 | .initialize = avr_cpu_tcg_init, |
215 | .synchronize_from_tb = avr_cpu_synchronize_from_tb, | |
f06c1ad4 | 216 | .restore_state_to_opc = avr_restore_state_to_opc, |
78271684 CF |
217 | .cpu_exec_interrupt = avr_cpu_exec_interrupt, |
218 | .tlb_fill = avr_cpu_tlb_fill, | |
78271684 | 219 | .do_interrupt = avr_cpu_do_interrupt, |
78271684 CF |
220 | }; |
221 | ||
f1c671f9 MR |
222 | static void avr_cpu_class_init(ObjectClass *oc, void *data) |
223 | { | |
224 | DeviceClass *dc = DEVICE_CLASS(oc); | |
225 | CPUClass *cc = CPU_CLASS(oc); | |
226 | AVRCPUClass *mcc = AVR_CPU_CLASS(oc); | |
60578760 | 227 | ResettableClass *rc = RESETTABLE_CLASS(oc); |
f1c671f9 | 228 | |
27aefd66 | 229 | device_class_set_parent_realize(dc, avr_cpu_realizefn, &mcc->parent_realize); |
60578760 | 230 | |
235948bf GN |
231 | device_class_set_props(dc, avr_cpu_properties); |
232 | ||
60578760 PM |
233 | resettable_class_set_parent_phases(rc, NULL, avr_cpu_reset_hold, NULL, |
234 | &mcc->parent_phases); | |
f1c671f9 MR |
235 | |
236 | cc->class_by_name = avr_cpu_class_by_name; | |
237 | ||
238 | cc->has_work = avr_cpu_has_work; | |
239 | cc->dump_state = avr_cpu_dump_state; | |
240 | cc->set_pc = avr_cpu_set_pc; | |
e4fdf9df | 241 | cc->get_pc = avr_cpu_get_pc; |
c2cf139d | 242 | dc->vmsd = &vms_avr_cpu; |
8b80bd28 | 243 | cc->sysemu_ops = &avr_sysemu_ops; |
f1c671f9 | 244 | cc->disas_set_info = avr_cpu_disas_set_info; |
12b35405 MR |
245 | cc->gdb_read_register = avr_cpu_gdb_read_register; |
246 | cc->gdb_write_register = avr_cpu_gdb_write_register; | |
e64cb6c2 | 247 | cc->gdb_adjust_breakpoint = avr_cpu_gdb_adjust_breakpoint; |
12b35405 MR |
248 | cc->gdb_num_core_regs = 35; |
249 | cc->gdb_core_xml_file = "avr-cpu.xml"; | |
78271684 | 250 | cc->tcg_ops = &avr_tcg_ops; |
f1c671f9 | 251 | } |
669d27e2 MR |
252 | |
253 | /* | |
254 | * Setting features of AVR core type avr5 | |
255 | * -------------------------------------- | |
256 | * | |
257 | * This type of AVR core is present in the following AVR MCUs: | |
258 | * | |
259 | * ata5702m322, ata5782, ata5790, ata5790n, ata5791, ata5795, ata5831, ata6613c, | |
260 | * ata6614q, ata8210, ata8510, atmega16, atmega16a, atmega161, atmega162, | |
261 | * atmega163, atmega164a, atmega164p, atmega164pa, atmega165, atmega165a, | |
262 | * atmega165p, atmega165pa, atmega168, atmega168a, atmega168p, atmega168pa, | |
263 | * atmega168pb, atmega169, atmega169a, atmega169p, atmega169pa, atmega16hvb, | |
264 | * atmega16hvbrevb, atmega16m1, atmega16u4, atmega32a, atmega32, atmega323, | |
265 | * atmega324a, atmega324p, atmega324pa, atmega325, atmega325a, atmega325p, | |
266 | * atmega325pa, atmega3250, atmega3250a, atmega3250p, atmega3250pa, atmega328, | |
267 | * atmega328p, atmega328pb, atmega329, atmega329a, atmega329p, atmega329pa, | |
268 | * atmega3290, atmega3290a, atmega3290p, atmega3290pa, atmega32c1, atmega32m1, | |
269 | * atmega32u4, atmega32u6, atmega406, atmega64, atmega64a, atmega640, atmega644, | |
270 | * atmega644a, atmega644p, atmega644pa, atmega645, atmega645a, atmega645p, | |
271 | * atmega6450, atmega6450a, atmega6450p, atmega649, atmega649a, atmega649p, | |
272 | * atmega6490, atmega16hva, atmega16hva2, atmega32hvb, atmega6490a, atmega6490p, | |
273 | * atmega64c1, atmega64m1, atmega64hve, atmega64hve2, atmega64rfr2, | |
274 | * atmega644rfr2, atmega32hvbrevb, at90can32, at90can64, at90pwm161, at90pwm216, | |
275 | * at90pwm316, at90scr100, at90usb646, at90usb647, at94k, m3000 | |
276 | */ | |
277 | static void avr_avr5_initfn(Object *obj) | |
278 | { | |
279 | AVRCPU *cpu = AVR_CPU(obj); | |
280 | CPUAVRState *env = &cpu->env; | |
281 | ||
282 | set_avr_feature(env, AVR_FEATURE_LPM); | |
283 | set_avr_feature(env, AVR_FEATURE_IJMP_ICALL); | |
284 | set_avr_feature(env, AVR_FEATURE_ADIW_SBIW); | |
285 | set_avr_feature(env, AVR_FEATURE_SRAM); | |
286 | set_avr_feature(env, AVR_FEATURE_BREAK); | |
287 | ||
288 | set_avr_feature(env, AVR_FEATURE_2_BYTE_PC); | |
289 | set_avr_feature(env, AVR_FEATURE_2_BYTE_SP); | |
290 | set_avr_feature(env, AVR_FEATURE_JMP_CALL); | |
291 | set_avr_feature(env, AVR_FEATURE_LPMX); | |
292 | set_avr_feature(env, AVR_FEATURE_MOVW); | |
293 | set_avr_feature(env, AVR_FEATURE_MUL); | |
294 | } | |
295 | ||
296 | /* | |
297 | * Setting features of AVR core type avr51 | |
298 | * -------------------------------------- | |
299 | * | |
300 | * This type of AVR core is present in the following AVR MCUs: | |
301 | * | |
302 | * atmega128, atmega128a, atmega1280, atmega1281, atmega1284, atmega1284p, | |
303 | * atmega128rfa1, atmega128rfr2, atmega1284rfr2, at90can128, at90usb1286, | |
304 | * at90usb1287 | |
305 | */ | |
306 | static void avr_avr51_initfn(Object *obj) | |
307 | { | |
308 | AVRCPU *cpu = AVR_CPU(obj); | |
309 | CPUAVRState *env = &cpu->env; | |
310 | ||
311 | set_avr_feature(env, AVR_FEATURE_LPM); | |
312 | set_avr_feature(env, AVR_FEATURE_IJMP_ICALL); | |
313 | set_avr_feature(env, AVR_FEATURE_ADIW_SBIW); | |
314 | set_avr_feature(env, AVR_FEATURE_SRAM); | |
315 | set_avr_feature(env, AVR_FEATURE_BREAK); | |
316 | ||
317 | set_avr_feature(env, AVR_FEATURE_2_BYTE_PC); | |
318 | set_avr_feature(env, AVR_FEATURE_2_BYTE_SP); | |
319 | set_avr_feature(env, AVR_FEATURE_RAMPZ); | |
320 | set_avr_feature(env, AVR_FEATURE_ELPMX); | |
321 | set_avr_feature(env, AVR_FEATURE_ELPM); | |
322 | set_avr_feature(env, AVR_FEATURE_JMP_CALL); | |
323 | set_avr_feature(env, AVR_FEATURE_LPMX); | |
324 | set_avr_feature(env, AVR_FEATURE_MOVW); | |
325 | set_avr_feature(env, AVR_FEATURE_MUL); | |
326 | } | |
327 | ||
328 | /* | |
329 | * Setting features of AVR core type avr6 | |
330 | * -------------------------------------- | |
331 | * | |
332 | * This type of AVR core is present in the following AVR MCUs: | |
333 | * | |
334 | * atmega2560, atmega2561, atmega256rfr2, atmega2564rfr2 | |
335 | */ | |
336 | static void avr_avr6_initfn(Object *obj) | |
337 | { | |
338 | AVRCPU *cpu = AVR_CPU(obj); | |
339 | CPUAVRState *env = &cpu->env; | |
340 | ||
341 | set_avr_feature(env, AVR_FEATURE_LPM); | |
342 | set_avr_feature(env, AVR_FEATURE_IJMP_ICALL); | |
343 | set_avr_feature(env, AVR_FEATURE_ADIW_SBIW); | |
344 | set_avr_feature(env, AVR_FEATURE_SRAM); | |
345 | set_avr_feature(env, AVR_FEATURE_BREAK); | |
346 | ||
347 | set_avr_feature(env, AVR_FEATURE_3_BYTE_PC); | |
348 | set_avr_feature(env, AVR_FEATURE_2_BYTE_SP); | |
349 | set_avr_feature(env, AVR_FEATURE_RAMPZ); | |
350 | set_avr_feature(env, AVR_FEATURE_EIJMP_EICALL); | |
351 | set_avr_feature(env, AVR_FEATURE_ELPMX); | |
352 | set_avr_feature(env, AVR_FEATURE_ELPM); | |
353 | set_avr_feature(env, AVR_FEATURE_JMP_CALL); | |
354 | set_avr_feature(env, AVR_FEATURE_LPMX); | |
355 | set_avr_feature(env, AVR_FEATURE_MOVW); | |
356 | set_avr_feature(env, AVR_FEATURE_MUL); | |
357 | } | |
358 | ||
359 | typedef struct AVRCPUInfo { | |
360 | const char *name; | |
361 | void (*initfn)(Object *obj); | |
362 | } AVRCPUInfo; | |
363 | ||
364 | ||
669d27e2 MR |
365 | #define DEFINE_AVR_CPU_TYPE(model, initfn) \ |
366 | { \ | |
367 | .parent = TYPE_AVR_CPU, \ | |
368 | .instance_init = initfn, \ | |
369 | .name = AVR_CPU_TYPE_NAME(model), \ | |
370 | } | |
371 | ||
372 | static const TypeInfo avr_cpu_type_info[] = { | |
373 | { | |
374 | .name = TYPE_AVR_CPU, | |
375 | .parent = TYPE_CPU, | |
376 | .instance_size = sizeof(AVRCPU), | |
f669c992 | 377 | .instance_align = __alignof(AVRCPU), |
669d27e2 MR |
378 | .instance_init = avr_cpu_initfn, |
379 | .class_size = sizeof(AVRCPUClass), | |
380 | .class_init = avr_cpu_class_init, | |
381 | .abstract = true, | |
382 | }, | |
383 | DEFINE_AVR_CPU_TYPE("avr5", avr_avr5_initfn), | |
384 | DEFINE_AVR_CPU_TYPE("avr51", avr_avr51_initfn), | |
385 | DEFINE_AVR_CPU_TYPE("avr6", avr_avr6_initfn), | |
386 | }; | |
387 | ||
388 | DEFINE_TYPES(avr_cpu_type_info) |