1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "cpu.h"
23#include "exec/exec-all.h"
24#include "exec/gdbstub.h"
25
26#include "exec/helper-proto.h"
27#include "fpu/softfloat.h"
28
29#define SIGNBIT (1u << 31)
30
31
32static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
33{
34 ObjectClass *class_a = (ObjectClass *)a;
35 ObjectClass *class_b = (ObjectClass *)b;
36 const char *name_a, *name_b;
37
38 name_a = object_class_get_name(class_a);
39 name_b = object_class_get_name(class_b);
40 if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
41 return 1;
42 } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
43 return -1;
44 } else {
45 return strcasecmp(name_a, name_b);
46 }
47}
48
49static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
50{
51 ObjectClass *c = data;
52 CPUListState *s = user_data;
53 const char *typename;
54 char *name;
55
56 typename = object_class_get_name(c);
57 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
58 (*s->cpu_fprintf)(s->file, "%s\n",
59 name);
60 g_free(name);
61}
62
63void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
64{
65 CPUListState s = {
66 .file = f,
67 .cpu_fprintf = cpu_fprintf,
68 };
69 GSList *list;
70
71 list = object_class_get_list(TYPE_M68K_CPU, false);
72 list = g_slist_sort(list, m68k_cpu_list_compare);
73 g_slist_foreach(list, m68k_cpu_list_entry, &s);
74 g_slist_free(list);
75}
76
77static int cf_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
78{
79 if (n < 8) {
80 float_status s;
81 stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
82 return 8;
83 }
84 switch (n) {
85 case 8:
86 stl_be_p(mem_buf, env->fpcr);
87 return 4;
88 case 9:
89 stl_be_p(mem_buf, env->fpsr);
90 return 4;
91 case 10:
92 memset(mem_buf, 0, 4);
93 return 4;
94 }
95 return 0;
96}
97
98static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
99{
100 if (n < 8) {
101 float_status s;
102 env->fregs[n].d = float64_to_floatx80(ldfq_p(mem_buf), &s);
103 return 8;
104 }
105 switch (n) {
106 case 8:
107 cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
108 return 4;
109 case 9:
110 env->fpsr = ldl_p(mem_buf);
111 return 4;
112 case 10:
113 return 4;
114 }
115 return 0;
116}
117
118static int m68k_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
119{
120 if (n < 8) {
121 stw_be_p(mem_buf, env->fregs[n].l.upper);
122 memset(mem_buf + 2, 0, 2);
123 stq_be_p(mem_buf + 4, env->fregs[n].l.lower);
124 return 12;
125 }
126 switch (n) {
127 case 8:
128 stl_be_p(mem_buf, env->fpcr);
129 return 4;
130 case 9:
131 stl_be_p(mem_buf, env->fpsr);
132 return 4;
133 case 10:
134 memset(mem_buf, 0, 4);
135 return 4;
136 }
137 return 0;
138}
139
140static int m68k_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
141{
142 if (n < 8) {
143 env->fregs[n].l.upper = lduw_be_p(mem_buf);
144 env->fregs[n].l.lower = ldq_be_p(mem_buf + 4);
145 return 12;
146 }
147 switch (n) {
148 case 8:
149 cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
150 return 4;
151 case 9:
152 env->fpsr = ldl_p(mem_buf);
153 return 4;
154 case 10:
155 return 4;
156 }
157 return 0;
158}
159
160void m68k_cpu_init_gdb(M68kCPU *cpu)
161{
162 CPUState *cs = CPU(cpu);
163 CPUM68KState *env = &cpu->env;
164
165 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
166 gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
167 11, "cf-fp.xml", 18);
168 } else if (m68k_feature(env, M68K_FEATURE_FPU)) {
169 gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg,
170 m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", 18);
171 }
172
173}
174
175void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
176{
177 M68kCPU *cpu = m68k_env_get_cpu(env);
178
179 switch (reg) {
180 case M68K_CR_CACR:
181 env->cacr = val;
182 m68k_switch_sp(env);
183 break;
184 case M68K_CR_ACR0:
185 case M68K_CR_ACR1:
186 case M68K_CR_ACR2:
187 case M68K_CR_ACR3:
188
189 break;
190 case M68K_CR_VBR:
191 env->vbr = val;
192 break;
193
194 default:
195 cpu_abort(CPU(cpu),
196 "Unimplemented control register write 0x%x = 0x%x\n",
197 reg, val);
198 }
199}
200
201void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
202{
203 M68kCPU *cpu = m68k_env_get_cpu(env);
204
205 switch (reg) {
206
207 case M68K_CR_SFC:
208 env->sfc = val & 7;
209 return;
210 case M68K_CR_DFC:
211 env->dfc = val & 7;
212 return;
213 case M68K_CR_VBR:
214 env->vbr = val;
215 return;
216
217 case M68K_CR_CACR:
218 env->cacr = val;
219 m68k_switch_sp(env);
220 return;
221
222 case M68K_CR_TC:
223 env->mmu.tcr = val;
224 return;
225 case M68K_CR_MMUSR:
226 env->mmu.mmusr = val;
227 return;
228 case M68K_CR_SRP:
229 env->mmu.srp = val;
230 return;
231 case M68K_CR_URP:
232 env->mmu.urp = val;
233 return;
234 case M68K_CR_USP:
235 env->sp[M68K_USP] = val;
236 return;
237 case M68K_CR_MSP:
238 env->sp[M68K_SSP] = val;
239 return;
240 case M68K_CR_ISP:
241 env->sp[M68K_ISP] = val;
242 return;
243
244 case M68K_CR_ITT0:
245 env->mmu.ttr[M68K_ITTR0] = val;
246 return;
247 case M68K_CR_ITT1:
248 env->mmu.ttr[M68K_ITTR1] = val;
249 return;
250 case M68K_CR_DTT0:
251 env->mmu.ttr[M68K_DTTR0] = val;
252 return;
253 case M68K_CR_DTT1:
254 env->mmu.ttr[M68K_DTTR1] = val;
255 return;
256 }
257 cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
258 reg, val);
259}
260
261uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg)
262{
263 M68kCPU *cpu = m68k_env_get_cpu(env);
264
265 switch (reg) {
266
267 case M68K_CR_SFC:
268 return env->sfc;
269 case M68K_CR_DFC:
270 return env->dfc;
271 case M68K_CR_VBR:
272 return env->vbr;
273
274 case M68K_CR_CACR:
275 return env->cacr;
276
277 case M68K_CR_TC:
278 return env->mmu.tcr;
279 case M68K_CR_MMUSR:
280 return env->mmu.mmusr;
281 case M68K_CR_SRP:
282 return env->mmu.srp;
283 case M68K_CR_USP:
284 return env->sp[M68K_USP];
285 case M68K_CR_MSP:
286 return env->sp[M68K_SSP];
287 case M68K_CR_ISP:
288 return env->sp[M68K_ISP];
289
290 case M68K_CR_URP:
291 return env->mmu.urp;
292 case M68K_CR_ITT0:
293 return env->mmu.ttr[M68K_ITTR0];
294 case M68K_CR_ITT1:
295 return env->mmu.ttr[M68K_ITTR1];
296 case M68K_CR_DTT0:
297 return env->mmu.ttr[M68K_DTTR0];
298 case M68K_CR_DTT1:
299 return env->mmu.ttr[M68K_DTTR1];
300 }
301 cpu_abort(CPU(cpu), "Unimplemented control register read 0x%x\n",
302 reg);
303}
304
305void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
306{
307 uint32_t acc;
308 int8_t exthigh;
309 uint8_t extlow;
310 uint64_t regval;
311 int i;
312 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
313 for (i = 0; i < 4; i++) {
314 regval = env->macc[i];
315 exthigh = regval >> 40;
316 if (env->macsr & MACSR_FI) {
317 acc = regval >> 8;
318 extlow = regval;
319 } else {
320 acc = regval;
321 extlow = regval >> 32;
322 }
323 if (env->macsr & MACSR_FI) {
324 regval = (((uint64_t)acc) << 8) | extlow;
325 regval |= ((int64_t)exthigh) << 40;
326 } else if (env->macsr & MACSR_SU) {
327 regval = acc | (((int64_t)extlow) << 32);
328 regval |= ((int64_t)exthigh) << 40;
329 } else {
330 regval = acc | (((uint64_t)extlow) << 32);
331 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
332 }
333 env->macc[i] = regval;
334 }
335 }
336 env->macsr = val;
337}
338
339void m68k_switch_sp(CPUM68KState *env)
340{
341 int new_sp;
342
343 env->sp[env->current_sp] = env->aregs[7];
344 if (m68k_feature(env, M68K_FEATURE_M68000)) {
345 if (env->sr & SR_S) {
346 if (env->sr & SR_M) {
347 new_sp = M68K_SSP;
348 } else {
349 new_sp = M68K_ISP;
350 }
351 } else {
352 new_sp = M68K_USP;
353 }
354 } else {
355 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
356 ? M68K_SSP : M68K_USP;
357 }
358 env->aregs[7] = env->sp[new_sp];
359 env->current_sp = new_sp;
360}
361
362#if defined(CONFIG_USER_ONLY)
363
364int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
365 int mmu_idx)
366{
367 M68kCPU *cpu = M68K_CPU(cs);
368
369 cs->exception_index = EXCP_ACCESS;
370 cpu->env.mmu.ar = address;
371 return 1;
372}
373
374#else
375
376
377
378static void print_address_zone(FILE *f, fprintf_function cpu_fprintf,
379 uint32_t logical, uint32_t physical,
380 uint32_t size, int attr)
381{
382 cpu_fprintf(f, "%08x - %08x -> %08x - %08x %c ",
383 logical, logical + size - 1,
384 physical, physical + size - 1,
385 attr & 4 ? 'W' : '-');
386 size >>= 10;
387 if (size < 1024) {
388 cpu_fprintf(f, "(%d KiB)\n", size);
389 } else {
390 size >>= 10;
391 if (size < 1024) {
392 cpu_fprintf(f, "(%d MiB)\n", size);
393 } else {
394 size >>= 10;
395 cpu_fprintf(f, "(%d GiB)\n", size);
396 }
397 }
398}
399
400static void dump_address_map(FILE *f, fprintf_function cpu_fprintf,
401 CPUM68KState *env, uint32_t root_pointer)
402{
403 int i, j, k;
404 int tic_size, tic_shift;
405 uint32_t tib_mask;
406 uint32_t tia, tib, tic;
407 uint32_t logical = 0xffffffff, physical = 0xffffffff;
408 uint32_t first_logical = 0xffffffff, first_physical = 0xffffffff;
409 uint32_t last_logical, last_physical;
410 int32_t size;
411 int last_attr = -1, attr = -1;
412 M68kCPU *cpu = m68k_env_get_cpu(env);
413 CPUState *cs = CPU(cpu);
414
415 if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
416
417 tic_size = 32;
418 tic_shift = 13;
419 tib_mask = M68K_8K_PAGE_MASK;
420 } else {
421
422 tic_size = 64;
423 tic_shift = 12;
424 tib_mask = M68K_4K_PAGE_MASK;
425 }
426 for (i = 0; i < M68K_ROOT_POINTER_ENTRIES; i++) {
427 tia = ldl_phys(cs->as, M68K_POINTER_BASE(root_pointer) + i * 4);
428 if (!M68K_UDT_VALID(tia)) {
429 continue;
430 }
431 for (j = 0; j < M68K_ROOT_POINTER_ENTRIES; j++) {
432 tib = ldl_phys(cs->as, M68K_POINTER_BASE(tia) + j * 4);
433 if (!M68K_UDT_VALID(tib)) {
434 continue;
435 }
436 for (k = 0; k < tic_size; k++) {
437 tic = ldl_phys(cs->as, (tib & tib_mask) + k * 4);
438 if (!M68K_PDT_VALID(tic)) {
439 continue;
440 }
441 if (M68K_PDT_INDIRECT(tic)) {
442 tic = ldl_phys(cs->as, M68K_INDIRECT_POINTER(tic));
443 }
444
445 last_logical = logical;
446 logical = (i << M68K_TTS_ROOT_SHIFT) |
447 (j << M68K_TTS_POINTER_SHIFT) |
448 (k << tic_shift);
449
450 last_physical = physical;
451 physical = tic & ~((1 << tic_shift) - 1);
452
453 last_attr = attr;
454 attr = tic & ((1 << tic_shift) - 1);
455
456 if ((logical != (last_logical + (1 << tic_shift))) ||
457 (physical != (last_physical + (1 << tic_shift))) ||
458 (attr & 4) != (last_attr & 4)) {
459
460 if (first_logical != 0xffffffff) {
461 size = last_logical + (1 << tic_shift) -
462 first_logical;
463 print_address_zone(f, cpu_fprintf, first_logical,
464 first_physical, size, last_attr);
465 }
466 first_logical = logical;
467 first_physical = physical;
468 }
469 }
470 }
471 }
472 if (first_logical != logical || (attr & 4) != (last_attr & 4)) {
473 size = logical + (1 << tic_shift) - first_logical;
474 print_address_zone(f, cpu_fprintf, first_logical, first_physical, size,
475 last_attr);
476 }
477}
478
479#define DUMP_CACHEFLAGS(a) \
480 switch (a & M68K_DESC_CACHEMODE) { \
481 case M68K_DESC_CM_WRTHRU: \
482 cpu_fprintf(f, "T"); \
483 break; \
484 case M68K_DESC_CM_COPYBK: \
485 cpu_fprintf(f, "C"); \
486 break; \
487 case M68K_DESC_CM_SERIAL: \
488 cpu_fprintf(f, "S"); \
489 break; \
490 case M68K_DESC_CM_NCACHE: \
491 cpu_fprintf(f, "N"); \
492 break; \
493 }
494
495static void dump_ttr(FILE *f, fprintf_function cpu_fprintf, uint32_t ttr)
496{
497 if ((ttr & M68K_TTR_ENABLED) == 0) {
498 cpu_fprintf(f, "disabled\n");
499 return;
500 }
501 cpu_fprintf(f, "Base: 0x%08x Mask: 0x%08x Control: ",
502 ttr & M68K_TTR_ADDR_BASE,
503 (ttr & M68K_TTR_ADDR_MASK) << M68K_TTR_ADDR_MASK_SHIFT);
504 switch (ttr & M68K_TTR_SFIELD) {
505 case M68K_TTR_SFIELD_USER:
506 cpu_fprintf(f, "U");
507 break;
508 case M68K_TTR_SFIELD_SUPER:
509 cpu_fprintf(f, "S");
510 break;
511 default:
512 cpu_fprintf(f, "*");
513 break;
514 }
515 DUMP_CACHEFLAGS(ttr);
516 if (ttr & M68K_DESC_WRITEPROT) {
517 cpu_fprintf(f, "R");
518 } else {
519 cpu_fprintf(f, "W");
520 }
521 cpu_fprintf(f, " U: %d\n", (ttr & M68K_DESC_USERATTR) >>
522 M68K_DESC_USERATTR_SHIFT);
523}
524
525void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUM68KState *env)
526{
527 if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
528 cpu_fprintf(f, "Translation disabled\n");
529 return;
530 }
531 cpu_fprintf(f, "Page Size: ");
532 if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
533 cpu_fprintf(f, "8kB\n");
534 } else {
535 cpu_fprintf(f, "4kB\n");
536 }
537
538 cpu_fprintf(f, "MMUSR: ");
539 if (env->mmu.mmusr & M68K_MMU_B_040) {
540 cpu_fprintf(f, "BUS ERROR\n");
541 } else {
542 cpu_fprintf(f, "Phy=%08x Flags: ", env->mmu.mmusr & 0xfffff000);
543
544 if (env->mmu.mmusr & M68K_MMU_G_040) {
545 cpu_fprintf(f, "G");
546 } else {
547 cpu_fprintf(f, ".");
548 }
549 if (env->mmu.mmusr & M68K_MMU_S_040) {
550 cpu_fprintf(f, "S");
551 } else {
552 cpu_fprintf(f, ".");
553 }
554 if (env->mmu.mmusr & M68K_MMU_M_040) {
555 cpu_fprintf(f, "M");
556 } else {
557 cpu_fprintf(f, ".");
558 }
559 if (env->mmu.mmusr & M68K_MMU_WP_040) {
560 cpu_fprintf(f, "W");
561 } else {
562 cpu_fprintf(f, ".");
563 }
564 if (env->mmu.mmusr & M68K_MMU_T_040) {
565 cpu_fprintf(f, "T");
566 } else {
567 cpu_fprintf(f, ".");
568 }
569 if (env->mmu.mmusr & M68K_MMU_R_040) {
570 cpu_fprintf(f, "R");
571 } else {
572 cpu_fprintf(f, ".");
573 }
574 cpu_fprintf(f, " Cache: ");
575 DUMP_CACHEFLAGS(env->mmu.mmusr);
576 cpu_fprintf(f, " U: %d\n", (env->mmu.mmusr >> 8) & 3);
577 cpu_fprintf(f, "\n");
578 }
579
580 cpu_fprintf(f, "ITTR0: ");
581 dump_ttr(f, cpu_fprintf, env->mmu.ttr[M68K_ITTR0]);
582 cpu_fprintf(f, "ITTR1: ");
583 dump_ttr(f, cpu_fprintf, env->mmu.ttr[M68K_ITTR1]);
584 cpu_fprintf(f, "DTTR0: ");
585 dump_ttr(f, cpu_fprintf, env->mmu.ttr[M68K_DTTR0]);
586 cpu_fprintf(f, "DTTR1: ");
587 dump_ttr(f, cpu_fprintf, env->mmu.ttr[M68K_DTTR1]);
588
589 cpu_fprintf(f, "SRP: 0x%08x\n", env->mmu.srp);
590 dump_address_map(f, cpu_fprintf, env, env->mmu.srp);
591
592 cpu_fprintf(f, "URP: 0x%08x\n", env->mmu.urp);
593 dump_address_map(f, cpu_fprintf, env, env->mmu.urp);
594}
595
596static int check_TTR(uint32_t ttr, int *prot, target_ulong addr,
597 int access_type)
598{
599 uint32_t base, mask;
600
601
602 if ((ttr & M68K_TTR_ENABLED) == 0) {
603 return 0;
604 }
605
606
607 switch (ttr & M68K_TTR_SFIELD) {
608 case M68K_TTR_SFIELD_USER:
609
610 if ((access_type & ACCESS_SUPER) != 0) {
611 return 0;
612 }
613 break;
614 case M68K_TTR_SFIELD_SUPER:
615
616 if ((access_type & ACCESS_SUPER) == 0) {
617 return 0;
618 }
619 break;
620 default:
621
622 break;
623 }
624
625
626
627 base = ttr & M68K_TTR_ADDR_BASE;
628 mask = (ttr & M68K_TTR_ADDR_MASK) ^ M68K_TTR_ADDR_MASK;
629 mask <<= M68K_TTR_ADDR_MASK_SHIFT;
630
631 if ((addr & mask) != (base & mask)) {
632 return 0;
633 }
634
635 *prot = PAGE_READ | PAGE_EXEC;
636 if ((ttr & M68K_DESC_WRITEPROT) == 0) {
637 *prot |= PAGE_WRITE;
638 }
639
640 return 1;
641}
642
643static int get_physical_address(CPUM68KState *env, hwaddr *physical,
644 int *prot, target_ulong address,
645 int access_type, target_ulong *page_size)
646{
647 M68kCPU *cpu = m68k_env_get_cpu(env);
648 CPUState *cs = CPU(cpu);
649 uint32_t entry;
650 uint32_t next;
651 target_ulong page_mask;
652 bool debug = access_type & ACCESS_DEBUG;
653 int page_bits;
654 int i;
655
656
657 for (i = 0; i < M68K_MAX_TTR; i++) {
658 if (check_TTR(env->mmu.TTR(access_type, i),
659 prot, address, access_type)) {
660 if (access_type & ACCESS_PTEST) {
661
662 env->mmu.mmusr = M68K_MMU_T_040 | M68K_MMU_R_040;
663 }
664 *physical = address & TARGET_PAGE_MASK;
665 *page_size = TARGET_PAGE_SIZE;
666 return 0;
667 }
668 }
669
670
671 *prot = PAGE_READ | PAGE_WRITE;
672 if (access_type & ACCESS_CODE) {
673 *prot |= PAGE_EXEC;
674 }
675 if (access_type & ACCESS_SUPER) {
676 next = env->mmu.srp;
677 } else {
678 next = env->mmu.urp;
679 }
680
681
682 entry = M68K_POINTER_BASE(next) | M68K_ROOT_INDEX(address);
683
684 next = ldl_phys(cs->as, entry);
685 if (!M68K_UDT_VALID(next)) {
686 return -1;
687 }
688 if (!(next & M68K_DESC_USED) && !debug) {
689 stl_phys(cs->as, entry, next | M68K_DESC_USED);
690 }
691 if (next & M68K_DESC_WRITEPROT) {
692 if (access_type & ACCESS_PTEST) {
693 env->mmu.mmusr |= M68K_MMU_WP_040;
694 }
695 *prot &= ~PAGE_WRITE;
696 if (access_type & ACCESS_STORE) {
697 return -1;
698 }
699 }
700
701
702 entry = M68K_POINTER_BASE(next) | M68K_POINTER_INDEX(address);
703
704 next = ldl_phys(cs->as, entry);
705 if (!M68K_UDT_VALID(next)) {
706 return -1;
707 }
708 if (!(next & M68K_DESC_USED) && !debug) {
709 stl_phys(cs->as, entry, next | M68K_DESC_USED);
710 }
711 if (next & M68K_DESC_WRITEPROT) {
712 if (access_type & ACCESS_PTEST) {
713 env->mmu.mmusr |= M68K_MMU_WP_040;
714 }
715 *prot &= ~PAGE_WRITE;
716 if (access_type & ACCESS_STORE) {
717 return -1;
718 }
719 }
720
721
722 if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
723 entry = M68K_8K_PAGE_BASE(next) | M68K_8K_PAGE_INDEX(address);
724 } else {
725 entry = M68K_4K_PAGE_BASE(next) | M68K_4K_PAGE_INDEX(address);
726 }
727
728 next = ldl_phys(cs->as, entry);
729
730 if (!M68K_PDT_VALID(next)) {
731 return -1;
732 }
733 if (M68K_PDT_INDIRECT(next)) {
734 next = ldl_phys(cs->as, M68K_INDIRECT_POINTER(next));
735 }
736 if (access_type & ACCESS_STORE) {
737 if (next & M68K_DESC_WRITEPROT) {
738 if (!(next & M68K_DESC_USED) && !debug) {
739 stl_phys(cs->as, entry, next | M68K_DESC_USED);
740 }
741 } else if ((next & (M68K_DESC_MODIFIED | M68K_DESC_USED)) !=
742 (M68K_DESC_MODIFIED | M68K_DESC_USED) && !debug) {
743 stl_phys(cs->as, entry,
744 next | (M68K_DESC_MODIFIED | M68K_DESC_USED));
745 }
746 } else {
747 if (!(next & M68K_DESC_USED) && !debug) {
748 stl_phys(cs->as, entry, next | M68K_DESC_USED);
749 }
750 }
751
752 if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
753 page_bits = 13;
754 } else {
755 page_bits = 12;
756 }
757 *page_size = 1 << page_bits;
758 page_mask = ~(*page_size - 1);
759 *physical = next & page_mask;
760
761 if (access_type & ACCESS_PTEST) {
762 env->mmu.mmusr |= next & M68K_MMU_SR_MASK_040;
763 env->mmu.mmusr |= *physical & 0xfffff000;
764 env->mmu.mmusr |= M68K_MMU_R_040;
765 }
766
767 if (next & M68K_DESC_WRITEPROT) {
768 *prot &= ~PAGE_WRITE;
769 if (access_type & ACCESS_STORE) {
770 return -1;
771 }
772 }
773 if (next & M68K_DESC_SUPERONLY) {
774 if ((access_type & ACCESS_SUPER) == 0) {
775 return -1;
776 }
777 }
778
779 return 0;
780}
781
782hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
783{
784 M68kCPU *cpu = M68K_CPU(cs);
785 CPUM68KState *env = &cpu->env;
786 hwaddr phys_addr;
787 int prot;
788 int access_type;
789 target_ulong page_size;
790
791 if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
792
793 return addr;
794 }
795
796 access_type = ACCESS_DATA | ACCESS_DEBUG;
797 if (env->sr & SR_S) {
798 access_type |= ACCESS_SUPER;
799 }
800 if (get_physical_address(env, &phys_addr, &prot,
801 addr, access_type, &page_size) != 0) {
802 return -1;
803 }
804 return phys_addr;
805}
806
807int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
808 int mmu_idx)
809{
810 M68kCPU *cpu = M68K_CPU(cs);
811 CPUM68KState *env = &cpu->env;
812 hwaddr physical;
813 int prot;
814 int access_type;
815 int ret;
816 target_ulong page_size;
817
818 if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
819
820 tlb_set_page(cs, address & TARGET_PAGE_MASK,
821 address & TARGET_PAGE_MASK,
822 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
823 mmu_idx, TARGET_PAGE_SIZE);
824 return 0;
825 }
826
827 if (rw == 2) {
828 access_type = ACCESS_CODE;
829 rw = 0;
830 } else {
831 access_type = ACCESS_DATA;
832 if (rw) {
833 access_type |= ACCESS_STORE;
834 }
835 }
836
837 if (mmu_idx != MMU_USER_IDX) {
838 access_type |= ACCESS_SUPER;
839 }
840
841 ret = get_physical_address(&cpu->env, &physical, &prot,
842 address, access_type, &page_size);
843 if (ret == 0) {
844 address &= TARGET_PAGE_MASK;
845 physical += address & (page_size - 1);
846 tlb_set_page(cs, address, physical,
847 prot, mmu_idx, TARGET_PAGE_SIZE);
848 return 0;
849 }
850
851 env->mmu.ssw = M68K_ATC_040;
852 switch (size) {
853 case 1:
854 env->mmu.ssw |= M68K_BA_SIZE_BYTE;
855 break;
856 case 2:
857 env->mmu.ssw |= M68K_BA_SIZE_WORD;
858 break;
859 case 4:
860 env->mmu.ssw |= M68K_BA_SIZE_LONG;
861 break;
862 }
863 if (access_type & ACCESS_SUPER) {
864 env->mmu.ssw |= M68K_TM_040_SUPER;
865 }
866 if (access_type & ACCESS_CODE) {
867 env->mmu.ssw |= M68K_TM_040_CODE;
868 } else {
869 env->mmu.ssw |= M68K_TM_040_DATA;
870 }
871 if (!(access_type & ACCESS_STORE)) {
872 env->mmu.ssw |= M68K_RW_040;
873 }
874 env->mmu.ar = address;
875 cs->exception_index = EXCP_ACCESS;
876 return 1;
877}
878
879
880
881
882
883void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
884{
885 CPUState *cs = CPU(cpu);
886 CPUM68KState *env = &cpu->env;
887
888 env->pending_level = level;
889 env->pending_vector = vector;
890 if (level) {
891 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
892 } else {
893 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
894 }
895}
896
897#endif
898
899uint32_t HELPER(bitrev)(uint32_t x)
900{
901 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
902 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
903 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
904 return bswap32(x);
905}
906
907uint32_t HELPER(ff1)(uint32_t x)
908{
909 int n;
910 for (n = 32; x; n--)
911 x >>= 1;
912 return n;
913}
914
915uint32_t HELPER(sats)(uint32_t val, uint32_t v)
916{
917
918 if ((int32_t)v < 0) {
919 val = (((int32_t)val) >> 31) ^ SIGNBIT;
920 }
921 return val;
922}
923
924void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
925{
926 env->sr = sr & 0xffe0;
927 cpu_m68k_set_ccr(env, sr);
928 m68k_switch_sp(env);
929}
930
931void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
932{
933 cpu_m68k_set_sr(env, val);
934}
935
936
937
938
939
940void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
941{
942 uint32_t mask;
943 env->macc[dest] = env->macc[src];
944 mask = MACSR_PAV0 << dest;
945 if (env->macsr & (MACSR_PAV0 << src))
946 env->macsr |= mask;
947 else
948 env->macsr &= ~mask;
949}
950
951uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
952{
953 int64_t product;
954 int64_t res;
955
956 product = (uint64_t)op1 * op2;
957 res = (product << 24) >> 24;
958 if (res != product) {
959 env->macsr |= MACSR_V;
960 if (env->macsr & MACSR_OMC) {
961
962 if (product < 0)
963 res = ~(1ll << 50);
964 else
965 res = 1ll << 50;
966 }
967 }
968 return res;
969}
970
971uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
972{
973 uint64_t product;
974
975 product = (uint64_t)op1 * op2;
976 if (product & (0xffffffull << 40)) {
977 env->macsr |= MACSR_V;
978 if (env->macsr & MACSR_OMC) {
979
980 product = 1ll << 50;
981 } else {
982 product &= ((1ull << 40) - 1);
983 }
984 }
985 return product;
986}
987
988uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
989{
990 uint64_t product;
991 uint32_t remainder;
992
993 product = (uint64_t)op1 * op2;
994 if (env->macsr & MACSR_RT) {
995 remainder = product & 0xffffff;
996 product >>= 24;
997 if (remainder > 0x800000)
998 product++;
999 else if (remainder == 0x800000)
1000 product += (product & 1);
1001 } else {
1002 product >>= 24;
1003 }
1004 return product;
1005}
1006
1007void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
1008{
1009 int64_t tmp;
1010 int64_t result;
1011 tmp = env->macc[acc];
1012 result = ((tmp << 16) >> 16);
1013 if (result != tmp) {
1014 env->macsr |= MACSR_V;
1015 }
1016 if (env->macsr & MACSR_V) {
1017 env->macsr |= MACSR_PAV0 << acc;
1018 if (env->macsr & MACSR_OMC) {
1019
1020
1021
1022 result = (result >> 63) ^ 0x7fffffff;
1023 }
1024 }
1025 env->macc[acc] = result;
1026}
1027
1028void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
1029{
1030 uint64_t val;
1031
1032 val = env->macc[acc];
1033 if (val & (0xffffull << 48)) {
1034 env->macsr |= MACSR_V;
1035 }
1036 if (env->macsr & MACSR_V) {
1037 env->macsr |= MACSR_PAV0 << acc;
1038 if (env->macsr & MACSR_OMC) {
1039 if (val > (1ull << 53))
1040 val = 0;
1041 else
1042 val = (1ull << 48) - 1;
1043 } else {
1044 val &= ((1ull << 48) - 1);
1045 }
1046 }
1047 env->macc[acc] = val;
1048}
1049
1050void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
1051{
1052 int64_t sum;
1053 int64_t result;
1054
1055 sum = env->macc[acc];
1056 result = (sum << 16) >> 16;
1057 if (result != sum) {
1058 env->macsr |= MACSR_V;
1059 }
1060 if (env->macsr & MACSR_V) {
1061 env->macsr |= MACSR_PAV0 << acc;
1062 if (env->macsr & MACSR_OMC) {
1063 result = (result >> 63) ^ 0x7fffffffffffll;
1064 }
1065 }
1066 env->macc[acc] = result;
1067}
1068
1069void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
1070{
1071 uint64_t val;
1072 val = env->macc[acc];
1073 if (val == 0) {
1074 env->macsr |= MACSR_Z;
1075 } else if (val & (1ull << 47)) {
1076 env->macsr |= MACSR_N;
1077 }
1078 if (env->macsr & (MACSR_PAV0 << acc)) {
1079 env->macsr |= MACSR_V;
1080 }
1081 if (env->macsr & MACSR_FI) {
1082 val = ((int64_t)val) >> 40;
1083 if (val != 0 && val != -1)
1084 env->macsr |= MACSR_EV;
1085 } else if (env->macsr & MACSR_SU) {
1086 val = ((int64_t)val) >> 32;
1087 if (val != 0 && val != -1)
1088 env->macsr |= MACSR_EV;
1089 } else {
1090 if ((val >> 32) != 0)
1091 env->macsr |= MACSR_EV;
1092 }
1093}
1094
1095#define EXTSIGN(val, index) ( \
1096 (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
1097)
1098
1099#define COMPUTE_CCR(op, x, n, z, v, c) { \
1100 switch (op) { \
1101 case CC_OP_FLAGS: \
1102 \
1103 break; \
1104 case CC_OP_ADDB: \
1105 case CC_OP_ADDW: \
1106 case CC_OP_ADDL: \
1107 res = n; \
1108 src2 = v; \
1109 src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \
1110 c = x; \
1111 z = n; \
1112 v = (res ^ src1) & ~(src1 ^ src2); \
1113 break; \
1114 case CC_OP_SUBB: \
1115 case CC_OP_SUBW: \
1116 case CC_OP_SUBL: \
1117 res = n; \
1118 src2 = v; \
1119 src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \
1120 c = x; \
1121 z = n; \
1122 v = (res ^ src1) & (src1 ^ src2); \
1123 break; \
1124 case CC_OP_CMPB: \
1125 case CC_OP_CMPW: \
1126 case CC_OP_CMPL: \
1127 src1 = n; \
1128 src2 = v; \
1129 res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \
1130 n = res; \
1131 z = res; \
1132 c = src1 < src2; \
1133 v = (res ^ src1) & (src1 ^ src2); \
1134 break; \
1135 case CC_OP_LOGIC: \
1136 c = v = 0; \
1137 z = n; \
1138 break; \
1139 default: \
1140 cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op); \
1141 } \
1142} while (0)
1143
1144uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
1145{
1146 uint32_t x, c, n, z, v;
1147 uint32_t res, src1, src2;
1148
1149 x = env->cc_x;
1150 n = env->cc_n;
1151 z = env->cc_z;
1152 v = env->cc_v;
1153 c = env->cc_c;
1154
1155 COMPUTE_CCR(env->cc_op, x, n, z, v, c);
1156
1157 n = n >> 31;
1158 z = (z == 0);
1159 v = v >> 31;
1160
1161 return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
1162}
1163
1164uint32_t HELPER(get_ccr)(CPUM68KState *env)
1165{
1166 return cpu_m68k_get_ccr(env);
1167}
1168
1169void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
1170{
1171 env->cc_x = (ccr & CCF_X ? 1 : 0);
1172 env->cc_n = (ccr & CCF_N ? -1 : 0);
1173 env->cc_z = (ccr & CCF_Z ? 0 : 1);
1174 env->cc_v = (ccr & CCF_V ? -1 : 0);
1175 env->cc_c = (ccr & CCF_C ? 1 : 0);
1176 env->cc_op = CC_OP_FLAGS;
1177}
1178
1179void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
1180{
1181 cpu_m68k_set_ccr(env, ccr);
1182}
1183
1184void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
1185{
1186 uint32_t res, src1, src2;
1187
1188 COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
1189 env->cc_op = CC_OP_FLAGS;
1190}
1191
1192uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
1193{
1194 int rem;
1195 uint32_t result;
1196
1197 if (env->macsr & MACSR_SU) {
1198
1199 rem = val & 0xffffff;
1200 val = (val >> 24) & 0xffffu;
1201 if (rem > 0x800000)
1202 val++;
1203 else if (rem == 0x800000)
1204 val += (val & 1);
1205 } else if (env->macsr & MACSR_RT) {
1206
1207 rem = val & 0xff;
1208 val >>= 8;
1209 if (rem > 0x80)
1210 val++;
1211 else if (rem == 0x80)
1212 val += (val & 1);
1213 } else {
1214
1215 val >>= 8;
1216 }
1217 if (env->macsr & MACSR_OMC) {
1218
1219 if (env->macsr & MACSR_SU) {
1220 if (val != (uint16_t) val) {
1221 result = ((val >> 63) ^ 0x7fff) & 0xffff;
1222 } else {
1223 result = val & 0xffff;
1224 }
1225 } else {
1226 if (val != (uint32_t)val) {
1227 result = ((uint32_t)(val >> 63) & 0x7fffffff);
1228 } else {
1229 result = (uint32_t)val;
1230 }
1231 }
1232 } else {
1233
1234 if (env->macsr & MACSR_SU) {
1235 result = val & 0xffff;
1236 } else {
1237 result = (uint32_t)val;
1238 }
1239 }
1240 return result;
1241}
1242
1243uint32_t HELPER(get_macs)(uint64_t val)
1244{
1245 if (val == (int32_t)val) {
1246 return (int32_t)val;
1247 } else {
1248 return (val >> 61) ^ ~SIGNBIT;
1249 }
1250}
1251
1252uint32_t HELPER(get_macu)(uint64_t val)
1253{
1254 if ((val >> 32) == 0) {
1255 return (uint32_t)val;
1256 } else {
1257 return 0xffffffffu;
1258 }
1259}
1260
1261uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
1262{
1263 uint32_t val;
1264 val = env->macc[acc] & 0x00ff;
1265 val |= (env->macc[acc] >> 32) & 0xff00;
1266 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
1267 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
1268 return val;
1269}
1270
1271uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
1272{
1273 uint32_t val;
1274 val = (env->macc[acc] >> 32) & 0xffff;
1275 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
1276 return val;
1277}
1278
1279void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
1280{
1281 int64_t res;
1282 int32_t tmp;
1283 res = env->macc[acc] & 0xffffffff00ull;
1284 tmp = (int16_t)(val & 0xff00);
1285 res |= ((int64_t)tmp) << 32;
1286 res |= val & 0xff;
1287 env->macc[acc] = res;
1288 res = env->macc[acc + 1] & 0xffffffff00ull;
1289 tmp = (val & 0xff000000);
1290 res |= ((int64_t)tmp) << 16;
1291 res |= (val >> 16) & 0xff;
1292 env->macc[acc + 1] = res;
1293}
1294
1295void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
1296{
1297 int64_t res;
1298 int32_t tmp;
1299 res = (uint32_t)env->macc[acc];
1300 tmp = (int16_t)val;
1301 res |= ((int64_t)tmp) << 32;
1302 env->macc[acc] = res;
1303 res = (uint32_t)env->macc[acc + 1];
1304 tmp = val & 0xffff0000;
1305 res |= (int64_t)tmp << 16;
1306 env->macc[acc + 1] = res;
1307}
1308
1309void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
1310{
1311 uint64_t res;
1312 res = (uint32_t)env->macc[acc];
1313 res |= ((uint64_t)(val & 0xffff)) << 32;
1314 env->macc[acc] = res;
1315 res = (uint32_t)env->macc[acc + 1];
1316 res |= (uint64_t)(val & 0xffff0000) << 16;
1317 env->macc[acc + 1] = res;
1318}
1319
1320#if defined(CONFIG_SOFTMMU)
1321void HELPER(ptest)(CPUM68KState *env, uint32_t addr, uint32_t is_read)
1322{
1323 M68kCPU *cpu = m68k_env_get_cpu(env);
1324 CPUState *cs = CPU(cpu);
1325 hwaddr physical;
1326 int access_type;
1327 int prot;
1328 int ret;
1329 target_ulong page_size;
1330
1331 access_type = ACCESS_PTEST;
1332 if (env->dfc & 4) {
1333 access_type |= ACCESS_SUPER;
1334 }
1335 if ((env->dfc & 3) == 2) {
1336 access_type |= ACCESS_CODE;
1337 }
1338 if (!is_read) {
1339 access_type |= ACCESS_STORE;
1340 }
1341
1342 env->mmu.mmusr = 0;
1343 env->mmu.ssw = 0;
1344 ret = get_physical_address(env, &physical, &prot, addr,
1345 access_type, &page_size);
1346 if (ret == 0) {
1347 addr &= TARGET_PAGE_MASK;
1348 physical += addr & (page_size - 1);
1349 tlb_set_page(cs, addr, physical,
1350 prot, access_type & ACCESS_SUPER ?
1351 MMU_KERNEL_IDX : MMU_USER_IDX, page_size);
1352 }
1353}
1354
1355void HELPER(pflush)(CPUM68KState *env, uint32_t addr, uint32_t opmode)
1356{
1357 M68kCPU *cpu = m68k_env_get_cpu(env);
1358
1359 switch (opmode) {
1360 case 0:
1361 case 1:
1362 tlb_flush_page(CPU(cpu), addr);
1363 break;
1364 case 2:
1365 tlb_flush(CPU(cpu));
1366 break;
1367 case 3:
1368 tlb_flush(CPU(cpu));
1369 break;
1370 }
1371}
1372
1373void HELPER(reset)(CPUM68KState *env)
1374{
1375
1376}
1377#endif
1378