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