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