Commit ead9360e2fbcaae10a8ca3d8bfed885422205dca
1 parent
606b41e7
Partial support for 34K multithreading, not functional yet.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3156 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
18 changed files
with
2305 additions
and
826 deletions
cpu-exec.c
| ... | ... | @@ -194,7 +194,7 @@ static inline TranslationBlock *tb_find_fast(void) |
| 194 | 194 | #elif defined(TARGET_MIPS) |
| 195 | 195 | flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); |
| 196 | 196 | cs_base = 0; |
| 197 | - pc = env->PC; | |
| 197 | + pc = env->PC[env->current_tc]; | |
| 198 | 198 | #elif defined(TARGET_M68K) |
| 199 | 199 | flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */ |
| 200 | 200 | | (env->sr & SR_S) /* Bit 13 */ | ... | ... |
gdbstub.c
| ... | ... | @@ -559,17 +559,17 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) |
| 559 | 559 | ptr = mem_buf; |
| 560 | 560 | for (i = 0; i < 32; i++) |
| 561 | 561 | { |
| 562 | - *(target_ulong *)ptr = tswapl(env->gpr[i]); | |
| 562 | + *(target_ulong *)ptr = tswapl(env->gpr[i][env->current_tc]); | |
| 563 | 563 | ptr += sizeof(target_ulong); |
| 564 | 564 | } |
| 565 | 565 | |
| 566 | 566 | *(target_ulong *)ptr = tswapl(env->CP0_Status); |
| 567 | 567 | ptr += sizeof(target_ulong); |
| 568 | 568 | |
| 569 | - *(target_ulong *)ptr = tswapl(env->LO); | |
| 569 | + *(target_ulong *)ptr = tswapl(env->LO[0][env->current_tc]); | |
| 570 | 570 | ptr += sizeof(target_ulong); |
| 571 | 571 | |
| 572 | - *(target_ulong *)ptr = tswapl(env->HI); | |
| 572 | + *(target_ulong *)ptr = tswapl(env->HI[0][env->current_tc]); | |
| 573 | 573 | ptr += sizeof(target_ulong); |
| 574 | 574 | |
| 575 | 575 | *(target_ulong *)ptr = tswapl(env->CP0_BadVAddr); |
| ... | ... | @@ -578,21 +578,21 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) |
| 578 | 578 | *(target_ulong *)ptr = tswapl(env->CP0_Cause); |
| 579 | 579 | ptr += sizeof(target_ulong); |
| 580 | 580 | |
| 581 | - *(target_ulong *)ptr = tswapl(env->PC); | |
| 581 | + *(target_ulong *)ptr = tswapl(env->PC[env->current_tc]); | |
| 582 | 582 | ptr += sizeof(target_ulong); |
| 583 | 583 | |
| 584 | 584 | if (env->CP0_Config1 & (1 << CP0C1_FP)) |
| 585 | 585 | { |
| 586 | 586 | for (i = 0; i < 32; i++) |
| 587 | 587 | { |
| 588 | - *(target_ulong *)ptr = tswapl(env->fpr[i].fs[FP_ENDIAN_IDX]); | |
| 588 | + *(target_ulong *)ptr = tswapl(env->fpu->fpr[i].fs[FP_ENDIAN_IDX]); | |
| 589 | 589 | ptr += sizeof(target_ulong); |
| 590 | 590 | } |
| 591 | 591 | |
| 592 | - *(target_ulong *)ptr = tswapl(env->fcr31); | |
| 592 | + *(target_ulong *)ptr = tswapl(env->fpu->fcr31); | |
| 593 | 593 | ptr += sizeof(target_ulong); |
| 594 | 594 | |
| 595 | - *(target_ulong *)ptr = tswapl(env->fcr0); | |
| 595 | + *(target_ulong *)ptr = tswapl(env->fpu->fcr0); | |
| 596 | 596 | ptr += sizeof(target_ulong); |
| 597 | 597 | } |
| 598 | 598 | |
| ... | ... | @@ -611,7 +611,7 @@ static unsigned int ieee_rm[] = |
| 611 | 611 | float_round_down |
| 612 | 612 | }; |
| 613 | 613 | #define RESTORE_ROUNDING_MODE \ |
| 614 | - set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status) | |
| 614 | + set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status) | |
| 615 | 615 | |
| 616 | 616 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) |
| 617 | 617 | { |
| ... | ... | @@ -621,17 +621,17 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) |
| 621 | 621 | ptr = mem_buf; |
| 622 | 622 | for (i = 0; i < 32; i++) |
| 623 | 623 | { |
| 624 | - env->gpr[i] = tswapl(*(target_ulong *)ptr); | |
| 624 | + env->gpr[i][env->current_tc] = tswapl(*(target_ulong *)ptr); | |
| 625 | 625 | ptr += sizeof(target_ulong); |
| 626 | 626 | } |
| 627 | 627 | |
| 628 | 628 | env->CP0_Status = tswapl(*(target_ulong *)ptr); |
| 629 | 629 | ptr += sizeof(target_ulong); |
| 630 | 630 | |
| 631 | - env->LO = tswapl(*(target_ulong *)ptr); | |
| 631 | + env->LO[0][env->current_tc] = tswapl(*(target_ulong *)ptr); | |
| 632 | 632 | ptr += sizeof(target_ulong); |
| 633 | 633 | |
| 634 | - env->HI = tswapl(*(target_ulong *)ptr); | |
| 634 | + env->HI[0][env->current_tc] = tswapl(*(target_ulong *)ptr); | |
| 635 | 635 | ptr += sizeof(target_ulong); |
| 636 | 636 | |
| 637 | 637 | env->CP0_BadVAddr = tswapl(*(target_ulong *)ptr); |
| ... | ... | @@ -640,21 +640,21 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) |
| 640 | 640 | env->CP0_Cause = tswapl(*(target_ulong *)ptr); |
| 641 | 641 | ptr += sizeof(target_ulong); |
| 642 | 642 | |
| 643 | - env->PC = tswapl(*(target_ulong *)ptr); | |
| 643 | + env->PC[env->current_tc] = tswapl(*(target_ulong *)ptr); | |
| 644 | 644 | ptr += sizeof(target_ulong); |
| 645 | 645 | |
| 646 | 646 | if (env->CP0_Config1 & (1 << CP0C1_FP)) |
| 647 | 647 | { |
| 648 | 648 | for (i = 0; i < 32; i++) |
| 649 | 649 | { |
| 650 | - env->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr); | |
| 650 | + env->fpu->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr); | |
| 651 | 651 | ptr += sizeof(target_ulong); |
| 652 | 652 | } |
| 653 | 653 | |
| 654 | - env->fcr31 = tswapl(*(target_ulong *)ptr) & 0x0183FFFF; | |
| 654 | + env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0x0183FFFF; | |
| 655 | 655 | ptr += sizeof(target_ulong); |
| 656 | 656 | |
| 657 | - env->fcr0 = tswapl(*(target_ulong *)ptr); | |
| 657 | + env->fpu->fcr0 = tswapl(*(target_ulong *)ptr); | |
| 658 | 658 | ptr += sizeof(target_ulong); |
| 659 | 659 | |
| 660 | 660 | /* set rounding mode */ |
| ... | ... | @@ -775,7 +775,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) |
| 775 | 775 | #elif defined (TARGET_SH4) |
| 776 | 776 | env->pc = addr; |
| 777 | 777 | #elif defined (TARGET_MIPS) |
| 778 | - env->PC = addr; | |
| 778 | + env->PC[env->current_tc] = addr; | |
| 779 | 779 | #endif |
| 780 | 780 | } |
| 781 | 781 | #ifdef CONFIG_USER_ONLY |
| ... | ... | @@ -799,7 +799,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) |
| 799 | 799 | #elif defined (TARGET_SH4) |
| 800 | 800 | env->pc = addr; |
| 801 | 801 | #elif defined (TARGET_MIPS) |
| 802 | - env->PC = addr; | |
| 802 | + env->PC[env->current_tc] = addr; | |
| 803 | 803 | #endif |
| 804 | 804 | } |
| 805 | 805 | cpu_single_step(env, 1); | ... | ... |
hw/mips_r4k.c
| ... | ... | @@ -77,7 +77,7 @@ void load_kernel (CPUState *env, int ram_size, const char *kernel_filename, |
| 77 | 77 | if (kernel_size >= 0) { |
| 78 | 78 | if ((entry & ~0x7fffffffULL) == 0x80000000) |
| 79 | 79 | entry = (int32_t)entry; |
| 80 | - env->PC = entry; | |
| 80 | + env->PC[env->current_tc] = entry; | |
| 81 | 81 | } else { |
| 82 | 82 | fprintf(stderr, "qemu: could not load kernel '%s'\n", |
| 83 | 83 | kernel_filename); | ... | ... |
hw/mips_timer.c
| ... | ... | @@ -10,7 +10,7 @@ uint32_t cpu_mips_get_random (CPUState *env) |
| 10 | 10 | static uint32_t seed = 0; |
| 11 | 11 | uint32_t idx; |
| 12 | 12 | seed = seed * 314159 + 1; |
| 13 | - idx = (seed >> 16) % (env->nb_tlb - env->CP0_Wired) + env->CP0_Wired; | |
| 13 | + idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired; | |
| 14 | 14 | return idx; |
| 15 | 15 | } |
| 16 | 16 | ... | ... |
linux-user/main.c
| ... | ... | @@ -1374,8 +1374,8 @@ void cpu_loop(CPUMIPSState *env) |
| 1374 | 1374 | trapnr = cpu_mips_exec(env); |
| 1375 | 1375 | switch(trapnr) { |
| 1376 | 1376 | case EXCP_SYSCALL: |
| 1377 | - syscall_num = env->gpr[2] - 4000; | |
| 1378 | - env->PC += 4; | |
| 1377 | + syscall_num = env->gpr[2][env->current_tc] - 4000; | |
| 1378 | + env->PC[env->current_tc] += 4; | |
| 1379 | 1379 | if (syscall_num >= sizeof(mips_syscall_args)) { |
| 1380 | 1380 | ret = -ENOSYS; |
| 1381 | 1381 | } else { |
| ... | ... | @@ -1384,7 +1384,7 @@ void cpu_loop(CPUMIPSState *env) |
| 1384 | 1384 | target_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; |
| 1385 | 1385 | |
| 1386 | 1386 | nb_args = mips_syscall_args[syscall_num]; |
| 1387 | - sp_reg = env->gpr[29]; | |
| 1387 | + sp_reg = env->gpr[29][env->current_tc]; | |
| 1388 | 1388 | switch (nb_args) { |
| 1389 | 1389 | /* these arguments are taken from the stack */ |
| 1390 | 1390 | case 8: arg8 = tgetl(sp_reg + 28); |
| ... | ... | @@ -1394,18 +1394,20 @@ void cpu_loop(CPUMIPSState *env) |
| 1394 | 1394 | default: |
| 1395 | 1395 | break; |
| 1396 | 1396 | } |
| 1397 | - ret = do_syscall(env, env->gpr[2], | |
| 1398 | - env->gpr[4], env->gpr[5], | |
| 1399 | - env->gpr[6], env->gpr[7], | |
| 1397 | + ret = do_syscall(env, env->gpr[2][env->current_tc], | |
| 1398 | + env->gpr[4][env->current_tc], | |
| 1399 | + env->gpr[5][env->current_tc], | |
| 1400 | + env->gpr[6][env->current_tc], | |
| 1401 | + env->gpr[7][env->current_tc], | |
| 1400 | 1402 | arg5, arg6/*, arg7, arg8*/); |
| 1401 | 1403 | } |
| 1402 | 1404 | if ((unsigned int)ret >= (unsigned int)(-1133)) { |
| 1403 | - env->gpr[7] = 1; /* error flag */ | |
| 1405 | + env->gpr[7][env->current_tc] = 1; /* error flag */ | |
| 1404 | 1406 | ret = -ret; |
| 1405 | 1407 | } else { |
| 1406 | - env->gpr[7] = 0; /* error flag */ | |
| 1408 | + env->gpr[7][env->current_tc] = 0; /* error flag */ | |
| 1407 | 1409 | } |
| 1408 | - env->gpr[2] = ret; | |
| 1410 | + env->gpr[2][env->current_tc] = ret; | |
| 1409 | 1411 | break; |
| 1410 | 1412 | case EXCP_TLBL: |
| 1411 | 1413 | case EXCP_TLBS: |
| ... | ... | @@ -2053,9 +2055,9 @@ int main(int argc, char **argv) |
| 2053 | 2055 | cpu_mips_register(env, def); |
| 2054 | 2056 | |
| 2055 | 2057 | for(i = 0; i < 32; i++) { |
| 2056 | - env->gpr[i] = regs->regs[i]; | |
| 2058 | + env->gpr[i][env->current_tc] = regs->regs[i]; | |
| 2057 | 2059 | } |
| 2058 | - env->PC = regs->cp0_epc; | |
| 2060 | + env->PC[env->current_tc] = regs->cp0_epc; | |
| 2059 | 2061 | } |
| 2060 | 2062 | #elif defined(TARGET_SH4) |
| 2061 | 2063 | { | ... | ... |
linux-user/signal.c
| ... | ... | @@ -1686,10 +1686,10 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc) |
| 1686 | 1686 | { |
| 1687 | 1687 | int err = 0; |
| 1688 | 1688 | |
| 1689 | - err |= __put_user(regs->PC, &sc->sc_pc); | |
| 1689 | + err |= __put_user(regs->PC[regs->current_tc], &sc->sc_pc); | |
| 1690 | 1690 | |
| 1691 | -#define save_gp_reg(i) do { \ | |
| 1692 | - err |= __put_user(regs->gpr[i], &sc->sc_regs[i]); \ | |
| 1691 | +#define save_gp_reg(i) do { \ | |
| 1692 | + err |= __put_user(regs->gpr[i][regs->current_tc], &sc->sc_regs[i]); \ | |
| 1693 | 1693 | } while(0) |
| 1694 | 1694 | __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); |
| 1695 | 1695 | save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); |
| ... | ... | @@ -1702,8 +1702,8 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc) |
| 1702 | 1702 | save_gp_reg(31); |
| 1703 | 1703 | #undef save_gp_reg |
| 1704 | 1704 | |
| 1705 | - err |= __put_user(regs->HI, &sc->sc_mdhi); | |
| 1706 | - err |= __put_user(regs->LO, &sc->sc_mdlo); | |
| 1705 | + err |= __put_user(regs->HI[0][regs->current_tc], &sc->sc_mdhi); | |
| 1706 | + err |= __put_user(regs->LO[0][regs->current_tc], &sc->sc_mdlo); | |
| 1707 | 1707 | |
| 1708 | 1708 | /* Not used yet, but might be useful if we ever have DSP suppport */ |
| 1709 | 1709 | #if 0 |
| ... | ... | @@ -1763,11 +1763,11 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc) |
| 1763 | 1763 | |
| 1764 | 1764 | err |= __get_user(regs->CP0_EPC, &sc->sc_pc); |
| 1765 | 1765 | |
| 1766 | - err |= __get_user(regs->HI, &sc->sc_mdhi); | |
| 1767 | - err |= __get_user(regs->LO, &sc->sc_mdlo); | |
| 1766 | + err |= __get_user(regs->HI[0][regs->current_tc], &sc->sc_mdhi); | |
| 1767 | + err |= __get_user(regs->LO[0][regs->current_tc], &sc->sc_mdlo); | |
| 1768 | 1768 | |
| 1769 | -#define restore_gp_reg(i) do { \ | |
| 1770 | - err |= __get_user(regs->gpr[i], &sc->sc_regs[i]); \ | |
| 1769 | +#define restore_gp_reg(i) do { \ | |
| 1770 | + err |= __get_user(regs->gpr[i][regs->current_tc], &sc->sc_regs[i]); \ | |
| 1771 | 1771 | } while(0) |
| 1772 | 1772 | restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); |
| 1773 | 1773 | restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); |
| ... | ... | @@ -1833,7 +1833,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) |
| 1833 | 1833 | unsigned long sp; |
| 1834 | 1834 | |
| 1835 | 1835 | /* Default to using normal stack */ |
| 1836 | - sp = regs->gpr[29]; | |
| 1836 | + sp = regs->gpr[29][regs->current_tc]; | |
| 1837 | 1837 | |
| 1838 | 1838 | /* |
| 1839 | 1839 | * FPU emulator may have it's own trampoline active just |
| ... | ... | @@ -1881,15 +1881,15 @@ static void setup_frame(int sig, struct emulated_sigaction * ka, |
| 1881 | 1881 | * $25 and PC point to the signal handler, $29 points to the |
| 1882 | 1882 | * struct sigframe. |
| 1883 | 1883 | */ |
| 1884 | - regs->gpr[ 4] = sig; | |
| 1885 | - regs->gpr[ 5] = 0; | |
| 1886 | - regs->gpr[ 6] = h2g(&frame->sf_sc); | |
| 1887 | - regs->gpr[29] = h2g(frame); | |
| 1888 | - regs->gpr[31] = h2g(frame->sf_code); | |
| 1884 | + regs->gpr[ 4][regs->current_tc] = sig; | |
| 1885 | + regs->gpr[ 5][regs->current_tc] = 0; | |
| 1886 | + regs->gpr[ 6][regs->current_tc] = h2g(&frame->sf_sc); | |
| 1887 | + regs->gpr[29][regs->current_tc] = h2g(frame); | |
| 1888 | + regs->gpr[31][regs->current_tc] = h2g(frame->sf_code); | |
| 1889 | 1889 | /* The original kernel code sets CP0_EPC to the handler |
| 1890 | 1890 | * since it returns to userland using eret |
| 1891 | 1891 | * we cannot do this here, and we must set PC directly */ |
| 1892 | - regs->PC = regs->gpr[25] = ka->sa._sa_handler; | |
| 1892 | + regs->PC[regs->current_tc] = regs->gpr[25][regs->current_tc] = ka->sa._sa_handler; | |
| 1893 | 1893 | return; |
| 1894 | 1894 | |
| 1895 | 1895 | give_sigsegv: |
| ... | ... | @@ -1907,7 +1907,7 @@ long do_sigreturn(CPUState *regs) |
| 1907 | 1907 | #if defined(DEBUG_SIGNAL) |
| 1908 | 1908 | fprintf(stderr, "do_sigreturn\n"); |
| 1909 | 1909 | #endif |
| 1910 | - frame = (struct sigframe *) regs->gpr[29]; | |
| 1910 | + frame = (struct sigframe *) regs->gpr[29][regs->current_tc]; | |
| 1911 | 1911 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 1912 | 1912 | goto badframe; |
| 1913 | 1913 | |
| ... | ... | @@ -1934,7 +1934,7 @@ long do_sigreturn(CPUState *regs) |
| 1934 | 1934 | /* Unreached */ |
| 1935 | 1935 | #endif |
| 1936 | 1936 | |
| 1937 | - regs->PC = regs->CP0_EPC; | |
| 1937 | + regs->PC[regs->current_tc] = regs->CP0_EPC; | |
| 1938 | 1938 | /* I am not sure this is right, but it seems to work |
| 1939 | 1939 | * maybe a problem with nested signals ? */ |
| 1940 | 1940 | regs->CP0_EPC = 0; | ... | ... |
linux-user/syscall.c
| ... | ... | @@ -2189,8 +2189,8 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) |
| 2189 | 2189 | /* ??? is this sufficient? */ |
| 2190 | 2190 | #elif defined(TARGET_MIPS) |
| 2191 | 2191 | if (!newsp) |
| 2192 | - newsp = env->gpr[29]; | |
| 2193 | - new_env->gpr[29] = newsp; | |
| 2192 | + newsp = env->gpr[29][env->current_tc]; | |
| 2193 | + new_env->gpr[29][env->current_tc] = newsp; | |
| 2194 | 2194 | #elif defined(TARGET_PPC) |
| 2195 | 2195 | if (!newsp) |
| 2196 | 2196 | newsp = env->gpr[1]; |
| ... | ... | @@ -2777,7 +2777,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
| 2777 | 2777 | ret = get_errno(pipe(host_pipe)); |
| 2778 | 2778 | if (!is_error(ret)) { |
| 2779 | 2779 | #if defined(TARGET_MIPS) |
| 2780 | - ((CPUMIPSState*)cpu_env)->gpr[3] = host_pipe[1]; | |
| 2780 | + CPUMIPSState *env = (CPUMIPSState*)cpu_env; | |
| 2781 | + env->gpr[3][env->current_tc] = host_pipe[1]; | |
| 2781 | 2782 | ret = host_pipe[0]; |
| 2782 | 2783 | #else |
| 2783 | 2784 | tput32(arg1, host_pipe[0]); | ... | ... |
monitor.c
| ... | ... | @@ -309,6 +309,10 @@ static void do_info_cpus(void) |
| 309 | 309 | term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc); |
| 310 | 310 | if (env->halted) |
| 311 | 311 | term_printf(" (halted)"); |
| 312 | +#elif defined(TARGET_MIPS) | |
| 313 | + term_printf(" PC=0x" TARGET_FMT_lx, env->PC[env->current_tc]); | |
| 314 | + if (env->halted) | |
| 315 | + term_printf(" (halted)"); | |
| 312 | 316 | #endif |
| 313 | 317 | term_printf("\n"); |
| 314 | 318 | } | ... | ... |
target-mips/cpu.h
| ... | ... | @@ -17,21 +17,7 @@ typedef unsigned char uint_fast8_t; |
| 17 | 17 | typedef unsigned int uint_fast16_t; |
| 18 | 18 | #endif |
| 19 | 19 | |
| 20 | -typedef union fpr_t fpr_t; | |
| 21 | -union fpr_t { | |
| 22 | - float64 fd; /* ieee double precision */ | |
| 23 | - float32 fs[2];/* ieee single precision */ | |
| 24 | - uint64_t d; /* binary double fixed-point */ | |
| 25 | - uint32_t w[2]; /* binary single fixed-point */ | |
| 26 | -}; | |
| 27 | -/* define FP_ENDIAN_IDX to access the same location | |
| 28 | - * in the fpr_t union regardless of the host endianess | |
| 29 | - */ | |
| 30 | -#if defined(WORDS_BIGENDIAN) | |
| 31 | -# define FP_ENDIAN_IDX 1 | |
| 32 | -#else | |
| 33 | -# define FP_ENDIAN_IDX 0 | |
| 34 | -#endif | |
| 20 | +struct CPUMIPSState; | |
| 35 | 21 | |
| 36 | 22 | typedef struct r4k_tlb_t r4k_tlb_t; |
| 37 | 23 | struct r4k_tlb_t { |
| ... | ... | @@ -48,20 +34,40 @@ struct r4k_tlb_t { |
| 48 | 34 | target_ulong PFN[2]; |
| 49 | 35 | }; |
| 50 | 36 | |
| 51 | -typedef struct mips_def_t mips_def_t; | |
| 37 | +typedef struct CPUMIPSTLBContext CPUMIPSTLBContext; | |
| 38 | +struct CPUMIPSTLBContext { | |
| 39 | + uint32_t nb_tlb; | |
| 40 | + uint32_t tlb_in_use; | |
| 41 | + int (*map_address) (struct CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type); | |
| 42 | + void (*do_tlbwi) (void); | |
| 43 | + void (*do_tlbwr) (void); | |
| 44 | + void (*do_tlbp) (void); | |
| 45 | + void (*do_tlbr) (void); | |
| 46 | + union { | |
| 47 | + struct { | |
| 48 | + r4k_tlb_t tlb[MIPS_TLB_MAX]; | |
| 49 | + } r4k; | |
| 50 | + } mmu; | |
| 51 | +}; | |
| 52 | 52 | |
| 53 | -typedef struct CPUMIPSState CPUMIPSState; | |
| 54 | -struct CPUMIPSState { | |
| 55 | - /* General integer registers */ | |
| 56 | - target_ulong gpr[32]; | |
| 57 | - /* Special registers */ | |
| 58 | - target_ulong PC; | |
| 59 | -#if TARGET_LONG_BITS > HOST_LONG_BITS | |
| 60 | - target_ulong t0; | |
| 61 | - target_ulong t1; | |
| 62 | - target_ulong t2; | |
| 53 | +typedef union fpr_t fpr_t; | |
| 54 | +union fpr_t { | |
| 55 | + float64 fd; /* ieee double precision */ | |
| 56 | + float32 fs[2];/* ieee single precision */ | |
| 57 | + uint64_t d; /* binary double fixed-point */ | |
| 58 | + uint32_t w[2]; /* binary single fixed-point */ | |
| 59 | +}; | |
| 60 | +/* define FP_ENDIAN_IDX to access the same location | |
| 61 | + * in the fpr_t union regardless of the host endianess | |
| 62 | + */ | |
| 63 | +#if defined(WORDS_BIGENDIAN) | |
| 64 | +# define FP_ENDIAN_IDX 1 | |
| 65 | +#else | |
| 66 | +# define FP_ENDIAN_IDX 0 | |
| 63 | 67 | #endif |
| 64 | - target_ulong HI, LO; | |
| 68 | + | |
| 69 | +typedef struct CPUMIPSFPUContext CPUMIPSFPUContext; | |
| 70 | +struct CPUMIPSFPUContext { | |
| 65 | 71 | /* Floating point registers */ |
| 66 | 72 | fpr_t fpr[32]; |
| 67 | 73 | #ifndef USE_HOST_FLOAT_REGS |
| ... | ... | @@ -99,30 +105,161 @@ struct CPUMIPSState { |
| 99 | 105 | #define FP_DIV0 8 |
| 100 | 106 | #define FP_INVALID 16 |
| 101 | 107 | #define FP_UNIMPLEMENTED 32 |
| 108 | +}; | |
| 109 | + | |
| 110 | +typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; | |
| 111 | +struct CPUMIPSMVPContext { | |
| 112 | + int32_t CP0_MVPControl; | |
| 113 | +#define CP0MVPCo_CPA 3 | |
| 114 | +#define CP0MVPCo_STLB 2 | |
| 115 | +#define CP0MVPCo_VPC 1 | |
| 116 | +#define CP0MVPCo_EVP 0 | |
| 117 | + int32_t CP0_MVPConf0; | |
| 118 | +#define CP0MVPC0_M 31 | |
| 119 | +#define CP0MVPC0_TLBS 29 | |
| 120 | +#define CP0MVPC0_GS 28 | |
| 121 | +#define CP0MVPC0_PCP 27 | |
| 122 | +#define CP0MVPC0_PTLBE 16 | |
| 123 | +#define CP0MVPC0_TCA 15 | |
| 124 | +#define CP0MVPC0_PVPE 10 | |
| 125 | +#define CP0MVPC0_PTC 0 | |
| 126 | + int32_t CP0_MVPConf1; | |
| 127 | +#define CP0MVPC1_CIM 31 | |
| 128 | +#define CP0MVPC1_CIF 30 | |
| 129 | +#define CP0MVPC1_PCX 20 | |
| 130 | +#define CP0MVPC1_PCP2 10 | |
| 131 | +#define CP0MVPC1_PCP1 0 | |
| 132 | +}; | |
| 133 | + | |
| 134 | +typedef struct mips_def_t mips_def_t; | |
| 135 | + | |
| 136 | +#define MIPS_SHADOW_SET_MAX 16 | |
| 137 | +#define MIPS_TC_MAX 5 | |
| 138 | +#define MIPS_DSP_ACC 4 | |
| 139 | + | |
| 140 | +typedef struct CPUMIPSState CPUMIPSState; | |
| 141 | +struct CPUMIPSState { | |
| 142 | + /* General integer registers */ | |
| 143 | + target_ulong gpr[32][MIPS_SHADOW_SET_MAX]; | |
| 144 | + /* Special registers */ | |
| 145 | + target_ulong PC[MIPS_TC_MAX]; | |
| 146 | +#if TARGET_LONG_BITS > HOST_LONG_BITS | |
| 147 | + target_ulong t0; | |
| 148 | + target_ulong t1; | |
| 149 | + target_ulong t2; | |
| 150 | +#endif | |
| 151 | + target_ulong HI[MIPS_DSP_ACC][MIPS_TC_MAX]; | |
| 152 | + target_ulong LO[MIPS_DSP_ACC][MIPS_TC_MAX]; | |
| 153 | + target_ulong ACX[MIPS_DSP_ACC][MIPS_TC_MAX]; | |
| 154 | + target_ulong DSPControl[MIPS_TC_MAX]; | |
| 155 | + | |
| 156 | + CPUMIPSMVPContext *mvp; | |
| 157 | + CPUMIPSTLBContext *tlb; | |
| 158 | + CPUMIPSFPUContext *fpu; | |
| 159 | + uint32_t current_tc; | |
| 102 | 160 | |
| 103 | - uint32_t nb_tlb; | |
| 104 | - uint32_t tlb_in_use; | |
| 105 | 161 | uint32_t SEGBITS; |
| 106 | 162 | target_ulong SEGMask; |
| 107 | - int (*map_address) (CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type); | |
| 108 | - void (*do_tlbwi) (void); | |
| 109 | - void (*do_tlbwr) (void); | |
| 110 | - void (*do_tlbp) (void); | |
| 111 | - void (*do_tlbr) (void); | |
| 112 | - union { | |
| 113 | - struct { | |
| 114 | - r4k_tlb_t tlb[MIPS_TLB_MAX]; | |
| 115 | - } r4k; | |
| 116 | - } mmu; | |
| 117 | 163 | |
| 118 | 164 | int32_t CP0_Index; |
| 165 | + /* CP0_MVP* are per MVP registers. */ | |
| 119 | 166 | int32_t CP0_Random; |
| 167 | + int32_t CP0_VPEControl; | |
| 168 | +#define CP0VPECo_YSI 21 | |
| 169 | +#define CP0VPECo_GSI 20 | |
| 170 | +#define CP0VPECo_EXCPT 16 | |
| 171 | +#define CP0VPECo_TE 15 | |
| 172 | +#define CP0VPECo_TargTC 0 | |
| 173 | + int32_t CP0_VPEConf0; | |
| 174 | +#define CP0VPEC0_M 31 | |
| 175 | +#define CP0VPEC0_XTC 21 | |
| 176 | +#define CP0VPEC0_TCS 19 | |
| 177 | +#define CP0VPEC0_SCS 18 | |
| 178 | +#define CP0VPEC0_DSC 17 | |
| 179 | +#define CP0VPEC0_ICS 16 | |
| 180 | +#define CP0VPEC0_MVP 1 | |
| 181 | +#define CP0VPEC0_VPA 0 | |
| 182 | + int32_t CP0_VPEConf1; | |
| 183 | +#define CP0VPEC1_NCX 20 | |
| 184 | +#define CP0VPEC1_NCP2 10 | |
| 185 | +#define CP0VPEC1_NCP1 0 | |
| 186 | + target_ulong CP0_YQMask; | |
| 187 | + target_ulong CP0_VPESchedule; | |
| 188 | + target_ulong CP0_VPEScheFBack; | |
| 189 | + int32_t CP0_VPEOpt; | |
| 190 | +#define CP0VPEOpt_IWX7 15 | |
| 191 | +#define CP0VPEOpt_IWX6 14 | |
| 192 | +#define CP0VPEOpt_IWX5 13 | |
| 193 | +#define CP0VPEOpt_IWX4 12 | |
| 194 | +#define CP0VPEOpt_IWX3 11 | |
| 195 | +#define CP0VPEOpt_IWX2 10 | |
| 196 | +#define CP0VPEOpt_IWX1 9 | |
| 197 | +#define CP0VPEOpt_IWX0 8 | |
| 198 | +#define CP0VPEOpt_DWX7 7 | |
| 199 | +#define CP0VPEOpt_DWX6 6 | |
| 200 | +#define CP0VPEOpt_DWX5 5 | |
| 201 | +#define CP0VPEOpt_DWX4 4 | |
| 202 | +#define CP0VPEOpt_DWX3 3 | |
| 203 | +#define CP0VPEOpt_DWX2 2 | |
| 204 | +#define CP0VPEOpt_DWX1 1 | |
| 205 | +#define CP0VPEOpt_DWX0 0 | |
| 120 | 206 | target_ulong CP0_EntryLo0; |
| 207 | + int32_t CP0_TCStatus[MIPS_TC_MAX]; | |
| 208 | +#define CP0TCSt_TCU3 31 | |
| 209 | +#define CP0TCSt_TCU2 30 | |
| 210 | +#define CP0TCSt_TCU1 29 | |
| 211 | +#define CP0TCSt_TCU0 28 | |
| 212 | +#define CP0TCSt_TMX 27 | |
| 213 | +#define CP0TCSt_RNST 23 | |
| 214 | +#define CP0TCSt_TDS 21 | |
| 215 | +#define CP0TCSt_DT 20 | |
| 216 | +#define CP0TCSt_DA 15 | |
| 217 | +#define CP0TCSt_A 13 | |
| 218 | +#define CP0TCSt_TKSU 11 | |
| 219 | +#define CP0TCSt_IXMT 10 | |
| 220 | +#define CP0TCSt_TASID 0 | |
| 221 | + int32_t CP0_TCBind[MIPS_TC_MAX]; | |
| 222 | +#define CP0TCBd_CurTC 21 | |
| 223 | +#define CP0TCBd_TBE 17 | |
| 224 | +#define CP0TCBd_CurVPE 0 | |
| 225 | + target_ulong CP0_TCHalt[MIPS_TC_MAX]; | |
| 226 | + target_ulong CP0_TCContext[MIPS_TC_MAX]; | |
| 227 | + target_ulong CP0_TCSchedule[MIPS_TC_MAX]; | |
| 228 | + target_ulong CP0_TCScheFBack[MIPS_TC_MAX]; | |
| 121 | 229 | target_ulong CP0_EntryLo1; |
| 122 | 230 | target_ulong CP0_Context; |
| 123 | 231 | int32_t CP0_PageMask; |
| 124 | 232 | int32_t CP0_PageGrain; |
| 125 | 233 | int32_t CP0_Wired; |
| 234 | + int32_t CP0_SRSConf0_rw_bitmask; | |
| 235 | + int32_t CP0_SRSConf0; | |
| 236 | +#define CP0SRSC0_M 31 | |
| 237 | +#define CP0SRSC0_SRS3 20 | |
| 238 | +#define CP0SRSC0_SRS2 10 | |
| 239 | +#define CP0SRSC0_SRS1 0 | |
| 240 | + int32_t CP0_SRSConf1_rw_bitmask; | |
| 241 | + int32_t CP0_SRSConf1; | |
| 242 | +#define CP0SRSC1_M 31 | |
| 243 | +#define CP0SRSC1_SRS6 20 | |
| 244 | +#define CP0SRSC1_SRS5 10 | |
| 245 | +#define CP0SRSC1_SRS4 0 | |
| 246 | + int32_t CP0_SRSConf2_rw_bitmask; | |
| 247 | + int32_t CP0_SRSConf2; | |
| 248 | +#define CP0SRSC2_M 31 | |
| 249 | +#define CP0SRSC2_SRS9 20 | |
| 250 | +#define CP0SRSC2_SRS8 10 | |
| 251 | +#define CP0SRSC2_SRS7 0 | |
| 252 | + int32_t CP0_SRSConf3_rw_bitmask; | |
| 253 | + int32_t CP0_SRSConf3; | |
| 254 | +#define CP0SRSC3_M 31 | |
| 255 | +#define CP0SRSC3_SRS12 20 | |
| 256 | +#define CP0SRSC3_SRS11 10 | |
| 257 | +#define CP0SRSC3_SRS10 0 | |
| 258 | + int32_t CP0_SRSConf4_rw_bitmask; | |
| 259 | + int32_t CP0_SRSConf4; | |
| 260 | +#define CP0SRSC4_SRS15 20 | |
| 261 | +#define CP0SRSC4_SRS14 10 | |
| 262 | +#define CP0SRSC4_SRS13 0 | |
| 126 | 263 | int32_t CP0_HWREna; |
| 127 | 264 | target_ulong CP0_BadVAddr; |
| 128 | 265 | int32_t CP0_Count; |
| ... | ... | @@ -152,8 +289,24 @@ struct CPUMIPSState { |
| 152 | 289 | #define CP0St_EXL 1 |
| 153 | 290 | #define CP0St_IE 0 |
| 154 | 291 | int32_t CP0_IntCtl; |
| 292 | +#define CP0IntCtl_IPTI 29 | |
| 293 | +#define CP0IntCtl_IPPC1 26 | |
| 294 | +#define CP0IntCtl_VS 5 | |
| 155 | 295 | int32_t CP0_SRSCtl; |
| 296 | +#define CP0SRSCtl_HSS 26 | |
| 297 | +#define CP0SRSCtl_EICSS 18 | |
| 298 | +#define CP0SRSCtl_ESS 12 | |
| 299 | +#define CP0SRSCtl_PSS 6 | |
| 300 | +#define CP0SRSCtl_CSS 0 | |
| 156 | 301 | int32_t CP0_SRSMap; |
| 302 | +#define CP0SRSMap_SSV7 28 | |
| 303 | +#define CP0SRSMap_SSV6 24 | |
| 304 | +#define CP0SRSMap_SSV5 20 | |
| 305 | +#define CP0SRSMap_SSV4 16 | |
| 306 | +#define CP0SRSMap_SSV3 12 | |
| 307 | +#define CP0SRSMap_SSV2 8 | |
| 308 | +#define CP0SRSMap_SSV1 4 | |
| 309 | +#define CP0SRSMap_SSV0 0 | |
| 157 | 310 | int32_t CP0_Cause; |
| 158 | 311 | #define CP0Ca_BD 31 |
| 159 | 312 | #define CP0Ca_TI 30 |
| ... | ... | @@ -219,13 +372,14 @@ struct CPUMIPSState { |
| 219 | 372 | #define CP0C3_TL 0 |
| 220 | 373 | int32_t CP0_Config6; |
| 221 | 374 | int32_t CP0_Config7; |
| 375 | + /* XXX: Maybe make LLAddr per-TC? */ | |
| 222 | 376 | target_ulong CP0_LLAddr; |
| 223 | 377 | target_ulong CP0_WatchLo[8]; |
| 224 | 378 | int32_t CP0_WatchHi[8]; |
| 225 | 379 | target_ulong CP0_XContext; |
| 226 | 380 | int32_t CP0_Framemask; |
| 227 | 381 | int32_t CP0_Debug; |
| 228 | -#define CPDB_DBD 31 | |
| 382 | +#define CP0DB_DBD 31 | |
| 229 | 383 | #define CP0DB_DM 30 |
| 230 | 384 | #define CP0DB_LSNM 28 |
| 231 | 385 | #define CP0DB_Doze 27 |
| ... | ... | @@ -243,6 +397,7 @@ struct CPUMIPSState { |
| 243 | 397 | #define CP0DB_DDBL 2 |
| 244 | 398 | #define CP0DB_DBp 1 |
| 245 | 399 | #define CP0DB_DSS 0 |
| 400 | + int32_t CP0_Debug_tcstatus[MIPS_TC_MAX]; | |
| 246 | 401 | target_ulong CP0_DEPC; |
| 247 | 402 | int32_t CP0_Performance0; |
| 248 | 403 | int32_t CP0_TagLo; |
| ... | ... | @@ -284,7 +439,8 @@ struct CPUMIPSState { |
| 284 | 439 | |
| 285 | 440 | int SYNCI_Step; /* Address step size for SYNCI */ |
| 286 | 441 | int CCRes; /* Cycle count resolution/divisor */ |
| 287 | - int Status_rw_bitmask; /* Read/write bits in CP0_Status */ | |
| 442 | + uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */ | |
| 443 | + uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */ | |
| 288 | 444 | |
| 289 | 445 | #ifdef CONFIG_USER_ONLY |
| 290 | 446 | target_ulong tls_value; |
| ... | ... | @@ -376,6 +532,7 @@ enum { |
| 376 | 532 | EXCP_TLBS, |
| 377 | 533 | EXCP_DBE, |
| 378 | 534 | EXCP_DDBL, |
| 535 | + EXCP_THREAD, | |
| 379 | 536 | EXCP_MTCP0 = 0x104, /* mtmsr instruction: */ |
| 380 | 537 | /* may change privilege level */ |
| 381 | 538 | EXCP_BRANCH = 0x108, /* branch instruction */ | ... | ... |
target-mips/exec.h
| ... | ... | @@ -23,24 +23,24 @@ register target_ulong T2 asm(AREG3); |
| 23 | 23 | #if defined (USE_HOST_FLOAT_REGS) |
| 24 | 24 | #error "implement me." |
| 25 | 25 | #else |
| 26 | -#define FDT0 (env->ft0.fd) | |
| 27 | -#define FDT1 (env->ft1.fd) | |
| 28 | -#define FDT2 (env->ft2.fd) | |
| 29 | -#define FST0 (env->ft0.fs[FP_ENDIAN_IDX]) | |
| 30 | -#define FST1 (env->ft1.fs[FP_ENDIAN_IDX]) | |
| 31 | -#define FST2 (env->ft2.fs[FP_ENDIAN_IDX]) | |
| 32 | -#define FSTH0 (env->ft0.fs[!FP_ENDIAN_IDX]) | |
| 33 | -#define FSTH1 (env->ft1.fs[!FP_ENDIAN_IDX]) | |
| 34 | -#define FSTH2 (env->ft2.fs[!FP_ENDIAN_IDX]) | |
| 35 | -#define DT0 (env->ft0.d) | |
| 36 | -#define DT1 (env->ft1.d) | |
| 37 | -#define DT2 (env->ft2.d) | |
| 38 | -#define WT0 (env->ft0.w[FP_ENDIAN_IDX]) | |
| 39 | -#define WT1 (env->ft1.w[FP_ENDIAN_IDX]) | |
| 40 | -#define WT2 (env->ft2.w[FP_ENDIAN_IDX]) | |
| 41 | -#define WTH0 (env->ft0.w[!FP_ENDIAN_IDX]) | |
| 42 | -#define WTH1 (env->ft1.w[!FP_ENDIAN_IDX]) | |
| 43 | -#define WTH2 (env->ft2.w[!FP_ENDIAN_IDX]) | |
| 26 | +#define FDT0 (env->fpu->ft0.fd) | |
| 27 | +#define FDT1 (env->fpu->ft1.fd) | |
| 28 | +#define FDT2 (env->fpu->ft2.fd) | |
| 29 | +#define FST0 (env->fpu->ft0.fs[FP_ENDIAN_IDX]) | |
| 30 | +#define FST1 (env->fpu->ft1.fs[FP_ENDIAN_IDX]) | |
| 31 | +#define FST2 (env->fpu->ft2.fs[FP_ENDIAN_IDX]) | |
| 32 | +#define FSTH0 (env->fpu->ft0.fs[!FP_ENDIAN_IDX]) | |
| 33 | +#define FSTH1 (env->fpu->ft1.fs[!FP_ENDIAN_IDX]) | |
| 34 | +#define FSTH2 (env->fpu->ft2.fs[!FP_ENDIAN_IDX]) | |
| 35 | +#define DT0 (env->fpu->ft0.d) | |
| 36 | +#define DT1 (env->fpu->ft1.d) | |
| 37 | +#define DT2 (env->fpu->ft2.d) | |
| 38 | +#define WT0 (env->fpu->ft0.w[FP_ENDIAN_IDX]) | |
| 39 | +#define WT1 (env->fpu->ft1.w[FP_ENDIAN_IDX]) | |
| 40 | +#define WT2 (env->fpu->ft2.w[FP_ENDIAN_IDX]) | |
| 41 | +#define WTH0 (env->fpu->ft0.w[!FP_ENDIAN_IDX]) | |
| 42 | +#define WTH1 (env->fpu->ft1.w[!FP_ENDIAN_IDX]) | |
| 43 | +#define WTH2 (env->fpu->ft2.w[!FP_ENDIAN_IDX]) | |
| 44 | 44 | #endif |
| 45 | 45 | |
| 46 | 46 | #if defined (DEBUG_OP) |
| ... | ... | @@ -157,7 +157,8 @@ void cpu_mips_update_irq (CPUState *env); |
| 157 | 157 | void cpu_mips_clock_init (CPUState *env); |
| 158 | 158 | void cpu_mips_tlb_flush (CPUState *env, int flush_global); |
| 159 | 159 | |
| 160 | -void do_ctc1 (void); | |
| 160 | +void do_cfc1 (int reg); | |
| 161 | +void do_ctc1 (int reg); | |
| 161 | 162 | |
| 162 | 163 | #define FOP_PROTO(op) \ |
| 163 | 164 | void do_float_ ## op ## _s(void); \ | ... | ... |
target-mips/fop_template.c
| ... | ... | @@ -24,14 +24,14 @@ |
| 24 | 24 | #define OP_WLOAD_FREG(treg, tregname, FREG) \ |
| 25 | 25 | void glue(glue(op_load_fpr_,tregname), FREG) (void) \ |
| 26 | 26 | { \ |
| 27 | - treg = env->fpr[FREG].fs[FP_ENDIAN_IDX]; \ | |
| 27 | + treg = env->fpu->fpr[FREG].fs[FP_ENDIAN_IDX]; \ | |
| 28 | 28 | RETURN(); \ |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | 31 | #define OP_WSTORE_FREG(treg, tregname, FREG) \ |
| 32 | 32 | void glue(glue(op_store_fpr_,tregname), FREG) (void) \ |
| 33 | 33 | { \ |
| 34 | - env->fpr[FREG].fs[FP_ENDIAN_IDX] = treg; \ | |
| 34 | + env->fpu->fpr[FREG].fs[FP_ENDIAN_IDX] = treg; \ | |
| 35 | 35 | RETURN(); \ |
| 36 | 36 | } |
| 37 | 37 | |
| ... | ... | @@ -50,10 +50,10 @@ OP_WSTORE_FREG(WT2, WT2_fpr, FREG) |
| 50 | 50 | void glue(glue(op_load_fpr_,tregname), FREG) (void) \ |
| 51 | 51 | { \ |
| 52 | 52 | if (env->hflags & MIPS_HFLAG_F64) \ |
| 53 | - treg = env->fpr[FREG].fd; \ | |
| 53 | + treg = env->fpu->fpr[FREG].fd; \ | |
| 54 | 54 | else \ |
| 55 | - treg = (uint64_t)(env->fpr[FREG | 1].fs[FP_ENDIAN_IDX]) << 32 | \ | |
| 56 | - env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX]; \ | |
| 55 | + treg = (uint64_t)(env->fpu->fpr[FREG | 1].fs[FP_ENDIAN_IDX]) << 32 | \ | |
| 56 | + env->fpu->fpr[FREG & ~1].fs[FP_ENDIAN_IDX]; \ | |
| 57 | 57 | RETURN(); \ |
| 58 | 58 | } |
| 59 | 59 | |
| ... | ... | @@ -61,10 +61,10 @@ OP_WSTORE_FREG(WT2, WT2_fpr, FREG) |
| 61 | 61 | void glue(glue(op_store_fpr_,tregname), FREG) (void) \ |
| 62 | 62 | { \ |
| 63 | 63 | if (env->hflags & MIPS_HFLAG_F64) \ |
| 64 | - env->fpr[FREG].fd = treg; \ | |
| 64 | + env->fpu->fpr[FREG].fd = treg; \ | |
| 65 | 65 | else { \ |
| 66 | - env->fpr[FREG | 1].fs[FP_ENDIAN_IDX] = treg >> 32; \ | |
| 67 | - env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX] = treg; \ | |
| 66 | + env->fpu->fpr[FREG | 1].fs[FP_ENDIAN_IDX] = treg >> 32; \ | |
| 67 | + env->fpu->fpr[FREG & ~1].fs[FP_ENDIAN_IDX] = treg; \ | |
| 68 | 68 | } \ |
| 69 | 69 | RETURN(); \ |
| 70 | 70 | } |
| ... | ... | @@ -81,14 +81,14 @@ OP_DSTORE_FREG(DT2, DT2_fpr, FREG) |
| 81 | 81 | #define OP_PSLOAD_FREG(treg, tregname, FREG) \ |
| 82 | 82 | void glue(glue(op_load_fpr_,tregname), FREG) (void) \ |
| 83 | 83 | { \ |
| 84 | - treg = env->fpr[FREG].fs[!FP_ENDIAN_IDX]; \ | |
| 84 | + treg = env->fpu->fpr[FREG].fs[!FP_ENDIAN_IDX]; \ | |
| 85 | 85 | RETURN(); \ |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | #define OP_PSSTORE_FREG(treg, tregname, FREG) \ |
| 89 | 89 | void glue(glue(op_store_fpr_,tregname), FREG) (void) \ |
| 90 | 90 | { \ |
| 91 | - env->fpr[FREG].fs[!FP_ENDIAN_IDX] = treg; \ | |
| 91 | + env->fpu->fpr[FREG].fs[!FP_ENDIAN_IDX] = treg; \ | |
| 92 | 92 | RETURN(); \ |
| 93 | 93 | } |
| 94 | 94 | ... | ... |
target-mips/helper.c
| ... | ... | @@ -70,8 +70,8 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot, |
| 70 | 70 | uint8_t ASID = env->CP0_EntryHi & 0xFF; |
| 71 | 71 | int i; |
| 72 | 72 | |
| 73 | - for (i = 0; i < env->tlb_in_use; i++) { | |
| 74 | - r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i]; | |
| 73 | + for (i = 0; i < env->tlb->tlb_in_use; i++) { | |
| 74 | + r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i]; | |
| 75 | 75 | /* 1k pages are not supported. */ |
| 76 | 76 | target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); |
| 77 | 77 | target_ulong tag = address & ~mask; |
| ... | ... | @@ -134,7 +134,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
| 134 | 134 | *physical = address & 0xFFFFFFFF; |
| 135 | 135 | *prot = PAGE_READ | PAGE_WRITE; |
| 136 | 136 | } else { |
| 137 | - ret = env->map_address(env, physical, prot, address, rw, access_type); | |
| 137 | + ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | |
| 138 | 138 | } |
| 139 | 139 | #ifdef TARGET_MIPS64 |
| 140 | 140 | /* |
| ... | ... | @@ -144,14 +144,14 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
| 144 | 144 | } else if (address < 0x3FFFFFFFFFFFFFFFULL) { |
| 145 | 145 | /* xuseg */ |
| 146 | 146 | if (UX && address < (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) { |
| 147 | - ret = env->map_address(env, physical, prot, address, rw, access_type); | |
| 147 | + ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | |
| 148 | 148 | } else { |
| 149 | 149 | ret = TLBRET_BADADDR; |
| 150 | 150 | } |
| 151 | 151 | } else if (address < 0x7FFFFFFFFFFFFFFFULL) { |
| 152 | 152 | /* xsseg */ |
| 153 | 153 | if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { |
| 154 | - ret = env->map_address(env, physical, prot, address, rw, access_type); | |
| 154 | + ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | |
| 155 | 155 | } else { |
| 156 | 156 | ret = TLBRET_BADADDR; |
| 157 | 157 | } |
| ... | ... | @@ -169,7 +169,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
| 169 | 169 | /* xkseg */ |
| 170 | 170 | /* XXX: check supervisor mode */ |
| 171 | 171 | if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) { |
| 172 | - ret = env->map_address(env, physical, prot, address, rw, access_type); | |
| 172 | + ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | |
| 173 | 173 | } else { |
| 174 | 174 | ret = TLBRET_BADADDR; |
| 175 | 175 | } |
| ... | ... | @@ -186,12 +186,12 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
| 186 | 186 | *prot = PAGE_READ | PAGE_WRITE; |
| 187 | 187 | } else if (address < (int32_t)0xE0000000UL) { |
| 188 | 188 | /* kseg2 */ |
| 189 | - ret = env->map_address(env, physical, prot, address, rw, access_type); | |
| 189 | + ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | |
| 190 | 190 | } else { |
| 191 | 191 | /* kseg3 */ |
| 192 | 192 | /* XXX: check supervisor mode */ |
| 193 | 193 | /* XXX: debug segment is not emulated */ |
| 194 | - ret = env->map_address(env, physical, prot, address, rw, access_type); | |
| 194 | + ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | |
| 195 | 195 | } |
| 196 | 196 | #if 0 |
| 197 | 197 | if (logfile) { |
| ... | ... | @@ -238,7 +238,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
| 238 | 238 | cpu_dump_state(env, logfile, fprintf, 0); |
| 239 | 239 | #endif |
| 240 | 240 | fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d is_user %d smmu %d\n", |
| 241 | - __func__, env->PC, address, rw, is_user, is_softmmu); | |
| 241 | + __func__, env->PC[env->current_tc], address, rw, is_user, is_softmmu); | |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | 244 | rw &= 1; |
| ... | ... | @@ -328,7 +328,7 @@ void do_interrupt (CPUState *env) |
| 328 | 328 | |
| 329 | 329 | if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { |
| 330 | 330 | fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d excp %d\n", |
| 331 | - __func__, env->PC, env->CP0_EPC, cause, env->exception_index); | |
| 331 | + __func__, env->PC[env->current_tc], env->CP0_EPC, cause, env->exception_index); | |
| 332 | 332 | } |
| 333 | 333 | if (env->exception_index == EXCP_EXT_INTERRUPT && |
| 334 | 334 | (env->hflags & MIPS_HFLAG_DM)) |
| ... | ... | @@ -342,7 +342,7 @@ void do_interrupt (CPUState *env) |
| 342 | 342 | * (but we assume the pc has always been updated during |
| 343 | 343 | * code translation). |
| 344 | 344 | */ |
| 345 | - env->CP0_DEPC = env->PC; | |
| 345 | + env->CP0_DEPC = env->PC[env->current_tc]; | |
| 346 | 346 | goto enter_debug_mode; |
| 347 | 347 | case EXCP_DINT: |
| 348 | 348 | env->CP0_Debug |= 1 << CP0DB_DINT; |
| ... | ... | @@ -362,10 +362,10 @@ void do_interrupt (CPUState *env) |
| 362 | 362 | if (env->hflags & MIPS_HFLAG_BMASK) { |
| 363 | 363 | /* If the exception was raised from a delay slot, |
| 364 | 364 | come back to the jump. */ |
| 365 | - env->CP0_DEPC = env->PC - 4; | |
| 365 | + env->CP0_DEPC = env->PC[env->current_tc] - 4; | |
| 366 | 366 | env->hflags &= ~MIPS_HFLAG_BMASK; |
| 367 | 367 | } else { |
| 368 | - env->CP0_DEPC = env->PC; | |
| 368 | + env->CP0_DEPC = env->PC[env->current_tc]; | |
| 369 | 369 | } |
| 370 | 370 | enter_debug_mode: |
| 371 | 371 | env->hflags |= MIPS_HFLAG_DM; |
| ... | ... | @@ -375,7 +375,7 @@ void do_interrupt (CPUState *env) |
| 375 | 375 | /* EJTAG probe trap enable is not implemented... */ |
| 376 | 376 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
| 377 | 377 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
| 378 | - env->PC = (int32_t)0xBFC00480; | |
| 378 | + env->PC[env->current_tc] = (int32_t)0xBFC00480; | |
| 379 | 379 | break; |
| 380 | 380 | case EXCP_RESET: |
| 381 | 381 | cpu_reset(env); |
| ... | ... | @@ -390,10 +390,10 @@ void do_interrupt (CPUState *env) |
| 390 | 390 | if (env->hflags & MIPS_HFLAG_BMASK) { |
| 391 | 391 | /* If the exception was raised from a delay slot, |
| 392 | 392 | come back to the jump. */ |
| 393 | - env->CP0_ErrorEPC = env->PC - 4; | |
| 393 | + env->CP0_ErrorEPC = env->PC[env->current_tc] - 4; | |
| 394 | 394 | env->hflags &= ~MIPS_HFLAG_BMASK; |
| 395 | 395 | } else { |
| 396 | - env->CP0_ErrorEPC = env->PC; | |
| 396 | + env->CP0_ErrorEPC = env->PC[env->current_tc]; | |
| 397 | 397 | } |
| 398 | 398 | env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); |
| 399 | 399 | if ((env->CP0_Config0 & (0x3 << CP0C0_AT))) |
| ... | ... | @@ -401,7 +401,7 @@ void do_interrupt (CPUState *env) |
| 401 | 401 | env->hflags &= ~MIPS_HFLAG_UM; |
| 402 | 402 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
| 403 | 403 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
| 404 | - env->PC = (int32_t)0xBFC00000; | |
| 404 | + env->PC[env->current_tc] = (int32_t)0xBFC00000; | |
| 405 | 405 | break; |
| 406 | 406 | case EXCP_MCHECK: |
| 407 | 407 | cause = 24; |
| ... | ... | @@ -471,6 +471,9 @@ void do_interrupt (CPUState *env) |
| 471 | 471 | goto set_EPC; |
| 472 | 472 | case EXCP_TLBS: |
| 473 | 473 | cause = 3; |
| 474 | + goto set_EPC; | |
| 475 | + case EXCP_THREAD: | |
| 476 | + cause = 25; | |
| 474 | 477 | if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) { |
| 475 | 478 | #ifdef TARGET_MIPS64 |
| 476 | 479 | int R = env->CP0_BadVAddr >> 62; |
| ... | ... | @@ -489,10 +492,10 @@ void do_interrupt (CPUState *env) |
| 489 | 492 | if (env->hflags & MIPS_HFLAG_BMASK) { |
| 490 | 493 | /* If the exception was raised from a delay slot, |
| 491 | 494 | come back to the jump. */ |
| 492 | - env->CP0_EPC = env->PC - 4; | |
| 495 | + env->CP0_EPC = env->PC[env->current_tc] - 4; | |
| 493 | 496 | env->CP0_Cause |= (1 << CP0Ca_BD); |
| 494 | 497 | } else { |
| 495 | - env->CP0_EPC = env->PC; | |
| 498 | + env->CP0_EPC = env->PC[env->current_tc]; | |
| 496 | 499 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
| 497 | 500 | } |
| 498 | 501 | env->CP0_Status |= (1 << CP0St_EXL); |
| ... | ... | @@ -502,11 +505,11 @@ void do_interrupt (CPUState *env) |
| 502 | 505 | } |
| 503 | 506 | env->hflags &= ~MIPS_HFLAG_BMASK; |
| 504 | 507 | if (env->CP0_Status & (1 << CP0St_BEV)) { |
| 505 | - env->PC = (int32_t)0xBFC00200; | |
| 508 | + env->PC[env->current_tc] = (int32_t)0xBFC00200; | |
| 506 | 509 | } else { |
| 507 | - env->PC = (int32_t)(env->CP0_EBase & ~0x3ff); | |
| 510 | + env->PC[env->current_tc] = (int32_t)(env->CP0_EBase & ~0x3ff); | |
| 508 | 511 | } |
| 509 | - env->PC += offset; | |
| 512 | + env->PC[env->current_tc] += offset; | |
| 510 | 513 | env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); |
| 511 | 514 | break; |
| 512 | 515 | default: |
| ... | ... | @@ -520,7 +523,7 @@ void do_interrupt (CPUState *env) |
| 520 | 523 | if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { |
| 521 | 524 | fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d excp %d\n" |
| 522 | 525 | " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n", |
| 523 | - __func__, env->PC, env->CP0_EPC, cause, env->exception_index, | |
| 526 | + __func__, env->PC[env->current_tc], env->CP0_EPC, cause, env->exception_index, | |
| 524 | 527 | env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, |
| 525 | 528 | env->CP0_DEPC); |
| 526 | 529 | } |
| ... | ... | @@ -536,19 +539,19 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) |
| 536 | 539 | uint8_t ASID = env->CP0_EntryHi & 0xFF; |
| 537 | 540 | target_ulong mask; |
| 538 | 541 | |
| 539 | - tlb = &env->mmu.r4k.tlb[idx]; | |
| 542 | + tlb = &env->tlb->mmu.r4k.tlb[idx]; | |
| 540 | 543 | /* The qemu TLB is flushed when the ASID changes, so no need to |
| 541 | 544 | flush these entries again. */ |
| 542 | 545 | if (tlb->G == 0 && tlb->ASID != ASID) { |
| 543 | 546 | return; |
| 544 | 547 | } |
| 545 | 548 | |
| 546 | - if (use_extra && env->tlb_in_use < MIPS_TLB_MAX) { | |
| 549 | + if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) { | |
| 547 | 550 | /* For tlbwr, we can shadow the discarded entry into |
| 548 | 551 | a new (fake) TLB entry, as long as the guest can not |
| 549 | 552 | tell that it's there. */ |
| 550 | - env->mmu.r4k.tlb[env->tlb_in_use] = *tlb; | |
| 551 | - env->tlb_in_use++; | |
| 553 | + env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb; | |
| 554 | + env->tlb->tlb_in_use++; | |
| 552 | 555 | return; |
| 553 | 556 | } |
| 554 | 557 | ... | ... |
target-mips/op.c
| ... | ... | @@ -254,25 +254,25 @@ void op_dup_T0 (void) |
| 254 | 254 | |
| 255 | 255 | void op_load_HI (void) |
| 256 | 256 | { |
| 257 | - T0 = env->HI; | |
| 257 | + T0 = env->HI[PARAM1][env->current_tc]; | |
| 258 | 258 | RETURN(); |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | 261 | void op_store_HI (void) |
| 262 | 262 | { |
| 263 | - env->HI = T0; | |
| 263 | + env->HI[PARAM1][env->current_tc] = T0; | |
| 264 | 264 | RETURN(); |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | 267 | void op_load_LO (void) |
| 268 | 268 | { |
| 269 | - T0 = env->LO; | |
| 269 | + T0 = env->LO[PARAM1][env->current_tc]; | |
| 270 | 270 | RETURN(); |
| 271 | 271 | } |
| 272 | 272 | |
| 273 | 273 | void op_store_LO (void) |
| 274 | 274 | { |
| 275 | - env->LO = T0; | |
| 275 | + env->LO[PARAM1][env->current_tc] = T0; | |
| 276 | 276 | RETURN(); |
| 277 | 277 | } |
| 278 | 278 | |
| ... | ... | @@ -363,8 +363,8 @@ void op_div (void) |
| 363 | 363 | void op_div (void) |
| 364 | 364 | { |
| 365 | 365 | if (T1 != 0) { |
| 366 | - env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); | |
| 367 | - env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); | |
| 366 | + env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); | |
| 367 | + env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); | |
| 368 | 368 | } |
| 369 | 369 | RETURN(); |
| 370 | 370 | } |
| ... | ... | @@ -373,8 +373,8 @@ void op_div (void) |
| 373 | 373 | void op_divu (void) |
| 374 | 374 | { |
| 375 | 375 | if (T1 != 0) { |
| 376 | - env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1); | |
| 377 | - env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1); | |
| 376 | + env->LO[0][env->current_tc] = (int32_t)((uint32_t)T0 / (uint32_t)T1); | |
| 377 | + env->HI[0][env->current_tc] = (int32_t)((uint32_t)T0 % (uint32_t)T1); | |
| 378 | 378 | } |
| 379 | 379 | RETURN(); |
| 380 | 380 | } |
| ... | ... | @@ -442,8 +442,8 @@ void op_ddivu (void) |
| 442 | 442 | void op_ddivu (void) |
| 443 | 443 | { |
| 444 | 444 | if (T1 != 0) { |
| 445 | - env->LO = T0 / T1; | |
| 446 | - env->HI = T0 % T1; | |
| 445 | + env->LO[0][env->current_tc] = T0 / T1; | |
| 446 | + env->HI[0][env->current_tc] = T0 % T1; | |
| 447 | 447 | } |
| 448 | 448 | RETURN(); |
| 449 | 449 | } |
| ... | ... | @@ -814,13 +814,14 @@ void op_msubu (void) |
| 814 | 814 | |
| 815 | 815 | static inline uint64_t get_HILO (void) |
| 816 | 816 | { |
| 817 | - return ((uint64_t)env->HI << 32) | ((uint64_t)(uint32_t)env->LO); | |
| 817 | + return ((uint64_t)env->HI[0][env->current_tc] << 32) | | |
| 818 | + ((uint64_t)(uint32_t)env->LO[0][env->current_tc]); | |
| 818 | 819 | } |
| 819 | 820 | |
| 820 | 821 | static inline void set_HILO (uint64_t HILO) |
| 821 | 822 | { |
| 822 | - env->LO = (int32_t)(HILO & 0xFFFFFFFF); | |
| 823 | - env->HI = (int32_t)(HILO >> 32); | |
| 823 | + env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF); | |
| 824 | + env->HI[0][env->current_tc] = (int32_t)(HILO >> 32); | |
| 824 | 825 | } |
| 825 | 826 | |
| 826 | 827 | void op_mult (void) |
| ... | ... | @@ -875,13 +876,13 @@ void op_msubu (void) |
| 875 | 876 | #ifdef TARGET_MIPS64 |
| 876 | 877 | void op_dmult (void) |
| 877 | 878 | { |
| 878 | - CALL_FROM_TB4(muls64, &(env->HI), &(env->LO), T0, T1); | |
| 879 | + CALL_FROM_TB4(muls64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1); | |
| 879 | 880 | RETURN(); |
| 880 | 881 | } |
| 881 | 882 | |
| 882 | 883 | void op_dmultu (void) |
| 883 | 884 | { |
| 884 | - CALL_FROM_TB4(mulu64, &(env->HI), &(env->LO), T0, T1); | |
| 885 | + CALL_FROM_TB4(mulu64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1); | |
| 885 | 886 | RETURN(); |
| 886 | 887 | } |
| 887 | 888 | #endif |
| ... | ... | @@ -890,27 +891,27 @@ void op_dmultu (void) |
| 890 | 891 | void op_movn (void) |
| 891 | 892 | { |
| 892 | 893 | if (T1 != 0) |
| 893 | - env->gpr[PARAM1] = T0; | |
| 894 | + env->gpr[PARAM1][env->current_tc] = T0; | |
| 894 | 895 | RETURN(); |
| 895 | 896 | } |
| 896 | 897 | |
| 897 | 898 | void op_movz (void) |
| 898 | 899 | { |
| 899 | 900 | if (T1 == 0) |
| 900 | - env->gpr[PARAM1] = T0; | |
| 901 | + env->gpr[PARAM1][env->current_tc] = T0; | |
| 901 | 902 | RETURN(); |
| 902 | 903 | } |
| 903 | 904 | |
| 904 | 905 | void op_movf (void) |
| 905 | 906 | { |
| 906 | - if (!(env->fcr31 & PARAM1)) | |
| 907 | + if (!(env->fpu->fcr31 & PARAM1)) | |
| 907 | 908 | T0 = T1; |
| 908 | 909 | RETURN(); |
| 909 | 910 | } |
| 910 | 911 | |
| 911 | 912 | void op_movt (void) |
| 912 | 913 | { |
| 913 | - if (env->fcr31 & PARAM1) | |
| 914 | + if (env->fpu->fcr31 & PARAM1) | |
| 914 | 915 | T0 = T1; |
| 915 | 916 | RETURN(); |
| 916 | 917 | } |
| ... | ... | @@ -966,7 +967,7 @@ void op_restore_breg_target (void) |
| 966 | 967 | |
| 967 | 968 | void op_breg (void) |
| 968 | 969 | { |
| 969 | - env->PC = T2; | |
| 970 | + env->PC[env->current_tc] = T2; | |
| 970 | 971 | RETURN(); |
| 971 | 972 | } |
| 972 | 973 | |
| ... | ... | @@ -1017,18 +1018,176 @@ void op_mfc0_index (void) |
| 1017 | 1018 | RETURN(); |
| 1018 | 1019 | } |
| 1019 | 1020 | |
| 1021 | +void op_mfc0_mvpcontrol (void) | |
| 1022 | +{ | |
| 1023 | + T0 = env->mvp->CP0_MVPControl; | |
| 1024 | + RETURN(); | |
| 1025 | +} | |
| 1026 | + | |
| 1027 | +void op_mfc0_mvpconf0 (void) | |
| 1028 | +{ | |
| 1029 | + T0 = env->mvp->CP0_MVPConf0; | |
| 1030 | + RETURN(); | |
| 1031 | +} | |
| 1032 | + | |
| 1033 | +void op_mfc0_mvpconf1 (void) | |
| 1034 | +{ | |
| 1035 | + T0 = env->mvp->CP0_MVPConf1; | |
| 1036 | + RETURN(); | |
| 1037 | +} | |
| 1038 | + | |
| 1020 | 1039 | void op_mfc0_random (void) |
| 1021 | 1040 | { |
| 1022 | 1041 | CALL_FROM_TB0(do_mfc0_random); |
| 1023 | 1042 | RETURN(); |
| 1024 | 1043 | } |
| 1025 | 1044 | |
| 1045 | +void op_mfc0_vpecontrol (void) | |
| 1046 | +{ | |
| 1047 | + T0 = env->CP0_VPEControl; | |
| 1048 | + RETURN(); | |
| 1049 | +} | |
| 1050 | + | |
| 1051 | +void op_mfc0_vpeconf0 (void) | |
| 1052 | +{ | |
| 1053 | + T0 = env->CP0_VPEConf0; | |
| 1054 | + RETURN(); | |
| 1055 | +} | |
| 1056 | + | |
| 1057 | +void op_mfc0_vpeconf1 (void) | |
| 1058 | +{ | |
| 1059 | + T0 = env->CP0_VPEConf1; | |
| 1060 | + RETURN(); | |
| 1061 | +} | |
| 1062 | + | |
| 1063 | +void op_mfc0_yqmask (void) | |
| 1064 | +{ | |
| 1065 | + T0 = env->CP0_YQMask; | |
| 1066 | + RETURN(); | |
| 1067 | +} | |
| 1068 | + | |
| 1069 | +void op_mfc0_vpeschedule (void) | |
| 1070 | +{ | |
| 1071 | + T0 = env->CP0_VPESchedule; | |
| 1072 | + RETURN(); | |
| 1073 | +} | |
| 1074 | + | |
| 1075 | +void op_mfc0_vpeschefback (void) | |
| 1076 | +{ | |
| 1077 | + T0 = env->CP0_VPEScheFBack; | |
| 1078 | + RETURN(); | |
| 1079 | +} | |
| 1080 | + | |
| 1081 | +void op_mfc0_vpeopt (void) | |
| 1082 | +{ | |
| 1083 | + T0 = env->CP0_VPEOpt; | |
| 1084 | + RETURN(); | |
| 1085 | +} | |
| 1086 | + | |
| 1026 | 1087 | void op_mfc0_entrylo0 (void) |
| 1027 | 1088 | { |
| 1028 | 1089 | T0 = (int32_t)env->CP0_EntryLo0; |
| 1029 | 1090 | RETURN(); |
| 1030 | 1091 | } |
| 1031 | 1092 | |
| 1093 | +void op_mfc0_tcstatus (void) | |
| 1094 | +{ | |
| 1095 | + T0 = env->CP0_TCStatus[env->current_tc]; | |
| 1096 | + RETURN(); | |
| 1097 | +} | |
| 1098 | + | |
| 1099 | +void op_mftc0_tcstatus(void) | |
| 1100 | +{ | |
| 1101 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1102 | + | |
| 1103 | + T0 = env->CP0_TCStatus[other_tc]; | |
| 1104 | + RETURN(); | |
| 1105 | +} | |
| 1106 | + | |
| 1107 | +void op_mfc0_tcbind (void) | |
| 1108 | +{ | |
| 1109 | + T0 = env->CP0_TCBind[env->current_tc]; | |
| 1110 | + RETURN(); | |
| 1111 | +} | |
| 1112 | + | |
| 1113 | +void op_mftc0_tcbind(void) | |
| 1114 | +{ | |
| 1115 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1116 | + | |
| 1117 | + T0 = env->CP0_TCBind[other_tc]; | |
| 1118 | + RETURN(); | |
| 1119 | +} | |
| 1120 | + | |
| 1121 | +void op_mfc0_tcrestart (void) | |
| 1122 | +{ | |
| 1123 | + T0 = env->PC[env->current_tc]; | |
| 1124 | + RETURN(); | |
| 1125 | +} | |
| 1126 | + | |
| 1127 | +void op_mftc0_tcrestart(void) | |
| 1128 | +{ | |
| 1129 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1130 | + | |
| 1131 | + T0 = env->PC[other_tc]; | |
| 1132 | + RETURN(); | |
| 1133 | +} | |
| 1134 | + | |
| 1135 | +void op_mfc0_tchalt (void) | |
| 1136 | +{ | |
| 1137 | + T0 = env->CP0_TCHalt[env->current_tc]; | |
| 1138 | + RETURN(); | |
| 1139 | +} | |
| 1140 | + | |
| 1141 | +void op_mftc0_tchalt(void) | |
| 1142 | +{ | |
| 1143 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1144 | + | |
| 1145 | + T0 = env->CP0_TCHalt[other_tc]; | |
| 1146 | + RETURN(); | |
| 1147 | +} | |
| 1148 | + | |
| 1149 | +void op_mfc0_tccontext (void) | |
| 1150 | +{ | |
| 1151 | + T0 = env->CP0_TCContext[env->current_tc]; | |
| 1152 | + RETURN(); | |
| 1153 | +} | |
| 1154 | + | |
| 1155 | +void op_mftc0_tccontext(void) | |
| 1156 | +{ | |
| 1157 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1158 | + | |
| 1159 | + T0 = env->CP0_TCContext[other_tc]; | |
| 1160 | + RETURN(); | |
| 1161 | +} | |
| 1162 | + | |
| 1163 | +void op_mfc0_tcschedule (void) | |
| 1164 | +{ | |
| 1165 | + T0 = env->CP0_TCSchedule[env->current_tc]; | |
| 1166 | + RETURN(); | |
| 1167 | +} | |
| 1168 | + | |
| 1169 | +void op_mftc0_tcschedule(void) | |
| 1170 | +{ | |
| 1171 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1172 | + | |
| 1173 | + T0 = env->CP0_TCSchedule[other_tc]; | |
| 1174 | + RETURN(); | |
| 1175 | +} | |
| 1176 | + | |
| 1177 | +void op_mfc0_tcschefback (void) | |
| 1178 | +{ | |
| 1179 | + T0 = env->CP0_TCScheFBack[env->current_tc]; | |
| 1180 | + RETURN(); | |
| 1181 | +} | |
| 1182 | + | |
| 1183 | +void op_mftc0_tcschefback(void) | |
| 1184 | +{ | |
| 1185 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1186 | + | |
| 1187 | + T0 = env->CP0_TCScheFBack[other_tc]; | |
| 1188 | + RETURN(); | |
| 1189 | +} | |
| 1190 | + | |
| 1032 | 1191 | void op_mfc0_entrylo1 (void) |
| 1033 | 1192 | { |
| 1034 | 1193 | T0 = (int32_t)env->CP0_EntryLo1; |
| ... | ... | @@ -1059,6 +1218,36 @@ void op_mfc0_wired (void) |
| 1059 | 1218 | RETURN(); |
| 1060 | 1219 | } |
| 1061 | 1220 | |
| 1221 | +void op_mfc0_srsconf0 (void) | |
| 1222 | +{ | |
| 1223 | + T0 = env->CP0_SRSConf0; | |
| 1224 | + RETURN(); | |
| 1225 | +} | |
| 1226 | + | |
| 1227 | +void op_mfc0_srsconf1 (void) | |
| 1228 | +{ | |
| 1229 | + T0 = env->CP0_SRSConf1; | |
| 1230 | + RETURN(); | |
| 1231 | +} | |
| 1232 | + | |
| 1233 | +void op_mfc0_srsconf2 (void) | |
| 1234 | +{ | |
| 1235 | + T0 = env->CP0_SRSConf2; | |
| 1236 | + RETURN(); | |
| 1237 | +} | |
| 1238 | + | |
| 1239 | +void op_mfc0_srsconf3 (void) | |
| 1240 | +{ | |
| 1241 | + T0 = env->CP0_SRSConf3; | |
| 1242 | + RETURN(); | |
| 1243 | +} | |
| 1244 | + | |
| 1245 | +void op_mfc0_srsconf4 (void) | |
| 1246 | +{ | |
| 1247 | + T0 = env->CP0_SRSConf4; | |
| 1248 | + RETURN(); | |
| 1249 | +} | |
| 1250 | + | |
| 1062 | 1251 | void op_mfc0_hwrena (void) |
| 1063 | 1252 | { |
| 1064 | 1253 | T0 = env->CP0_HWREna; |
| ... | ... | @@ -1083,6 +1272,14 @@ void op_mfc0_entryhi (void) |
| 1083 | 1272 | RETURN(); |
| 1084 | 1273 | } |
| 1085 | 1274 | |
| 1275 | +void op_mftc0_entryhi(void) | |
| 1276 | +{ | |
| 1277 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1278 | + | |
| 1279 | + T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff); | |
| 1280 | + RETURN(); | |
| 1281 | +} | |
| 1282 | + | |
| 1086 | 1283 | void op_mfc0_compare (void) |
| 1087 | 1284 | { |
| 1088 | 1285 | T0 = env->CP0_Compare; |
| ... | ... | @@ -1095,6 +1292,18 @@ void op_mfc0_status (void) |
| 1095 | 1292 | RETURN(); |
| 1096 | 1293 | } |
| 1097 | 1294 | |
| 1295 | +void op_mftc0_status(void) | |
| 1296 | +{ | |
| 1297 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1298 | + uint32_t tcstatus = env->CP0_TCStatus[other_tc]; | |
| 1299 | + | |
| 1300 | + T0 = env->CP0_Status & ~0xf1000018; | |
| 1301 | + T0 |= tcstatus & (0xf << CP0TCSt_TCU0); | |
| 1302 | + T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX); | |
| 1303 | + T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_R0); | |
| 1304 | + RETURN(); | |
| 1305 | +} | |
| 1306 | + | |
| 1098 | 1307 | void op_mfc0_intctl (void) |
| 1099 | 1308 | { |
| 1100 | 1309 | T0 = env->CP0_IntCtl; |
| ... | ... | @@ -1211,6 +1420,17 @@ void op_mfc0_debug (void) |
| 1211 | 1420 | RETURN(); |
| 1212 | 1421 | } |
| 1213 | 1422 | |
| 1423 | +void op_mftc0_debug(void) | |
| 1424 | +{ | |
| 1425 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1426 | + | |
| 1427 | + /* XXX: Might be wrong, check with EJTAG spec. */ | |
| 1428 | + T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | | |
| 1429 | + (env->CP0_Debug_tcstatus[other_tc] & | |
| 1430 | + ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); | |
| 1431 | + RETURN(); | |
| 1432 | +} | |
| 1433 | + | |
| 1214 | 1434 | void op_mfc0_depc (void) |
| 1215 | 1435 | { |
| 1216 | 1436 | T0 = (int32_t)env->CP0_DEPC; |
| ... | ... | @@ -1261,7 +1481,105 @@ void op_mfc0_desave (void) |
| 1261 | 1481 | |
| 1262 | 1482 | void op_mtc0_index (void) |
| 1263 | 1483 | { |
| 1264 | - env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb); | |
| 1484 | + env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->tlb->nb_tlb); | |
| 1485 | + RETURN(); | |
| 1486 | +} | |
| 1487 | + | |
| 1488 | +void op_mtc0_mvpcontrol (void) | |
| 1489 | +{ | |
| 1490 | + uint32_t mask = 0; | |
| 1491 | + uint32_t newval; | |
| 1492 | + | |
| 1493 | + if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) | |
| 1494 | + mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) | | |
| 1495 | + (1 << CP0MVPCo_EVP); | |
| 1496 | + if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) | |
| 1497 | + mask |= (1 << CP0MVPCo_STLB); | |
| 1498 | + newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask); | |
| 1499 | + | |
| 1500 | + // TODO: Enable/disable shared TLB, enable/disable VPEs. | |
| 1501 | + | |
| 1502 | + env->mvp->CP0_MVPControl = newval; | |
| 1503 | + RETURN(); | |
| 1504 | +} | |
| 1505 | + | |
| 1506 | +void op_mtc0_vpecontrol (void) | |
| 1507 | +{ | |
| 1508 | + uint32_t mask; | |
| 1509 | + uint32_t newval; | |
| 1510 | + | |
| 1511 | + mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) | | |
| 1512 | + (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC); | |
| 1513 | + newval = (env->CP0_VPEControl & ~mask) | (T0 & mask); | |
| 1514 | + | |
| 1515 | + /* Yield scheduler intercept not implemented. */ | |
| 1516 | + /* Gating storage scheduler intercept not implemented. */ | |
| 1517 | + | |
| 1518 | + // TODO: Enable/disable TCs. | |
| 1519 | + | |
| 1520 | + env->CP0_VPEControl = newval; | |
| 1521 | + RETURN(); | |
| 1522 | +} | |
| 1523 | + | |
| 1524 | +void op_mtc0_vpeconf0 (void) | |
| 1525 | +{ | |
| 1526 | + uint32_t mask = 0; | |
| 1527 | + uint32_t newval; | |
| 1528 | + | |
| 1529 | + if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) { | |
| 1530 | + if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA)) | |
| 1531 | + mask |= (0xff << CP0VPEC0_XTC); | |
| 1532 | + mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); | |
| 1533 | + } | |
| 1534 | + newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask); | |
| 1535 | + | |
| 1536 | + // TODO: TC exclusive handling due to ERL/EXL. | |
| 1537 | + | |
| 1538 | + env->CP0_VPEConf0 = newval; | |
| 1539 | + RETURN(); | |
| 1540 | +} | |
| 1541 | + | |
| 1542 | +void op_mtc0_vpeconf1 (void) | |
| 1543 | +{ | |
| 1544 | + uint32_t mask = 0; | |
| 1545 | + uint32_t newval; | |
| 1546 | + | |
| 1547 | + if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) | |
| 1548 | + mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) | | |
| 1549 | + (0xff << CP0VPEC1_NCP1); | |
| 1550 | + newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask); | |
| 1551 | + | |
| 1552 | + /* UDI not implemented. */ | |
| 1553 | + /* CP2 not implemented. */ | |
| 1554 | + | |
| 1555 | + // TODO: Handle FPU (CP1) binding. | |
| 1556 | + | |
| 1557 | + env->CP0_VPEConf1 = newval; | |
| 1558 | + RETURN(); | |
| 1559 | +} | |
| 1560 | + | |
| 1561 | +void op_mtc0_yqmask (void) | |
| 1562 | +{ | |
| 1563 | + /* Yield qualifier inputs not implemented. */ | |
| 1564 | + env->CP0_YQMask = 0x00000000; | |
| 1565 | + RETURN(); | |
| 1566 | +} | |
| 1567 | + | |
| 1568 | +void op_mtc0_vpeschedule (void) | |
| 1569 | +{ | |
| 1570 | + env->CP0_VPESchedule = T0; | |
| 1571 | + RETURN(); | |
| 1572 | +} | |
| 1573 | + | |
| 1574 | +void op_mtc0_vpeschefback (void) | |
| 1575 | +{ | |
| 1576 | + env->CP0_VPEScheFBack = T0; | |
| 1577 | + RETURN(); | |
| 1578 | +} | |
| 1579 | + | |
| 1580 | +void op_mtc0_vpeopt (void) | |
| 1581 | +{ | |
| 1582 | + env->CP0_VPEOpt = T0 & 0x0000ffff; | |
| 1265 | 1583 | RETURN(); |
| 1266 | 1584 | } |
| 1267 | 1585 | |
| ... | ... | @@ -1273,6 +1591,135 @@ void op_mtc0_entrylo0 (void) |
| 1273 | 1591 | RETURN(); |
| 1274 | 1592 | } |
| 1275 | 1593 | |
| 1594 | +void op_mtc0_tcstatus (void) | |
| 1595 | +{ | |
| 1596 | + uint32_t mask = env->CP0_TCStatus_rw_bitmask; | |
| 1597 | + uint32_t newval; | |
| 1598 | + | |
| 1599 | + newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask); | |
| 1600 | + | |
| 1601 | + // TODO: Sync with CP0_Status. | |
| 1602 | + | |
| 1603 | + env->CP0_TCStatus[env->current_tc] = newval; | |
| 1604 | + RETURN(); | |
| 1605 | +} | |
| 1606 | + | |
| 1607 | +void op_mttc0_tcstatus (void) | |
| 1608 | +{ | |
| 1609 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1610 | + | |
| 1611 | + // TODO: Sync with CP0_Status. | |
| 1612 | + | |
| 1613 | + env->CP0_TCStatus[other_tc] = T0; | |
| 1614 | + RETURN(); | |
| 1615 | +} | |
| 1616 | + | |
| 1617 | +void op_mtc0_tcbind (void) | |
| 1618 | +{ | |
| 1619 | + uint32_t mask = (1 << CP0TCBd_TBE); | |
| 1620 | + uint32_t newval; | |
| 1621 | + | |
| 1622 | + if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) | |
| 1623 | + mask |= (1 << CP0TCBd_CurVPE); | |
| 1624 | + newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask); | |
| 1625 | + env->CP0_TCBind[env->current_tc] = newval; | |
| 1626 | + RETURN(); | |
| 1627 | +} | |
| 1628 | + | |
| 1629 | +void op_mttc0_tcbind (void) | |
| 1630 | +{ | |
| 1631 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1632 | + uint32_t mask = (1 << CP0TCBd_TBE); | |
| 1633 | + uint32_t newval; | |
| 1634 | + | |
| 1635 | + if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) | |
| 1636 | + mask |= (1 << CP0TCBd_CurVPE); | |
| 1637 | + newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask); | |
| 1638 | + env->CP0_TCBind[other_tc] = newval; | |
| 1639 | + RETURN(); | |
| 1640 | +} | |
| 1641 | + | |
| 1642 | +void op_mtc0_tcrestart (void) | |
| 1643 | +{ | |
| 1644 | + env->PC[env->current_tc] = T0; | |
| 1645 | + env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS); | |
| 1646 | + env->CP0_LLAddr = 0ULL; | |
| 1647 | + /* MIPS16 not implemented. */ | |
| 1648 | + RETURN(); | |
| 1649 | +} | |
| 1650 | + | |
| 1651 | +void op_mttc0_tcrestart (void) | |
| 1652 | +{ | |
| 1653 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1654 | + | |
| 1655 | + env->PC[other_tc] = T0; | |
| 1656 | + env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS); | |
| 1657 | + env->CP0_LLAddr = 0ULL; | |
| 1658 | + /* MIPS16 not implemented. */ | |
| 1659 | + RETURN(); | |
| 1660 | +} | |
| 1661 | + | |
| 1662 | +void op_mtc0_tchalt (void) | |
| 1663 | +{ | |
| 1664 | + env->CP0_TCHalt[env->current_tc] = T0 & 0x1; | |
| 1665 | + | |
| 1666 | + // TODO: Halt TC / Restart (if allocated+active) TC. | |
| 1667 | + | |
| 1668 | + RETURN(); | |
| 1669 | +} | |
| 1670 | + | |
| 1671 | +void op_mttc0_tchalt (void) | |
| 1672 | +{ | |
| 1673 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1674 | + | |
| 1675 | + // TODO: Halt TC / Restart (if allocated+active) TC. | |
| 1676 | + | |
| 1677 | + env->CP0_TCHalt[other_tc] = T0; | |
| 1678 | + RETURN(); | |
| 1679 | +} | |
| 1680 | + | |
| 1681 | +void op_mtc0_tccontext (void) | |
| 1682 | +{ | |
| 1683 | + env->CP0_TCContext[env->current_tc] = T0; | |
| 1684 | + RETURN(); | |
| 1685 | +} | |
| 1686 | + | |
| 1687 | +void op_mttc0_tccontext (void) | |
| 1688 | +{ | |
| 1689 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1690 | + | |
| 1691 | + env->CP0_TCContext[other_tc] = T0; | |
| 1692 | + RETURN(); | |
| 1693 | +} | |
| 1694 | + | |
| 1695 | +void op_mtc0_tcschedule (void) | |
| 1696 | +{ | |
| 1697 | + env->CP0_TCSchedule[env->current_tc] = T0; | |
| 1698 | + RETURN(); | |
| 1699 | +} | |
| 1700 | + | |
| 1701 | +void op_mttc0_tcschedule (void) | |
| 1702 | +{ | |
| 1703 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1704 | + | |
| 1705 | + env->CP0_TCSchedule[other_tc] = T0; | |
| 1706 | + RETURN(); | |
| 1707 | +} | |
| 1708 | + | |
| 1709 | +void op_mtc0_tcschefback (void) | |
| 1710 | +{ | |
| 1711 | + env->CP0_TCScheFBack[env->current_tc] = T0; | |
| 1712 | + RETURN(); | |
| 1713 | +} | |
| 1714 | + | |
| 1715 | +void op_mttc0_tcschefback (void) | |
| 1716 | +{ | |
| 1717 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1718 | + | |
| 1719 | + env->CP0_TCScheFBack[other_tc] = T0; | |
| 1720 | + RETURN(); | |
| 1721 | +} | |
| 1722 | + | |
| 1276 | 1723 | void op_mtc0_entrylo1 (void) |
| 1277 | 1724 | { |
| 1278 | 1725 | /* Large physaddr not implemented */ |
| ... | ... | @@ -1305,7 +1752,37 @@ void op_mtc0_pagegrain (void) |
| 1305 | 1752 | |
| 1306 | 1753 | void op_mtc0_wired (void) |
| 1307 | 1754 | { |
| 1308 | - env->CP0_Wired = T0 % env->nb_tlb; | |
| 1755 | + env->CP0_Wired = T0 % env->tlb->nb_tlb; | |
| 1756 | + RETURN(); | |
| 1757 | +} | |
| 1758 | + | |
| 1759 | +void op_mtc0_srsconf0 (void) | |
| 1760 | +{ | |
| 1761 | + env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask; | |
| 1762 | + RETURN(); | |
| 1763 | +} | |
| 1764 | + | |
| 1765 | +void op_mtc0_srsconf1 (void) | |
| 1766 | +{ | |
| 1767 | + env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask; | |
| 1768 | + RETURN(); | |
| 1769 | +} | |
| 1770 | + | |
| 1771 | +void op_mtc0_srsconf2 (void) | |
| 1772 | +{ | |
| 1773 | + env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask; | |
| 1774 | + RETURN(); | |
| 1775 | +} | |
| 1776 | + | |
| 1777 | +void op_mtc0_srsconf3 (void) | |
| 1778 | +{ | |
| 1779 | + env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask; | |
| 1780 | + RETURN(); | |
| 1781 | +} | |
| 1782 | + | |
| 1783 | +void op_mtc0_srsconf4 (void) | |
| 1784 | +{ | |
| 1785 | + env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask; | |
| 1309 | 1786 | RETURN(); |
| 1310 | 1787 | } |
| 1311 | 1788 | |
| ... | ... | @@ -1332,12 +1809,25 @@ void op_mtc0_entryhi (void) |
| 1332 | 1809 | #endif |
| 1333 | 1810 | old = env->CP0_EntryHi; |
| 1334 | 1811 | env->CP0_EntryHi = val; |
| 1812 | + if (env->CP0_Config3 & (1 << CP0C3_MT)) { | |
| 1813 | + uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff; | |
| 1814 | + env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff); | |
| 1815 | + } | |
| 1335 | 1816 | /* If the ASID changes, flush qemu's TLB. */ |
| 1336 | 1817 | if ((old & 0xFF) != (val & 0xFF)) |
| 1337 | 1818 | CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1); |
| 1338 | 1819 | RETURN(); |
| 1339 | 1820 | } |
| 1340 | 1821 | |
| 1822 | +void op_mttc0_entryhi(void) | |
| 1823 | +{ | |
| 1824 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1825 | + | |
| 1826 | + env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff); | |
| 1827 | + env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff); | |
| 1828 | + RETURN(); | |
| 1829 | +} | |
| 1830 | + | |
| 1341 | 1831 | void op_mtc0_compare (void) |
| 1342 | 1832 | { |
| 1343 | 1833 | CALL_FROM_TB2(cpu_mips_store_compare, env, T0); |
| ... | ... | @@ -1347,9 +1837,8 @@ void op_mtc0_compare (void) |
| 1347 | 1837 | void op_mtc0_status (void) |
| 1348 | 1838 | { |
| 1349 | 1839 | uint32_t val, old; |
| 1350 | - uint32_t mask = env->Status_rw_bitmask; | |
| 1840 | + uint32_t mask = env->CP0_Status_rw_bitmask; | |
| 1351 | 1841 | |
| 1352 | - /* No reverse endianness, no MDMX/DSP implemented. */ | |
| 1353 | 1842 | val = T0 & mask; |
| 1354 | 1843 | old = env->CP0_Status; |
| 1355 | 1844 | if (!(val & (1 << CP0St_EXL)) && |
| ... | ... | @@ -1379,6 +1868,19 @@ void op_mtc0_status (void) |
| 1379 | 1868 | RETURN(); |
| 1380 | 1869 | } |
| 1381 | 1870 | |
| 1871 | +void op_mttc0_status(void) | |
| 1872 | +{ | |
| 1873 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1874 | + uint32_t tcstatus = env->CP0_TCStatus[other_tc]; | |
| 1875 | + | |
| 1876 | + env->CP0_Status = T0 & ~0xf1000018; | |
| 1877 | + tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0)); | |
| 1878 | + tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX)); | |
| 1879 | + tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_R0)) << (CP0TCSt_TKSU - CP0St_R0)); | |
| 1880 | + env->CP0_TCStatus[other_tc] = tcstatus; | |
| 1881 | + RETURN(); | |
| 1882 | +} | |
| 1883 | + | |
| 1382 | 1884 | void op_mtc0_intctl (void) |
| 1383 | 1885 | { |
| 1384 | 1886 | /* vectored interrupts not implemented, timer on int 7, |
| ... | ... | @@ -1389,15 +1891,14 @@ void op_mtc0_intctl (void) |
| 1389 | 1891 | |
| 1390 | 1892 | void op_mtc0_srsctl (void) |
| 1391 | 1893 | { |
| 1392 | - /* shadow registers not implemented */ | |
| 1393 | - env->CP0_SRSCtl = 0; | |
| 1894 | + uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS); | |
| 1895 | + env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask); | |
| 1394 | 1896 | RETURN(); |
| 1395 | 1897 | } |
| 1396 | 1898 | |
| 1397 | 1899 | void op_mtc0_srsmap (void) |
| 1398 | 1900 | { |
| 1399 | - /* shadow registers not implemented */ | |
| 1400 | - env->CP0_SRSMap = 0; | |
| 1901 | + env->CP0_SRSMap = T0; | |
| 1401 | 1902 | RETURN(); |
| 1402 | 1903 | } |
| 1403 | 1904 | |
| ... | ... | @@ -1460,6 +1961,13 @@ void op_mtc0_watchhi (void) |
| 1460 | 1961 | RETURN(); |
| 1461 | 1962 | } |
| 1462 | 1963 | |
| 1964 | +void op_mtc0_xcontext (void) | |
| 1965 | +{ | |
| 1966 | + target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1; | |
| 1967 | + env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask); | |
| 1968 | + RETURN(); | |
| 1969 | +} | |
| 1970 | + | |
| 1463 | 1971 | void op_mtc0_framemask (void) |
| 1464 | 1972 | { |
| 1465 | 1973 | env->CP0_Framemask = T0; /* XXX */ |
| ... | ... | @@ -1476,6 +1984,17 @@ void op_mtc0_debug (void) |
| 1476 | 1984 | RETURN(); |
| 1477 | 1985 | } |
| 1478 | 1986 | |
| 1987 | +void op_mttc0_debug(void) | |
| 1988 | +{ | |
| 1989 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 1990 | + | |
| 1991 | + /* XXX: Might be wrong, check with EJTAG spec. */ | |
| 1992 | + env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); | |
| 1993 | + env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | | |
| 1994 | + (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); | |
| 1995 | + RETURN(); | |
| 1996 | +} | |
| 1997 | + | |
| 1479 | 1998 | void op_mtc0_depc (void) |
| 1480 | 1999 | { |
| 1481 | 2000 | env->CP0_DEPC = T0; |
| ... | ... | @@ -1525,10 +2044,21 @@ void op_mtc0_desave (void) |
| 1525 | 2044 | } |
| 1526 | 2045 | |
| 1527 | 2046 | #ifdef TARGET_MIPS64 |
| 1528 | -void op_mtc0_xcontext (void) | |
| 2047 | +void op_dmfc0_yqmask (void) | |
| 1529 | 2048 | { |
| 1530 | - target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1; | |
| 1531 | - env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask); | |
| 2049 | + T0 = env->CP0_YQMask; | |
| 2050 | + RETURN(); | |
| 2051 | +} | |
| 2052 | + | |
| 2053 | +void op_dmfc0_vpeschedule (void) | |
| 2054 | +{ | |
| 2055 | + T0 = env->CP0_VPESchedule; | |
| 2056 | + RETURN(); | |
| 2057 | +} | |
| 2058 | + | |
| 2059 | +void op_dmfc0_vpeschefback (void) | |
| 2060 | +{ | |
| 2061 | + T0 = env->CP0_VPEScheFBack; | |
| 1532 | 2062 | RETURN(); |
| 1533 | 2063 | } |
| 1534 | 2064 | |
| ... | ... | @@ -1538,6 +2068,36 @@ void op_dmfc0_entrylo0 (void) |
| 1538 | 2068 | RETURN(); |
| 1539 | 2069 | } |
| 1540 | 2070 | |
| 2071 | +void op_dmfc0_tcrestart (void) | |
| 2072 | +{ | |
| 2073 | + T0 = env->PC[env->current_tc]; | |
| 2074 | + RETURN(); | |
| 2075 | +} | |
| 2076 | + | |
| 2077 | +void op_dmfc0_tchalt (void) | |
| 2078 | +{ | |
| 2079 | + T0 = env->CP0_TCHalt[env->current_tc]; | |
| 2080 | + RETURN(); | |
| 2081 | +} | |
| 2082 | + | |
| 2083 | +void op_dmfc0_tccontext (void) | |
| 2084 | +{ | |
| 2085 | + T0 = env->CP0_TCContext[env->current_tc]; | |
| 2086 | + RETURN(); | |
| 2087 | +} | |
| 2088 | + | |
| 2089 | +void op_dmfc0_tcschedule (void) | |
| 2090 | +{ | |
| 2091 | + T0 = env->CP0_TCSchedule[env->current_tc]; | |
| 2092 | + RETURN(); | |
| 2093 | +} | |
| 2094 | + | |
| 2095 | +void op_dmfc0_tcschefback (void) | |
| 2096 | +{ | |
| 2097 | + T0 = env->CP0_TCScheFBack[env->current_tc]; | |
| 2098 | + RETURN(); | |
| 2099 | +} | |
| 2100 | + | |
| 1541 | 2101 | void op_dmfc0_entrylo1 (void) |
| 1542 | 2102 | { |
| 1543 | 2103 | T0 = env->CP0_EntryLo1; |
| ... | ... | @@ -1599,6 +2159,157 @@ void op_dmfc0_errorepc (void) |
| 1599 | 2159 | } |
| 1600 | 2160 | #endif /* TARGET_MIPS64 */ |
| 1601 | 2161 | |
| 2162 | +/* MIPS MT functions */ | |
| 2163 | +void op_mftgpr(void) | |
| 2164 | +{ | |
| 2165 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2166 | + | |
| 2167 | + T0 = env->gpr[PARAM1][other_tc]; | |
| 2168 | + RETURN(); | |
| 2169 | +} | |
| 2170 | + | |
| 2171 | +void op_mftlo(void) | |
| 2172 | +{ | |
| 2173 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2174 | + | |
| 2175 | + T0 = env->LO[PARAM1][other_tc]; | |
| 2176 | + RETURN(); | |
| 2177 | +} | |
| 2178 | + | |
| 2179 | +void op_mfthi(void) | |
| 2180 | +{ | |
| 2181 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2182 | + | |
| 2183 | + T0 = env->HI[PARAM1][other_tc]; | |
| 2184 | + RETURN(); | |
| 2185 | +} | |
| 2186 | + | |
| 2187 | +void op_mftacx(void) | |
| 2188 | +{ | |
| 2189 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2190 | + | |
| 2191 | + T0 = env->ACX[PARAM1][other_tc]; | |
| 2192 | + RETURN(); | |
| 2193 | +} | |
| 2194 | + | |
| 2195 | +void op_mftdsp(void) | |
| 2196 | +{ | |
| 2197 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2198 | + | |
| 2199 | + T0 = env->DSPControl[other_tc]; | |
| 2200 | + RETURN(); | |
| 2201 | +} | |
| 2202 | + | |
| 2203 | +void op_mttgpr(void) | |
| 2204 | +{ | |
| 2205 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2206 | + | |
| 2207 | + T0 = env->gpr[PARAM1][other_tc]; | |
| 2208 | + RETURN(); | |
| 2209 | +} | |
| 2210 | + | |
| 2211 | +void op_mttlo(void) | |
| 2212 | +{ | |
| 2213 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2214 | + | |
| 2215 | + T0 = env->LO[PARAM1][other_tc]; | |
| 2216 | + RETURN(); | |
| 2217 | +} | |
| 2218 | + | |
| 2219 | +void op_mtthi(void) | |
| 2220 | +{ | |
| 2221 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2222 | + | |
| 2223 | + T0 = env->HI[PARAM1][other_tc]; | |
| 2224 | + RETURN(); | |
| 2225 | +} | |
| 2226 | + | |
| 2227 | +void op_mttacx(void) | |
| 2228 | +{ | |
| 2229 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2230 | + | |
| 2231 | + T0 = env->ACX[PARAM1][other_tc]; | |
| 2232 | + RETURN(); | |
| 2233 | +} | |
| 2234 | + | |
| 2235 | +void op_mttdsp(void) | |
| 2236 | +{ | |
| 2237 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 2238 | + | |
| 2239 | + T0 = env->DSPControl[other_tc]; | |
| 2240 | + RETURN(); | |
| 2241 | +} | |
| 2242 | + | |
| 2243 | + | |
| 2244 | +void op_dmt(void) | |
| 2245 | +{ | |
| 2246 | + // TODO | |
| 2247 | + T0 = 0; | |
| 2248 | + // rt = T0 | |
| 2249 | + RETURN(); | |
| 2250 | +} | |
| 2251 | + | |
| 2252 | +void op_emt(void) | |
| 2253 | +{ | |
| 2254 | + // TODO | |
| 2255 | + T0 = 0; | |
| 2256 | + // rt = T0 | |
| 2257 | + RETURN(); | |
| 2258 | +} | |
| 2259 | + | |
| 2260 | +void op_dvpe(void) | |
| 2261 | +{ | |
| 2262 | + // TODO | |
| 2263 | + T0 = 0; | |
| 2264 | + // rt = T0 | |
| 2265 | + RETURN(); | |
| 2266 | +} | |
| 2267 | + | |
| 2268 | +void op_evpe(void) | |
| 2269 | +{ | |
| 2270 | + // TODO | |
| 2271 | + T0 = 0; | |
| 2272 | + // rt = T0 | |
| 2273 | + RETURN(); | |
| 2274 | +} | |
| 2275 | + | |
| 2276 | +void op_fork(void) | |
| 2277 | +{ | |
| 2278 | + // T0 = rt, T1 = rs | |
| 2279 | + T0 = 0; | |
| 2280 | + // TODO: store to TC register | |
| 2281 | + RETURN(); | |
| 2282 | +} | |
| 2283 | + | |
| 2284 | +void op_yield(void) | |
| 2285 | +{ | |
| 2286 | + if (T0 < 0) { | |
| 2287 | + /* No scheduling policy implemented. */ | |
| 2288 | + if (T0 != -2) { | |
| 2289 | + if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) && | |
| 2290 | + env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) { | |
| 2291 | + env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); | |
| 2292 | + env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT; | |
| 2293 | + CALL_FROM_TB1(do_raise_exception, EXCP_THREAD); | |
| 2294 | + } | |
| 2295 | + } | |
| 2296 | + } else if (T0 == 0) { | |
| 2297 | + if (0 /* TODO: TC underflow */) { | |
| 2298 | + env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); | |
| 2299 | + CALL_FROM_TB1(do_raise_exception, EXCP_THREAD); | |
| 2300 | + } else { | |
| 2301 | + // TODO: Deallocate TC | |
| 2302 | + } | |
| 2303 | + } else if (T0 > 0) { | |
| 2304 | + /* Yield qualifier inputs not implemented. */ | |
| 2305 | + env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); | |
| 2306 | + env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT; | |
| 2307 | + CALL_FROM_TB1(do_raise_exception, EXCP_THREAD); | |
| 2308 | + } | |
| 2309 | + T0 = env->CP0_YQMask; | |
| 2310 | + RETURN(); | |
| 2311 | +} | |
| 2312 | + | |
| 1602 | 2313 | /* CP1 functions */ |
| 1603 | 2314 | #if 0 |
| 1604 | 2315 | # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env) |
| ... | ... | @@ -1617,30 +2328,14 @@ void op_cp0_enabled(void) |
| 1617 | 2328 | |
| 1618 | 2329 | void op_cfc1 (void) |
| 1619 | 2330 | { |
| 1620 | - switch (T1) { | |
| 1621 | - case 0: | |
| 1622 | - T0 = (int32_t)env->fcr0; | |
| 1623 | - break; | |
| 1624 | - case 25: | |
| 1625 | - T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1); | |
| 1626 | - break; | |
| 1627 | - case 26: | |
| 1628 | - T0 = env->fcr31 & 0x0003f07c; | |
| 1629 | - break; | |
| 1630 | - case 28: | |
| 1631 | - T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4); | |
| 1632 | - break; | |
| 1633 | - default: | |
| 1634 | - T0 = (int32_t)env->fcr31; | |
| 1635 | - break; | |
| 1636 | - } | |
| 2331 | + CALL_FROM_TB1(do_cfc1, PARAM1); | |
| 1637 | 2332 | DEBUG_FPU_STATE(); |
| 1638 | 2333 | RETURN(); |
| 1639 | 2334 | } |
| 1640 | 2335 | |
| 1641 | 2336 | void op_ctc1 (void) |
| 1642 | 2337 | { |
| 1643 | - CALL_FROM_TB0(do_ctc1); | |
| 2338 | + CALL_FROM_TB1(do_ctc1, PARAM1); | |
| 1644 | 2339 | DEBUG_FPU_STATE(); |
| 1645 | 2340 | RETURN(); |
| 1646 | 2341 | } |
| ... | ... | @@ -1842,21 +2537,21 @@ FLOAT_ROUNDOP(floor, w, s) |
| 1842 | 2537 | |
| 1843 | 2538 | FLOAT_OP(movf, d) |
| 1844 | 2539 | { |
| 1845 | - if (!(env->fcr31 & PARAM1)) | |
| 2540 | + if (!(env->fpu->fcr31 & PARAM1)) | |
| 1846 | 2541 | DT2 = DT0; |
| 1847 | 2542 | DEBUG_FPU_STATE(); |
| 1848 | 2543 | RETURN(); |
| 1849 | 2544 | } |
| 1850 | 2545 | FLOAT_OP(movf, s) |
| 1851 | 2546 | { |
| 1852 | - if (!(env->fcr31 & PARAM1)) | |
| 2547 | + if (!(env->fpu->fcr31 & PARAM1)) | |
| 1853 | 2548 | WT2 = WT0; |
| 1854 | 2549 | DEBUG_FPU_STATE(); |
| 1855 | 2550 | RETURN(); |
| 1856 | 2551 | } |
| 1857 | 2552 | FLOAT_OP(movf, ps) |
| 1858 | 2553 | { |
| 1859 | - if (!(env->fcr31 & PARAM1)) { | |
| 2554 | + if (!(env->fpu->fcr31 & PARAM1)) { | |
| 1860 | 2555 | WT2 = WT0; |
| 1861 | 2556 | WTH2 = WTH0; |
| 1862 | 2557 | } |
| ... | ... | @@ -1865,21 +2560,21 @@ FLOAT_OP(movf, ps) |
| 1865 | 2560 | } |
| 1866 | 2561 | FLOAT_OP(movt, d) |
| 1867 | 2562 | { |
| 1868 | - if (env->fcr31 & PARAM1) | |
| 2563 | + if (env->fpu->fcr31 & PARAM1) | |
| 1869 | 2564 | DT2 = DT0; |
| 1870 | 2565 | DEBUG_FPU_STATE(); |
| 1871 | 2566 | RETURN(); |
| 1872 | 2567 | } |
| 1873 | 2568 | FLOAT_OP(movt, s) |
| 1874 | 2569 | { |
| 1875 | - if (env->fcr31 & PARAM1) | |
| 2570 | + if (env->fpu->fcr31 & PARAM1) | |
| 1876 | 2571 | WT2 = WT0; |
| 1877 | 2572 | DEBUG_FPU_STATE(); |
| 1878 | 2573 | RETURN(); |
| 1879 | 2574 | } |
| 1880 | 2575 | FLOAT_OP(movt, ps) |
| 1881 | 2576 | { |
| 1882 | - if (env->fcr31 & PARAM1) { | |
| 2577 | + if (env->fpu->fcr31 & PARAM1) { | |
| 1883 | 2578 | WT2 = WT0; |
| 1884 | 2579 | WTH2 = WTH0; |
| 1885 | 2580 | } |
| ... | ... | @@ -1997,24 +2692,24 @@ FLOAT_HOP(mulr) |
| 1997 | 2692 | #define FLOAT_TERNOP(name1, name2) \ |
| 1998 | 2693 | FLOAT_OP(name1 ## name2, d) \ |
| 1999 | 2694 | { \ |
| 2000 | - FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \ | |
| 2001 | - FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \ | |
| 2695 | + FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \ | |
| 2696 | + FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \ | |
| 2002 | 2697 | DEBUG_FPU_STATE(); \ |
| 2003 | 2698 | RETURN(); \ |
| 2004 | 2699 | } \ |
| 2005 | 2700 | FLOAT_OP(name1 ## name2, s) \ |
| 2006 | 2701 | { \ |
| 2007 | - FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ | |
| 2008 | - FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ | |
| 2702 | + FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \ | |
| 2703 | + FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \ | |
| 2009 | 2704 | DEBUG_FPU_STATE(); \ |
| 2010 | 2705 | RETURN(); \ |
| 2011 | 2706 | } \ |
| 2012 | 2707 | FLOAT_OP(name1 ## name2, ps) \ |
| 2013 | 2708 | { \ |
| 2014 | - FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ | |
| 2015 | - FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \ | |
| 2016 | - FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ | |
| 2017 | - FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \ | |
| 2709 | + FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \ | |
| 2710 | + FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \ | |
| 2711 | + FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \ | |
| 2712 | + FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \ | |
| 2018 | 2713 | DEBUG_FPU_STATE(); \ |
| 2019 | 2714 | RETURN(); \ |
| 2020 | 2715 | } |
| ... | ... | @@ -2026,26 +2721,26 @@ FLOAT_TERNOP(mul, sub) |
| 2026 | 2721 | #define FLOAT_NTERNOP(name1, name2) \ |
| 2027 | 2722 | FLOAT_OP(n ## name1 ## name2, d) \ |
| 2028 | 2723 | { \ |
| 2029 | - FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \ | |
| 2030 | - FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \ | |
| 2724 | + FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \ | |
| 2725 | + FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \ | |
| 2031 | 2726 | FDT2 ^= 1ULL << 63; \ |
| 2032 | 2727 | DEBUG_FPU_STATE(); \ |
| 2033 | 2728 | RETURN(); \ |
| 2034 | 2729 | } \ |
| 2035 | 2730 | FLOAT_OP(n ## name1 ## name2, s) \ |
| 2036 | 2731 | { \ |
| 2037 | - FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ | |
| 2038 | - FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ | |
| 2732 | + FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \ | |
| 2733 | + FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \ | |
| 2039 | 2734 | FST2 ^= 1 << 31; \ |
| 2040 | 2735 | DEBUG_FPU_STATE(); \ |
| 2041 | 2736 | RETURN(); \ |
| 2042 | 2737 | } \ |
| 2043 | 2738 | FLOAT_OP(n ## name1 ## name2, ps) \ |
| 2044 | 2739 | { \ |
| 2045 | - FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ | |
| 2046 | - FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \ | |
| 2047 | - FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ | |
| 2048 | - FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \ | |
| 2740 | + FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \ | |
| 2741 | + FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \ | |
| 2742 | + FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \ | |
| 2743 | + FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \ | |
| 2049 | 2744 | FST2 ^= 1 << 31; \ |
| 2050 | 2745 | FSTH2 ^= 1 << 31; \ |
| 2051 | 2746 | DEBUG_FPU_STATE(); \ |
| ... | ... | @@ -2059,13 +2754,13 @@ FLOAT_NTERNOP(mul, sub) |
| 2059 | 2754 | #define FLOAT_UNOP(name) \ |
| 2060 | 2755 | FLOAT_OP(name, d) \ |
| 2061 | 2756 | { \ |
| 2062 | - FDT2 = float64_ ## name(FDT0, &env->fp_status); \ | |
| 2757 | + FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \ | |
| 2063 | 2758 | DEBUG_FPU_STATE(); \ |
| 2064 | 2759 | RETURN(); \ |
| 2065 | 2760 | } \ |
| 2066 | 2761 | FLOAT_OP(name, s) \ |
| 2067 | 2762 | { \ |
| 2068 | - FST2 = float32_ ## name(FST0, &env->fp_status); \ | |
| 2763 | + FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \ | |
| 2069 | 2764 | DEBUG_FPU_STATE(); \ |
| 2070 | 2765 | RETURN(); \ |
| 2071 | 2766 | } |
| ... | ... | @@ -2141,9 +2836,9 @@ FLOAT_OP(alnv, ps) |
| 2141 | 2836 | |
| 2142 | 2837 | #ifdef CONFIG_SOFTFLOAT |
| 2143 | 2838 | #define clear_invalid() do { \ |
| 2144 | - int flags = get_float_exception_flags(&env->fp_status); \ | |
| 2839 | + int flags = get_float_exception_flags(&env->fpu->fp_status); \ | |
| 2145 | 2840 | flags &= ~float_flag_invalid; \ |
| 2146 | - set_float_exception_flags(flags, &env->fp_status); \ | |
| 2841 | + set_float_exception_flags(flags, &env->fpu->fp_status); \ | |
| 2147 | 2842 | } while(0) |
| 2148 | 2843 | #else |
| 2149 | 2844 | #define clear_invalid() do { } while(0) |
| ... | ... | @@ -2190,63 +2885,63 @@ CMP_OPS(ngt) |
| 2190 | 2885 | |
| 2191 | 2886 | void op_bc1f (void) |
| 2192 | 2887 | { |
| 2193 | - T0 = !!(~GET_FP_COND(env) & (0x1 << PARAM1)); | |
| 2888 | + T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1)); | |
| 2194 | 2889 | DEBUG_FPU_STATE(); |
| 2195 | 2890 | RETURN(); |
| 2196 | 2891 | } |
| 2197 | 2892 | void op_bc1any2f (void) |
| 2198 | 2893 | { |
| 2199 | - T0 = !!(~GET_FP_COND(env) & (0x3 << PARAM1)); | |
| 2894 | + T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1)); | |
| 2200 | 2895 | DEBUG_FPU_STATE(); |
| 2201 | 2896 | RETURN(); |
| 2202 | 2897 | } |
| 2203 | 2898 | void op_bc1any4f (void) |
| 2204 | 2899 | { |
| 2205 | - T0 = !!(~GET_FP_COND(env) & (0xf << PARAM1)); | |
| 2900 | + T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1)); | |
| 2206 | 2901 | DEBUG_FPU_STATE(); |
| 2207 | 2902 | RETURN(); |
| 2208 | 2903 | } |
| 2209 | 2904 | |
| 2210 | 2905 | void op_bc1t (void) |
| 2211 | 2906 | { |
| 2212 | - T0 = !!(GET_FP_COND(env) & (0x1 << PARAM1)); | |
| 2907 | + T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1)); | |
| 2213 | 2908 | DEBUG_FPU_STATE(); |
| 2214 | 2909 | RETURN(); |
| 2215 | 2910 | } |
| 2216 | 2911 | void op_bc1any2t (void) |
| 2217 | 2912 | { |
| 2218 | - T0 = !!(GET_FP_COND(env) & (0x3 << PARAM1)); | |
| 2913 | + T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1)); | |
| 2219 | 2914 | DEBUG_FPU_STATE(); |
| 2220 | 2915 | RETURN(); |
| 2221 | 2916 | } |
| 2222 | 2917 | void op_bc1any4t (void) |
| 2223 | 2918 | { |
| 2224 | - T0 = !!(GET_FP_COND(env) & (0xf << PARAM1)); | |
| 2919 | + T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1)); | |
| 2225 | 2920 | DEBUG_FPU_STATE(); |
| 2226 | 2921 | RETURN(); |
| 2227 | 2922 | } |
| 2228 | 2923 | |
| 2229 | 2924 | void op_tlbwi (void) |
| 2230 | 2925 | { |
| 2231 | - CALL_FROM_TB0(env->do_tlbwi); | |
| 2926 | + CALL_FROM_TB0(env->tlb->do_tlbwi); | |
| 2232 | 2927 | RETURN(); |
| 2233 | 2928 | } |
| 2234 | 2929 | |
| 2235 | 2930 | void op_tlbwr (void) |
| 2236 | 2931 | { |
| 2237 | - CALL_FROM_TB0(env->do_tlbwr); | |
| 2932 | + CALL_FROM_TB0(env->tlb->do_tlbwr); | |
| 2238 | 2933 | RETURN(); |
| 2239 | 2934 | } |
| 2240 | 2935 | |
| 2241 | 2936 | void op_tlbp (void) |
| 2242 | 2937 | { |
| 2243 | - CALL_FROM_TB0(env->do_tlbp); | |
| 2938 | + CALL_FROM_TB0(env->tlb->do_tlbp); | |
| 2244 | 2939 | RETURN(); |
| 2245 | 2940 | } |
| 2246 | 2941 | |
| 2247 | 2942 | void op_tlbr (void) |
| 2248 | 2943 | { |
| 2249 | - CALL_FROM_TB0(env->do_tlbr); | |
| 2944 | + CALL_FROM_TB0(env->tlb->do_tlbr); | |
| 2250 | 2945 | RETURN(); |
| 2251 | 2946 | } |
| 2252 | 2947 | |
| ... | ... | @@ -2307,10 +3002,10 @@ void op_eret (void) |
| 2307 | 3002 | if (loglevel & CPU_LOG_EXEC) |
| 2308 | 3003 | CALL_FROM_TB0(debug_pre_eret); |
| 2309 | 3004 | if (env->CP0_Status & (1 << CP0St_ERL)) { |
| 2310 | - env->PC = env->CP0_ErrorEPC; | |
| 3005 | + env->PC[env->current_tc] = env->CP0_ErrorEPC; | |
| 2311 | 3006 | env->CP0_Status &= ~(1 << CP0St_ERL); |
| 2312 | 3007 | } else { |
| 2313 | - env->PC = env->CP0_EPC; | |
| 3008 | + env->PC[env->current_tc] = env->CP0_EPC; | |
| 2314 | 3009 | env->CP0_Status &= ~(1 << CP0St_EXL); |
| 2315 | 3010 | } |
| 2316 | 3011 | if (!(env->CP0_Status & (1 << CP0St_EXL)) && |
| ... | ... | @@ -2335,7 +3030,7 @@ void op_deret (void) |
| 2335 | 3030 | { |
| 2336 | 3031 | if (loglevel & CPU_LOG_EXEC) |
| 2337 | 3032 | CALL_FROM_TB0(debug_pre_eret); |
| 2338 | - env->PC = env->CP0_DEPC; | |
| 3033 | + env->PC[env->current_tc] = env->CP0_DEPC; | |
| 2339 | 3034 | env->hflags |= MIPS_HFLAG_DM; |
| 2340 | 3035 | if (!(env->CP0_Status & (1 << CP0St_EXL)) && |
| 2341 | 3036 | !(env->CP0_Status & (1 << CP0St_ERL)) && |
| ... | ... | @@ -2407,14 +3102,14 @@ void op_save_state (void) |
| 2407 | 3102 | |
| 2408 | 3103 | void op_save_pc (void) |
| 2409 | 3104 | { |
| 2410 | - env->PC = PARAM1; | |
| 3105 | + env->PC[env->current_tc] = PARAM1; | |
| 2411 | 3106 | RETURN(); |
| 2412 | 3107 | } |
| 2413 | 3108 | |
| 2414 | 3109 | #ifdef TARGET_MIPS64 |
| 2415 | 3110 | void op_save_pc64 (void) |
| 2416 | 3111 | { |
| 2417 | - env->PC = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2; | |
| 3112 | + env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2; | |
| 2418 | 3113 | RETURN(); |
| 2419 | 3114 | } |
| 2420 | 3115 | #endif | ... | ... |
target-mips/op_helper.c
| ... | ... | @@ -160,13 +160,13 @@ void do_drotrv (void) |
| 160 | 160 | #if TARGET_LONG_BITS > HOST_LONG_BITS |
| 161 | 161 | static inline uint64_t get_HILO (void) |
| 162 | 162 | { |
| 163 | - return (env->HI << 32) | (uint32_t)env->LO; | |
| 163 | + return (env->HI[0][env->current_tc] << 32) | (uint32_t)env->LO[0][env->current_tc]; | |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | 166 | static inline void set_HILO (uint64_t HILO) |
| 167 | 167 | { |
| 168 | - env->LO = (int32_t)HILO; | |
| 169 | - env->HI = (int32_t)(HILO >> 32); | |
| 168 | + env->LO[0][env->current_tc] = (int32_t)HILO; | |
| 169 | + env->HI[0][env->current_tc] = (int32_t)(HILO >> 32); | |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | 172 | void do_mult (void) |
| ... | ... | @@ -217,8 +217,8 @@ void do_div (void) |
| 217 | 217 | { |
| 218 | 218 | /* 64bit datatypes because we may see overflow/underflow. */ |
| 219 | 219 | if (T1 != 0) { |
| 220 | - env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); | |
| 221 | - env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); | |
| 220 | + env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); | |
| 221 | + env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); | |
| 222 | 222 | } |
| 223 | 223 | } |
| 224 | 224 | #endif |
| ... | ... | @@ -228,8 +228,8 @@ void do_ddiv (void) |
| 228 | 228 | { |
| 229 | 229 | if (T1 != 0) { |
| 230 | 230 | lldiv_t res = lldiv((int64_t)T0, (int64_t)T1); |
| 231 | - env->LO = res.quot; | |
| 232 | - env->HI = res.rem; | |
| 231 | + env->LO[0][env->current_tc] = res.quot; | |
| 232 | + env->HI[0][env->current_tc] = res.rem; | |
| 233 | 233 | } |
| 234 | 234 | } |
| 235 | 235 | |
| ... | ... | @@ -237,8 +237,8 @@ void do_ddiv (void) |
| 237 | 237 | void do_ddivu (void) |
| 238 | 238 | { |
| 239 | 239 | if (T1 != 0) { |
| 240 | - env->LO = T0 / T1; | |
| 241 | - env->HI = T0 % T1; | |
| 240 | + env->LO[0][env->current_tc] = T0 / T1; | |
| 241 | + env->HI[0][env->current_tc] = T0 % T1; | |
| 242 | 242 | } |
| 243 | 243 | } |
| 244 | 244 | #endif |
| ... | ... | @@ -316,10 +316,10 @@ void do_mtc0_status_irqraise_debug(void) |
| 316 | 316 | void fpu_handle_exception(void) |
| 317 | 317 | { |
| 318 | 318 | #ifdef CONFIG_SOFTFLOAT |
| 319 | - int flags = get_float_exception_flags(&env->fp_status); | |
| 319 | + int flags = get_float_exception_flags(&env->fpu->fp_status); | |
| 320 | 320 | unsigned int cpuflags = 0, enable, cause = 0; |
| 321 | 321 | |
| 322 | - enable = GET_FP_ENABLE(env->fcr31); | |
| 322 | + enable = GET_FP_ENABLE(env->fpu->fcr31); | |
| 323 | 323 | |
| 324 | 324 | /* determine current flags */ |
| 325 | 325 | if (flags & float_flag_invalid) { |
| ... | ... | @@ -342,11 +342,11 @@ void fpu_handle_exception(void) |
| 342 | 342 | cpuflags |= FP_INEXACT; |
| 343 | 343 | cause |= FP_INEXACT & enable; |
| 344 | 344 | } |
| 345 | - SET_FP_FLAGS(env->fcr31, cpuflags); | |
| 346 | - SET_FP_CAUSE(env->fcr31, cause); | |
| 345 | + SET_FP_FLAGS(env->fpu->fcr31, cpuflags); | |
| 346 | + SET_FP_CAUSE(env->fpu->fcr31, cause); | |
| 347 | 347 | #else |
| 348 | - SET_FP_FLAGS(env->fcr31, 0); | |
| 349 | - SET_FP_CAUSE(env->fcr31, 0); | |
| 348 | + SET_FP_FLAGS(env->fpu->fcr31, 0); | |
| 349 | + SET_FP_CAUSE(env->fpu->fcr31, 0); | |
| 350 | 350 | #endif |
| 351 | 351 | } |
| 352 | 352 | |
| ... | ... | @@ -355,14 +355,14 @@ void cpu_mips_tlb_flush (CPUState *env, int flush_global) |
| 355 | 355 | { |
| 356 | 356 | /* Flush qemu's TLB and discard all shadowed entries. */ |
| 357 | 357 | tlb_flush (env, flush_global); |
| 358 | - env->tlb_in_use = env->nb_tlb; | |
| 358 | + env->tlb->tlb_in_use = env->tlb->nb_tlb; | |
| 359 | 359 | } |
| 360 | 360 | |
| 361 | 361 | static void r4k_mips_tlb_flush_extra (CPUState *env, int first) |
| 362 | 362 | { |
| 363 | 363 | /* Discard entries from env->tlb[first] onwards. */ |
| 364 | - while (env->tlb_in_use > first) { | |
| 365 | - r4k_invalidate_tlb(env, --env->tlb_in_use, 0); | |
| 364 | + while (env->tlb->tlb_in_use > first) { | |
| 365 | + r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0); | |
| 366 | 366 | } |
| 367 | 367 | } |
| 368 | 368 | |
| ... | ... | @@ -371,7 +371,7 @@ static void r4k_fill_tlb (int idx) |
| 371 | 371 | r4k_tlb_t *tlb; |
| 372 | 372 | |
| 373 | 373 | /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ |
| 374 | - tlb = &env->mmu.r4k.tlb[idx]; | |
| 374 | + tlb = &env->tlb->mmu.r4k.tlb[idx]; | |
| 375 | 375 | tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); |
| 376 | 376 | #ifdef TARGET_MIPS64 |
| 377 | 377 | tlb->VPN &= env->SEGMask; |
| ... | ... | @@ -394,10 +394,10 @@ void r4k_do_tlbwi (void) |
| 394 | 394 | /* Discard cached TLB entries. We could avoid doing this if the |
| 395 | 395 | tlbwi is just upgrading access permissions on the current entry; |
| 396 | 396 | that might be a further win. */ |
| 397 | - r4k_mips_tlb_flush_extra (env, env->nb_tlb); | |
| 397 | + r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb); | |
| 398 | 398 | |
| 399 | - r4k_invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0); | |
| 400 | - r4k_fill_tlb(env->CP0_Index % env->nb_tlb); | |
| 399 | + r4k_invalidate_tlb(env, env->CP0_Index % env->tlb->nb_tlb, 0); | |
| 400 | + r4k_fill_tlb(env->CP0_Index % env->tlb->nb_tlb); | |
| 401 | 401 | } |
| 402 | 402 | |
| 403 | 403 | void r4k_do_tlbwr (void) |
| ... | ... | @@ -418,8 +418,8 @@ void r4k_do_tlbp (void) |
| 418 | 418 | int i; |
| 419 | 419 | |
| 420 | 420 | ASID = env->CP0_EntryHi & 0xFF; |
| 421 | - for (i = 0; i < env->nb_tlb; i++) { | |
| 422 | - tlb = &env->mmu.r4k.tlb[i]; | |
| 421 | + for (i = 0; i < env->tlb->nb_tlb; i++) { | |
| 422 | + tlb = &env->tlb->mmu.r4k.tlb[i]; | |
| 423 | 423 | /* 1k pages are not supported. */ |
| 424 | 424 | mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); |
| 425 | 425 | tag = env->CP0_EntryHi & ~mask; |
| ... | ... | @@ -431,10 +431,10 @@ void r4k_do_tlbp (void) |
| 431 | 431 | break; |
| 432 | 432 | } |
| 433 | 433 | } |
| 434 | - if (i == env->nb_tlb) { | |
| 434 | + if (i == env->tlb->nb_tlb) { | |
| 435 | 435 | /* No match. Discard any shadow entries, if any of them match. */ |
| 436 | - for (i = env->nb_tlb; i < env->tlb_in_use; i++) { | |
| 437 | - tlb = &env->mmu.r4k.tlb[i]; | |
| 436 | + for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) { | |
| 437 | + tlb = &env->tlb->mmu.r4k.tlb[i]; | |
| 438 | 438 | /* 1k pages are not supported. */ |
| 439 | 439 | mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); |
| 440 | 440 | tag = env->CP0_EntryHi & ~mask; |
| ... | ... | @@ -456,13 +456,13 @@ void r4k_do_tlbr (void) |
| 456 | 456 | uint8_t ASID; |
| 457 | 457 | |
| 458 | 458 | ASID = env->CP0_EntryHi & 0xFF; |
| 459 | - tlb = &env->mmu.r4k.tlb[env->CP0_Index % env->nb_tlb]; | |
| 459 | + tlb = &env->tlb->mmu.r4k.tlb[env->CP0_Index % env->tlb->nb_tlb]; | |
| 460 | 460 | |
| 461 | 461 | /* If this will change the current ASID, flush qemu's TLB. */ |
| 462 | 462 | if (ASID != tlb->ASID) |
| 463 | 463 | cpu_mips_tlb_flush (env, 1); |
| 464 | 464 | |
| 465 | - r4k_mips_tlb_flush_extra(env, env->nb_tlb); | |
| 465 | + r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); | |
| 466 | 466 | |
| 467 | 467 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
| 468 | 468 | env->CP0_PageMask = tlb->PageMask; |
| ... | ... | @@ -491,7 +491,7 @@ void dump_sc (void) |
| 491 | 491 | void debug_pre_eret (void) |
| 492 | 492 | { |
| 493 | 493 | fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, |
| 494 | - env->PC, env->CP0_EPC); | |
| 494 | + env->PC[env->current_tc], env->CP0_EPC); | |
| 495 | 495 | if (env->CP0_Status & (1 << CP0St_ERL)) |
| 496 | 496 | fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); |
| 497 | 497 | if (env->hflags & MIPS_HFLAG_DM) |
| ... | ... | @@ -502,7 +502,7 @@ void debug_pre_eret (void) |
| 502 | 502 | void debug_post_eret (void) |
| 503 | 503 | { |
| 504 | 504 | fprintf(logfile, " => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, |
| 505 | - env->PC, env->CP0_EPC); | |
| 505 | + env->PC[env->current_tc], env->CP0_EPC); | |
| 506 | 506 | if (env->CP0_Status & (1 << CP0St_ERL)) |
| 507 | 507 | fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); |
| 508 | 508 | if (env->hflags & MIPS_HFLAG_DM) |
| ... | ... | @@ -518,21 +518,21 @@ void do_pmon (int function) |
| 518 | 518 | function /= 2; |
| 519 | 519 | switch (function) { |
| 520 | 520 | case 2: /* TODO: char inbyte(int waitflag); */ |
| 521 | - if (env->gpr[4] == 0) | |
| 522 | - env->gpr[2] = -1; | |
| 521 | + if (env->gpr[4][env->current_tc] == 0) | |
| 522 | + env->gpr[2][env->current_tc] = -1; | |
| 523 | 523 | /* Fall through */ |
| 524 | 524 | case 11: /* TODO: char inbyte (void); */ |
| 525 | - env->gpr[2] = -1; | |
| 525 | + env->gpr[2][env->current_tc] = -1; | |
| 526 | 526 | break; |
| 527 | 527 | case 3: |
| 528 | 528 | case 12: |
| 529 | - printf("%c", (char)(env->gpr[4] & 0xFF)); | |
| 529 | + printf("%c", (char)(env->gpr[4][env->current_tc] & 0xFF)); | |
| 530 | 530 | break; |
| 531 | 531 | case 17: |
| 532 | 532 | break; |
| 533 | 533 | case 158: |
| 534 | 534 | { |
| 535 | - unsigned char *fmt = (void *)(unsigned long)env->gpr[4]; | |
| 535 | + unsigned char *fmt = (void *)(unsigned long)env->gpr[4][env->current_tc]; | |
| 536 | 536 | printf("%s", fmt); |
| 537 | 537 | } |
| 538 | 538 | break; |
| ... | ... | @@ -613,40 +613,61 @@ unsigned int ieee_rm[] = { |
| 613 | 613 | }; |
| 614 | 614 | |
| 615 | 615 | #define RESTORE_ROUNDING_MODE \ |
| 616 | - set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status) | |
| 616 | + set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status) | |
| 617 | 617 | |
| 618 | -void do_ctc1 (void) | |
| 618 | +void do_cfc1 (int reg) | |
| 619 | 619 | { |
| 620 | - switch(T1) { | |
| 620 | + switch (reg) { | |
| 621 | + case 0: | |
| 622 | + T0 = (int32_t)env->fpu->fcr0; | |
| 623 | + break; | |
| 624 | + case 25: | |
| 625 | + T0 = ((env->fpu->fcr31 >> 24) & 0xfe) | ((env->fpu->fcr31 >> 23) & 0x1); | |
| 626 | + break; | |
| 627 | + case 26: | |
| 628 | + T0 = env->fpu->fcr31 & 0x0003f07c; | |
| 629 | + break; | |
| 630 | + case 28: | |
| 631 | + T0 = (env->fpu->fcr31 & 0x00000f83) | ((env->fpu->fcr31 >> 22) & 0x4); | |
| 632 | + break; | |
| 633 | + default: | |
| 634 | + T0 = (int32_t)env->fpu->fcr31; | |
| 635 | + break; | |
| 636 | + } | |
| 637 | +} | |
| 638 | + | |
| 639 | +void do_ctc1 (int reg) | |
| 640 | +{ | |
| 641 | + switch(reg) { | |
| 621 | 642 | case 25: |
| 622 | 643 | if (T0 & 0xffffff00) |
| 623 | 644 | return; |
| 624 | - env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) | | |
| 645 | + env->fpu->fcr31 = (env->fpu->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) | | |
| 625 | 646 | ((T0 & 0x1) << 23); |
| 626 | 647 | break; |
| 627 | 648 | case 26: |
| 628 | 649 | if (T0 & 0x007c0000) |
| 629 | 650 | return; |
| 630 | - env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c); | |
| 651 | + env->fpu->fcr31 = (env->fpu->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c); | |
| 631 | 652 | break; |
| 632 | 653 | case 28: |
| 633 | 654 | if (T0 & 0x007c0000) |
| 634 | 655 | return; |
| 635 | - env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) | | |
| 656 | + env->fpu->fcr31 = (env->fpu->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) | | |
| 636 | 657 | ((T0 & 0x4) << 22); |
| 637 | 658 | break; |
| 638 | 659 | case 31: |
| 639 | 660 | if (T0 & 0x007c0000) |
| 640 | 661 | return; |
| 641 | - env->fcr31 = T0; | |
| 662 | + env->fpu->fcr31 = T0; | |
| 642 | 663 | break; |
| 643 | 664 | default: |
| 644 | 665 | return; |
| 645 | 666 | } |
| 646 | 667 | /* set rounding mode */ |
| 647 | 668 | RESTORE_ROUNDING_MODE; |
| 648 | - set_float_exception_flags(0, &env->fp_status); | |
| 649 | - if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31)) | |
| 669 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 670 | + if ((GET_FP_ENABLE(env->fpu->fcr31) | 0x20) & GET_FP_CAUSE(env->fpu->fcr31)) | |
| 650 | 671 | do_raise_exception(EXCP_FPE); |
| 651 | 672 | } |
| 652 | 673 | |
| ... | ... | @@ -670,325 +691,325 @@ inline char mips_ex_to_ieee(char xcpt) |
| 670 | 691 | |
| 671 | 692 | inline void update_fcr31(void) |
| 672 | 693 | { |
| 673 | - int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status)); | |
| 694 | + int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status)); | |
| 674 | 695 | |
| 675 | - SET_FP_CAUSE(env->fcr31, tmp); | |
| 676 | - if (GET_FP_ENABLE(env->fcr31) & tmp) | |
| 696 | + SET_FP_CAUSE(env->fpu->fcr31, tmp); | |
| 697 | + if (GET_FP_ENABLE(env->fpu->fcr31) & tmp) | |
| 677 | 698 | do_raise_exception(EXCP_FPE); |
| 678 | 699 | else |
| 679 | - UPDATE_FP_FLAGS(env->fcr31, tmp); | |
| 700 | + UPDATE_FP_FLAGS(env->fpu->fcr31, tmp); | |
| 680 | 701 | } |
| 681 | 702 | |
| 682 | 703 | #define FLOAT_OP(name, p) void do_float_##name##_##p(void) |
| 683 | 704 | |
| 684 | 705 | FLOAT_OP(cvtd, s) |
| 685 | 706 | { |
| 686 | - set_float_exception_flags(0, &env->fp_status); | |
| 687 | - FDT2 = float32_to_float64(FST0, &env->fp_status); | |
| 707 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 708 | + FDT2 = float32_to_float64(FST0, &env->fpu->fp_status); | |
| 688 | 709 | update_fcr31(); |
| 689 | 710 | } |
| 690 | 711 | FLOAT_OP(cvtd, w) |
| 691 | 712 | { |
| 692 | - set_float_exception_flags(0, &env->fp_status); | |
| 693 | - FDT2 = int32_to_float64(WT0, &env->fp_status); | |
| 713 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 714 | + FDT2 = int32_to_float64(WT0, &env->fpu->fp_status); | |
| 694 | 715 | update_fcr31(); |
| 695 | 716 | } |
| 696 | 717 | FLOAT_OP(cvtd, l) |
| 697 | 718 | { |
| 698 | - set_float_exception_flags(0, &env->fp_status); | |
| 699 | - FDT2 = int64_to_float64(DT0, &env->fp_status); | |
| 719 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 720 | + FDT2 = int64_to_float64(DT0, &env->fpu->fp_status); | |
| 700 | 721 | update_fcr31(); |
| 701 | 722 | } |
| 702 | 723 | FLOAT_OP(cvtl, d) |
| 703 | 724 | { |
| 704 | - set_float_exception_flags(0, &env->fp_status); | |
| 705 | - DT2 = float64_to_int64(FDT0, &env->fp_status); | |
| 725 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 726 | + DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); | |
| 706 | 727 | update_fcr31(); |
| 707 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 728 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 708 | 729 | DT2 = 0x7fffffffffffffffULL; |
| 709 | 730 | } |
| 710 | 731 | FLOAT_OP(cvtl, s) |
| 711 | 732 | { |
| 712 | - set_float_exception_flags(0, &env->fp_status); | |
| 713 | - DT2 = float32_to_int64(FST0, &env->fp_status); | |
| 733 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 734 | + DT2 = float32_to_int64(FST0, &env->fpu->fp_status); | |
| 714 | 735 | update_fcr31(); |
| 715 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 736 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 716 | 737 | DT2 = 0x7fffffffffffffffULL; |
| 717 | 738 | } |
| 718 | 739 | |
| 719 | 740 | FLOAT_OP(cvtps, pw) |
| 720 | 741 | { |
| 721 | - set_float_exception_flags(0, &env->fp_status); | |
| 722 | - FST2 = int32_to_float32(WT0, &env->fp_status); | |
| 723 | - FSTH2 = int32_to_float32(WTH0, &env->fp_status); | |
| 742 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 743 | + FST2 = int32_to_float32(WT0, &env->fpu->fp_status); | |
| 744 | + FSTH2 = int32_to_float32(WTH0, &env->fpu->fp_status); | |
| 724 | 745 | update_fcr31(); |
| 725 | 746 | } |
| 726 | 747 | FLOAT_OP(cvtpw, ps) |
| 727 | 748 | { |
| 728 | - set_float_exception_flags(0, &env->fp_status); | |
| 729 | - WT2 = float32_to_int32(FST0, &env->fp_status); | |
| 730 | - WTH2 = float32_to_int32(FSTH0, &env->fp_status); | |
| 749 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 750 | + WT2 = float32_to_int32(FST0, &env->fpu->fp_status); | |
| 751 | + WTH2 = float32_to_int32(FSTH0, &env->fpu->fp_status); | |
| 731 | 752 | update_fcr31(); |
| 732 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 753 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 733 | 754 | WT2 = 0x7fffffff; |
| 734 | 755 | } |
| 735 | 756 | FLOAT_OP(cvts, d) |
| 736 | 757 | { |
| 737 | - set_float_exception_flags(0, &env->fp_status); | |
| 738 | - FST2 = float64_to_float32(FDT0, &env->fp_status); | |
| 758 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 759 | + FST2 = float64_to_float32(FDT0, &env->fpu->fp_status); | |
| 739 | 760 | update_fcr31(); |
| 740 | 761 | } |
| 741 | 762 | FLOAT_OP(cvts, w) |
| 742 | 763 | { |
| 743 | - set_float_exception_flags(0, &env->fp_status); | |
| 744 | - FST2 = int32_to_float32(WT0, &env->fp_status); | |
| 764 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 765 | + FST2 = int32_to_float32(WT0, &env->fpu->fp_status); | |
| 745 | 766 | update_fcr31(); |
| 746 | 767 | } |
| 747 | 768 | FLOAT_OP(cvts, l) |
| 748 | 769 | { |
| 749 | - set_float_exception_flags(0, &env->fp_status); | |
| 750 | - FST2 = int64_to_float32(DT0, &env->fp_status); | |
| 770 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 771 | + FST2 = int64_to_float32(DT0, &env->fpu->fp_status); | |
| 751 | 772 | update_fcr31(); |
| 752 | 773 | } |
| 753 | 774 | FLOAT_OP(cvts, pl) |
| 754 | 775 | { |
| 755 | - set_float_exception_flags(0, &env->fp_status); | |
| 776 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 756 | 777 | WT2 = WT0; |
| 757 | 778 | update_fcr31(); |
| 758 | 779 | } |
| 759 | 780 | FLOAT_OP(cvts, pu) |
| 760 | 781 | { |
| 761 | - set_float_exception_flags(0, &env->fp_status); | |
| 782 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 762 | 783 | WT2 = WTH0; |
| 763 | 784 | update_fcr31(); |
| 764 | 785 | } |
| 765 | 786 | FLOAT_OP(cvtw, s) |
| 766 | 787 | { |
| 767 | - set_float_exception_flags(0, &env->fp_status); | |
| 768 | - WT2 = float32_to_int32(FST0, &env->fp_status); | |
| 788 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 789 | + WT2 = float32_to_int32(FST0, &env->fpu->fp_status); | |
| 769 | 790 | update_fcr31(); |
| 770 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 791 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 771 | 792 | WT2 = 0x7fffffff; |
| 772 | 793 | } |
| 773 | 794 | FLOAT_OP(cvtw, d) |
| 774 | 795 | { |
| 775 | - set_float_exception_flags(0, &env->fp_status); | |
| 776 | - WT2 = float64_to_int32(FDT0, &env->fp_status); | |
| 796 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 797 | + WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); | |
| 777 | 798 | update_fcr31(); |
| 778 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 799 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 779 | 800 | WT2 = 0x7fffffff; |
| 780 | 801 | } |
| 781 | 802 | |
| 782 | 803 | FLOAT_OP(roundl, d) |
| 783 | 804 | { |
| 784 | - set_float_rounding_mode(float_round_nearest_even, &env->fp_status); | |
| 785 | - DT2 = float64_to_int64(FDT0, &env->fp_status); | |
| 805 | + set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); | |
| 806 | + DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); | |
| 786 | 807 | RESTORE_ROUNDING_MODE; |
| 787 | 808 | update_fcr31(); |
| 788 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 809 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 789 | 810 | DT2 = 0x7fffffffffffffffULL; |
| 790 | 811 | } |
| 791 | 812 | FLOAT_OP(roundl, s) |
| 792 | 813 | { |
| 793 | - set_float_rounding_mode(float_round_nearest_even, &env->fp_status); | |
| 794 | - DT2 = float32_to_int64(FST0, &env->fp_status); | |
| 814 | + set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); | |
| 815 | + DT2 = float32_to_int64(FST0, &env->fpu->fp_status); | |
| 795 | 816 | RESTORE_ROUNDING_MODE; |
| 796 | 817 | update_fcr31(); |
| 797 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 818 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 798 | 819 | DT2 = 0x7fffffffffffffffULL; |
| 799 | 820 | } |
| 800 | 821 | FLOAT_OP(roundw, d) |
| 801 | 822 | { |
| 802 | - set_float_rounding_mode(float_round_nearest_even, &env->fp_status); | |
| 803 | - WT2 = float64_to_int32(FDT0, &env->fp_status); | |
| 823 | + set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); | |
| 824 | + WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); | |
| 804 | 825 | RESTORE_ROUNDING_MODE; |
| 805 | 826 | update_fcr31(); |
| 806 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 827 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 807 | 828 | WT2 = 0x7fffffff; |
| 808 | 829 | } |
| 809 | 830 | FLOAT_OP(roundw, s) |
| 810 | 831 | { |
| 811 | - set_float_rounding_mode(float_round_nearest_even, &env->fp_status); | |
| 812 | - WT2 = float32_to_int32(FST0, &env->fp_status); | |
| 832 | + set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); | |
| 833 | + WT2 = float32_to_int32(FST0, &env->fpu->fp_status); | |
| 813 | 834 | RESTORE_ROUNDING_MODE; |
| 814 | 835 | update_fcr31(); |
| 815 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 836 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 816 | 837 | WT2 = 0x7fffffff; |
| 817 | 838 | } |
| 818 | 839 | |
| 819 | 840 | FLOAT_OP(truncl, d) |
| 820 | 841 | { |
| 821 | - DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status); | |
| 842 | + DT2 = float64_to_int64_round_to_zero(FDT0, &env->fpu->fp_status); | |
| 822 | 843 | update_fcr31(); |
| 823 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 844 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 824 | 845 | DT2 = 0x7fffffffffffffffULL; |
| 825 | 846 | } |
| 826 | 847 | FLOAT_OP(truncl, s) |
| 827 | 848 | { |
| 828 | - DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status); | |
| 849 | + DT2 = float32_to_int64_round_to_zero(FST0, &env->fpu->fp_status); | |
| 829 | 850 | update_fcr31(); |
| 830 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 851 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 831 | 852 | DT2 = 0x7fffffffffffffffULL; |
| 832 | 853 | } |
| 833 | 854 | FLOAT_OP(truncw, d) |
| 834 | 855 | { |
| 835 | - WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); | |
| 856 | + WT2 = float64_to_int32_round_to_zero(FDT0, &env->fpu->fp_status); | |
| 836 | 857 | update_fcr31(); |
| 837 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 858 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 838 | 859 | WT2 = 0x7fffffff; |
| 839 | 860 | } |
| 840 | 861 | FLOAT_OP(truncw, s) |
| 841 | 862 | { |
| 842 | - WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status); | |
| 863 | + WT2 = float32_to_int32_round_to_zero(FST0, &env->fpu->fp_status); | |
| 843 | 864 | update_fcr31(); |
| 844 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 865 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 845 | 866 | WT2 = 0x7fffffff; |
| 846 | 867 | } |
| 847 | 868 | |
| 848 | 869 | FLOAT_OP(ceill, d) |
| 849 | 870 | { |
| 850 | - set_float_rounding_mode(float_round_up, &env->fp_status); | |
| 851 | - DT2 = float64_to_int64(FDT0, &env->fp_status); | |
| 871 | + set_float_rounding_mode(float_round_up, &env->fpu->fp_status); | |
| 872 | + DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); | |
| 852 | 873 | RESTORE_ROUNDING_MODE; |
| 853 | 874 | update_fcr31(); |
| 854 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 875 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 855 | 876 | DT2 = 0x7fffffffffffffffULL; |
| 856 | 877 | } |
| 857 | 878 | FLOAT_OP(ceill, s) |
| 858 | 879 | { |
| 859 | - set_float_rounding_mode(float_round_up, &env->fp_status); | |
| 860 | - DT2 = float32_to_int64(FST0, &env->fp_status); | |
| 880 | + set_float_rounding_mode(float_round_up, &env->fpu->fp_status); | |
| 881 | + DT2 = float32_to_int64(FST0, &env->fpu->fp_status); | |
| 861 | 882 | RESTORE_ROUNDING_MODE; |
| 862 | 883 | update_fcr31(); |
| 863 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 884 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 864 | 885 | DT2 = 0x7fffffffffffffffULL; |
| 865 | 886 | } |
| 866 | 887 | FLOAT_OP(ceilw, d) |
| 867 | 888 | { |
| 868 | - set_float_rounding_mode(float_round_up, &env->fp_status); | |
| 869 | - WT2 = float64_to_int32(FDT0, &env->fp_status); | |
| 889 | + set_float_rounding_mode(float_round_up, &env->fpu->fp_status); | |
| 890 | + WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); | |
| 870 | 891 | RESTORE_ROUNDING_MODE; |
| 871 | 892 | update_fcr31(); |
| 872 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 893 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 873 | 894 | WT2 = 0x7fffffff; |
| 874 | 895 | } |
| 875 | 896 | FLOAT_OP(ceilw, s) |
| 876 | 897 | { |
| 877 | - set_float_rounding_mode(float_round_up, &env->fp_status); | |
| 878 | - WT2 = float32_to_int32(FST0, &env->fp_status); | |
| 898 | + set_float_rounding_mode(float_round_up, &env->fpu->fp_status); | |
| 899 | + WT2 = float32_to_int32(FST0, &env->fpu->fp_status); | |
| 879 | 900 | RESTORE_ROUNDING_MODE; |
| 880 | 901 | update_fcr31(); |
| 881 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 902 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 882 | 903 | WT2 = 0x7fffffff; |
| 883 | 904 | } |
| 884 | 905 | |
| 885 | 906 | FLOAT_OP(floorl, d) |
| 886 | 907 | { |
| 887 | - set_float_rounding_mode(float_round_down, &env->fp_status); | |
| 888 | - DT2 = float64_to_int64(FDT0, &env->fp_status); | |
| 908 | + set_float_rounding_mode(float_round_down, &env->fpu->fp_status); | |
| 909 | + DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); | |
| 889 | 910 | RESTORE_ROUNDING_MODE; |
| 890 | 911 | update_fcr31(); |
| 891 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 912 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 892 | 913 | DT2 = 0x7fffffffffffffffULL; |
| 893 | 914 | } |
| 894 | 915 | FLOAT_OP(floorl, s) |
| 895 | 916 | { |
| 896 | - set_float_rounding_mode(float_round_down, &env->fp_status); | |
| 897 | - DT2 = float32_to_int64(FST0, &env->fp_status); | |
| 917 | + set_float_rounding_mode(float_round_down, &env->fpu->fp_status); | |
| 918 | + DT2 = float32_to_int64(FST0, &env->fpu->fp_status); | |
| 898 | 919 | RESTORE_ROUNDING_MODE; |
| 899 | 920 | update_fcr31(); |
| 900 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 921 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 901 | 922 | DT2 = 0x7fffffffffffffffULL; |
| 902 | 923 | } |
| 903 | 924 | FLOAT_OP(floorw, d) |
| 904 | 925 | { |
| 905 | - set_float_rounding_mode(float_round_down, &env->fp_status); | |
| 906 | - WT2 = float64_to_int32(FDT0, &env->fp_status); | |
| 926 | + set_float_rounding_mode(float_round_down, &env->fpu->fp_status); | |
| 927 | + WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); | |
| 907 | 928 | RESTORE_ROUNDING_MODE; |
| 908 | 929 | update_fcr31(); |
| 909 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 930 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 910 | 931 | WT2 = 0x7fffffff; |
| 911 | 932 | } |
| 912 | 933 | FLOAT_OP(floorw, s) |
| 913 | 934 | { |
| 914 | - set_float_rounding_mode(float_round_down, &env->fp_status); | |
| 915 | - WT2 = float32_to_int32(FST0, &env->fp_status); | |
| 935 | + set_float_rounding_mode(float_round_down, &env->fpu->fp_status); | |
| 936 | + WT2 = float32_to_int32(FST0, &env->fpu->fp_status); | |
| 916 | 937 | RESTORE_ROUNDING_MODE; |
| 917 | 938 | update_fcr31(); |
| 918 | - if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 939 | + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 919 | 940 | WT2 = 0x7fffffff; |
| 920 | 941 | } |
| 921 | 942 | |
| 922 | 943 | /* MIPS specific unary operations */ |
| 923 | 944 | FLOAT_OP(recip, d) |
| 924 | 945 | { |
| 925 | - set_float_exception_flags(0, &env->fp_status); | |
| 926 | - FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status); | |
| 946 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 947 | + FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status); | |
| 927 | 948 | update_fcr31(); |
| 928 | 949 | } |
| 929 | 950 | FLOAT_OP(recip, s) |
| 930 | 951 | { |
| 931 | - set_float_exception_flags(0, &env->fp_status); | |
| 932 | - FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status); | |
| 952 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 953 | + FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); | |
| 933 | 954 | update_fcr31(); |
| 934 | 955 | } |
| 935 | 956 | |
| 936 | 957 | FLOAT_OP(rsqrt, d) |
| 937 | 958 | { |
| 938 | - set_float_exception_flags(0, &env->fp_status); | |
| 939 | - FDT2 = float64_sqrt(FDT0, &env->fp_status); | |
| 940 | - FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fp_status); | |
| 959 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 960 | + FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status); | |
| 961 | + FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status); | |
| 941 | 962 | update_fcr31(); |
| 942 | 963 | } |
| 943 | 964 | FLOAT_OP(rsqrt, s) |
| 944 | 965 | { |
| 945 | - set_float_exception_flags(0, &env->fp_status); | |
| 946 | - FST2 = float32_sqrt(FST0, &env->fp_status); | |
| 947 | - FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status); | |
| 966 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 967 | + FST2 = float32_sqrt(FST0, &env->fpu->fp_status); | |
| 968 | + FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); | |
| 948 | 969 | update_fcr31(); |
| 949 | 970 | } |
| 950 | 971 | |
| 951 | 972 | FLOAT_OP(recip1, d) |
| 952 | 973 | { |
| 953 | - set_float_exception_flags(0, &env->fp_status); | |
| 954 | - FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status); | |
| 974 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 975 | + FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status); | |
| 955 | 976 | update_fcr31(); |
| 956 | 977 | } |
| 957 | 978 | FLOAT_OP(recip1, s) |
| 958 | 979 | { |
| 959 | - set_float_exception_flags(0, &env->fp_status); | |
| 960 | - FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status); | |
| 980 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 981 | + FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); | |
| 961 | 982 | update_fcr31(); |
| 962 | 983 | } |
| 963 | 984 | FLOAT_OP(recip1, ps) |
| 964 | 985 | { |
| 965 | - set_float_exception_flags(0, &env->fp_status); | |
| 966 | - FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status); | |
| 967 | - FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fp_status); | |
| 986 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 987 | + FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); | |
| 988 | + FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fpu->fp_status); | |
| 968 | 989 | update_fcr31(); |
| 969 | 990 | } |
| 970 | 991 | |
| 971 | 992 | FLOAT_OP(rsqrt1, d) |
| 972 | 993 | { |
| 973 | - set_float_exception_flags(0, &env->fp_status); | |
| 974 | - FDT2 = float64_sqrt(FDT0, &env->fp_status); | |
| 975 | - FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fp_status); | |
| 994 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 995 | + FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status); | |
| 996 | + FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status); | |
| 976 | 997 | update_fcr31(); |
| 977 | 998 | } |
| 978 | 999 | FLOAT_OP(rsqrt1, s) |
| 979 | 1000 | { |
| 980 | - set_float_exception_flags(0, &env->fp_status); | |
| 981 | - FST2 = float32_sqrt(FST0, &env->fp_status); | |
| 982 | - FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status); | |
| 1001 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1002 | + FST2 = float32_sqrt(FST0, &env->fpu->fp_status); | |
| 1003 | + FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); | |
| 983 | 1004 | update_fcr31(); |
| 984 | 1005 | } |
| 985 | 1006 | FLOAT_OP(rsqrt1, ps) |
| 986 | 1007 | { |
| 987 | - set_float_exception_flags(0, &env->fp_status); | |
| 988 | - FST2 = float32_sqrt(FST0, &env->fp_status); | |
| 989 | - FSTH2 = float32_sqrt(FSTH0, &env->fp_status); | |
| 990 | - FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status); | |
| 991 | - FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fp_status); | |
| 1008 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1009 | + FST2 = float32_sqrt(FST0, &env->fpu->fp_status); | |
| 1010 | + FSTH2 = float32_sqrt(FSTH0, &env->fpu->fp_status); | |
| 1011 | + FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); | |
| 1012 | + FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fpu->fp_status); | |
| 992 | 1013 | update_fcr31(); |
| 993 | 1014 | } |
| 994 | 1015 | |
| ... | ... | @@ -996,41 +1017,41 @@ FLOAT_OP(rsqrt1, ps) |
| 996 | 1017 | #define FLOAT_BINOP(name) \ |
| 997 | 1018 | FLOAT_OP(name, d) \ |
| 998 | 1019 | { \ |
| 999 | - set_float_exception_flags(0, &env->fp_status); \ | |
| 1000 | - FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ | |
| 1001 | - update_fcr31(); \ | |
| 1002 | - if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) \ | |
| 1003 | - FDT2 = 0x7ff7ffffffffffffULL; \ | |
| 1004 | - else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | |
| 1005 | - if ((env->fcr31 & 0x3) == 0) \ | |
| 1006 | - FDT2 &= FLOAT_SIGN64; \ | |
| 1020 | + set_float_exception_flags(0, &env->fpu->fp_status); \ | |
| 1021 | + FDT2 = float64_ ## name (FDT0, FDT1, &env->fpu->fp_status); \ | |
| 1022 | + update_fcr31(); \ | |
| 1023 | + if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \ | |
| 1024 | + FDT2 = 0x7ff7ffffffffffffULL; \ | |
| 1025 | + else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) { \ | |
| 1026 | + if ((env->fpu->fcr31 & 0x3) == 0) \ | |
| 1027 | + FDT2 &= FLOAT_SIGN64; \ | |
| 1007 | 1028 | } \ |
| 1008 | 1029 | } \ |
| 1009 | 1030 | FLOAT_OP(name, s) \ |
| 1010 | 1031 | { \ |
| 1011 | - set_float_exception_flags(0, &env->fp_status); \ | |
| 1012 | - FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ | |
| 1013 | - update_fcr31(); \ | |
| 1014 | - if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) \ | |
| 1015 | - FST2 = 0x7fbfffff; \ | |
| 1016 | - else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | |
| 1017 | - if ((env->fcr31 & 0x3) == 0) \ | |
| 1018 | - FST2 &= FLOAT_SIGN32; \ | |
| 1032 | + set_float_exception_flags(0, &env->fpu->fp_status); \ | |
| 1033 | + FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \ | |
| 1034 | + update_fcr31(); \ | |
| 1035 | + if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \ | |
| 1036 | + FST2 = 0x7fbfffff; \ | |
| 1037 | + else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) { \ | |
| 1038 | + if ((env->fpu->fcr31 & 0x3) == 0) \ | |
| 1039 | + FST2 &= FLOAT_SIGN32; \ | |
| 1019 | 1040 | } \ |
| 1020 | 1041 | } \ |
| 1021 | 1042 | FLOAT_OP(name, ps) \ |
| 1022 | 1043 | { \ |
| 1023 | - set_float_exception_flags(0, &env->fp_status); \ | |
| 1024 | - FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ | |
| 1025 | - FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ | |
| 1044 | + set_float_exception_flags(0, &env->fpu->fp_status); \ | |
| 1045 | + FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \ | |
| 1046 | + FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fpu->fp_status); \ | |
| 1026 | 1047 | update_fcr31(); \ |
| 1027 | - if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) { \ | |
| 1028 | - FST2 = 0x7fbfffff; \ | |
| 1029 | - FSTH2 = 0x7fbfffff; \ | |
| 1030 | - } else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | |
| 1031 | - if ((env->fcr31 & 0x3) == 0) { \ | |
| 1032 | - FST2 &= FLOAT_SIGN32; \ | |
| 1033 | - FSTH2 &= FLOAT_SIGN32; \ | |
| 1048 | + if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) { \ | |
| 1049 | + FST2 = 0x7fbfffff; \ | |
| 1050 | + FSTH2 = 0x7fbfffff; \ | |
| 1051 | + } else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) { \ | |
| 1052 | + if ((env->fpu->fcr31 & 0x3) == 0) { \ | |
| 1053 | + FST2 &= FLOAT_SIGN32; \ | |
| 1054 | + FSTH2 &= FLOAT_SIGN32; \ | |
| 1034 | 1055 | } \ |
| 1035 | 1056 | } \ |
| 1036 | 1057 | } |
| ... | ... | @@ -1043,69 +1064,69 @@ FLOAT_BINOP(div) |
| 1043 | 1064 | /* MIPS specific binary operations */ |
| 1044 | 1065 | FLOAT_OP(recip2, d) |
| 1045 | 1066 | { |
| 1046 | - set_float_exception_flags(0, &env->fp_status); | |
| 1047 | - FDT2 = float64_mul(FDT0, FDT2, &env->fp_status); | |
| 1048 | - FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fp_status) ^ FLOAT_SIGN64; | |
| 1067 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1068 | + FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status); | |
| 1069 | + FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status) ^ FLOAT_SIGN64; | |
| 1049 | 1070 | update_fcr31(); |
| 1050 | 1071 | } |
| 1051 | 1072 | FLOAT_OP(recip2, s) |
| 1052 | 1073 | { |
| 1053 | - set_float_exception_flags(0, &env->fp_status); | |
| 1054 | - FST2 = float32_mul(FST0, FST2, &env->fp_status); | |
| 1055 | - FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32; | |
| 1074 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1075 | + FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); | |
| 1076 | + FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32; | |
| 1056 | 1077 | update_fcr31(); |
| 1057 | 1078 | } |
| 1058 | 1079 | FLOAT_OP(recip2, ps) |
| 1059 | 1080 | { |
| 1060 | - set_float_exception_flags(0, &env->fp_status); | |
| 1061 | - FST2 = float32_mul(FST0, FST2, &env->fp_status); | |
| 1062 | - FSTH2 = float32_mul(FSTH0, FSTH2, &env->fp_status); | |
| 1063 | - FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32; | |
| 1064 | - FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32; | |
| 1081 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1082 | + FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); | |
| 1083 | + FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status); | |
| 1084 | + FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32; | |
| 1085 | + FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32; | |
| 1065 | 1086 | update_fcr31(); |
| 1066 | 1087 | } |
| 1067 | 1088 | |
| 1068 | 1089 | FLOAT_OP(rsqrt2, d) |
| 1069 | 1090 | { |
| 1070 | - set_float_exception_flags(0, &env->fp_status); | |
| 1071 | - FDT2 = float64_mul(FDT0, FDT2, &env->fp_status); | |
| 1072 | - FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fp_status); | |
| 1073 | - FDT2 = float64_div(FDT2, FLOAT_TWO64, &env->fp_status) ^ FLOAT_SIGN64; | |
| 1091 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1092 | + FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status); | |
| 1093 | + FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status); | |
| 1094 | + FDT2 = float64_div(FDT2, FLOAT_TWO64, &env->fpu->fp_status) ^ FLOAT_SIGN64; | |
| 1074 | 1095 | update_fcr31(); |
| 1075 | 1096 | } |
| 1076 | 1097 | FLOAT_OP(rsqrt2, s) |
| 1077 | 1098 | { |
| 1078 | - set_float_exception_flags(0, &env->fp_status); | |
| 1079 | - FST2 = float32_mul(FST0, FST2, &env->fp_status); | |
| 1080 | - FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status); | |
| 1081 | - FST2 = float32_div(FST2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32; | |
| 1099 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1100 | + FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); | |
| 1101 | + FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status); | |
| 1102 | + FST2 = float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32; | |
| 1082 | 1103 | update_fcr31(); |
| 1083 | 1104 | } |
| 1084 | 1105 | FLOAT_OP(rsqrt2, ps) |
| 1085 | 1106 | { |
| 1086 | - set_float_exception_flags(0, &env->fp_status); | |
| 1087 | - FST2 = float32_mul(FST0, FST2, &env->fp_status); | |
| 1088 | - FSTH2 = float32_mul(FSTH0, FSTH2, &env->fp_status); | |
| 1089 | - FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status); | |
| 1090 | - FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status); | |
| 1091 | - FST2 = float32_div(FST2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32; | |
| 1092 | - FSTH2 = float32_div(FSTH2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32; | |
| 1107 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1108 | + FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); | |
| 1109 | + FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status); | |
| 1110 | + FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status); | |
| 1111 | + FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status); | |
| 1112 | + FST2 = float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32; | |
| 1113 | + FSTH2 = float32_div(FSTH2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32; | |
| 1093 | 1114 | update_fcr31(); |
| 1094 | 1115 | } |
| 1095 | 1116 | |
| 1096 | 1117 | FLOAT_OP(addr, ps) |
| 1097 | 1118 | { |
| 1098 | - set_float_exception_flags(0, &env->fp_status); | |
| 1099 | - FST2 = float32_add (FST0, FSTH0, &env->fp_status); | |
| 1100 | - FSTH2 = float32_add (FST1, FSTH1, &env->fp_status); | |
| 1119 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1120 | + FST2 = float32_add (FST0, FSTH0, &env->fpu->fp_status); | |
| 1121 | + FSTH2 = float32_add (FST1, FSTH1, &env->fpu->fp_status); | |
| 1101 | 1122 | update_fcr31(); |
| 1102 | 1123 | } |
| 1103 | 1124 | |
| 1104 | 1125 | FLOAT_OP(mulr, ps) |
| 1105 | 1126 | { |
| 1106 | - set_float_exception_flags(0, &env->fp_status); | |
| 1107 | - FST2 = float32_mul (FST0, FSTH0, &env->fp_status); | |
| 1108 | - FSTH2 = float32_mul (FST1, FSTH1, &env->fp_status); | |
| 1127 | + set_float_exception_flags(0, &env->fpu->fp_status); | |
| 1128 | + FST2 = float32_mul (FST0, FSTH0, &env->fpu->fp_status); | |
| 1129 | + FSTH2 = float32_mul (FST1, FSTH1, &env->fpu->fp_status); | |
| 1109 | 1130 | update_fcr31(); |
| 1110 | 1131 | } |
| 1111 | 1132 | |
| ... | ... | @@ -1116,9 +1137,9 @@ void do_cmp_d_ ## op (long cc) \ |
| 1116 | 1137 | int c = cond; \ |
| 1117 | 1138 | update_fcr31(); \ |
| 1118 | 1139 | if (c) \ |
| 1119 | - SET_FP_COND(cc, env); \ | |
| 1140 | + SET_FP_COND(cc, env->fpu); \ | |
| 1120 | 1141 | else \ |
| 1121 | - CLEAR_FP_COND(cc, env); \ | |
| 1142 | + CLEAR_FP_COND(cc, env->fpu); \ | |
| 1122 | 1143 | } \ |
| 1123 | 1144 | void do_cmpabs_d_ ## op (long cc) \ |
| 1124 | 1145 | { \ |
| ... | ... | @@ -1128,9 +1149,9 @@ void do_cmpabs_d_ ## op (long cc) \ |
| 1128 | 1149 | c = cond; \ |
| 1129 | 1150 | update_fcr31(); \ |
| 1130 | 1151 | if (c) \ |
| 1131 | - SET_FP_COND(cc, env); \ | |
| 1152 | + SET_FP_COND(cc, env->fpu); \ | |
| 1132 | 1153 | else \ |
| 1133 | - CLEAR_FP_COND(cc, env); \ | |
| 1154 | + CLEAR_FP_COND(cc, env->fpu); \ | |
| 1134 | 1155 | } |
| 1135 | 1156 | |
| 1136 | 1157 | int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) |
| ... | ... | @@ -1149,24 +1170,24 @@ int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) |
| 1149 | 1170 | |
| 1150 | 1171 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1151 | 1172 | * but float*_is_unordered() is still called. */ |
| 1152 | -FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0)) | |
| 1153 | -FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)) | |
| 1154 | -FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status)) | |
| 1155 | -FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) | |
| 1156 | -FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status)) | |
| 1157 | -FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) | |
| 1158 | -FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status)) | |
| 1159 | -FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) | |
| 1173 | +FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status), 0)) | |
| 1174 | +FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)) | |
| 1175 | +FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1176 | +FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_eq(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1177 | +FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1178 | +FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_lt(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1179 | +FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1180 | +FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_le(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1160 | 1181 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1161 | 1182 | * but float*_is_unordered() is still called. */ |
| 1162 | -FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0)) | |
| 1163 | -FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status)) | |
| 1164 | -FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status)) | |
| 1165 | -FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) | |
| 1166 | -FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status)) | |
| 1167 | -FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) | |
| 1168 | -FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status)) | |
| 1169 | -FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) | |
| 1183 | +FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status), 0)) | |
| 1184 | +FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)) | |
| 1185 | +FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1186 | +FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_eq(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1187 | +FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1188 | +FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_lt(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1189 | +FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1190 | +FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_le(FDT0, FDT1, &env->fpu->fp_status)) | |
| 1170 | 1191 | |
| 1171 | 1192 | #define FOP_COND_S(op, cond) \ |
| 1172 | 1193 | void do_cmp_s_ ## op (long cc) \ |
| ... | ... | @@ -1174,9 +1195,9 @@ void do_cmp_s_ ## op (long cc) \ |
| 1174 | 1195 | int c = cond; \ |
| 1175 | 1196 | update_fcr31(); \ |
| 1176 | 1197 | if (c) \ |
| 1177 | - SET_FP_COND(cc, env); \ | |
| 1198 | + SET_FP_COND(cc, env->fpu); \ | |
| 1178 | 1199 | else \ |
| 1179 | - CLEAR_FP_COND(cc, env); \ | |
| 1200 | + CLEAR_FP_COND(cc, env->fpu); \ | |
| 1180 | 1201 | } \ |
| 1181 | 1202 | void do_cmpabs_s_ ## op (long cc) \ |
| 1182 | 1203 | { \ |
| ... | ... | @@ -1186,9 +1207,9 @@ void do_cmpabs_s_ ## op (long cc) \ |
| 1186 | 1207 | c = cond; \ |
| 1187 | 1208 | update_fcr31(); \ |
| 1188 | 1209 | if (c) \ |
| 1189 | - SET_FP_COND(cc, env); \ | |
| 1210 | + SET_FP_COND(cc, env->fpu); \ | |
| 1190 | 1211 | else \ |
| 1191 | - CLEAR_FP_COND(cc, env); \ | |
| 1212 | + CLEAR_FP_COND(cc, env->fpu); \ | |
| 1192 | 1213 | } |
| 1193 | 1214 | |
| 1194 | 1215 | flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) |
| ... | ... | @@ -1207,24 +1228,24 @@ flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) |
| 1207 | 1228 | |
| 1208 | 1229 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1209 | 1230 | * but float*_is_unordered() is still called. */ |
| 1210 | -FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0)) | |
| 1211 | -FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fp_status)) | |
| 1212 | -FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status)) | |
| 1213 | -FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) | |
| 1214 | -FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status)) | |
| 1215 | -FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) | |
| 1216 | -FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status)) | |
| 1217 | -FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) | |
| 1231 | +FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0)) | |
| 1232 | +FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)) | |
| 1233 | +FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status)) | |
| 1234 | +FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status)) | |
| 1235 | +FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status)) | |
| 1236 | +FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status)) | |
| 1237 | +FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status)) | |
| 1238 | +FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status)) | |
| 1218 | 1239 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1219 | 1240 | * but float*_is_unordered() is still called. */ |
| 1220 | -FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0)) | |
| 1221 | -FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status)) | |
| 1222 | -FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status)) | |
| 1223 | -FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) | |
| 1224 | -FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status)) | |
| 1225 | -FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) | |
| 1226 | -FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status)) | |
| 1227 | -FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) | |
| 1241 | +FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0)) | |
| 1242 | +FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)) | |
| 1243 | +FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status)) | |
| 1244 | +FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status)) | |
| 1245 | +FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status)) | |
| 1246 | +FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status)) | |
| 1247 | +FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status)) | |
| 1248 | +FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status)) | |
| 1228 | 1249 | |
| 1229 | 1250 | #define FOP_COND_PS(op, condl, condh) \ |
| 1230 | 1251 | void do_cmp_ps_ ## op (long cc) \ |
| ... | ... | @@ -1233,13 +1254,13 @@ void do_cmp_ps_ ## op (long cc) \ |
| 1233 | 1254 | int ch = condh; \ |
| 1234 | 1255 | update_fcr31(); \ |
| 1235 | 1256 | if (cl) \ |
| 1236 | - SET_FP_COND(cc, env); \ | |
| 1257 | + SET_FP_COND(cc, env->fpu); \ | |
| 1237 | 1258 | else \ |
| 1238 | - CLEAR_FP_COND(cc, env); \ | |
| 1259 | + CLEAR_FP_COND(cc, env->fpu); \ | |
| 1239 | 1260 | if (ch) \ |
| 1240 | - SET_FP_COND(cc + 1, env); \ | |
| 1261 | + SET_FP_COND(cc + 1, env->fpu); \ | |
| 1241 | 1262 | else \ |
| 1242 | - CLEAR_FP_COND(cc + 1, env); \ | |
| 1263 | + CLEAR_FP_COND(cc + 1, env->fpu); \ | |
| 1243 | 1264 | } \ |
| 1244 | 1265 | void do_cmpabs_ps_ ## op (long cc) \ |
| 1245 | 1266 | { \ |
| ... | ... | @@ -1252,48 +1273,48 @@ void do_cmpabs_ps_ ## op (long cc) \ |
| 1252 | 1273 | ch = condh; \ |
| 1253 | 1274 | update_fcr31(); \ |
| 1254 | 1275 | if (cl) \ |
| 1255 | - SET_FP_COND(cc, env); \ | |
| 1276 | + SET_FP_COND(cc, env->fpu); \ | |
| 1256 | 1277 | else \ |
| 1257 | - CLEAR_FP_COND(cc, env); \ | |
| 1278 | + CLEAR_FP_COND(cc, env->fpu); \ | |
| 1258 | 1279 | if (ch) \ |
| 1259 | - SET_FP_COND(cc + 1, env); \ | |
| 1280 | + SET_FP_COND(cc + 1, env->fpu); \ | |
| 1260 | 1281 | else \ |
| 1261 | - CLEAR_FP_COND(cc + 1, env); \ | |
| 1282 | + CLEAR_FP_COND(cc + 1, env->fpu); \ | |
| 1262 | 1283 | } |
| 1263 | 1284 | |
| 1264 | 1285 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1265 | 1286 | * but float*_is_unordered() is still called. */ |
| 1266 | -FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0), | |
| 1267 | - (float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0)) | |
| 1268 | -FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fp_status), | |
| 1269 | - float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)) | |
| 1270 | -FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status), | |
| 1271 | - !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status)) | |
| 1272 | -FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status), | |
| 1273 | - float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status)) | |
| 1274 | -FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status), | |
| 1275 | - !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status)) | |
| 1276 | -FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status), | |
| 1277 | - float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status)) | |
| 1278 | -FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status), | |
| 1279 | - !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status)) | |
| 1280 | -FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status), | |
| 1281 | - float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status)) | |
| 1287 | +FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0), | |
| 1288 | + (float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status), 0)) | |
| 1289 | +FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), | |
| 1290 | + float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)) | |
| 1291 | +FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status), | |
| 1292 | + !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1293 | +FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status), | |
| 1294 | + float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1295 | +FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status), | |
| 1296 | + !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1297 | +FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status), | |
| 1298 | + float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1299 | +FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status), | |
| 1300 | + !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1301 | +FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status), | |
| 1302 | + float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1282 | 1303 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1283 | 1304 | * but float*_is_unordered() is still called. */ |
| 1284 | -FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0), | |
| 1285 | - (float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0)) | |
| 1286 | -FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status), | |
| 1287 | - float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)) | |
| 1288 | -FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status), | |
| 1289 | - !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status)) | |
| 1290 | -FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status), | |
| 1291 | - float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status)) | |
| 1292 | -FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status), | |
| 1293 | - !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status)) | |
| 1294 | -FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status), | |
| 1295 | - float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status)) | |
| 1296 | -FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status), | |
| 1297 | - !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status)) | |
| 1298 | -FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status), | |
| 1299 | - float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status)) | |
| 1305 | +FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0), | |
| 1306 | + (float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status), 0)) | |
| 1307 | +FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), | |
| 1308 | + float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)) | |
| 1309 | +FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status), | |
| 1310 | + !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1311 | +FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status), | |
| 1312 | + float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1313 | +FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status), | |
| 1314 | + !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1315 | +FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status), | |
| 1316 | + float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1317 | +FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status), | |
| 1318 | + !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) | |
| 1319 | +FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status), | |
| 1320 | + float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) | ... | ... |
target-mips/op_template.c
| ... | ... | @@ -21,31 +21,44 @@ |
| 21 | 21 | #if defined(REG) |
| 22 | 22 | void glue(op_load_gpr_T0_gpr, REG) (void) |
| 23 | 23 | { |
| 24 | - T0 = env->gpr[REG]; | |
| 24 | + T0 = env->gpr[REG][env->current_tc]; | |
| 25 | 25 | RETURN(); |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | void glue(op_store_T0_gpr_gpr, REG) (void) |
| 29 | 29 | { |
| 30 | - env->gpr[REG] = T0; | |
| 30 | + env->gpr[REG][env->current_tc] = T0; | |
| 31 | 31 | RETURN(); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | void glue(op_load_gpr_T1_gpr, REG) (void) |
| 35 | 35 | { |
| 36 | - T1 = env->gpr[REG]; | |
| 36 | + T1 = env->gpr[REG][env->current_tc]; | |
| 37 | 37 | RETURN(); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | void glue(op_store_T1_gpr_gpr, REG) (void) |
| 41 | 41 | { |
| 42 | - env->gpr[REG] = T1; | |
| 42 | + env->gpr[REG][env->current_tc] = T1; | |
| 43 | 43 | RETURN(); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | 46 | void glue(op_load_gpr_T2_gpr, REG) (void) |
| 47 | 47 | { |
| 48 | - T2 = env->gpr[REG]; | |
| 48 | + T2 = env->gpr[REG][env->current_tc]; | |
| 49 | + RETURN(); | |
| 50 | +} | |
| 51 | + | |
| 52 | + | |
| 53 | +void glue(op_load_srsgpr_T0_gpr, REG) (void) | |
| 54 | +{ | |
| 55 | + T0 = env->gpr[REG][(env->CP0_SRSCtl >> CP0SRSCtl_PSS) & 0xf]; | |
| 56 | + RETURN(); | |
| 57 | +} | |
| 58 | + | |
| 59 | +void glue(op_store_T0_srsgpr_gpr, REG) (void) | |
| 60 | +{ | |
| 61 | + env->gpr[REG][(env->CP0_SRSCtl >> CP0SRSCtl_PSS) & 0xf] = T0; | |
| 49 | 62 | RETURN(); |
| 50 | 63 | } |
| 51 | 64 | #endif | ... | ... |
target-mips/translate.c
| ... | ... | @@ -266,6 +266,8 @@ enum { |
| 266 | 266 | OPC_DINSM = 0x05 | OPC_SPECIAL3, |
| 267 | 267 | OPC_DINSU = 0x06 | OPC_SPECIAL3, |
| 268 | 268 | OPC_DINS = 0x07 | OPC_SPECIAL3, |
| 269 | + OPC_FORK = 0x08 | OPC_SPECIAL3, | |
| 270 | + OPC_YIELD = 0x09 | OPC_SPECIAL3, | |
| 269 | 271 | OPC_BSHFL = 0x20 | OPC_SPECIAL3, |
| 270 | 272 | OPC_DBSHFL = 0x24 | OPC_SPECIAL3, |
| 271 | 273 | OPC_RDHWR = 0x3B | OPC_SPECIAL3, |
| ... | ... | @@ -296,8 +298,10 @@ enum { |
| 296 | 298 | OPC_DMFC0 = (0x01 << 21) | OPC_CP0, |
| 297 | 299 | OPC_MTC0 = (0x04 << 21) | OPC_CP0, |
| 298 | 300 | OPC_DMTC0 = (0x05 << 21) | OPC_CP0, |
| 301 | + OPC_MFTR = (0x08 << 21) | OPC_CP0, | |
| 299 | 302 | OPC_RDPGPR = (0x0A << 21) | OPC_CP0, |
| 300 | 303 | OPC_MFMC0 = (0x0B << 21) | OPC_CP0, |
| 304 | + OPC_MTTR = (0x0C << 21) | OPC_CP0, | |
| 301 | 305 | OPC_WRPGPR = (0x0E << 21) | OPC_CP0, |
| 302 | 306 | OPC_C0 = (0x10 << 21) | OPC_CP0, |
| 303 | 307 | OPC_C0_FIRST = (0x10 << 21) | OPC_CP0, |
| ... | ... | @@ -308,6 +312,10 @@ enum { |
| 308 | 312 | #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF) |
| 309 | 313 | |
| 310 | 314 | enum { |
| 315 | + OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0, | |
| 316 | + OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0, | |
| 317 | + OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0, | |
| 318 | + OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0, | |
| 311 | 319 | OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0, |
| 312 | 320 | OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0, |
| 313 | 321 | }; |
| ... | ... | @@ -441,6 +449,10 @@ GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr); |
| 441 | 449 | GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr); |
| 442 | 450 | GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr); |
| 443 | 451 | |
| 452 | +/* Moves to/from shadow registers */ | |
| 453 | +GEN32(gen_op_load_srsgpr_T0, gen_op_load_srsgpr_T0_gpr); | |
| 454 | +GEN32(gen_op_store_T0_srsgpr, gen_op_store_T0_srsgpr_gpr); | |
| 455 | + | |
| 444 | 456 | static const char *fregnames[] = |
| 445 | 457 | { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
| 446 | 458 | "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", |
| ... | ... | @@ -569,6 +581,15 @@ do { \ |
| 569 | 581 | } \ |
| 570 | 582 | } while (0) |
| 571 | 583 | |
| 584 | +#define GEN_LOAD_SRSREG_TN(Tn, Rn) \ | |
| 585 | +do { \ | |
| 586 | + if (Rn == 0) { \ | |
| 587 | + glue(gen_op_reset_, Tn)(); \ | |
| 588 | + } else { \ | |
| 589 | + glue(gen_op_load_srsgpr_, Tn)(Rn); \ | |
| 590 | + } \ | |
| 591 | +} while (0) | |
| 592 | + | |
| 572 | 593 | #ifdef TARGET_MIPS64 |
| 573 | 594 | #define GEN_LOAD_IMM_TN(Tn, Imm) \ |
| 574 | 595 | do { \ |
| ... | ... | @@ -598,6 +619,13 @@ do { \ |
| 598 | 619 | } \ |
| 599 | 620 | } while (0) |
| 600 | 621 | |
| 622 | +#define GEN_STORE_TN_SRSREG(Rn, Tn) \ | |
| 623 | +do { \ | |
| 624 | + if (Rn != 0) { \ | |
| 625 | + glue(glue(gen_op_store_, Tn),_srsgpr)(Rn); \ | |
| 626 | + } \ | |
| 627 | +} while (0) | |
| 628 | + | |
| 601 | 629 | #define GEN_LOAD_FREG_FTN(FTn, Fn) \ |
| 602 | 630 | do { \ |
| 603 | 631 | glue(gen_op_load_fpr_, FTn)(Fn); \ |
| ... | ... | @@ -740,6 +768,14 @@ static inline void check_mips_r2(CPUState *env, DisasContext *ctx) |
| 740 | 768 | generate_exception(ctx, EXCP_RI); |
| 741 | 769 | } |
| 742 | 770 | |
| 771 | +/* This code generates a "reserved instruction" exception if the | |
| 772 | + CPU is not MIPS MT capable. */ | |
| 773 | +static inline void check_mips_mt(CPUState *env, DisasContext *ctx) | |
| 774 | +{ | |
| 775 | + if (!(env->CP0_Config3 & (1 << CP0C3_MT))) | |
| 776 | + generate_exception(ctx, EXCP_RI); | |
| 777 | +} | |
| 778 | + | |
| 743 | 779 | #if defined(CONFIG_USER_ONLY) |
| 744 | 780 | #define op_ldst(name) gen_op_##name##_raw() |
| 745 | 781 | #define OP_LD_TABLE(width) |
| ... | ... | @@ -806,8 +842,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, |
| 806 | 842 | gen_op_addr_add(); |
| 807 | 843 | } |
| 808 | 844 | /* Don't do NOP if destination is zero: we must perform the actual |
| 809 | - * memory access | |
| 810 | - */ | |
| 845 | + memory access. */ | |
| 811 | 846 | switch (opc) { |
| 812 | 847 | #ifdef TARGET_MIPS64 |
| 813 | 848 | case OPC_LWU: |
| ... | ... | @@ -958,8 +993,7 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, |
| 958 | 993 | gen_op_addr_add(); |
| 959 | 994 | } |
| 960 | 995 | /* Don't do NOP if destination is zero: we must perform the actual |
| 961 | - * memory access | |
| 962 | - */ | |
| 996 | + memory access. */ | |
| 963 | 997 | switch (opc) { |
| 964 | 998 | case OPC_LWC1: |
| 965 | 999 | op_ldst(lwc1); |
| ... | ... | @@ -997,9 +1031,8 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
| 997 | 1031 | const char *opn = "imm arith"; |
| 998 | 1032 | |
| 999 | 1033 | if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { |
| 1000 | - /* if no destination, treat it as a NOP | |
| 1001 | - * For addi, we must generate the overflow exception when needed. | |
| 1002 | - */ | |
| 1034 | + /* If no destination, treat it as a NOP. | |
| 1035 | + For addi, we must generate the overflow exception when needed. */ | |
| 1003 | 1036 | MIPS_DEBUG("NOP"); |
| 1004 | 1037 | return; |
| 1005 | 1038 | } |
| ... | ... | @@ -1175,9 +1208,8 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, |
| 1175 | 1208 | |
| 1176 | 1209 | if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB |
| 1177 | 1210 | && opc != OPC_DADD && opc != OPC_DSUB) { |
| 1178 | - /* if no destination, treat it as a NOP | |
| 1179 | - * For add & sub, we must generate the overflow exception when needed. | |
| 1180 | - */ | |
| 1211 | + /* If no destination, treat it as a NOP. | |
| 1212 | + For add & sub, we must generate the overflow exception when needed. */ | |
| 1181 | 1213 | MIPS_DEBUG("NOP"); |
| 1182 | 1214 | return; |
| 1183 | 1215 | } |
| ... | ... | @@ -1324,29 +1356,29 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) |
| 1324 | 1356 | const char *opn = "hilo"; |
| 1325 | 1357 | |
| 1326 | 1358 | if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { |
| 1327 | - /* Treat as a NOP */ | |
| 1359 | + /* Treat as NOP. */ | |
| 1328 | 1360 | MIPS_DEBUG("NOP"); |
| 1329 | 1361 | return; |
| 1330 | 1362 | } |
| 1331 | 1363 | switch (opc) { |
| 1332 | 1364 | case OPC_MFHI: |
| 1333 | - gen_op_load_HI(); | |
| 1365 | + gen_op_load_HI(0); | |
| 1334 | 1366 | GEN_STORE_TN_REG(reg, T0); |
| 1335 | 1367 | opn = "mfhi"; |
| 1336 | 1368 | break; |
| 1337 | 1369 | case OPC_MFLO: |
| 1338 | - gen_op_load_LO(); | |
| 1370 | + gen_op_load_LO(0); | |
| 1339 | 1371 | GEN_STORE_TN_REG(reg, T0); |
| 1340 | 1372 | opn = "mflo"; |
| 1341 | 1373 | break; |
| 1342 | 1374 | case OPC_MTHI: |
| 1343 | 1375 | GEN_LOAD_REG_TN(T0, reg); |
| 1344 | - gen_op_store_HI(); | |
| 1376 | + gen_op_store_HI(0); | |
| 1345 | 1377 | opn = "mthi"; |
| 1346 | 1378 | break; |
| 1347 | 1379 | case OPC_MTLO: |
| 1348 | 1380 | GEN_LOAD_REG_TN(T0, reg); |
| 1349 | - gen_op_store_LO(); | |
| 1381 | + gen_op_store_LO(0); | |
| 1350 | 1382 | opn = "mtlo"; |
| 1351 | 1383 | break; |
| 1352 | 1384 | default: |
| ... | ... | @@ -1428,7 +1460,7 @@ static void gen_cl (DisasContext *ctx, uint32_t opc, |
| 1428 | 1460 | { |
| 1429 | 1461 | const char *opn = "CLx"; |
| 1430 | 1462 | if (rd == 0) { |
| 1431 | - /* Treat as a NOP */ | |
| 1463 | + /* Treat as NOP. */ | |
| 1432 | 1464 | MIPS_DEBUG("NOP"); |
| 1433 | 1465 | return; |
| 1434 | 1466 | } |
| ... | ... | @@ -1514,7 +1546,7 @@ static void gen_trap (DisasContext *ctx, uint32_t opc, |
| 1514 | 1546 | case OPC_TLTIU: /* r0 < 0 unsigned */ |
| 1515 | 1547 | case OPC_TNE: /* rs != rs */ |
| 1516 | 1548 | case OPC_TNEI: /* r0 != 0 */ |
| 1517 | - /* Never trap: treat as NOP */ | |
| 1549 | + /* Never trap: treat as NOP. */ | |
| 1518 | 1550 | return; |
| 1519 | 1551 | default: |
| 1520 | 1552 | MIPS_INVAL("trap"); |
| ... | ... | @@ -1674,7 +1706,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, |
| 1674 | 1706 | case OPC_BNE: /* rx != rx */ |
| 1675 | 1707 | case OPC_BGTZ: /* 0 > 0 */ |
| 1676 | 1708 | case OPC_BLTZ: /* 0 < 0 */ |
| 1677 | - /* Treated as NOP */ | |
| 1709 | + /* Treat as NOP. */ | |
| 1678 | 1710 | MIPS_DEBUG("bnever (NOP)"); |
| 1679 | 1711 | return; |
| 1680 | 1712 | case OPC_BLTZAL: /* 0 < 0 */ |
| ... | ... | @@ -1886,17 +1918,20 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 1886 | 1918 | rn = "Index"; |
| 1887 | 1919 | break; |
| 1888 | 1920 | case 1: |
| 1889 | -// gen_op_mfc0_mvpcontrol(); /* MT ASE */ | |
| 1921 | + check_mips_mt(env, ctx); | |
| 1922 | + gen_op_mfc0_mvpcontrol(); | |
| 1890 | 1923 | rn = "MVPControl"; |
| 1891 | -// break; | |
| 1924 | + break; | |
| 1892 | 1925 | case 2: |
| 1893 | -// gen_op_mfc0_mvpconf0(); /* MT ASE */ | |
| 1926 | + check_mips_mt(env, ctx); | |
| 1927 | + gen_op_mfc0_mvpconf0(); | |
| 1894 | 1928 | rn = "MVPConf0"; |
| 1895 | -// break; | |
| 1929 | + break; | |
| 1896 | 1930 | case 3: |
| 1897 | -// gen_op_mfc0_mvpconf1(); /* MT ASE */ | |
| 1931 | + check_mips_mt(env, ctx); | |
| 1932 | + gen_op_mfc0_mvpconf1(); | |
| 1898 | 1933 | rn = "MVPConf1"; |
| 1899 | -// break; | |
| 1934 | + break; | |
| 1900 | 1935 | default: |
| 1901 | 1936 | goto die; |
| 1902 | 1937 | } |
| ... | ... | @@ -1908,33 +1943,40 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 1908 | 1943 | rn = "Random"; |
| 1909 | 1944 | break; |
| 1910 | 1945 | case 1: |
| 1911 | -// gen_op_mfc0_vpecontrol(); /* MT ASE */ | |
| 1946 | + check_mips_mt(env, ctx); | |
| 1947 | + gen_op_mfc0_vpecontrol(); | |
| 1912 | 1948 | rn = "VPEControl"; |
| 1913 | -// break; | |
| 1949 | + break; | |
| 1914 | 1950 | case 2: |
| 1915 | -// gen_op_mfc0_vpeconf0(); /* MT ASE */ | |
| 1951 | + check_mips_mt(env, ctx); | |
| 1952 | + gen_op_mfc0_vpeconf0(); | |
| 1916 | 1953 | rn = "VPEConf0"; |
| 1917 | -// break; | |
| 1954 | + break; | |
| 1918 | 1955 | case 3: |
| 1919 | -// gen_op_mfc0_vpeconf1(); /* MT ASE */ | |
| 1956 | + check_mips_mt(env, ctx); | |
| 1957 | + gen_op_mfc0_vpeconf1(); | |
| 1920 | 1958 | rn = "VPEConf1"; |
| 1921 | -// break; | |
| 1959 | + break; | |
| 1922 | 1960 | case 4: |
| 1923 | -// gen_op_mfc0_YQMask(); /* MT ASE */ | |
| 1961 | + check_mips_mt(env, ctx); | |
| 1962 | + gen_op_mfc0_yqmask(); | |
| 1924 | 1963 | rn = "YQMask"; |
| 1925 | -// break; | |
| 1964 | + break; | |
| 1926 | 1965 | case 5: |
| 1927 | -// gen_op_mfc0_vpeschedule(); /* MT ASE */ | |
| 1966 | + check_mips_mt(env, ctx); | |
| 1967 | + gen_op_mfc0_vpeschedule(); | |
| 1928 | 1968 | rn = "VPESchedule"; |
| 1929 | -// break; | |
| 1969 | + break; | |
| 1930 | 1970 | case 6: |
| 1931 | -// gen_op_mfc0_vpeschefback(); /* MT ASE */ | |
| 1971 | + check_mips_mt(env, ctx); | |
| 1972 | + gen_op_mfc0_vpeschefback(); | |
| 1932 | 1973 | rn = "VPEScheFBack"; |
| 1933 | -// break; | |
| 1974 | + break; | |
| 1934 | 1975 | case 7: |
| 1935 | -// gen_op_mfc0_vpeopt(); /* MT ASE */ | |
| 1976 | + check_mips_mt(env, ctx); | |
| 1977 | + gen_op_mfc0_vpeopt(); | |
| 1936 | 1978 | rn = "VPEOpt"; |
| 1937 | -// break; | |
| 1979 | + break; | |
| 1938 | 1980 | default: |
| 1939 | 1981 | goto die; |
| 1940 | 1982 | } |
| ... | ... | @@ -1946,33 +1988,40 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 1946 | 1988 | rn = "EntryLo0"; |
| 1947 | 1989 | break; |
| 1948 | 1990 | case 1: |
| 1949 | -// gen_op_mfc0_tcstatus(); /* MT ASE */ | |
| 1991 | + check_mips_mt(env, ctx); | |
| 1992 | + gen_op_mfc0_tcstatus(); | |
| 1950 | 1993 | rn = "TCStatus"; |
| 1951 | -// break; | |
| 1994 | + break; | |
| 1952 | 1995 | case 2: |
| 1953 | -// gen_op_mfc0_tcbind(); /* MT ASE */ | |
| 1996 | + check_mips_mt(env, ctx); | |
| 1997 | + gen_op_mfc0_tcbind(); | |
| 1954 | 1998 | rn = "TCBind"; |
| 1955 | -// break; | |
| 1999 | + break; | |
| 1956 | 2000 | case 3: |
| 1957 | -// gen_op_mfc0_tcrestart(); /* MT ASE */ | |
| 2001 | + check_mips_mt(env, ctx); | |
| 2002 | + gen_op_mfc0_tcrestart(); | |
| 1958 | 2003 | rn = "TCRestart"; |
| 1959 | -// break; | |
| 2004 | + break; | |
| 1960 | 2005 | case 4: |
| 1961 | -// gen_op_mfc0_tchalt(); /* MT ASE */ | |
| 2006 | + check_mips_mt(env, ctx); | |
| 2007 | + gen_op_mfc0_tchalt(); | |
| 1962 | 2008 | rn = "TCHalt"; |
| 1963 | -// break; | |
| 2009 | + break; | |
| 1964 | 2010 | case 5: |
| 1965 | -// gen_op_mfc0_tccontext(); /* MT ASE */ | |
| 2011 | + check_mips_mt(env, ctx); | |
| 2012 | + gen_op_mfc0_tccontext(); | |
| 1966 | 2013 | rn = "TCContext"; |
| 1967 | -// break; | |
| 2014 | + break; | |
| 1968 | 2015 | case 6: |
| 1969 | -// gen_op_mfc0_tcschedule(); /* MT ASE */ | |
| 2016 | + check_mips_mt(env, ctx); | |
| 2017 | + gen_op_mfc0_tcschedule(); | |
| 1970 | 2018 | rn = "TCSchedule"; |
| 1971 | -// break; | |
| 2019 | + break; | |
| 1972 | 2020 | case 7: |
| 1973 | -// gen_op_mfc0_tcschefback(); /* MT ASE */ | |
| 2021 | + check_mips_mt(env, ctx); | |
| 2022 | + gen_op_mfc0_tcschefback(); | |
| 1974 | 2023 | rn = "TCScheFBack"; |
| 1975 | -// break; | |
| 2024 | + break; | |
| 1976 | 2025 | default: |
| 1977 | 2026 | goto die; |
| 1978 | 2027 | } |
| ... | ... | @@ -2023,25 +2072,25 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 2023 | 2072 | rn = "Wired"; |
| 2024 | 2073 | break; |
| 2025 | 2074 | case 1: |
| 2026 | -// gen_op_mfc0_srsconf0(); /* shadow registers */ | |
| 2075 | + gen_op_mfc0_srsconf0(); | |
| 2027 | 2076 | rn = "SRSConf0"; |
| 2028 | -// break; | |
| 2077 | + break; | |
| 2029 | 2078 | case 2: |
| 2030 | -// gen_op_mfc0_srsconf1(); /* shadow registers */ | |
| 2079 | + gen_op_mfc0_srsconf1(); | |
| 2031 | 2080 | rn = "SRSConf1"; |
| 2032 | -// break; | |
| 2081 | + break; | |
| 2033 | 2082 | case 3: |
| 2034 | -// gen_op_mfc0_srsconf2(); /* shadow registers */ | |
| 2083 | + gen_op_mfc0_srsconf2(); | |
| 2035 | 2084 | rn = "SRSConf2"; |
| 2036 | -// break; | |
| 2085 | + break; | |
| 2037 | 2086 | case 4: |
| 2038 | -// gen_op_mfc0_srsconf3(); /* shadow registers */ | |
| 2087 | + gen_op_mfc0_srsconf3(); | |
| 2039 | 2088 | rn = "SRSConf3"; |
| 2040 | -// break; | |
| 2089 | + break; | |
| 2041 | 2090 | case 5: |
| 2042 | -// gen_op_mfc0_srsconf4(); /* shadow registers */ | |
| 2091 | + gen_op_mfc0_srsconf4(); | |
| 2043 | 2092 | rn = "SRSConf4"; |
| 2044 | -// break; | |
| 2093 | + break; | |
| 2045 | 2094 | default: |
| 2046 | 2095 | goto die; |
| 2047 | 2096 | } |
| ... | ... | @@ -2430,17 +2479,20 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 2430 | 2479 | rn = "Index"; |
| 2431 | 2480 | break; |
| 2432 | 2481 | case 1: |
| 2433 | -// gen_op_mtc0_mvpcontrol(); /* MT ASE */ | |
| 2482 | + check_mips_mt(env, ctx); | |
| 2483 | + gen_op_mtc0_mvpcontrol(); | |
| 2434 | 2484 | rn = "MVPControl"; |
| 2435 | -// break; | |
| 2485 | + break; | |
| 2436 | 2486 | case 2: |
| 2437 | -// gen_op_mtc0_mvpconf0(); /* MT ASE */ | |
| 2487 | + check_mips_mt(env, ctx); | |
| 2488 | + /* ignored */ | |
| 2438 | 2489 | rn = "MVPConf0"; |
| 2439 | -// break; | |
| 2490 | + break; | |
| 2440 | 2491 | case 3: |
| 2441 | -// gen_op_mtc0_mvpconf1(); /* MT ASE */ | |
| 2492 | + check_mips_mt(env, ctx); | |
| 2493 | + /* ignored */ | |
| 2442 | 2494 | rn = "MVPConf1"; |
| 2443 | -// break; | |
| 2495 | + break; | |
| 2444 | 2496 | default: |
| 2445 | 2497 | goto die; |
| 2446 | 2498 | } |
| ... | ... | @@ -2452,33 +2504,40 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 2452 | 2504 | rn = "Random"; |
| 2453 | 2505 | break; |
| 2454 | 2506 | case 1: |
| 2455 | -// gen_op_mtc0_vpecontrol(); /* MT ASE */ | |
| 2507 | + check_mips_mt(env, ctx); | |
| 2508 | + gen_op_mtc0_vpecontrol(); | |
| 2456 | 2509 | rn = "VPEControl"; |
| 2457 | -// break; | |
| 2510 | + break; | |
| 2458 | 2511 | case 2: |
| 2459 | -// gen_op_mtc0_vpeconf0(); /* MT ASE */ | |
| 2512 | + check_mips_mt(env, ctx); | |
| 2513 | + gen_op_mtc0_vpeconf0(); | |
| 2460 | 2514 | rn = "VPEConf0"; |
| 2461 | -// break; | |
| 2515 | + break; | |
| 2462 | 2516 | case 3: |
| 2463 | -// gen_op_mtc0_vpeconf1(); /* MT ASE */ | |
| 2517 | + check_mips_mt(env, ctx); | |
| 2518 | + gen_op_mtc0_vpeconf1(); | |
| 2464 | 2519 | rn = "VPEConf1"; |
| 2465 | -// break; | |
| 2520 | + break; | |
| 2466 | 2521 | case 4: |
| 2467 | -// gen_op_mtc0_YQMask(); /* MT ASE */ | |
| 2522 | + check_mips_mt(env, ctx); | |
| 2523 | + gen_op_mtc0_yqmask(); | |
| 2468 | 2524 | rn = "YQMask"; |
| 2469 | -// break; | |
| 2525 | + break; | |
| 2470 | 2526 | case 5: |
| 2471 | -// gen_op_mtc0_vpeschedule(); /* MT ASE */ | |
| 2527 | + check_mips_mt(env, ctx); | |
| 2528 | + gen_op_mtc0_vpeschedule(); | |
| 2472 | 2529 | rn = "VPESchedule"; |
| 2473 | -// break; | |
| 2530 | + break; | |
| 2474 | 2531 | case 6: |
| 2475 | -// gen_op_mtc0_vpeschefback(); /* MT ASE */ | |
| 2532 | + check_mips_mt(env, ctx); | |
| 2533 | + gen_op_mtc0_vpeschefback(); | |
| 2476 | 2534 | rn = "VPEScheFBack"; |
| 2477 | -// break; | |
| 2535 | + break; | |
| 2478 | 2536 | case 7: |
| 2479 | -// gen_op_mtc0_vpeopt(); /* MT ASE */ | |
| 2537 | + check_mips_mt(env, ctx); | |
| 2538 | + gen_op_mtc0_vpeopt(); | |
| 2480 | 2539 | rn = "VPEOpt"; |
| 2481 | -// break; | |
| 2540 | + break; | |
| 2482 | 2541 | default: |
| 2483 | 2542 | goto die; |
| 2484 | 2543 | } |
| ... | ... | @@ -2490,33 +2549,40 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 2490 | 2549 | rn = "EntryLo0"; |
| 2491 | 2550 | break; |
| 2492 | 2551 | case 1: |
| 2493 | -// gen_op_mtc0_tcstatus(); /* MT ASE */ | |
| 2552 | + check_mips_mt(env, ctx); | |
| 2553 | + gen_op_mtc0_tcstatus(); | |
| 2494 | 2554 | rn = "TCStatus"; |
| 2495 | -// break; | |
| 2555 | + break; | |
| 2496 | 2556 | case 2: |
| 2497 | -// gen_op_mtc0_tcbind(); /* MT ASE */ | |
| 2557 | + check_mips_mt(env, ctx); | |
| 2558 | + gen_op_mtc0_tcbind(); | |
| 2498 | 2559 | rn = "TCBind"; |
| 2499 | -// break; | |
| 2560 | + break; | |
| 2500 | 2561 | case 3: |
| 2501 | -// gen_op_mtc0_tcrestart(); /* MT ASE */ | |
| 2562 | + check_mips_mt(env, ctx); | |
| 2563 | + gen_op_mtc0_tcrestart(); | |
| 2502 | 2564 | rn = "TCRestart"; |
| 2503 | -// break; | |
| 2565 | + break; | |
| 2504 | 2566 | case 4: |
| 2505 | -// gen_op_mtc0_tchalt(); /* MT ASE */ | |
| 2567 | + check_mips_mt(env, ctx); | |
| 2568 | + gen_op_mtc0_tchalt(); | |
| 2506 | 2569 | rn = "TCHalt"; |
| 2507 | -// break; | |
| 2570 | + break; | |
| 2508 | 2571 | case 5: |
| 2509 | -// gen_op_mtc0_tccontext(); /* MT ASE */ | |
| 2572 | + check_mips_mt(env, ctx); | |
| 2573 | + gen_op_mtc0_tccontext(); | |
| 2510 | 2574 | rn = "TCContext"; |
| 2511 | -// break; | |
| 2575 | + break; | |
| 2512 | 2576 | case 6: |
| 2513 | -// gen_op_mtc0_tcschedule(); /* MT ASE */ | |
| 2577 | + check_mips_mt(env, ctx); | |
| 2578 | + gen_op_mtc0_tcschedule(); | |
| 2514 | 2579 | rn = "TCSchedule"; |
| 2515 | -// break; | |
| 2580 | + break; | |
| 2516 | 2581 | case 7: |
| 2517 | -// gen_op_mtc0_tcschefback(); /* MT ASE */ | |
| 2582 | + check_mips_mt(env, ctx); | |
| 2583 | + gen_op_mtc0_tcschefback(); | |
| 2518 | 2584 | rn = "TCScheFBack"; |
| 2519 | -// break; | |
| 2585 | + break; | |
| 2520 | 2586 | default: |
| 2521 | 2587 | goto die; |
| 2522 | 2588 | } |
| ... | ... | @@ -2567,25 +2633,25 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 2567 | 2633 | rn = "Wired"; |
| 2568 | 2634 | break; |
| 2569 | 2635 | case 1: |
| 2570 | -// gen_op_mtc0_srsconf0(); /* shadow registers */ | |
| 2636 | + gen_op_mtc0_srsconf0(); | |
| 2571 | 2637 | rn = "SRSConf0"; |
| 2572 | -// break; | |
| 2638 | + break; | |
| 2573 | 2639 | case 2: |
| 2574 | -// gen_op_mtc0_srsconf1(); /* shadow registers */ | |
| 2640 | + gen_op_mtc0_srsconf1(); | |
| 2575 | 2641 | rn = "SRSConf1"; |
| 2576 | -// break; | |
| 2642 | + break; | |
| 2577 | 2643 | case 3: |
| 2578 | -// gen_op_mtc0_srsconf2(); /* shadow registers */ | |
| 2644 | + gen_op_mtc0_srsconf2(); | |
| 2579 | 2645 | rn = "SRSConf2"; |
| 2580 | -// break; | |
| 2646 | + break; | |
| 2581 | 2647 | case 4: |
| 2582 | -// gen_op_mtc0_srsconf3(); /* shadow registers */ | |
| 2648 | + gen_op_mtc0_srsconf3(); | |
| 2583 | 2649 | rn = "SRSConf3"; |
| 2584 | -// break; | |
| 2650 | + break; | |
| 2585 | 2651 | case 5: |
| 2586 | -// gen_op_mtc0_srsconf4(); /* shadow registers */ | |
| 2652 | + gen_op_mtc0_srsconf4(); | |
| 2587 | 2653 | rn = "SRSConf4"; |
| 2588 | -// break; | |
| 2654 | + break; | |
| 2589 | 2655 | default: |
| 2590 | 2656 | goto die; |
| 2591 | 2657 | } |
| ... | ... | @@ -3006,17 +3072,20 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3006 | 3072 | rn = "Index"; |
| 3007 | 3073 | break; |
| 3008 | 3074 | case 1: |
| 3009 | -// gen_op_dmfc0_mvpcontrol(); /* MT ASE */ | |
| 3075 | + check_mips_mt(env, ctx); | |
| 3076 | + gen_op_mfc0_mvpcontrol(); | |
| 3010 | 3077 | rn = "MVPControl"; |
| 3011 | -// break; | |
| 3078 | + break; | |
| 3012 | 3079 | case 2: |
| 3013 | -// gen_op_dmfc0_mvpconf0(); /* MT ASE */ | |
| 3080 | + check_mips_mt(env, ctx); | |
| 3081 | + gen_op_mfc0_mvpconf0(); | |
| 3014 | 3082 | rn = "MVPConf0"; |
| 3015 | -// break; | |
| 3083 | + break; | |
| 3016 | 3084 | case 3: |
| 3017 | -// gen_op_dmfc0_mvpconf1(); /* MT ASE */ | |
| 3085 | + check_mips_mt(env, ctx); | |
| 3086 | + gen_op_mfc0_mvpconf1(); | |
| 3018 | 3087 | rn = "MVPConf1"; |
| 3019 | -// break; | |
| 3088 | + break; | |
| 3020 | 3089 | default: |
| 3021 | 3090 | goto die; |
| 3022 | 3091 | } |
| ... | ... | @@ -3028,33 +3097,40 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3028 | 3097 | rn = "Random"; |
| 3029 | 3098 | break; |
| 3030 | 3099 | case 1: |
| 3031 | -// gen_op_dmfc0_vpecontrol(); /* MT ASE */ | |
| 3100 | + check_mips_mt(env, ctx); | |
| 3101 | + gen_op_mfc0_vpecontrol(); | |
| 3032 | 3102 | rn = "VPEControl"; |
| 3033 | -// break; | |
| 3103 | + break; | |
| 3034 | 3104 | case 2: |
| 3035 | -// gen_op_dmfc0_vpeconf0(); /* MT ASE */ | |
| 3105 | + check_mips_mt(env, ctx); | |
| 3106 | + gen_op_mfc0_vpeconf0(); | |
| 3036 | 3107 | rn = "VPEConf0"; |
| 3037 | -// break; | |
| 3108 | + break; | |
| 3038 | 3109 | case 3: |
| 3039 | -// gen_op_dmfc0_vpeconf1(); /* MT ASE */ | |
| 3110 | + check_mips_mt(env, ctx); | |
| 3111 | + gen_op_mfc0_vpeconf1(); | |
| 3040 | 3112 | rn = "VPEConf1"; |
| 3041 | -// break; | |
| 3113 | + break; | |
| 3042 | 3114 | case 4: |
| 3043 | -// gen_op_dmfc0_YQMask(); /* MT ASE */ | |
| 3115 | + check_mips_mt(env, ctx); | |
| 3116 | + gen_op_dmfc0_yqmask(); | |
| 3044 | 3117 | rn = "YQMask"; |
| 3045 | -// break; | |
| 3118 | + break; | |
| 3046 | 3119 | case 5: |
| 3047 | -// gen_op_dmfc0_vpeschedule(); /* MT ASE */ | |
| 3120 | + check_mips_mt(env, ctx); | |
| 3121 | + gen_op_dmfc0_vpeschedule(); | |
| 3048 | 3122 | rn = "VPESchedule"; |
| 3049 | -// break; | |
| 3123 | + break; | |
| 3050 | 3124 | case 6: |
| 3051 | -// gen_op_dmfc0_vpeschefback(); /* MT ASE */ | |
| 3125 | + check_mips_mt(env, ctx); | |
| 3126 | + gen_op_dmfc0_vpeschefback(); | |
| 3052 | 3127 | rn = "VPEScheFBack"; |
| 3053 | -// break; | |
| 3128 | + break; | |
| 3054 | 3129 | case 7: |
| 3055 | -// gen_op_dmfc0_vpeopt(); /* MT ASE */ | |
| 3130 | + check_mips_mt(env, ctx); | |
| 3131 | + gen_op_mfc0_vpeopt(); | |
| 3056 | 3132 | rn = "VPEOpt"; |
| 3057 | -// break; | |
| 3133 | + break; | |
| 3058 | 3134 | default: |
| 3059 | 3135 | goto die; |
| 3060 | 3136 | } |
| ... | ... | @@ -3066,33 +3142,40 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3066 | 3142 | rn = "EntryLo0"; |
| 3067 | 3143 | break; |
| 3068 | 3144 | case 1: |
| 3069 | -// gen_op_dmfc0_tcstatus(); /* MT ASE */ | |
| 3145 | + check_mips_mt(env, ctx); | |
| 3146 | + gen_op_mfc0_tcstatus(); | |
| 3070 | 3147 | rn = "TCStatus"; |
| 3071 | -// break; | |
| 3148 | + break; | |
| 3072 | 3149 | case 2: |
| 3073 | -// gen_op_dmfc0_tcbind(); /* MT ASE */ | |
| 3150 | + check_mips_mt(env, ctx); | |
| 3151 | + gen_op_mfc0_tcbind(); | |
| 3074 | 3152 | rn = "TCBind"; |
| 3075 | -// break; | |
| 3153 | + break; | |
| 3076 | 3154 | case 3: |
| 3077 | -// gen_op_dmfc0_tcrestart(); /* MT ASE */ | |
| 3155 | + check_mips_mt(env, ctx); | |
| 3156 | + gen_op_dmfc0_tcrestart(); | |
| 3078 | 3157 | rn = "TCRestart"; |
| 3079 | -// break; | |
| 3158 | + break; | |
| 3080 | 3159 | case 4: |
| 3081 | -// gen_op_dmfc0_tchalt(); /* MT ASE */ | |
| 3160 | + check_mips_mt(env, ctx); | |
| 3161 | + gen_op_dmfc0_tchalt(); | |
| 3082 | 3162 | rn = "TCHalt"; |
| 3083 | -// break; | |
| 3163 | + break; | |
| 3084 | 3164 | case 5: |
| 3085 | -// gen_op_dmfc0_tccontext(); /* MT ASE */ | |
| 3165 | + check_mips_mt(env, ctx); | |
| 3166 | + gen_op_dmfc0_tccontext(); | |
| 3086 | 3167 | rn = "TCContext"; |
| 3087 | -// break; | |
| 3168 | + break; | |
| 3088 | 3169 | case 6: |
| 3089 | -// gen_op_dmfc0_tcschedule(); /* MT ASE */ | |
| 3170 | + check_mips_mt(env, ctx); | |
| 3171 | + gen_op_dmfc0_tcschedule(); | |
| 3090 | 3172 | rn = "TCSchedule"; |
| 3091 | -// break; | |
| 3173 | + break; | |
| 3092 | 3174 | case 7: |
| 3093 | -// gen_op_dmfc0_tcschefback(); /* MT ASE */ | |
| 3175 | + check_mips_mt(env, ctx); | |
| 3176 | + gen_op_dmfc0_tcschefback(); | |
| 3094 | 3177 | rn = "TCScheFBack"; |
| 3095 | -// break; | |
| 3178 | + break; | |
| 3096 | 3179 | default: |
| 3097 | 3180 | goto die; |
| 3098 | 3181 | } |
| ... | ... | @@ -3143,25 +3226,25 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3143 | 3226 | rn = "Wired"; |
| 3144 | 3227 | break; |
| 3145 | 3228 | case 1: |
| 3146 | -// gen_op_dmfc0_srsconf0(); /* shadow registers */ | |
| 3229 | + gen_op_mfc0_srsconf0(); | |
| 3147 | 3230 | rn = "SRSConf0"; |
| 3148 | -// break; | |
| 3231 | + break; | |
| 3149 | 3232 | case 2: |
| 3150 | -// gen_op_dmfc0_srsconf1(); /* shadow registers */ | |
| 3233 | + gen_op_mfc0_srsconf1(); | |
| 3151 | 3234 | rn = "SRSConf1"; |
| 3152 | -// break; | |
| 3235 | + break; | |
| 3153 | 3236 | case 3: |
| 3154 | -// gen_op_dmfc0_srsconf2(); /* shadow registers */ | |
| 3237 | + gen_op_mfc0_srsconf2(); | |
| 3155 | 3238 | rn = "SRSConf2"; |
| 3156 | -// break; | |
| 3239 | + break; | |
| 3157 | 3240 | case 4: |
| 3158 | -// gen_op_dmfc0_srsconf3(); /* shadow registers */ | |
| 3241 | + gen_op_mfc0_srsconf3(); | |
| 3159 | 3242 | rn = "SRSConf3"; |
| 3160 | -// break; | |
| 3243 | + break; | |
| 3161 | 3244 | case 5: |
| 3162 | -// gen_op_dmfc0_srsconf4(); /* shadow registers */ | |
| 3245 | + gen_op_mfc0_srsconf4(); | |
| 3163 | 3246 | rn = "SRSConf4"; |
| 3164 | -// break; | |
| 3247 | + break; | |
| 3165 | 3248 | default: |
| 3166 | 3249 | goto die; |
| 3167 | 3250 | } |
| ... | ... | @@ -3237,7 +3320,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3237 | 3320 | break; |
| 3238 | 3321 | case 3: |
| 3239 | 3322 | check_mips_r2(env, ctx); |
| 3240 | - gen_op_mfc0_srsmap(); /* shadow registers */ | |
| 3323 | + gen_op_mfc0_srsmap(); | |
| 3241 | 3324 | rn = "SRSMap"; |
| 3242 | 3325 | break; |
| 3243 | 3326 | default: |
| ... | ... | @@ -3537,17 +3620,20 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3537 | 3620 | rn = "Index"; |
| 3538 | 3621 | break; |
| 3539 | 3622 | case 1: |
| 3540 | -// gen_op_mtc0_mvpcontrol(); /* MT ASE */ | |
| 3623 | + check_mips_mt(env, ctx); | |
| 3624 | + gen_op_mtc0_mvpcontrol(); | |
| 3541 | 3625 | rn = "MVPControl"; |
| 3542 | -// break; | |
| 3626 | + break; | |
| 3543 | 3627 | case 2: |
| 3544 | -// gen_op_mtc0_mvpconf0(); /* MT ASE */ | |
| 3628 | + check_mips_mt(env, ctx); | |
| 3629 | + /* ignored */ | |
| 3545 | 3630 | rn = "MVPConf0"; |
| 3546 | -// break; | |
| 3631 | + break; | |
| 3547 | 3632 | case 3: |
| 3548 | -// gen_op_mtc0_mvpconf1(); /* MT ASE */ | |
| 3633 | + check_mips_mt(env, ctx); | |
| 3634 | + /* ignored */ | |
| 3549 | 3635 | rn = "MVPConf1"; |
| 3550 | -// break; | |
| 3636 | + break; | |
| 3551 | 3637 | default: |
| 3552 | 3638 | goto die; |
| 3553 | 3639 | } |
| ... | ... | @@ -3559,33 +3645,40 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3559 | 3645 | rn = "Random"; |
| 3560 | 3646 | break; |
| 3561 | 3647 | case 1: |
| 3562 | -// gen_op_mtc0_vpecontrol(); /* MT ASE */ | |
| 3648 | + check_mips_mt(env, ctx); | |
| 3649 | + gen_op_mtc0_vpecontrol(); | |
| 3563 | 3650 | rn = "VPEControl"; |
| 3564 | -// break; | |
| 3651 | + break; | |
| 3565 | 3652 | case 2: |
| 3566 | -// gen_op_mtc0_vpeconf0(); /* MT ASE */ | |
| 3653 | + check_mips_mt(env, ctx); | |
| 3654 | + gen_op_mtc0_vpeconf0(); | |
| 3567 | 3655 | rn = "VPEConf0"; |
| 3568 | -// break; | |
| 3656 | + break; | |
| 3569 | 3657 | case 3: |
| 3570 | -// gen_op_mtc0_vpeconf1(); /* MT ASE */ | |
| 3658 | + check_mips_mt(env, ctx); | |
| 3659 | + gen_op_mtc0_vpeconf1(); | |
| 3571 | 3660 | rn = "VPEConf1"; |
| 3572 | -// break; | |
| 3661 | + break; | |
| 3573 | 3662 | case 4: |
| 3574 | -// gen_op_mtc0_YQMask(); /* MT ASE */ | |
| 3663 | + check_mips_mt(env, ctx); | |
| 3664 | + gen_op_mtc0_yqmask(); | |
| 3575 | 3665 | rn = "YQMask"; |
| 3576 | -// break; | |
| 3666 | + break; | |
| 3577 | 3667 | case 5: |
| 3578 | -// gen_op_mtc0_vpeschedule(); /* MT ASE */ | |
| 3668 | + check_mips_mt(env, ctx); | |
| 3669 | + gen_op_mtc0_vpeschedule(); | |
| 3579 | 3670 | rn = "VPESchedule"; |
| 3580 | -// break; | |
| 3671 | + break; | |
| 3581 | 3672 | case 6: |
| 3582 | -// gen_op_mtc0_vpeschefback(); /* MT ASE */ | |
| 3673 | + check_mips_mt(env, ctx); | |
| 3674 | + gen_op_mtc0_vpeschefback(); | |
| 3583 | 3675 | rn = "VPEScheFBack"; |
| 3584 | -// break; | |
| 3676 | + break; | |
| 3585 | 3677 | case 7: |
| 3586 | -// gen_op_mtc0_vpeopt(); /* MT ASE */ | |
| 3678 | + check_mips_mt(env, ctx); | |
| 3679 | + gen_op_mtc0_vpeopt(); | |
| 3587 | 3680 | rn = "VPEOpt"; |
| 3588 | -// break; | |
| 3681 | + break; | |
| 3589 | 3682 | default: |
| 3590 | 3683 | goto die; |
| 3591 | 3684 | } |
| ... | ... | @@ -3597,33 +3690,40 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3597 | 3690 | rn = "EntryLo0"; |
| 3598 | 3691 | break; |
| 3599 | 3692 | case 1: |
| 3600 | -// gen_op_mtc0_tcstatus(); /* MT ASE */ | |
| 3693 | + check_mips_mt(env, ctx); | |
| 3694 | + gen_op_mtc0_tcstatus(); | |
| 3601 | 3695 | rn = "TCStatus"; |
| 3602 | -// break; | |
| 3696 | + break; | |
| 3603 | 3697 | case 2: |
| 3604 | -// gen_op_mtc0_tcbind(); /* MT ASE */ | |
| 3698 | + check_mips_mt(env, ctx); | |
| 3699 | + gen_op_mtc0_tcbind(); | |
| 3605 | 3700 | rn = "TCBind"; |
| 3606 | -// break; | |
| 3701 | + break; | |
| 3607 | 3702 | case 3: |
| 3608 | -// gen_op_mtc0_tcrestart(); /* MT ASE */ | |
| 3703 | + check_mips_mt(env, ctx); | |
| 3704 | + gen_op_mtc0_tcrestart(); | |
| 3609 | 3705 | rn = "TCRestart"; |
| 3610 | -// break; | |
| 3706 | + break; | |
| 3611 | 3707 | case 4: |
| 3612 | -// gen_op_mtc0_tchalt(); /* MT ASE */ | |
| 3708 | + check_mips_mt(env, ctx); | |
| 3709 | + gen_op_mtc0_tchalt(); | |
| 3613 | 3710 | rn = "TCHalt"; |
| 3614 | -// break; | |
| 3711 | + break; | |
| 3615 | 3712 | case 5: |
| 3616 | -// gen_op_mtc0_tccontext(); /* MT ASE */ | |
| 3713 | + check_mips_mt(env, ctx); | |
| 3714 | + gen_op_mtc0_tccontext(); | |
| 3617 | 3715 | rn = "TCContext"; |
| 3618 | -// break; | |
| 3716 | + break; | |
| 3619 | 3717 | case 6: |
| 3620 | -// gen_op_mtc0_tcschedule(); /* MT ASE */ | |
| 3718 | + check_mips_mt(env, ctx); | |
| 3719 | + gen_op_mtc0_tcschedule(); | |
| 3621 | 3720 | rn = "TCSchedule"; |
| 3622 | -// break; | |
| 3721 | + break; | |
| 3623 | 3722 | case 7: |
| 3624 | -// gen_op_mtc0_tcschefback(); /* MT ASE */ | |
| 3723 | + check_mips_mt(env, ctx); | |
| 3724 | + gen_op_mtc0_tcschefback(); | |
| 3625 | 3725 | rn = "TCScheFBack"; |
| 3626 | -// break; | |
| 3726 | + break; | |
| 3627 | 3727 | default: |
| 3628 | 3728 | goto die; |
| 3629 | 3729 | } |
| ... | ... | @@ -3674,25 +3774,25 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel) |
| 3674 | 3774 | rn = "Wired"; |
| 3675 | 3775 | break; |
| 3676 | 3776 | case 1: |
| 3677 | -// gen_op_mtc0_srsconf0(); /* shadow registers */ | |
| 3777 | + gen_op_mtc0_srsconf0(); | |
| 3678 | 3778 | rn = "SRSConf0"; |
| 3679 | -// break; | |
| 3779 | + break; | |
| 3680 | 3780 | case 2: |
| 3681 | -// gen_op_mtc0_srsconf1(); /* shadow registers */ | |
| 3781 | + gen_op_mtc0_srsconf1(); | |
| 3682 | 3782 | rn = "SRSConf1"; |
| 3683 | -// break; | |
| 3783 | + break; | |
| 3684 | 3784 | case 3: |
| 3685 | -// gen_op_mtc0_srsconf2(); /* shadow registers */ | |
| 3785 | + gen_op_mtc0_srsconf2(); | |
| 3686 | 3786 | rn = "SRSConf2"; |
| 3687 | -// break; | |
| 3787 | + break; | |
| 3688 | 3788 | case 4: |
| 3689 | -// gen_op_mtc0_srsconf3(); /* shadow registers */ | |
| 3789 | + gen_op_mtc0_srsconf3(); | |
| 3690 | 3790 | rn = "SRSConf3"; |
| 3691 | -// break; | |
| 3791 | + break; | |
| 3692 | 3792 | case 5: |
| 3693 | -// gen_op_mtc0_srsconf4(); /* shadow registers */ | |
| 3793 | + gen_op_mtc0_srsconf4(); | |
| 3694 | 3794 | rn = "SRSConf4"; |
| 3695 | -// break; | |
| 3795 | + break; | |
| 3696 | 3796 | default: |
| 3697 | 3797 | goto die; |
| 3698 | 3798 | } |
| ... | ... | @@ -4086,6 +4186,334 @@ die: |
| 4086 | 4186 | } |
| 4087 | 4187 | #endif /* TARGET_MIPS64 */ |
| 4088 | 4188 | |
| 4189 | +static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, | |
| 4190 | + int u, int sel, int h) | |
| 4191 | +{ | |
| 4192 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 4193 | + | |
| 4194 | + if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && | |
| 4195 | + ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) != | |
| 4196 | + (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE)))) | |
| 4197 | + gen_op_set_T0(-1); | |
| 4198 | + else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > | |
| 4199 | + (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) | |
| 4200 | + gen_op_set_T0(-1); | |
| 4201 | + else if (u == 0) { | |
| 4202 | + switch (rt) { | |
| 4203 | + case 2: | |
| 4204 | + switch (sel) { | |
| 4205 | + case 1: | |
| 4206 | + gen_op_mftc0_tcstatus(); | |
| 4207 | + break; | |
| 4208 | + case 2: | |
| 4209 | + gen_op_mftc0_tcbind(); | |
| 4210 | + break; | |
| 4211 | + case 3: | |
| 4212 | + gen_op_mftc0_tcrestart(); | |
| 4213 | + break; | |
| 4214 | + case 4: | |
| 4215 | + gen_op_mftc0_tchalt(); | |
| 4216 | + break; | |
| 4217 | + case 5: | |
| 4218 | + gen_op_mftc0_tccontext(); | |
| 4219 | + break; | |
| 4220 | + case 6: | |
| 4221 | + gen_op_mftc0_tcschedule(); | |
| 4222 | + break; | |
| 4223 | + case 7: | |
| 4224 | + gen_op_mftc0_tcschefback(); | |
| 4225 | + break; | |
| 4226 | + default: | |
| 4227 | + gen_mfc0(env, ctx, rt, sel); | |
| 4228 | + break; | |
| 4229 | + } | |
| 4230 | + break; | |
| 4231 | + case 10: | |
| 4232 | + switch (sel) { | |
| 4233 | + case 0: | |
| 4234 | + gen_op_mftc0_entryhi(); | |
| 4235 | + break; | |
| 4236 | + default: | |
| 4237 | + gen_mfc0(env, ctx, rt, sel); | |
| 4238 | + break; | |
| 4239 | + } | |
| 4240 | + case 12: | |
| 4241 | + switch (sel) { | |
| 4242 | + case 0: | |
| 4243 | + gen_op_mftc0_status(); | |
| 4244 | + break; | |
| 4245 | + default: | |
| 4246 | + gen_mfc0(env, ctx, rt, sel); | |
| 4247 | + break; | |
| 4248 | + } | |
| 4249 | + case 23: | |
| 4250 | + switch (sel) { | |
| 4251 | + case 0: | |
| 4252 | + gen_op_mftc0_debug(); | |
| 4253 | + break; | |
| 4254 | + default: | |
| 4255 | + gen_mfc0(env, ctx, rt, sel); | |
| 4256 | + break; | |
| 4257 | + } | |
| 4258 | + break; | |
| 4259 | + default: | |
| 4260 | + gen_mfc0(env, ctx, rt, sel); | |
| 4261 | + } | |
| 4262 | + } else switch (sel) { | |
| 4263 | + /* GPR registers. */ | |
| 4264 | + case 0: | |
| 4265 | + gen_op_mftgpr(rt); | |
| 4266 | + break; | |
| 4267 | + /* Auxiliary CPU registers */ | |
| 4268 | + case 1: | |
| 4269 | + switch (rt) { | |
| 4270 | + case 0: | |
| 4271 | + gen_op_mftlo(0); | |
| 4272 | + break; | |
| 4273 | + case 1: | |
| 4274 | + gen_op_mfthi(0); | |
| 4275 | + break; | |
| 4276 | + case 2: | |
| 4277 | + gen_op_mftacx(0); | |
| 4278 | + break; | |
| 4279 | + case 4: | |
| 4280 | + gen_op_mftlo(1); | |
| 4281 | + break; | |
| 4282 | + case 5: | |
| 4283 | + gen_op_mfthi(1); | |
| 4284 | + break; | |
| 4285 | + case 6: | |
| 4286 | + gen_op_mftacx(1); | |
| 4287 | + break; | |
| 4288 | + case 8: | |
| 4289 | + gen_op_mftlo(2); | |
| 4290 | + break; | |
| 4291 | + case 9: | |
| 4292 | + gen_op_mfthi(2); | |
| 4293 | + break; | |
| 4294 | + case 10: | |
| 4295 | + gen_op_mftacx(2); | |
| 4296 | + break; | |
| 4297 | + case 12: | |
| 4298 | + gen_op_mftlo(3); | |
| 4299 | + break; | |
| 4300 | + case 13: | |
| 4301 | + gen_op_mfthi(3); | |
| 4302 | + break; | |
| 4303 | + case 14: | |
| 4304 | + gen_op_mftacx(3); | |
| 4305 | + break; | |
| 4306 | + case 16: | |
| 4307 | + gen_op_mftdsp(); | |
| 4308 | + break; | |
| 4309 | + default: | |
| 4310 | + goto die; | |
| 4311 | + } | |
| 4312 | + break; | |
| 4313 | + /* Floating point (COP1). */ | |
| 4314 | + case 2: | |
| 4315 | + /* XXX: For now we support only a single FPU context. */ | |
| 4316 | + if (h == 0) { | |
| 4317 | + GEN_LOAD_FREG_FTN(WT0, rt); | |
| 4318 | + gen_op_mfc1(); | |
| 4319 | + } else { | |
| 4320 | + GEN_LOAD_FREG_FTN(WTH0, rt); | |
| 4321 | + gen_op_mfhc1(); | |
| 4322 | + } | |
| 4323 | + break; | |
| 4324 | + case 3: | |
| 4325 | + /* XXX: For now we support only a single FPU context. */ | |
| 4326 | + gen_op_cfc1(rt); | |
| 4327 | + break; | |
| 4328 | + /* COP2: Not implemented. */ | |
| 4329 | + case 4: | |
| 4330 | + case 5: | |
| 4331 | + /* fall through */ | |
| 4332 | + default: | |
| 4333 | + goto die; | |
| 4334 | + } | |
| 4335 | +#if defined MIPS_DEBUG_DISAS | |
| 4336 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | |
| 4337 | + fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n", | |
| 4338 | + rt, u, sel, h); | |
| 4339 | + } | |
| 4340 | +#endif | |
| 4341 | + return; | |
| 4342 | + | |
| 4343 | +die: | |
| 4344 | +#if defined MIPS_DEBUG_DISAS | |
| 4345 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | |
| 4346 | + fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n", | |
| 4347 | + rt, u, sel, h); | |
| 4348 | + } | |
| 4349 | +#endif | |
| 4350 | + generate_exception(ctx, EXCP_RI); | |
| 4351 | +} | |
| 4352 | + | |
| 4353 | +static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, | |
| 4354 | + int u, int sel, int h) | |
| 4355 | +{ | |
| 4356 | + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); | |
| 4357 | + | |
| 4358 | + if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && | |
| 4359 | + ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) != | |
| 4360 | + (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE)))) | |
| 4361 | + /* NOP */ ; | |
| 4362 | + else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > | |
| 4363 | + (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) | |
| 4364 | + /* NOP */ ; | |
| 4365 | + else if (u == 0) { | |
| 4366 | + switch (rd) { | |
| 4367 | + case 2: | |
| 4368 | + switch (sel) { | |
| 4369 | + case 1: | |
| 4370 | + gen_op_mttc0_tcstatus(); | |
| 4371 | + break; | |
| 4372 | + case 2: | |
| 4373 | + gen_op_mttc0_tcbind(); | |
| 4374 | + break; | |
| 4375 | + case 3: | |
| 4376 | + gen_op_mttc0_tcrestart(); | |
| 4377 | + break; | |
| 4378 | + case 4: | |
| 4379 | + gen_op_mttc0_tchalt(); | |
| 4380 | + break; | |
| 4381 | + case 5: | |
| 4382 | + gen_op_mttc0_tccontext(); | |
| 4383 | + break; | |
| 4384 | + case 6: | |
| 4385 | + gen_op_mttc0_tcschedule(); | |
| 4386 | + break; | |
| 4387 | + case 7: | |
| 4388 | + gen_op_mttc0_tcschefback(); | |
| 4389 | + break; | |
| 4390 | + default: | |
| 4391 | + gen_mtc0(env, ctx, rd, sel); | |
| 4392 | + break; | |
| 4393 | + } | |
| 4394 | + break; | |
| 4395 | + case 10: | |
| 4396 | + switch (sel) { | |
| 4397 | + case 0: | |
| 4398 | + gen_op_mttc0_entryhi(); | |
| 4399 | + break; | |
| 4400 | + default: | |
| 4401 | + gen_mtc0(env, ctx, rd, sel); | |
| 4402 | + break; | |
| 4403 | + } | |
| 4404 | + case 12: | |
| 4405 | + switch (sel) { | |
| 4406 | + case 0: | |
| 4407 | + gen_op_mttc0_status(); | |
| 4408 | + break; | |
| 4409 | + default: | |
| 4410 | + gen_mtc0(env, ctx, rd, sel); | |
| 4411 | + break; | |
| 4412 | + } | |
| 4413 | + case 23: | |
| 4414 | + switch (sel) { | |
| 4415 | + case 0: | |
| 4416 | + gen_op_mttc0_debug(); | |
| 4417 | + break; | |
| 4418 | + default: | |
| 4419 | + gen_mtc0(env, ctx, rd, sel); | |
| 4420 | + break; | |
| 4421 | + } | |
| 4422 | + break; | |
| 4423 | + default: | |
| 4424 | + gen_mtc0(env, ctx, rd, sel); | |
| 4425 | + } | |
| 4426 | + } else switch (sel) { | |
| 4427 | + /* GPR registers. */ | |
| 4428 | + case 0: | |
| 4429 | + gen_op_mttgpr(rd); | |
| 4430 | + break; | |
| 4431 | + /* Auxiliary CPU registers */ | |
| 4432 | + case 1: | |
| 4433 | + switch (rd) { | |
| 4434 | + case 0: | |
| 4435 | + gen_op_mttlo(0); | |
| 4436 | + break; | |
| 4437 | + case 1: | |
| 4438 | + gen_op_mtthi(0); | |
| 4439 | + break; | |
| 4440 | + case 2: | |
| 4441 | + gen_op_mttacx(0); | |
| 4442 | + break; | |
| 4443 | + case 4: | |
| 4444 | + gen_op_mttlo(1); | |
| 4445 | + break; | |
| 4446 | + case 5: | |
| 4447 | + gen_op_mtthi(1); | |
| 4448 | + break; | |
| 4449 | + case 6: | |
| 4450 | + gen_op_mttacx(1); | |
| 4451 | + break; | |
| 4452 | + case 8: | |
| 4453 | + gen_op_mttlo(2); | |
| 4454 | + break; | |
| 4455 | + case 9: | |
| 4456 | + gen_op_mtthi(2); | |
| 4457 | + break; | |
| 4458 | + case 10: | |
| 4459 | + gen_op_mttacx(2); | |
| 4460 | + break; | |
| 4461 | + case 12: | |
| 4462 | + gen_op_mttlo(3); | |
| 4463 | + break; | |
| 4464 | + case 13: | |
| 4465 | + gen_op_mtthi(3); | |
| 4466 | + break; | |
| 4467 | + case 14: | |
| 4468 | + gen_op_mttacx(3); | |
| 4469 | + break; | |
| 4470 | + case 16: | |
| 4471 | + gen_op_mttdsp(); | |
| 4472 | + break; | |
| 4473 | + default: | |
| 4474 | + goto die; | |
| 4475 | + } | |
| 4476 | + break; | |
| 4477 | + /* Floating point (COP1). */ | |
| 4478 | + case 2: | |
| 4479 | + /* XXX: For now we support only a single FPU context. */ | |
| 4480 | + if (h == 0) { | |
| 4481 | + gen_op_mtc1(); | |
| 4482 | + GEN_STORE_FTN_FREG(rd, WT0); | |
| 4483 | + } else { | |
| 4484 | + gen_op_mthc1(); | |
| 4485 | + GEN_STORE_FTN_FREG(rd, WTH0); | |
| 4486 | + } | |
| 4487 | + break; | |
| 4488 | + case 3: | |
| 4489 | + /* XXX: For now we support only a single FPU context. */ | |
| 4490 | + gen_op_ctc1(rd); | |
| 4491 | + break; | |
| 4492 | + /* COP2: Not implemented. */ | |
| 4493 | + case 4: | |
| 4494 | + case 5: | |
| 4495 | + /* fall through */ | |
| 4496 | + default: | |
| 4497 | + goto die; | |
| 4498 | + } | |
| 4499 | +#if defined MIPS_DEBUG_DISAS | |
| 4500 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | |
| 4501 | + fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n", | |
| 4502 | + rd, u, sel, h); | |
| 4503 | + } | |
| 4504 | +#endif | |
| 4505 | + return; | |
| 4506 | + | |
| 4507 | +die: | |
| 4508 | +#if defined MIPS_DEBUG_DISAS | |
| 4509 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | |
| 4510 | + fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n", | |
| 4511 | + rd, u, sel, h); | |
| 4512 | + } | |
| 4513 | +#endif | |
| 4514 | + generate_exception(ctx, EXCP_RI); | |
| 4515 | +} | |
| 4516 | + | |
| 4089 | 4517 | static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd) |
| 4090 | 4518 | { |
| 4091 | 4519 | const char *opn = "ldst"; |
| ... | ... | @@ -4093,7 +4521,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
| 4093 | 4521 | switch (opc) { |
| 4094 | 4522 | case OPC_MFC0: |
| 4095 | 4523 | if (rt == 0) { |
| 4096 | - /* Treat as NOP */ | |
| 4524 | + /* Treat as NOP. */ | |
| 4097 | 4525 | return; |
| 4098 | 4526 | } |
| 4099 | 4527 | gen_mfc0(env, ctx, rd, ctx->opcode & 0x7); |
| ... | ... | @@ -4110,7 +4538,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
| 4110 | 4538 | if (!(ctx->hflags & MIPS_HFLAG_64)) |
| 4111 | 4539 | generate_exception(ctx, EXCP_RI); |
| 4112 | 4540 | if (rt == 0) { |
| 4113 | - /* Treat as NOP */ | |
| 4541 | + /* Treat as NOP. */ | |
| 4114 | 4542 | return; |
| 4115 | 4543 | } |
| 4116 | 4544 | gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7); |
| ... | ... | @@ -4121,31 +4549,49 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
| 4121 | 4549 | if (!(ctx->hflags & MIPS_HFLAG_64)) |
| 4122 | 4550 | generate_exception(ctx, EXCP_RI); |
| 4123 | 4551 | GEN_LOAD_REG_TN(T0, rt); |
| 4124 | - gen_dmtc0(env,ctx, rd, ctx->opcode & 0x7); | |
| 4552 | + gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7); | |
| 4125 | 4553 | opn = "dmtc0"; |
| 4126 | 4554 | break; |
| 4127 | 4555 | #endif |
| 4556 | + case OPC_MFTR: | |
| 4557 | + check_mips_mt(env, ctx); | |
| 4558 | + if (rd == 0) { | |
| 4559 | + /* Treat as NOP. */ | |
| 4560 | + return; | |
| 4561 | + } | |
| 4562 | + gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1, | |
| 4563 | + ctx->opcode & 0x7, (ctx->opcode >> 4) & 1); | |
| 4564 | + gen_op_store_T0_gpr(rd); | |
| 4565 | + opn = "mftr"; | |
| 4566 | + break; | |
| 4567 | + case OPC_MTTR: | |
| 4568 | + check_mips_mt(env, ctx); | |
| 4569 | + GEN_LOAD_REG_TN(T0, rt); | |
| 4570 | + gen_mttr(env, ctx, rd, (ctx->opcode >> 5) & 1, | |
| 4571 | + ctx->opcode & 0x7, (ctx->opcode >> 4) & 1); | |
| 4572 | + opn = "mttr"; | |
| 4573 | + break; | |
| 4128 | 4574 | case OPC_TLBWI: |
| 4129 | 4575 | opn = "tlbwi"; |
| 4130 | - if (!env->do_tlbwi) | |
| 4576 | + if (!env->tlb->do_tlbwi) | |
| 4131 | 4577 | goto die; |
| 4132 | 4578 | gen_op_tlbwi(); |
| 4133 | 4579 | break; |
| 4134 | 4580 | case OPC_TLBWR: |
| 4135 | 4581 | opn = "tlbwr"; |
| 4136 | - if (!env->do_tlbwr) | |
| 4582 | + if (!env->tlb->do_tlbwr) | |
| 4137 | 4583 | goto die; |
| 4138 | 4584 | gen_op_tlbwr(); |
| 4139 | 4585 | break; |
| 4140 | 4586 | case OPC_TLBP: |
| 4141 | 4587 | opn = "tlbp"; |
| 4142 | - if (!env->do_tlbp) | |
| 4588 | + if (!env->tlb->do_tlbp) | |
| 4143 | 4589 | goto die; |
| 4144 | 4590 | gen_op_tlbp(); |
| 4145 | 4591 | break; |
| 4146 | 4592 | case OPC_TLBR: |
| 4147 | 4593 | opn = "tlbr"; |
| 4148 | - if (!env->do_tlbr) | |
| 4594 | + if (!env->tlb->do_tlbr) | |
| 4149 | 4595 | goto die; |
| 4150 | 4596 | gen_op_tlbr(); |
| 4151 | 4597 | break; |
| ... | ... | @@ -4263,15 +4709,13 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) |
| 4263 | 4709 | opn = "mtc1"; |
| 4264 | 4710 | break; |
| 4265 | 4711 | case OPC_CFC1: |
| 4266 | - GEN_LOAD_IMM_TN(T1, fs); | |
| 4267 | - gen_op_cfc1(); | |
| 4712 | + gen_op_cfc1(fs); | |
| 4268 | 4713 | GEN_STORE_TN_REG(rt, T0); |
| 4269 | 4714 | opn = "cfc1"; |
| 4270 | 4715 | break; |
| 4271 | 4716 | case OPC_CTC1: |
| 4272 | - GEN_LOAD_IMM_TN(T1, fs); | |
| 4273 | 4717 | GEN_LOAD_REG_TN(T0, rt); |
| 4274 | - gen_op_ctc1(); | |
| 4718 | + gen_op_ctc1(fs); | |
| 4275 | 4719 | opn = "ctc1"; |
| 4276 | 4720 | break; |
| 4277 | 4721 | case OPC_DMFC1: |
| ... | ... | @@ -5171,8 +5615,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, |
| 5171 | 5615 | gen_op_addr_add(); |
| 5172 | 5616 | } |
| 5173 | 5617 | /* Don't do NOP if destination is zero: we must perform the actual |
| 5174 | - * memory access | |
| 5175 | - */ | |
| 5618 | + memory access. */ | |
| 5176 | 5619 | switch (opc) { |
| 5177 | 5620 | case OPC_LWXC1: |
| 5178 | 5621 | op_ldst(lwc1); |
| ... | ... | @@ -5456,7 +5899,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5456 | 5899 | #endif |
| 5457 | 5900 | break; |
| 5458 | 5901 | case OPC_SYNC: |
| 5459 | - /* Treat as a noop. */ | |
| 5902 | + /* Treat as NOP. */ | |
| 5460 | 5903 | break; |
| 5461 | 5904 | |
| 5462 | 5905 | case OPC_MOVCI: |
| ... | ... | @@ -5521,7 +5964,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5521 | 5964 | } else { |
| 5522 | 5965 | generate_exception(ctx, EXCP_DBp); |
| 5523 | 5966 | } |
| 5524 | - /* Treat as a noop */ | |
| 5967 | + /* Treat as NOP. */ | |
| 5525 | 5968 | break; |
| 5526 | 5969 | #ifdef TARGET_MIPS64 |
| 5527 | 5970 | case OPC_DCLZ ... OPC_DCLO: |
| ... | ... | @@ -5586,7 +6029,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5586 | 6029 | break; |
| 5587 | 6030 | case 29: |
| 5588 | 6031 | #if defined (CONFIG_USER_ONLY) |
| 5589 | - gen_op_tls_value (); | |
| 6032 | + gen_op_tls_value(); | |
| 5590 | 6033 | break; |
| 5591 | 6034 | #endif |
| 5592 | 6035 | default: /* Invalid */ |
| ... | ... | @@ -5596,6 +6039,18 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5596 | 6039 | } |
| 5597 | 6040 | GEN_STORE_TN_REG(rt, T0); |
| 5598 | 6041 | break; |
| 6042 | + case OPC_FORK: | |
| 6043 | + check_mips_mt(env, ctx); | |
| 6044 | + GEN_LOAD_REG_TN(T0, rt); | |
| 6045 | + GEN_LOAD_REG_TN(T1, rs); | |
| 6046 | + gen_op_fork(); | |
| 6047 | + break; | |
| 6048 | + case OPC_YIELD: | |
| 6049 | + check_mips_mt(env, ctx); | |
| 6050 | + GEN_LOAD_REG_TN(T0, rs); | |
| 6051 | + gen_op_yield(); | |
| 6052 | + GEN_STORE_TN_REG(rd, T0); | |
| 6053 | + break; | |
| 5599 | 6054 | #ifdef TARGET_MIPS64 |
| 5600 | 6055 | case OPC_DEXTM ... OPC_DEXT: |
| 5601 | 6056 | case OPC_DINSM ... OPC_DINS: |
| ... | ... | @@ -5642,7 +6097,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5642 | 6097 | break; |
| 5643 | 6098 | case OPC_SYNCI: |
| 5644 | 6099 | check_mips_r2(env, ctx); |
| 5645 | - /* treat as noop */ | |
| 6100 | + /* Treat as NOP. */ | |
| 5646 | 6101 | break; |
| 5647 | 6102 | default: /* Invalid */ |
| 5648 | 6103 | MIPS_INVAL("regimm"); |
| ... | ... | @@ -5657,6 +6112,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5657 | 6112 | switch (op1) { |
| 5658 | 6113 | case OPC_MFC0: |
| 5659 | 6114 | case OPC_MTC0: |
| 6115 | + case OPC_MFTR: | |
| 6116 | + case OPC_MTTR: | |
| 5660 | 6117 | #ifdef TARGET_MIPS64 |
| 5661 | 6118 | case OPC_DMFC0: |
| 5662 | 6119 | case OPC_DMTC0: |
| ... | ... | @@ -5670,6 +6127,22 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5670 | 6127 | check_mips_r2(env, ctx); |
| 5671 | 6128 | op2 = MASK_MFMC0(ctx->opcode); |
| 5672 | 6129 | switch (op2) { |
| 6130 | + case OPC_DMT: | |
| 6131 | + check_mips_mt(env, ctx); | |
| 6132 | + gen_op_dmt(); | |
| 6133 | + break; | |
| 6134 | + case OPC_EMT: | |
| 6135 | + check_mips_mt(env, ctx); | |
| 6136 | + gen_op_emt(); | |
| 6137 | + break; | |
| 6138 | + case OPC_DVPE: | |
| 6139 | + check_mips_mt(env, ctx); | |
| 6140 | + gen_op_dvpe(); | |
| 6141 | + break; | |
| 6142 | + case OPC_EVPE: | |
| 6143 | + check_mips_mt(env, ctx); | |
| 6144 | + gen_op_evpe(); | |
| 6145 | + break; | |
| 5673 | 6146 | case OPC_DI: |
| 5674 | 6147 | gen_op_di(); |
| 5675 | 6148 | /* Stop translation as we may have switched the execution mode */ |
| ... | ... | @@ -5688,11 +6161,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5688 | 6161 | GEN_STORE_TN_REG(rt, T0); |
| 5689 | 6162 | break; |
| 5690 | 6163 | case OPC_RDPGPR: |
| 6164 | + check_mips_r2(env, ctx); | |
| 6165 | + GEN_LOAD_SRSREG_TN(T0, rt); | |
| 6166 | + GEN_STORE_TN_REG(rd, T0); | |
| 6167 | + break; | |
| 5691 | 6168 | case OPC_WRPGPR: |
| 5692 | 6169 | check_mips_r2(env, ctx); |
| 5693 | - /* Shadow registers not implemented. */ | |
| 5694 | 6170 | GEN_LOAD_REG_TN(T0, rt); |
| 5695 | - GEN_STORE_TN_REG(rd, T0); | |
| 6171 | + GEN_STORE_TN_SRSREG(rd, T0); | |
| 5696 | 6172 | break; |
| 5697 | 6173 | default: |
| 5698 | 6174 | MIPS_INVAL("cp0"); |
| ... | ... | @@ -5719,10 +6195,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5719 | 6195 | gen_ldst(ctx, op, rt, rs, imm); |
| 5720 | 6196 | break; |
| 5721 | 6197 | case OPC_CACHE: |
| 5722 | - /* Treat as a noop */ | |
| 6198 | + /* Treat as NOP. */ | |
| 5723 | 6199 | break; |
| 5724 | 6200 | case OPC_PREF: |
| 5725 | - /* Treat as a noop */ | |
| 6201 | + /* Treat as NOP. */ | |
| 5726 | 6202 | break; |
| 5727 | 6203 | |
| 5728 | 6204 | /* Floating point (COP1). */ |
| ... | ... | @@ -5807,7 +6283,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5807 | 6283 | gen_flt3_ldst(ctx, op1, sa, rd, rs, rt); |
| 5808 | 6284 | break; |
| 5809 | 6285 | case OPC_PREFX: |
| 5810 | - /* treat as noop */ | |
| 6286 | + /* Treat as NOP. */ | |
| 5811 | 6287 | break; |
| 5812 | 6288 | case OPC_ALNV_PS: |
| 5813 | 6289 | case OPC_MADD_S: |
| ... | ... | @@ -6079,13 +6555,14 @@ void fpu_dump_state(CPUState *env, FILE *f, |
| 6079 | 6555 | |
| 6080 | 6556 | |
| 6081 | 6557 | fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n", |
| 6082 | - env->fcr0, env->fcr31, is_fpu64, env->fp_status, get_float_exception_flags(&env->fp_status)); | |
| 6083 | - fpu_fprintf(f, "FT0: "); printfpr(&env->ft0); | |
| 6084 | - fpu_fprintf(f, "FT1: "); printfpr(&env->ft1); | |
| 6085 | - fpu_fprintf(f, "FT2: "); printfpr(&env->ft2); | |
| 6558 | + env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status, | |
| 6559 | + get_float_exception_flags(&env->fpu->fp_status)); | |
| 6560 | + fpu_fprintf(f, "FT0: "); printfpr(&env->fpu->ft0); | |
| 6561 | + fpu_fprintf(f, "FT1: "); printfpr(&env->fpu->ft1); | |
| 6562 | + fpu_fprintf(f, "FT2: "); printfpr(&env->fpu->ft2); | |
| 6086 | 6563 | for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) { |
| 6087 | 6564 | fpu_fprintf(f, "%3s: ", fregnames[i]); |
| 6088 | - printfpr(&env->fpr[i]); | |
| 6565 | + printfpr(&env->fpu->fpr[i]); | |
| 6089 | 6566 | } |
| 6090 | 6567 | |
| 6091 | 6568 | #undef printfpr |
| ... | ... | @@ -6095,7 +6572,7 @@ void dump_fpu (CPUState *env) |
| 6095 | 6572 | { |
| 6096 | 6573 | if (loglevel) { |
| 6097 | 6574 | fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n", |
| 6098 | - env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond); | |
| 6575 | + env->PC[env->current_tc], env->HI[0][env->current_tc], env->LO[0][env->current_tc], env->hflags, env->btarget, env->bcond); | |
| 6099 | 6576 | fpu_dump_state(env, logfile, fprintf, 0); |
| 6100 | 6577 | } |
| 6101 | 6578 | } |
| ... | ... | @@ -6112,18 +6589,18 @@ void cpu_mips_check_sign_extensions (CPUState *env, FILE *f, |
| 6112 | 6589 | { |
| 6113 | 6590 | int i; |
| 6114 | 6591 | |
| 6115 | - if (!SIGN_EXT_P(env->PC)) | |
| 6116 | - cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC); | |
| 6117 | - if (!SIGN_EXT_P(env->HI)) | |
| 6118 | - cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI); | |
| 6119 | - if (!SIGN_EXT_P(env->LO)) | |
| 6120 | - cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO); | |
| 6592 | + if (!SIGN_EXT_P(env->PC[env->current_tc])) | |
| 6593 | + cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]); | |
| 6594 | + if (!SIGN_EXT_P(env->HI[env->current_tc])) | |
| 6595 | + cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[env->current_tc]); | |
| 6596 | + if (!SIGN_EXT_P(env->LO[env->current_tc])) | |
| 6597 | + cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[env->current_tc]); | |
| 6121 | 6598 | if (!SIGN_EXT_P(env->btarget)) |
| 6122 | 6599 | cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget); |
| 6123 | 6600 | |
| 6124 | 6601 | for (i = 0; i < 32; i++) { |
| 6125 | - if (!SIGN_EXT_P(env->gpr[i])) | |
| 6126 | - cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]); | |
| 6602 | + if (!SIGN_EXT_P(env->gpr[i][env->current_tc])) | |
| 6603 | + cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i][env->current_tc]); | |
| 6127 | 6604 | } |
| 6128 | 6605 | |
| 6129 | 6606 | if (!SIGN_EXT_P(env->CP0_EPC)) |
| ... | ... | @@ -6140,11 +6617,11 @@ void cpu_dump_state (CPUState *env, FILE *f, |
| 6140 | 6617 | int i; |
| 6141 | 6618 | |
| 6142 | 6619 | cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n", |
| 6143 | - env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond); | |
| 6620 | + env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], env->hflags, env->btarget, env->bcond); | |
| 6144 | 6621 | for (i = 0; i < 32; i++) { |
| 6145 | 6622 | if ((i & 3) == 0) |
| 6146 | 6623 | cpu_fprintf(f, "GPR%02d:", i); |
| 6147 | - cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]); | |
| 6624 | + cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i][env->current_tc]); | |
| 6148 | 6625 | if ((i & 3) == 3) |
| 6149 | 6626 | cpu_fprintf(f, "\n"); |
| 6150 | 6627 | } |
| ... | ... | @@ -6183,12 +6660,12 @@ void cpu_reset (CPUMIPSState *env) |
| 6183 | 6660 | if (env->hflags & MIPS_HFLAG_BMASK) { |
| 6184 | 6661 | /* If the exception was raised from a delay slot, |
| 6185 | 6662 | * come back to the jump. */ |
| 6186 | - env->CP0_ErrorEPC = env->PC - 4; | |
| 6663 | + env->CP0_ErrorEPC = env->PC[env->current_tc] - 4; | |
| 6187 | 6664 | } else { |
| 6188 | - env->CP0_ErrorEPC = env->PC; | |
| 6665 | + env->CP0_ErrorEPC = env->PC[env->current_tc]; | |
| 6189 | 6666 | } |
| 6190 | 6667 | env->hflags = 0; |
| 6191 | - env->PC = (int32_t)0xBFC00000; | |
| 6668 | + env->PC[env->current_tc] = (int32_t)0xBFC00000; | |
| 6192 | 6669 | env->CP0_Wired = 0; |
| 6193 | 6670 | /* SMP not implemented */ |
| 6194 | 6671 | env->CP0_EBase = 0x80000000; | ... | ... |
target-mips/translate_init.c
| ... | ... | @@ -43,11 +43,11 @@ |
| 43 | 43 | |
| 44 | 44 | /* No config4, no DSP ASE, no large physaddr, |
| 45 | 45 | no external interrupt controller, no vectored interupts, |
| 46 | - no 1kb pages, no MT ASE, no SmartMIPS ASE, no trace logic */ | |
| 46 | + no 1kb pages, no SmartMIPS ASE, no trace logic */ | |
| 47 | 47 | #define MIPS_CONFIG3 \ |
| 48 | 48 | ((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ |
| 49 | 49 | (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ |
| 50 | - (0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL)) | |
| 50 | + (0 << CP0C3_SM) | (0 << CP0C3_TL)) | |
| 51 | 51 | |
| 52 | 52 | /* Define a implementation number of 1. |
| 53 | 53 | Define a major version 1, minor version 0. */ |
| ... | ... | @@ -65,9 +65,21 @@ struct mips_def_t { |
| 65 | 65 | int32_t CP0_Config7; |
| 66 | 66 | int32_t SYNCI_Step; |
| 67 | 67 | int32_t CCRes; |
| 68 | - int32_t Status_rw_bitmask; | |
| 68 | + int32_t CP0_Status_rw_bitmask; | |
| 69 | + int32_t CP0_TCStatus_rw_bitmask; | |
| 70 | + int32_t CP0_SRSCtl; | |
| 69 | 71 | int32_t CP1_fcr0; |
| 70 | 72 | int32_t SEGBITS; |
| 73 | + int32_t CP0_SRSConf0_rw_bitmask; | |
| 74 | + int32_t CP0_SRSConf0; | |
| 75 | + int32_t CP0_SRSConf1_rw_bitmask; | |
| 76 | + int32_t CP0_SRSConf1; | |
| 77 | + int32_t CP0_SRSConf2_rw_bitmask; | |
| 78 | + int32_t CP0_SRSConf2; | |
| 79 | + int32_t CP0_SRSConf3_rw_bitmask; | |
| 80 | + int32_t CP0_SRSConf3; | |
| 81 | + int32_t CP0_SRSConf4_rw_bitmask; | |
| 82 | + int32_t CP0_SRSConf4; | |
| 71 | 83 | }; |
| 72 | 84 | |
| 73 | 85 | /*****************************************************************************/ |
| ... | ... | @@ -85,7 +97,7 @@ static mips_def_t mips_defs[] = |
| 85 | 97 | .CP0_Config3 = MIPS_CONFIG3, |
| 86 | 98 | .SYNCI_Step = 32, |
| 87 | 99 | .CCRes = 2, |
| 88 | - .Status_rw_bitmask = 0x3278FF17, | |
| 100 | + .CP0_Status_rw_bitmask = 0x1278FF17, | |
| 89 | 101 | }, |
| 90 | 102 | { |
| 91 | 103 | .name = "4KEcR1", |
| ... | ... | @@ -98,7 +110,7 @@ static mips_def_t mips_defs[] = |
| 98 | 110 | .CP0_Config3 = MIPS_CONFIG3, |
| 99 | 111 | .SYNCI_Step = 32, |
| 100 | 112 | .CCRes = 2, |
| 101 | - .Status_rw_bitmask = 0x3278FF17, | |
| 113 | + .CP0_Status_rw_bitmask = 0x1278FF17, | |
| 102 | 114 | }, |
| 103 | 115 | { |
| 104 | 116 | .name = "4KEc", |
| ... | ... | @@ -108,10 +120,10 @@ static mips_def_t mips_defs[] = |
| 108 | 120 | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | |
| 109 | 121 | (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), |
| 110 | 122 | .CP0_Config2 = MIPS_CONFIG2, |
| 111 | - .CP0_Config3 = MIPS_CONFIG3, | |
| 123 | + .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt), | |
| 112 | 124 | .SYNCI_Step = 32, |
| 113 | 125 | .CCRes = 2, |
| 114 | - .Status_rw_bitmask = 0x3278FF17, | |
| 126 | + .CP0_Status_rw_bitmask = 0x1278FF17, | |
| 115 | 127 | }, |
| 116 | 128 | { |
| 117 | 129 | .name = "24Kc", |
| ... | ... | @@ -121,10 +133,11 @@ static mips_def_t mips_defs[] = |
| 121 | 133 | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | |
| 122 | 134 | (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), |
| 123 | 135 | .CP0_Config2 = MIPS_CONFIG2, |
| 124 | - .CP0_Config3 = MIPS_CONFIG3, | |
| 136 | + .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt), | |
| 125 | 137 | .SYNCI_Step = 32, |
| 126 | 138 | .CCRes = 2, |
| 127 | - .Status_rw_bitmask = 0x3278FF17, | |
| 139 | + /* No DSP implemented. */ | |
| 140 | + .CP0_Status_rw_bitmask = 0x1278FF17, | |
| 128 | 141 | }, |
| 129 | 142 | { |
| 130 | 143 | .name = "24Kf", |
| ... | ... | @@ -134,13 +147,53 @@ static mips_def_t mips_defs[] = |
| 134 | 147 | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | |
| 135 | 148 | (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), |
| 136 | 149 | .CP0_Config2 = MIPS_CONFIG2, |
| 137 | - .CP0_Config3 = MIPS_CONFIG3, | |
| 150 | + .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt), | |
| 138 | 151 | .SYNCI_Step = 32, |
| 139 | 152 | .CCRes = 2, |
| 140 | - .Status_rw_bitmask = 0x3678FF17, | |
| 153 | + /* No DSP implemented. */ | |
| 154 | + .CP0_Status_rw_bitmask = 0x3678FF17, | |
| 141 | 155 | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | |
| 142 | 156 | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), |
| 143 | 157 | }, |
| 158 | + { | |
| 159 | + .name = "34Kf", | |
| 160 | + .CP0_PRid = 0x00019500, | |
| 161 | + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), | |
| 162 | + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) | | |
| 163 | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | | |
| 164 | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), | |
| 165 | + .CP0_Config2 = MIPS_CONFIG2, | |
| 166 | + .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 << CP0C3_MT), | |
| 167 | + .SYNCI_Step = 32, | |
| 168 | + .CCRes = 2, | |
| 169 | + /* No DSP implemented. */ | |
| 170 | + .CP0_Status_rw_bitmask = 0x3678FF17, | |
| 171 | + /* No DSP implemented. */ | |
| 172 | + .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) | | |
| 173 | + (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | | |
| 174 | + (0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) | | |
| 175 | + (1 << CP0TCSt_DA) | (1 << CP0TCSt_A) | | |
| 176 | + (0x3 << CP0TCSt_TKSU) | (1 << CP0TCSt_IXMT) | | |
| 177 | + (0xff << CP0TCSt_TASID), | |
| 178 | + .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | | |
| 179 | + (1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID), | |
| 180 | + .CP0_SRSCtl = (0xf << CP0SRSCtl_HSS), | |
| 181 | + .CP0_SRSConf0_rw_bitmask = 0x3fffffff, | |
| 182 | + .CP0_SRSConf0 = (1 << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) | | |
| 183 | + (0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1), | |
| 184 | + .CP0_SRSConf1_rw_bitmask = 0x3fffffff, | |
| 185 | + .CP0_SRSConf1 = (1 << CP0SRSC1_M) | (0x3fe << CP0SRSC1_SRS6) | | |
| 186 | + (0x3fe << CP0SRSC1_SRS5) | (0x3fe << CP0SRSC1_SRS4), | |
| 187 | + .CP0_SRSConf2_rw_bitmask = 0x3fffffff, | |
| 188 | + .CP0_SRSConf2 = (1 << CP0SRSC2_M) | (0x3fe << CP0SRSC2_SRS9) | | |
| 189 | + (0x3fe << CP0SRSC2_SRS8) | (0x3fe << CP0SRSC2_SRS7), | |
| 190 | + .CP0_SRSConf3_rw_bitmask = 0x3fffffff, | |
| 191 | + .CP0_SRSConf3 = (1 << CP0SRSC3_M) | (0x3fe << CP0SRSC3_SRS12) | | |
| 192 | + (0x3fe << CP0SRSC3_SRS11) | (0x3fe << CP0SRSC3_SRS10), | |
| 193 | + .CP0_SRSConf4_rw_bitmask = 0x3fffffff, | |
| 194 | + .CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) | | |
| 195 | + (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13), | |
| 196 | + }, | |
| 144 | 197 | #ifdef TARGET_MIPS64 |
| 145 | 198 | { |
| 146 | 199 | .name = "R4000", |
| ... | ... | @@ -153,7 +206,7 @@ static mips_def_t mips_defs[] = |
| 153 | 206 | .CP0_Config3 = MIPS_CONFIG3, |
| 154 | 207 | .SYNCI_Step = 16, |
| 155 | 208 | .CCRes = 2, |
| 156 | - .Status_rw_bitmask = 0x3678FFFF, | |
| 209 | + .CP0_Status_rw_bitmask = 0x3678FFFF, | |
| 157 | 210 | /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */ |
| 158 | 211 | .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), |
| 159 | 212 | .SEGBITS = 40, |
| ... | ... | @@ -170,7 +223,7 @@ static mips_def_t mips_defs[] = |
| 170 | 223 | .CP0_Config3 = MIPS_CONFIG3, |
| 171 | 224 | .SYNCI_Step = 32, |
| 172 | 225 | .CCRes = 2, |
| 173 | - .Status_rw_bitmask = 0x32F8FFFF, | |
| 226 | + .CP0_Status_rw_bitmask = 0x32F8FFFF, | |
| 174 | 227 | .SEGBITS = 42, |
| 175 | 228 | }, |
| 176 | 229 | { |
| ... | ... | @@ -185,7 +238,7 @@ static mips_def_t mips_defs[] = |
| 185 | 238 | .CP0_Config3 = MIPS_CONFIG3, |
| 186 | 239 | .SYNCI_Step = 32, |
| 187 | 240 | .CCRes = 2, |
| 188 | - .Status_rw_bitmask = 0x36F8FFFF, | |
| 241 | + .CP0_Status_rw_bitmask = 0x36F8FFFF, | |
| 189 | 242 | /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ |
| 190 | 243 | .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) | |
| 191 | 244 | (0x81 << FCR0_PRID) | (0x0 << FCR0_REV), |
| ... | ... | @@ -205,7 +258,7 @@ static mips_def_t mips_defs[] = |
| 205 | 258 | .CP0_Config3 = MIPS_CONFIG3, |
| 206 | 259 | .SYNCI_Step = 32, |
| 207 | 260 | .CCRes = 2, |
| 208 | - .Status_rw_bitmask = 0x36FBFFFF, | |
| 261 | + .CP0_Status_rw_bitmask = 0x36FBFFFF, | |
| 209 | 262 | /* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */ |
| 210 | 263 | .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) | |
| 211 | 264 | (1 << FCR0_D) | (1 << FCR0_S) | |
| ... | ... | @@ -245,27 +298,88 @@ void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) |
| 245 | 298 | #ifndef CONFIG_USER_ONLY |
| 246 | 299 | static void no_mmu_init (CPUMIPSState *env, mips_def_t *def) |
| 247 | 300 | { |
| 248 | - env->nb_tlb = 1; | |
| 249 | - env->map_address = &no_mmu_map_address; | |
| 301 | + env->tlb->nb_tlb = 1; | |
| 302 | + env->tlb->map_address = &no_mmu_map_address; | |
| 250 | 303 | } |
| 251 | 304 | |
| 252 | 305 | static void fixed_mmu_init (CPUMIPSState *env, mips_def_t *def) |
| 253 | 306 | { |
| 254 | - env->nb_tlb = 1; | |
| 255 | - env->map_address = &fixed_mmu_map_address; | |
| 307 | + env->tlb->nb_tlb = 1; | |
| 308 | + env->tlb->map_address = &fixed_mmu_map_address; | |
| 256 | 309 | } |
| 257 | 310 | |
| 258 | 311 | static void r4k_mmu_init (CPUMIPSState *env, mips_def_t *def) |
| 259 | 312 | { |
| 260 | - env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); | |
| 261 | - env->map_address = &r4k_map_address; | |
| 262 | - env->do_tlbwi = r4k_do_tlbwi; | |
| 263 | - env->do_tlbwr = r4k_do_tlbwr; | |
| 264 | - env->do_tlbp = r4k_do_tlbp; | |
| 265 | - env->do_tlbr = r4k_do_tlbr; | |
| 313 | + env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); | |
| 314 | + env->tlb->map_address = &r4k_map_address; | |
| 315 | + env->tlb->do_tlbwi = r4k_do_tlbwi; | |
| 316 | + env->tlb->do_tlbwr = r4k_do_tlbwr; | |
| 317 | + env->tlb->do_tlbp = r4k_do_tlbp; | |
| 318 | + env->tlb->do_tlbr = r4k_do_tlbr; | |
| 319 | +} | |
| 320 | + | |
| 321 | +static void mmu_init (CPUMIPSState *env, mips_def_t *def) | |
| 322 | +{ | |
| 323 | + env->tlb = qemu_mallocz(sizeof(CPUMIPSTLBContext)); | |
| 324 | + | |
| 325 | + /* There are more full-featured MMU variants in older MIPS CPUs, | |
| 326 | + R3000, R6000 and R8000 come to mind. If we ever support them, | |
| 327 | + this check will need to look up a different place than those | |
| 328 | + newfangled config registers. */ | |
| 329 | + switch ((env->CP0_Config0 >> CP0C0_MT) & 3) { | |
| 330 | + case 0: | |
| 331 | + no_mmu_init(env, def); | |
| 332 | + break; | |
| 333 | + case 1: | |
| 334 | + r4k_mmu_init(env, def); | |
| 335 | + break; | |
| 336 | + case 3: | |
| 337 | + fixed_mmu_init(env, def); | |
| 338 | + break; | |
| 339 | + default: | |
| 340 | + cpu_abort(env, "MMU type not supported\n"); | |
| 341 | + } | |
| 342 | + env->CP0_Random = env->tlb->nb_tlb - 1; | |
| 343 | + env->tlb->tlb_in_use = env->tlb->nb_tlb; | |
| 266 | 344 | } |
| 267 | 345 | #endif /* CONFIG_USER_ONLY */ |
| 268 | 346 | |
| 347 | +static void fpu_init (CPUMIPSState *env, mips_def_t *def) | |
| 348 | +{ | |
| 349 | + env->fpu = qemu_mallocz(sizeof(CPUMIPSFPUContext)); | |
| 350 | + | |
| 351 | + env->fpu->fcr0 = def->CP1_fcr0; | |
| 352 | +#ifdef CONFIG_USER_ONLY | |
| 353 | + if (env->CP0_Config1 & (1 << CP0C1_FP)) | |
| 354 | + env->hflags |= MIPS_HFLAG_FPU; | |
| 355 | + if (env->fpu->fcr0 & (1 << FCR0_F64)) | |
| 356 | + env->hflags |= MIPS_HFLAG_F64; | |
| 357 | +#endif | |
| 358 | +} | |
| 359 | + | |
| 360 | +static void mvp_init (CPUMIPSState *env, mips_def_t *def) | |
| 361 | +{ | |
| 362 | + env->mvp = qemu_mallocz(sizeof(CPUMIPSMVPContext)); | |
| 363 | + | |
| 364 | + /* MVPConf1 implemented, TLB sharable, no gating storage support, | |
| 365 | + programmable cache partitioning implemented, number of allocatable | |
| 366 | + and sharable TLB entries, MVP has allocatable TCs, 2 VPEs | |
| 367 | + implemented, 5 TCs implemented. */ | |
| 368 | + env->mvp->CP0_MVPConf0 = (1 << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) | | |
| 369 | + (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) | | |
| 370 | + (env->tlb->nb_tlb << CP0MVPC0_PTLBE) | | |
| 371 | +// TODO: actually do 2 VPEs. | |
| 372 | +// (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE) | | |
| 373 | +// (0x04 << CP0MVPC0_PTC); | |
| 374 | + (1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE) | | |
| 375 | + (0x04 << CP0MVPC0_PTC); | |
| 376 | + /* Allocatable CP1 have media extensions, allocatable CP1 have FP support, | |
| 377 | + no UDI implemented, no CP2 implemented, 1 CP1 implemented. */ | |
| 378 | + env->mvp->CP0_MVPConf1 = (1 << CP0MVPC1_CIM) | (1 << CP0MVPC1_CIF) | | |
| 379 | + (0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PCP2) | | |
| 380 | + (0x1 << CP0MVPC1_PCP1); | |
| 381 | +} | |
| 382 | + | |
| 269 | 383 | int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) |
| 270 | 384 | { |
| 271 | 385 | if (!def) |
| ... | ... | @@ -285,8 +399,9 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) |
| 285 | 399 | env->CP0_Config7 = def->CP0_Config7; |
| 286 | 400 | env->SYNCI_Step = def->SYNCI_Step; |
| 287 | 401 | env->CCRes = def->CCRes; |
| 288 | - env->Status_rw_bitmask = def->Status_rw_bitmask; | |
| 289 | - env->fcr0 = def->CP1_fcr0; | |
| 402 | + env->CP0_Status_rw_bitmask = def->CP0_Status_rw_bitmask; | |
| 403 | + env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask; | |
| 404 | + env->CP0_SRSCtl = def->CP0_SRSCtl; | |
| 290 | 405 | #ifdef TARGET_MIPS64 |
| 291 | 406 | if ((env->CP0_Config0 & (0x3 << CP0C0_AT))) |
| 292 | 407 | { |
| ... | ... | @@ -298,31 +413,21 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) |
| 298 | 413 | env->SEGMask = 0xFFFFFFFF; |
| 299 | 414 | } |
| 300 | 415 | #endif |
| 301 | -#ifdef CONFIG_USER_ONLY | |
| 302 | - if (env->CP0_Config1 & (1 << CP0C1_FP)) | |
| 303 | - env->hflags |= MIPS_HFLAG_FPU; | |
| 304 | - if (env->fcr0 & (1 << FCR0_F64)) | |
| 305 | - env->hflags |= MIPS_HFLAG_F64; | |
| 306 | -#else | |
| 307 | - /* There are more full-featured MMU variants in older MIPS CPUs, | |
| 308 | - R3000, R6000 and R8000 come to mind. If we ever support them, | |
| 309 | - this check will need to look up a different place than those | |
| 310 | - newfangled config registers. */ | |
| 311 | - switch ((env->CP0_Config0 >> CP0C0_MT) & 3) { | |
| 312 | - case 0: | |
| 313 | - no_mmu_init(env, def); | |
| 314 | - break; | |
| 315 | - case 1: | |
| 316 | - r4k_mmu_init(env, def); | |
| 317 | - break; | |
| 318 | - case 3: | |
| 319 | - fixed_mmu_init(env, def); | |
| 320 | - break; | |
| 321 | - default: | |
| 322 | - cpu_abort(env, "MMU type not supported\n"); | |
| 323 | - } | |
| 324 | - env->CP0_Random = env->nb_tlb - 1; | |
| 325 | - env->tlb_in_use = env->nb_tlb; | |
| 326 | -#endif /* CONFIG_USER_ONLY */ | |
| 416 | + env->CP0_SRSConf0_rw_bitmask = def->CP0_SRSConf0_rw_bitmask; | |
| 417 | + env->CP0_SRSConf0 = def->CP0_SRSConf0; | |
| 418 | + env->CP0_SRSConf1_rw_bitmask = def->CP0_SRSConf1_rw_bitmask; | |
| 419 | + env->CP0_SRSConf1 = def->CP0_SRSConf1; | |
| 420 | + env->CP0_SRSConf2_rw_bitmask = def->CP0_SRSConf2_rw_bitmask; | |
| 421 | + env->CP0_SRSConf2 = def->CP0_SRSConf2; | |
| 422 | + env->CP0_SRSConf3_rw_bitmask = def->CP0_SRSConf3_rw_bitmask; | |
| 423 | + env->CP0_SRSConf3 = def->CP0_SRSConf3; | |
| 424 | + env->CP0_SRSConf4_rw_bitmask = def->CP0_SRSConf4_rw_bitmask; | |
| 425 | + env->CP0_SRSConf4 = def->CP0_SRSConf4; | |
| 426 | + | |
| 427 | +#ifndef CONFIG_USER_ONLY | |
| 428 | + mmu_init(env, def); | |
| 429 | +#endif | |
| 430 | + fpu_init(env, def); | |
| 431 | + mvp_init(env, def); | |
| 327 | 432 | return 0; |
| 328 | 433 | } | ... | ... |
translate-all.c
| ... | ... | @@ -305,7 +305,7 @@ int cpu_restore_state(TranslationBlock *tb, |
| 305 | 305 | #elif defined(TARGET_M68K) |
| 306 | 306 | env->pc = gen_opc_pc[j]; |
| 307 | 307 | #elif defined(TARGET_MIPS) |
| 308 | - env->PC = gen_opc_pc[j]; | |
| 308 | + env->PC[env->current_tc] = gen_opc_pc[j]; | |
| 309 | 309 | env->hflags &= ~MIPS_HFLAG_BMASK; |
| 310 | 310 | env->hflags |= gen_opc_hflags[j]; |
| 311 | 311 | #elif defined(TARGET_ALPHA) | ... | ... |