xref: /qemu/target/m68k/helper.c (revision 58883579)
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 
cf_fpu_gdb_get_reg(CPUState * cs,GByteArray * mem_buf,int n)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 
cf_fpu_gdb_set_reg(CPUState * cs,uint8_t * mem_buf,int n)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 
m68k_fpu_gdb_get_reg(CPUState * cs,GByteArray * mem_buf,int n)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 
m68k_fpu_gdb_set_reg(CPUState * cs,uint8_t * mem_buf,int n)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 
m68k_cpu_init_gdb(M68kCPU * cpu)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 
HELPER(cf_movec_to)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 
raise_exception_ra(CPUM68KState * env,int tt,uintptr_t raddr)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 
HELPER(m68k_movec_to)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 
HELPER(m68k_movec_from)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 
HELPER(set_macsr)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 
m68k_switch_sp(CPUM68KState * env)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 
print_address_zone(uint32_t logical,uint32_t physical,uint32_t size,int attr)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 
dump_address_map(CPUM68KState * env,uint32_t root_pointer)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 
dump_ttr(uint32_t ttr)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 
dump_mmu(CPUM68KState * env)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 
check_TTR(uint32_t ttr,int * prot,target_ulong addr,int access_type)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 
get_physical_address(CPUM68KState * env,hwaddr * physical,int * prot,target_ulong address,int access_type,target_ulong * page_size)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 
m68k_cpu_get_phys_page_debug(CPUState * cs,vaddr addr)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  */
m68k_set_irq_level(M68kCPU * cpu,int level,uint8_t vector)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 
m68k_cpu_tlb_fill(CPUState * cs,vaddr address,int size,MMUAccessType qemu_access_type,int mmu_idx,bool probe,uintptr_t retaddr)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 
HELPER(bitrev)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 
HELPER(ff1)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 
HELPER(sats)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 
cpu_m68k_set_sr(CPUM68KState * env,uint32_t sr)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 
HELPER(set_sr)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  */
HELPER(mac_move)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 
HELPER(macmuls)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 
HELPER(macmulu)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 
HELPER(macmulf)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 
HELPER(macsats)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 
HELPER(macsatu)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 
HELPER(macsatf)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 
HELPER(mac_set_flags)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 
cpu_m68k_get_ccr(CPUM68KState * env)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 
HELPER(get_ccr)1297 uint32_t HELPER(get_ccr)(CPUM68KState *env)
1298 {
1299     return cpu_m68k_get_ccr(env);
1300 }
1301 
cpu_m68k_set_ccr(CPUM68KState * env,uint32_t ccr)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 
HELPER(set_ccr)1312 void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
1313 {
1314     cpu_m68k_set_ccr(env, ccr);
1315 }
1316 
HELPER(flush_flags)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 
HELPER(get_macf)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 
HELPER(get_macs)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 
HELPER(get_macu)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 
HELPER(get_mac_extf)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 
HELPER(get_mac_exti)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 
HELPER(set_mac_extf)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 
HELPER(set_mac_exts)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 
HELPER(set_mac_extu)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)
HELPER(ptest)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 
HELPER(pflush)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 
HELPER(reset)1503 void HELPER(reset)(CPUM68KState *env)
1504 {
1505     /* FIXME: reset all except CPU */
1506 }
1507 #endif /* !CONFIG_USER_ONLY */
1508