Revision ead9360e
b/cpu-exec.c | ||
---|---|---|
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 */ |
b/gdbstub.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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); |
b/hw/mips_r4k.c | ||
---|---|---|
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); |
b/hw/mips_timer.c | ||
---|---|---|
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 |
|
b/linux-user/main.c | ||
---|---|---|
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 | 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 | 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 | 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 |
{ |
b/linux-user/signal.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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; |
b/linux-user/syscall.c | ||
---|---|---|
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 | 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]); |
b/monitor.c | ||
---|---|---|
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 |
} |
b/target-mips/cpu.h | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 */ |
b/target-mips/exec.h | ||
---|---|---|
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 | 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); \ |
b/target-mips/fop_template.c | ||
---|---|---|
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 | 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 | 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 | 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 |
|
b/target-mips/helper.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 |
|
b/target-mips/op.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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); |
Also available in: Unified diff