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