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