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