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