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) | ... | ... |