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