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