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