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