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