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