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