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