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