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