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