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