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