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