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