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