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