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