xref: /openbmc/qemu/target/mips/tcg/system/cp0_helper.c (revision fe9d41a734822506499c0c3ed7cc5d79e20c8723)
132cad1ffSPhilippe Mathieu-Daudé /*
232cad1ffSPhilippe Mathieu-Daudé  *  Helpers for emulation of CP0-related MIPS instructions.
332cad1ffSPhilippe Mathieu-Daudé  *
432cad1ffSPhilippe Mathieu-Daudé  *  Copyright (C) 2004-2005  Jocelyn Mayer
532cad1ffSPhilippe Mathieu-Daudé  *  Copyright (C) 2020  Wave Computing, Inc.
632cad1ffSPhilippe Mathieu-Daudé  *  Copyright (C) 2020  Aleksandar Markovic <amarkovic@wavecomp.com>
732cad1ffSPhilippe Mathieu-Daudé  *
832cad1ffSPhilippe Mathieu-Daudé  * This library is free software; you can redistribute it and/or
932cad1ffSPhilippe Mathieu-Daudé  * modify it under the terms of the GNU Lesser General Public
1032cad1ffSPhilippe Mathieu-Daudé  * License as published by the Free Software Foundation; either
1132cad1ffSPhilippe Mathieu-Daudé  * version 2.1 of the License, or (at your option) any later version.
1232cad1ffSPhilippe Mathieu-Daudé  *
1332cad1ffSPhilippe Mathieu-Daudé  * This library is distributed in the hope that it will be useful,
1432cad1ffSPhilippe Mathieu-Daudé  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1532cad1ffSPhilippe Mathieu-Daudé  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1632cad1ffSPhilippe Mathieu-Daudé  * Lesser General Public License for more details.
1732cad1ffSPhilippe Mathieu-Daudé  *
1832cad1ffSPhilippe Mathieu-Daudé  * You should have received a copy of the GNU Lesser General Public
1932cad1ffSPhilippe Mathieu-Daudé  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2032cad1ffSPhilippe Mathieu-Daudé  *
2132cad1ffSPhilippe Mathieu-Daudé  */
2232cad1ffSPhilippe Mathieu-Daudé 
2332cad1ffSPhilippe Mathieu-Daudé #include "qemu/osdep.h"
2432cad1ffSPhilippe Mathieu-Daudé #include "qemu/log.h"
2532cad1ffSPhilippe Mathieu-Daudé #include "qemu/main-loop.h"
2632cad1ffSPhilippe Mathieu-Daudé #include "cpu.h"
2732cad1ffSPhilippe Mathieu-Daudé #include "internal.h"
2832cad1ffSPhilippe Mathieu-Daudé #include "qemu/host-utils.h"
2932cad1ffSPhilippe Mathieu-Daudé #include "exec/helper-proto.h"
306ff5da16SPhilippe Mathieu-Daudé #include "exec/cputlb.h"
3132cad1ffSPhilippe Mathieu-Daudé 
3232cad1ffSPhilippe Mathieu-Daudé 
3332cad1ffSPhilippe Mathieu-Daudé /* SMP helpers.  */
mips_vpe_is_wfi(MIPSCPU * c)3432cad1ffSPhilippe Mathieu-Daudé static bool mips_vpe_is_wfi(MIPSCPU *c)
3532cad1ffSPhilippe Mathieu-Daudé {
3632cad1ffSPhilippe Mathieu-Daudé     CPUState *cpu = CPU(c);
3732cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *env = &c->env;
3832cad1ffSPhilippe Mathieu-Daudé 
3932cad1ffSPhilippe Mathieu-Daudé     /*
4032cad1ffSPhilippe Mathieu-Daudé      * If the VPE is halted but otherwise active, it means it's waiting for
4132cad1ffSPhilippe Mathieu-Daudé      * an interrupt.\
4232cad1ffSPhilippe Mathieu-Daudé      */
4332cad1ffSPhilippe Mathieu-Daudé     return cpu->halted && mips_vpe_active(env);
4432cad1ffSPhilippe Mathieu-Daudé }
4532cad1ffSPhilippe Mathieu-Daudé 
mips_vp_is_wfi(MIPSCPU * c)4632cad1ffSPhilippe Mathieu-Daudé static bool mips_vp_is_wfi(MIPSCPU *c)
4732cad1ffSPhilippe Mathieu-Daudé {
4832cad1ffSPhilippe Mathieu-Daudé     CPUState *cpu = CPU(c);
4932cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *env = &c->env;
5032cad1ffSPhilippe Mathieu-Daudé 
5132cad1ffSPhilippe Mathieu-Daudé     return cpu->halted && mips_vp_active(env);
5232cad1ffSPhilippe Mathieu-Daudé }
5332cad1ffSPhilippe Mathieu-Daudé 
mips_vpe_wake(MIPSCPU * c)5432cad1ffSPhilippe Mathieu-Daudé static inline void mips_vpe_wake(MIPSCPU *c)
5532cad1ffSPhilippe Mathieu-Daudé {
5632cad1ffSPhilippe Mathieu-Daudé     /*
5732cad1ffSPhilippe Mathieu-Daudé      * Don't set ->halted = 0 directly, let it be done via cpu_has_work
5832cad1ffSPhilippe Mathieu-Daudé      * because there might be other conditions that state that c should
5932cad1ffSPhilippe Mathieu-Daudé      * be sleeping.
6032cad1ffSPhilippe Mathieu-Daudé      */
6132cad1ffSPhilippe Mathieu-Daudé     bql_lock();
6232cad1ffSPhilippe Mathieu-Daudé     cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
6332cad1ffSPhilippe Mathieu-Daudé     bql_unlock();
6432cad1ffSPhilippe Mathieu-Daudé }
6532cad1ffSPhilippe Mathieu-Daudé 
mips_vpe_sleep(MIPSCPU * cpu)6632cad1ffSPhilippe Mathieu-Daudé static inline void mips_vpe_sleep(MIPSCPU *cpu)
6732cad1ffSPhilippe Mathieu-Daudé {
6832cad1ffSPhilippe Mathieu-Daudé     CPUState *cs = CPU(cpu);
6932cad1ffSPhilippe Mathieu-Daudé 
7032cad1ffSPhilippe Mathieu-Daudé     /*
7132cad1ffSPhilippe Mathieu-Daudé      * The VPE was shut off, really go to bed.
7232cad1ffSPhilippe Mathieu-Daudé      * Reset any old _WAKE requests.
7332cad1ffSPhilippe Mathieu-Daudé      */
7432cad1ffSPhilippe Mathieu-Daudé     cs->halted = 1;
7532cad1ffSPhilippe Mathieu-Daudé     cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
7632cad1ffSPhilippe Mathieu-Daudé }
7732cad1ffSPhilippe Mathieu-Daudé 
mips_tc_wake(MIPSCPU * cpu,int tc)7832cad1ffSPhilippe Mathieu-Daudé static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
7932cad1ffSPhilippe Mathieu-Daudé {
8032cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *c = &cpu->env;
8132cad1ffSPhilippe Mathieu-Daudé 
8232cad1ffSPhilippe Mathieu-Daudé     /* FIXME: TC reschedule.  */
8332cad1ffSPhilippe Mathieu-Daudé     if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
8432cad1ffSPhilippe Mathieu-Daudé         mips_vpe_wake(cpu);
8532cad1ffSPhilippe Mathieu-Daudé     }
8632cad1ffSPhilippe Mathieu-Daudé }
8732cad1ffSPhilippe Mathieu-Daudé 
mips_tc_sleep(MIPSCPU * cpu,int tc)8832cad1ffSPhilippe Mathieu-Daudé static inline void mips_tc_sleep(MIPSCPU *cpu, int tc)
8932cad1ffSPhilippe Mathieu-Daudé {
9032cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *c = &cpu->env;
9132cad1ffSPhilippe Mathieu-Daudé 
9232cad1ffSPhilippe Mathieu-Daudé     /* FIXME: TC reschedule.  */
9332cad1ffSPhilippe Mathieu-Daudé     if (!mips_vpe_active(c)) {
9432cad1ffSPhilippe Mathieu-Daudé         mips_vpe_sleep(cpu);
9532cad1ffSPhilippe Mathieu-Daudé     }
9632cad1ffSPhilippe Mathieu-Daudé }
9732cad1ffSPhilippe Mathieu-Daudé 
9832cad1ffSPhilippe Mathieu-Daudé /**
9932cad1ffSPhilippe Mathieu-Daudé  * mips_cpu_map_tc:
10032cad1ffSPhilippe Mathieu-Daudé  * @env: CPU from which mapping is performed.
10132cad1ffSPhilippe Mathieu-Daudé  * @tc: Should point to an int with the value of the global TC index.
10232cad1ffSPhilippe Mathieu-Daudé  *
10332cad1ffSPhilippe Mathieu-Daudé  * This function will transform @tc into a local index within the
10432cad1ffSPhilippe Mathieu-Daudé  * returned #CPUMIPSState.
10532cad1ffSPhilippe Mathieu-Daudé  */
10632cad1ffSPhilippe Mathieu-Daudé 
10732cad1ffSPhilippe Mathieu-Daudé /*
10832cad1ffSPhilippe Mathieu-Daudé  * FIXME: This code assumes that all VPEs have the same number of TCs,
10932cad1ffSPhilippe Mathieu-Daudé  *        which depends on runtime setup. Can probably be fixed by
11032cad1ffSPhilippe Mathieu-Daudé  *        walking the list of CPUMIPSStates.
11132cad1ffSPhilippe Mathieu-Daudé  */
mips_cpu_map_tc(CPUMIPSState * env,int * tc)11232cad1ffSPhilippe Mathieu-Daudé static CPUMIPSState *mips_cpu_map_tc(CPUMIPSState *env, int *tc)
11332cad1ffSPhilippe Mathieu-Daudé {
11432cad1ffSPhilippe Mathieu-Daudé     MIPSCPU *cpu;
11532cad1ffSPhilippe Mathieu-Daudé     CPUState *cs;
11632cad1ffSPhilippe Mathieu-Daudé     CPUState *other_cs;
11732cad1ffSPhilippe Mathieu-Daudé     int vpe_idx;
11832cad1ffSPhilippe Mathieu-Daudé     int tc_idx = *tc;
11932cad1ffSPhilippe Mathieu-Daudé 
12032cad1ffSPhilippe Mathieu-Daudé     if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) {
12132cad1ffSPhilippe Mathieu-Daudé         /* Not allowed to address other CPUs.  */
12232cad1ffSPhilippe Mathieu-Daudé         *tc = env->current_tc;
12332cad1ffSPhilippe Mathieu-Daudé         return env;
12432cad1ffSPhilippe Mathieu-Daudé     }
12532cad1ffSPhilippe Mathieu-Daudé 
12632cad1ffSPhilippe Mathieu-Daudé     cs = env_cpu(env);
12732cad1ffSPhilippe Mathieu-Daudé     vpe_idx = tc_idx / cs->nr_threads;
12832cad1ffSPhilippe Mathieu-Daudé     *tc = tc_idx % cs->nr_threads;
12932cad1ffSPhilippe Mathieu-Daudé     other_cs = qemu_get_cpu(vpe_idx);
13032cad1ffSPhilippe Mathieu-Daudé     if (other_cs == NULL) {
13132cad1ffSPhilippe Mathieu-Daudé         return env;
13232cad1ffSPhilippe Mathieu-Daudé     }
13332cad1ffSPhilippe Mathieu-Daudé     cpu = MIPS_CPU(other_cs);
13432cad1ffSPhilippe Mathieu-Daudé     return &cpu->env;
13532cad1ffSPhilippe Mathieu-Daudé }
13632cad1ffSPhilippe Mathieu-Daudé 
13732cad1ffSPhilippe Mathieu-Daudé /*
13832cad1ffSPhilippe Mathieu-Daudé  * The per VPE CP0_Status register shares some fields with the per TC
13932cad1ffSPhilippe Mathieu-Daudé  * CP0_TCStatus registers. These fields are wired to the same registers,
14032cad1ffSPhilippe Mathieu-Daudé  * so changes to either of them should be reflected on both registers.
14132cad1ffSPhilippe Mathieu-Daudé  *
14232cad1ffSPhilippe Mathieu-Daudé  * Also, EntryHi shares the bottom 8 bit ASID with TCStauts.
14332cad1ffSPhilippe Mathieu-Daudé  *
14432cad1ffSPhilippe Mathieu-Daudé  * These helper call synchronizes the regs for a given cpu.
14532cad1ffSPhilippe Mathieu-Daudé  */
14632cad1ffSPhilippe Mathieu-Daudé 
14732cad1ffSPhilippe Mathieu-Daudé /*
14832cad1ffSPhilippe Mathieu-Daudé  * Called for updates to CP0_Status.  Defined in "cpu.h" for gdbstub.c.
14932cad1ffSPhilippe Mathieu-Daudé  * static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu,
15032cad1ffSPhilippe Mathieu-Daudé  *                                   int tc);
15132cad1ffSPhilippe Mathieu-Daudé  */
15232cad1ffSPhilippe Mathieu-Daudé 
15332cad1ffSPhilippe Mathieu-Daudé /* Called for updates to CP0_TCStatus.  */
sync_c0_tcstatus(CPUMIPSState * cpu,int tc,target_ulong v)15432cad1ffSPhilippe Mathieu-Daudé static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc,
15532cad1ffSPhilippe Mathieu-Daudé                              target_ulong v)
15632cad1ffSPhilippe Mathieu-Daudé {
15732cad1ffSPhilippe Mathieu-Daudé     uint32_t status;
15832cad1ffSPhilippe Mathieu-Daudé     uint32_t tcu, tmx, tasid, tksu;
15932cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = ((1U << CP0St_CU3)
16032cad1ffSPhilippe Mathieu-Daudé                        | (1 << CP0St_CU2)
16132cad1ffSPhilippe Mathieu-Daudé                        | (1 << CP0St_CU1)
16232cad1ffSPhilippe Mathieu-Daudé                        | (1 << CP0St_CU0)
16332cad1ffSPhilippe Mathieu-Daudé                        | (1 << CP0St_MX)
16432cad1ffSPhilippe Mathieu-Daudé                        | (3 << CP0St_KSU));
16532cad1ffSPhilippe Mathieu-Daudé 
16632cad1ffSPhilippe Mathieu-Daudé     tcu = (v >> CP0TCSt_TCU0) & 0xf;
16732cad1ffSPhilippe Mathieu-Daudé     tmx = (v >> CP0TCSt_TMX) & 0x1;
16832cad1ffSPhilippe Mathieu-Daudé     tasid = v & cpu->CP0_EntryHi_ASID_mask;
16932cad1ffSPhilippe Mathieu-Daudé     tksu = (v >> CP0TCSt_TKSU) & 0x3;
17032cad1ffSPhilippe Mathieu-Daudé 
17132cad1ffSPhilippe Mathieu-Daudé     status = tcu << CP0St_CU0;
17232cad1ffSPhilippe Mathieu-Daudé     status |= tmx << CP0St_MX;
17332cad1ffSPhilippe Mathieu-Daudé     status |= tksu << CP0St_KSU;
17432cad1ffSPhilippe Mathieu-Daudé 
17532cad1ffSPhilippe Mathieu-Daudé     cpu->CP0_Status &= ~mask;
17632cad1ffSPhilippe Mathieu-Daudé     cpu->CP0_Status |= status;
17732cad1ffSPhilippe Mathieu-Daudé 
17832cad1ffSPhilippe Mathieu-Daudé     /* Sync the TASID with EntryHi.  */
17932cad1ffSPhilippe Mathieu-Daudé     cpu->CP0_EntryHi &= ~cpu->CP0_EntryHi_ASID_mask;
18032cad1ffSPhilippe Mathieu-Daudé     cpu->CP0_EntryHi |= tasid;
18132cad1ffSPhilippe Mathieu-Daudé 
18232cad1ffSPhilippe Mathieu-Daudé     compute_hflags(cpu);
18332cad1ffSPhilippe Mathieu-Daudé }
18432cad1ffSPhilippe Mathieu-Daudé 
18532cad1ffSPhilippe Mathieu-Daudé /* Called for updates to CP0_EntryHi.  */
sync_c0_entryhi(CPUMIPSState * cpu,int tc)18632cad1ffSPhilippe Mathieu-Daudé static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
18732cad1ffSPhilippe Mathieu-Daudé {
18832cad1ffSPhilippe Mathieu-Daudé     int32_t *tcst;
18932cad1ffSPhilippe Mathieu-Daudé     uint32_t asid, v = cpu->CP0_EntryHi;
19032cad1ffSPhilippe Mathieu-Daudé 
19132cad1ffSPhilippe Mathieu-Daudé     asid = v & cpu->CP0_EntryHi_ASID_mask;
19232cad1ffSPhilippe Mathieu-Daudé 
19332cad1ffSPhilippe Mathieu-Daudé     if (tc == cpu->current_tc) {
19432cad1ffSPhilippe Mathieu-Daudé         tcst = &cpu->active_tc.CP0_TCStatus;
19532cad1ffSPhilippe Mathieu-Daudé     } else {
19632cad1ffSPhilippe Mathieu-Daudé         tcst = &cpu->tcs[tc].CP0_TCStatus;
19732cad1ffSPhilippe Mathieu-Daudé     }
19832cad1ffSPhilippe Mathieu-Daudé 
19932cad1ffSPhilippe Mathieu-Daudé     *tcst &= ~cpu->CP0_EntryHi_ASID_mask;
20032cad1ffSPhilippe Mathieu-Daudé     *tcst |= asid;
20132cad1ffSPhilippe Mathieu-Daudé }
20232cad1ffSPhilippe Mathieu-Daudé 
20332cad1ffSPhilippe Mathieu-Daudé /* XXX: do not use a global */
cpu_mips_get_random(CPUMIPSState * env)20432cad1ffSPhilippe Mathieu-Daudé uint32_t cpu_mips_get_random(CPUMIPSState *env)
20532cad1ffSPhilippe Mathieu-Daudé {
20632cad1ffSPhilippe Mathieu-Daudé     static uint32_t seed = 1;
20732cad1ffSPhilippe Mathieu-Daudé     static uint32_t prev_idx;
20832cad1ffSPhilippe Mathieu-Daudé     uint32_t idx;
20932cad1ffSPhilippe Mathieu-Daudé     uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired;
21032cad1ffSPhilippe Mathieu-Daudé 
21132cad1ffSPhilippe Mathieu-Daudé     if (nb_rand_tlb == 1) {
21232cad1ffSPhilippe Mathieu-Daudé         return env->tlb->nb_tlb - 1;
21332cad1ffSPhilippe Mathieu-Daudé     }
21432cad1ffSPhilippe Mathieu-Daudé 
21532cad1ffSPhilippe Mathieu-Daudé     /* Don't return same value twice, so get another value */
21632cad1ffSPhilippe Mathieu-Daudé     do {
21732cad1ffSPhilippe Mathieu-Daudé         /*
21832cad1ffSPhilippe Mathieu-Daudé          * Use a simple algorithm of Linear Congruential Generator
21932cad1ffSPhilippe Mathieu-Daudé          * from ISO/IEC 9899 standard.
22032cad1ffSPhilippe Mathieu-Daudé          */
22132cad1ffSPhilippe Mathieu-Daudé         seed = 1103515245 * seed + 12345;
22232cad1ffSPhilippe Mathieu-Daudé         idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired;
22332cad1ffSPhilippe Mathieu-Daudé     } while (idx == prev_idx);
22432cad1ffSPhilippe Mathieu-Daudé     prev_idx = idx;
22532cad1ffSPhilippe Mathieu-Daudé     return idx;
22632cad1ffSPhilippe Mathieu-Daudé }
22732cad1ffSPhilippe Mathieu-Daudé 
22832cad1ffSPhilippe Mathieu-Daudé /* CP0 helpers */
helper_mfc0_mvpcontrol(CPUMIPSState * env)22932cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env)
23032cad1ffSPhilippe Mathieu-Daudé {
23132cad1ffSPhilippe Mathieu-Daudé     return env->mvp->CP0_MVPControl;
23232cad1ffSPhilippe Mathieu-Daudé }
23332cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_mvpconf0(CPUMIPSState * env)23432cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_mvpconf0(CPUMIPSState *env)
23532cad1ffSPhilippe Mathieu-Daudé {
23632cad1ffSPhilippe Mathieu-Daudé     return env->mvp->CP0_MVPConf0;
23732cad1ffSPhilippe Mathieu-Daudé }
23832cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_mvpconf1(CPUMIPSState * env)23932cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_mvpconf1(CPUMIPSState *env)
24032cad1ffSPhilippe Mathieu-Daudé {
24132cad1ffSPhilippe Mathieu-Daudé     return env->mvp->CP0_MVPConf1;
24232cad1ffSPhilippe Mathieu-Daudé }
24332cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_random(CPUMIPSState * env)24432cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_random(CPUMIPSState *env)
24532cad1ffSPhilippe Mathieu-Daudé {
24632cad1ffSPhilippe Mathieu-Daudé     return (int32_t)cpu_mips_get_random(env);
24732cad1ffSPhilippe Mathieu-Daudé }
24832cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_tcstatus(CPUMIPSState * env)24932cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcstatus(CPUMIPSState *env)
25032cad1ffSPhilippe Mathieu-Daudé {
25132cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCStatus;
25232cad1ffSPhilippe Mathieu-Daudé }
25332cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_tcstatus(CPUMIPSState * env)25432cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcstatus(CPUMIPSState *env)
25532cad1ffSPhilippe Mathieu-Daudé {
25632cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
25732cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
25832cad1ffSPhilippe Mathieu-Daudé 
25932cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
26032cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCStatus;
26132cad1ffSPhilippe Mathieu-Daudé     } else {
26232cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCStatus;
26332cad1ffSPhilippe Mathieu-Daudé     }
26432cad1ffSPhilippe Mathieu-Daudé }
26532cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_tcbind(CPUMIPSState * env)26632cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcbind(CPUMIPSState *env)
26732cad1ffSPhilippe Mathieu-Daudé {
26832cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCBind;
26932cad1ffSPhilippe Mathieu-Daudé }
27032cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_tcbind(CPUMIPSState * env)27132cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcbind(CPUMIPSState *env)
27232cad1ffSPhilippe Mathieu-Daudé {
27332cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
27432cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
27532cad1ffSPhilippe Mathieu-Daudé 
27632cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
27732cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCBind;
27832cad1ffSPhilippe Mathieu-Daudé     } else {
27932cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCBind;
28032cad1ffSPhilippe Mathieu-Daudé     }
28132cad1ffSPhilippe Mathieu-Daudé }
28232cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_tcrestart(CPUMIPSState * env)28332cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcrestart(CPUMIPSState *env)
28432cad1ffSPhilippe Mathieu-Daudé {
28532cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.PC;
28632cad1ffSPhilippe Mathieu-Daudé }
28732cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_tcrestart(CPUMIPSState * env)28832cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcrestart(CPUMIPSState *env)
28932cad1ffSPhilippe Mathieu-Daudé {
29032cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
29132cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
29232cad1ffSPhilippe Mathieu-Daudé 
29332cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
29432cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.PC;
29532cad1ffSPhilippe Mathieu-Daudé     } else {
29632cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].PC;
29732cad1ffSPhilippe Mathieu-Daudé     }
29832cad1ffSPhilippe Mathieu-Daudé }
29932cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_tchalt(CPUMIPSState * env)30032cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_tchalt(CPUMIPSState *env)
30132cad1ffSPhilippe Mathieu-Daudé {
30232cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCHalt;
30332cad1ffSPhilippe Mathieu-Daudé }
30432cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_tchalt(CPUMIPSState * env)30532cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_tchalt(CPUMIPSState *env)
30632cad1ffSPhilippe Mathieu-Daudé {
30732cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
30832cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
30932cad1ffSPhilippe Mathieu-Daudé 
31032cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
31132cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCHalt;
31232cad1ffSPhilippe Mathieu-Daudé     } else {
31332cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCHalt;
31432cad1ffSPhilippe Mathieu-Daudé     }
31532cad1ffSPhilippe Mathieu-Daudé }
31632cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_tccontext(CPUMIPSState * env)31732cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_tccontext(CPUMIPSState *env)
31832cad1ffSPhilippe Mathieu-Daudé {
31932cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCContext;
32032cad1ffSPhilippe Mathieu-Daudé }
32132cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_tccontext(CPUMIPSState * env)32232cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_tccontext(CPUMIPSState *env)
32332cad1ffSPhilippe Mathieu-Daudé {
32432cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
32532cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
32632cad1ffSPhilippe Mathieu-Daudé 
32732cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
32832cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCContext;
32932cad1ffSPhilippe Mathieu-Daudé     } else {
33032cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCContext;
33132cad1ffSPhilippe Mathieu-Daudé     }
33232cad1ffSPhilippe Mathieu-Daudé }
33332cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_tcschedule(CPUMIPSState * env)33432cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcschedule(CPUMIPSState *env)
33532cad1ffSPhilippe Mathieu-Daudé {
33632cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCSchedule;
33732cad1ffSPhilippe Mathieu-Daudé }
33832cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_tcschedule(CPUMIPSState * env)33932cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcschedule(CPUMIPSState *env)
34032cad1ffSPhilippe Mathieu-Daudé {
34132cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
34232cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
34332cad1ffSPhilippe Mathieu-Daudé 
34432cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
34532cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCSchedule;
34632cad1ffSPhilippe Mathieu-Daudé     } else {
34732cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCSchedule;
34832cad1ffSPhilippe Mathieu-Daudé     }
34932cad1ffSPhilippe Mathieu-Daudé }
35032cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_tcschefback(CPUMIPSState * env)35132cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcschefback(CPUMIPSState *env)
35232cad1ffSPhilippe Mathieu-Daudé {
35332cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCScheFBack;
35432cad1ffSPhilippe Mathieu-Daudé }
35532cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_tcschefback(CPUMIPSState * env)35632cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcschefback(CPUMIPSState *env)
35732cad1ffSPhilippe Mathieu-Daudé {
35832cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
35932cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
36032cad1ffSPhilippe Mathieu-Daudé 
36132cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
36232cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCScheFBack;
36332cad1ffSPhilippe Mathieu-Daudé     } else {
36432cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCScheFBack;
36532cad1ffSPhilippe Mathieu-Daudé     }
36632cad1ffSPhilippe Mathieu-Daudé }
36732cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_count(CPUMIPSState * env)36832cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_count(CPUMIPSState *env)
36932cad1ffSPhilippe Mathieu-Daudé {
37032cad1ffSPhilippe Mathieu-Daudé     return (int32_t)cpu_mips_get_count(env);
37132cad1ffSPhilippe Mathieu-Daudé }
37232cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_entryhi(CPUMIPSState * env)37332cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_entryhi(CPUMIPSState *env)
37432cad1ffSPhilippe Mathieu-Daudé {
37532cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
37632cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
37732cad1ffSPhilippe Mathieu-Daudé 
37832cad1ffSPhilippe Mathieu-Daudé     return other->CP0_EntryHi;
37932cad1ffSPhilippe Mathieu-Daudé }
38032cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_cause(CPUMIPSState * env)38132cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_cause(CPUMIPSState *env)
38232cad1ffSPhilippe Mathieu-Daudé {
38332cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
38432cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
38532cad1ffSPhilippe Mathieu-Daudé 
38632cad1ffSPhilippe Mathieu-Daudé     return other->CP0_Cause;
38732cad1ffSPhilippe Mathieu-Daudé }
38832cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_status(CPUMIPSState * env)38932cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_status(CPUMIPSState *env)
39032cad1ffSPhilippe Mathieu-Daudé {
39132cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
39232cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
39332cad1ffSPhilippe Mathieu-Daudé 
39432cad1ffSPhilippe Mathieu-Daudé     return other->CP0_Status;
39532cad1ffSPhilippe Mathieu-Daudé }
39632cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_lladdr(CPUMIPSState * env)39732cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_lladdr(CPUMIPSState *env)
39832cad1ffSPhilippe Mathieu-Daudé {
39932cad1ffSPhilippe Mathieu-Daudé     return (int32_t)(env->CP0_LLAddr >> env->CP0_LLAddr_shift);
40032cad1ffSPhilippe Mathieu-Daudé }
40132cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_maar(CPUMIPSState * env)40232cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_maar(CPUMIPSState *env)
40332cad1ffSPhilippe Mathieu-Daudé {
40432cad1ffSPhilippe Mathieu-Daudé     return (int32_t) env->CP0_MAAR[env->CP0_MAARI];
40532cad1ffSPhilippe Mathieu-Daudé }
40632cad1ffSPhilippe Mathieu-Daudé 
helper_mfhc0_maar(CPUMIPSState * env)40732cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfhc0_maar(CPUMIPSState *env)
40832cad1ffSPhilippe Mathieu-Daudé {
40932cad1ffSPhilippe Mathieu-Daudé     return env->CP0_MAAR[env->CP0_MAARI] >> 32;
41032cad1ffSPhilippe Mathieu-Daudé }
41132cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_watchlo(CPUMIPSState * env,uint32_t sel)41232cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel)
41332cad1ffSPhilippe Mathieu-Daudé {
41432cad1ffSPhilippe Mathieu-Daudé     return (int32_t)env->CP0_WatchLo[sel];
41532cad1ffSPhilippe Mathieu-Daudé }
41632cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_watchhi(CPUMIPSState * env,uint32_t sel)41732cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel)
41832cad1ffSPhilippe Mathieu-Daudé {
41932cad1ffSPhilippe Mathieu-Daudé     return (int32_t) env->CP0_WatchHi[sel];
42032cad1ffSPhilippe Mathieu-Daudé }
42132cad1ffSPhilippe Mathieu-Daudé 
helper_mfhc0_watchhi(CPUMIPSState * env,uint32_t sel)42232cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfhc0_watchhi(CPUMIPSState *env, uint32_t sel)
42332cad1ffSPhilippe Mathieu-Daudé {
42432cad1ffSPhilippe Mathieu-Daudé     return env->CP0_WatchHi[sel] >> 32;
42532cad1ffSPhilippe Mathieu-Daudé }
42632cad1ffSPhilippe Mathieu-Daudé 
helper_mfc0_debug(CPUMIPSState * env)42732cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfc0_debug(CPUMIPSState *env)
42832cad1ffSPhilippe Mathieu-Daudé {
42932cad1ffSPhilippe Mathieu-Daudé     target_ulong t0 = env->CP0_Debug;
43032cad1ffSPhilippe Mathieu-Daudé     if (env->hflags & MIPS_HFLAG_DM) {
43132cad1ffSPhilippe Mathieu-Daudé         t0 |= 1 << CP0DB_DM;
43232cad1ffSPhilippe Mathieu-Daudé     }
43332cad1ffSPhilippe Mathieu-Daudé 
43432cad1ffSPhilippe Mathieu-Daudé     return t0;
43532cad1ffSPhilippe Mathieu-Daudé }
43632cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_debug(CPUMIPSState * env)43732cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_debug(CPUMIPSState *env)
43832cad1ffSPhilippe Mathieu-Daudé {
43932cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
44032cad1ffSPhilippe Mathieu-Daudé     int32_t tcstatus;
44132cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
44232cad1ffSPhilippe Mathieu-Daudé 
44332cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
44432cad1ffSPhilippe Mathieu-Daudé         tcstatus = other->active_tc.CP0_Debug_tcstatus;
44532cad1ffSPhilippe Mathieu-Daudé     } else {
44632cad1ffSPhilippe Mathieu-Daudé         tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus;
44732cad1ffSPhilippe Mathieu-Daudé     }
44832cad1ffSPhilippe Mathieu-Daudé 
44932cad1ffSPhilippe Mathieu-Daudé     /* XXX: Might be wrong, check with EJTAG spec. */
45032cad1ffSPhilippe Mathieu-Daudé     return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
45132cad1ffSPhilippe Mathieu-Daudé             (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
45232cad1ffSPhilippe Mathieu-Daudé }
45332cad1ffSPhilippe Mathieu-Daudé 
45432cad1ffSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
helper_dmfc0_tcrestart(CPUMIPSState * env)45532cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tcrestart(CPUMIPSState *env)
45632cad1ffSPhilippe Mathieu-Daudé {
45732cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.PC;
45832cad1ffSPhilippe Mathieu-Daudé }
45932cad1ffSPhilippe Mathieu-Daudé 
helper_dmfc0_tchalt(CPUMIPSState * env)46032cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tchalt(CPUMIPSState *env)
46132cad1ffSPhilippe Mathieu-Daudé {
46232cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCHalt;
46332cad1ffSPhilippe Mathieu-Daudé }
46432cad1ffSPhilippe Mathieu-Daudé 
helper_dmfc0_tccontext(CPUMIPSState * env)46532cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tccontext(CPUMIPSState *env)
46632cad1ffSPhilippe Mathieu-Daudé {
46732cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCContext;
46832cad1ffSPhilippe Mathieu-Daudé }
46932cad1ffSPhilippe Mathieu-Daudé 
helper_dmfc0_tcschedule(CPUMIPSState * env)47032cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tcschedule(CPUMIPSState *env)
47132cad1ffSPhilippe Mathieu-Daudé {
47232cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCSchedule;
47332cad1ffSPhilippe Mathieu-Daudé }
47432cad1ffSPhilippe Mathieu-Daudé 
helper_dmfc0_tcschefback(CPUMIPSState * env)47532cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tcschefback(CPUMIPSState *env)
47632cad1ffSPhilippe Mathieu-Daudé {
47732cad1ffSPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCScheFBack;
47832cad1ffSPhilippe Mathieu-Daudé }
47932cad1ffSPhilippe Mathieu-Daudé 
helper_dmfc0_lladdr(CPUMIPSState * env)48032cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_lladdr(CPUMIPSState *env)
48132cad1ffSPhilippe Mathieu-Daudé {
48232cad1ffSPhilippe Mathieu-Daudé     return env->CP0_LLAddr >> env->CP0_LLAddr_shift;
48332cad1ffSPhilippe Mathieu-Daudé }
48432cad1ffSPhilippe Mathieu-Daudé 
helper_dmfc0_maar(CPUMIPSState * env)48532cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_maar(CPUMIPSState *env)
48632cad1ffSPhilippe Mathieu-Daudé {
48732cad1ffSPhilippe Mathieu-Daudé     return env->CP0_MAAR[env->CP0_MAARI];
48832cad1ffSPhilippe Mathieu-Daudé }
48932cad1ffSPhilippe Mathieu-Daudé 
helper_dmfc0_watchlo(CPUMIPSState * env,uint32_t sel)49032cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
49132cad1ffSPhilippe Mathieu-Daudé {
49232cad1ffSPhilippe Mathieu-Daudé     return env->CP0_WatchLo[sel];
49332cad1ffSPhilippe Mathieu-Daudé }
49432cad1ffSPhilippe Mathieu-Daudé 
helper_dmfc0_watchhi(CPUMIPSState * env,uint32_t sel)49532cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmfc0_watchhi(CPUMIPSState *env, uint32_t sel)
49632cad1ffSPhilippe Mathieu-Daudé {
49732cad1ffSPhilippe Mathieu-Daudé     return env->CP0_WatchHi[sel];
49832cad1ffSPhilippe Mathieu-Daudé }
49932cad1ffSPhilippe Mathieu-Daudé 
50032cad1ffSPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */
50132cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_index(CPUMIPSState * env,target_ulong arg1)50232cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
50332cad1ffSPhilippe Mathieu-Daudé {
50432cad1ffSPhilippe Mathieu-Daudé     uint32_t index_p = env->CP0_Index & 0x80000000;
50532cad1ffSPhilippe Mathieu-Daudé     uint32_t tlb_index = arg1 & 0x7fffffff;
50632cad1ffSPhilippe Mathieu-Daudé     if (tlb_index < env->tlb->nb_tlb) {
50732cad1ffSPhilippe Mathieu-Daudé         if (env->insn_flags & ISA_MIPS_R6) {
50832cad1ffSPhilippe Mathieu-Daudé             index_p |= arg1 & 0x80000000;
50932cad1ffSPhilippe Mathieu-Daudé         }
51032cad1ffSPhilippe Mathieu-Daudé         env->CP0_Index = index_p | tlb_index;
51132cad1ffSPhilippe Mathieu-Daudé     }
51232cad1ffSPhilippe Mathieu-Daudé }
51332cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_mvpcontrol(CPUMIPSState * env,target_ulong arg1)51432cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
51532cad1ffSPhilippe Mathieu-Daudé {
51632cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = 0;
51732cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
51832cad1ffSPhilippe Mathieu-Daudé 
51932cad1ffSPhilippe Mathieu-Daudé     if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
52032cad1ffSPhilippe Mathieu-Daudé         mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
52132cad1ffSPhilippe Mathieu-Daudé                 (1 << CP0MVPCo_EVP);
52232cad1ffSPhilippe Mathieu-Daudé     }
52332cad1ffSPhilippe Mathieu-Daudé     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) {
52432cad1ffSPhilippe Mathieu-Daudé         mask |= (1 << CP0MVPCo_STLB);
52532cad1ffSPhilippe Mathieu-Daudé     }
52632cad1ffSPhilippe Mathieu-Daudé     newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
52732cad1ffSPhilippe Mathieu-Daudé 
52832cad1ffSPhilippe Mathieu-Daudé     /* TODO: Enable/disable shared TLB, enable/disable VPEs. */
52932cad1ffSPhilippe Mathieu-Daudé 
53032cad1ffSPhilippe Mathieu-Daudé     env->mvp->CP0_MVPControl = newval;
53132cad1ffSPhilippe Mathieu-Daudé }
53232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_vpecontrol(CPUMIPSState * env,target_ulong arg1)53332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
53432cad1ffSPhilippe Mathieu-Daudé {
53532cad1ffSPhilippe Mathieu-Daudé     uint32_t mask;
53632cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
53732cad1ffSPhilippe Mathieu-Daudé 
53832cad1ffSPhilippe Mathieu-Daudé     mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
53932cad1ffSPhilippe Mathieu-Daudé            (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
54032cad1ffSPhilippe Mathieu-Daudé     newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
54132cad1ffSPhilippe Mathieu-Daudé 
54232cad1ffSPhilippe Mathieu-Daudé     /*
54332cad1ffSPhilippe Mathieu-Daudé      * Yield scheduler intercept not implemented.
54432cad1ffSPhilippe Mathieu-Daudé      * Gating storage scheduler intercept not implemented.
54532cad1ffSPhilippe Mathieu-Daudé      */
54632cad1ffSPhilippe Mathieu-Daudé 
54732cad1ffSPhilippe Mathieu-Daudé     /* TODO: Enable/disable TCs. */
54832cad1ffSPhilippe Mathieu-Daudé 
54932cad1ffSPhilippe Mathieu-Daudé     env->CP0_VPEControl = newval;
55032cad1ffSPhilippe Mathieu-Daudé }
55132cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_vpecontrol(CPUMIPSState * env,target_ulong arg1)55232cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
55332cad1ffSPhilippe Mathieu-Daudé {
55432cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
55532cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
55632cad1ffSPhilippe Mathieu-Daudé     uint32_t mask;
55732cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
55832cad1ffSPhilippe Mathieu-Daudé 
55932cad1ffSPhilippe Mathieu-Daudé     mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
56032cad1ffSPhilippe Mathieu-Daudé            (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
56132cad1ffSPhilippe Mathieu-Daudé     newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask);
56232cad1ffSPhilippe Mathieu-Daudé 
56332cad1ffSPhilippe Mathieu-Daudé     /* TODO: Enable/disable TCs.  */
56432cad1ffSPhilippe Mathieu-Daudé 
56532cad1ffSPhilippe Mathieu-Daudé     other->CP0_VPEControl = newval;
56632cad1ffSPhilippe Mathieu-Daudé }
56732cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_vpecontrol(CPUMIPSState * env)56832cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_vpecontrol(CPUMIPSState *env)
56932cad1ffSPhilippe Mathieu-Daudé {
57032cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
57132cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
57232cad1ffSPhilippe Mathieu-Daudé     /* FIXME: Mask away return zero on read bits.  */
57332cad1ffSPhilippe Mathieu-Daudé     return other->CP0_VPEControl;
57432cad1ffSPhilippe Mathieu-Daudé }
57532cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_vpeconf0(CPUMIPSState * env)57632cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_vpeconf0(CPUMIPSState *env)
57732cad1ffSPhilippe Mathieu-Daudé {
57832cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
57932cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
58032cad1ffSPhilippe Mathieu-Daudé 
58132cad1ffSPhilippe Mathieu-Daudé     return other->CP0_VPEConf0;
58232cad1ffSPhilippe Mathieu-Daudé }
58332cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_vpeconf0(CPUMIPSState * env,target_ulong arg1)58432cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
58532cad1ffSPhilippe Mathieu-Daudé {
58632cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = 0;
58732cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
58832cad1ffSPhilippe Mathieu-Daudé 
58932cad1ffSPhilippe Mathieu-Daudé     if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
59032cad1ffSPhilippe Mathieu-Daudé         if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA)) {
59132cad1ffSPhilippe Mathieu-Daudé             mask |= (0xff << CP0VPEC0_XTC);
59232cad1ffSPhilippe Mathieu-Daudé         }
59332cad1ffSPhilippe Mathieu-Daudé         mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
59432cad1ffSPhilippe Mathieu-Daudé     }
59532cad1ffSPhilippe Mathieu-Daudé     newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
59632cad1ffSPhilippe Mathieu-Daudé 
59732cad1ffSPhilippe Mathieu-Daudé     /* TODO: TC exclusive handling due to ERL/EXL. */
59832cad1ffSPhilippe Mathieu-Daudé 
59932cad1ffSPhilippe Mathieu-Daudé     env->CP0_VPEConf0 = newval;
60032cad1ffSPhilippe Mathieu-Daudé }
60132cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_vpeconf0(CPUMIPSState * env,target_ulong arg1)60232cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
60332cad1ffSPhilippe Mathieu-Daudé {
60432cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
60532cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
60632cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = 0;
60732cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
60832cad1ffSPhilippe Mathieu-Daudé 
60932cad1ffSPhilippe Mathieu-Daudé     mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
61032cad1ffSPhilippe Mathieu-Daudé     newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask);
61132cad1ffSPhilippe Mathieu-Daudé 
61232cad1ffSPhilippe Mathieu-Daudé     /* TODO: TC exclusive handling due to ERL/EXL.  */
61332cad1ffSPhilippe Mathieu-Daudé     other->CP0_VPEConf0 = newval;
61432cad1ffSPhilippe Mathieu-Daudé }
61532cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_vpeconf1(CPUMIPSState * env,target_ulong arg1)61632cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_vpeconf1(CPUMIPSState *env, target_ulong arg1)
61732cad1ffSPhilippe Mathieu-Daudé {
61832cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = 0;
61932cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
62032cad1ffSPhilippe Mathieu-Daudé 
62132cad1ffSPhilippe Mathieu-Daudé     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
62232cad1ffSPhilippe Mathieu-Daudé         mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
62332cad1ffSPhilippe Mathieu-Daudé                 (0xff << CP0VPEC1_NCP1);
62432cad1ffSPhilippe Mathieu-Daudé     newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
62532cad1ffSPhilippe Mathieu-Daudé 
62632cad1ffSPhilippe Mathieu-Daudé     /* UDI not implemented. */
62732cad1ffSPhilippe Mathieu-Daudé     /* CP2 not implemented. */
62832cad1ffSPhilippe Mathieu-Daudé 
62932cad1ffSPhilippe Mathieu-Daudé     /* TODO: Handle FPU (CP1) binding. */
63032cad1ffSPhilippe Mathieu-Daudé 
63132cad1ffSPhilippe Mathieu-Daudé     env->CP0_VPEConf1 = newval;
63232cad1ffSPhilippe Mathieu-Daudé }
63332cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_yqmask(CPUMIPSState * env,target_ulong arg1)63432cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_yqmask(CPUMIPSState *env, target_ulong arg1)
63532cad1ffSPhilippe Mathieu-Daudé {
63632cad1ffSPhilippe Mathieu-Daudé     /* Yield qualifier inputs not implemented. */
63732cad1ffSPhilippe Mathieu-Daudé     env->CP0_YQMask = 0x00000000;
63832cad1ffSPhilippe Mathieu-Daudé }
63932cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_vpeopt(CPUMIPSState * env,target_ulong arg1)64032cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
64132cad1ffSPhilippe Mathieu-Daudé {
64232cad1ffSPhilippe Mathieu-Daudé     env->CP0_VPEOpt = arg1 & 0x0000ffff;
64332cad1ffSPhilippe Mathieu-Daudé }
64432cad1ffSPhilippe Mathieu-Daudé 
64532cad1ffSPhilippe Mathieu-Daudé #define MTC0_ENTRYLO_MASK(env) ((env->PAMask >> 6) & 0x3FFFFFFF)
64632cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_entrylo0(CPUMIPSState * env,target_ulong arg1)64732cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
64832cad1ffSPhilippe Mathieu-Daudé {
64932cad1ffSPhilippe Mathieu-Daudé     /* 1k pages not implemented */
65032cad1ffSPhilippe Mathieu-Daudé     target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
65132cad1ffSPhilippe Mathieu-Daudé     env->CP0_EntryLo0 = (arg1 & MTC0_ENTRYLO_MASK(env))
65232cad1ffSPhilippe Mathieu-Daudé                         | (rxi << (CP0EnLo_XI - 30));
65332cad1ffSPhilippe Mathieu-Daudé }
65432cad1ffSPhilippe Mathieu-Daudé 
65532cad1ffSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
65632cad1ffSPhilippe Mathieu-Daudé #define DMTC0_ENTRYLO_MASK(env) (env->PAMask >> 6)
65732cad1ffSPhilippe Mathieu-Daudé 
helper_dmtc0_entrylo0(CPUMIPSState * env,uint64_t arg1)65832cad1ffSPhilippe Mathieu-Daudé void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
65932cad1ffSPhilippe Mathieu-Daudé {
66032cad1ffSPhilippe Mathieu-Daudé     uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
66132cad1ffSPhilippe Mathieu-Daudé     env->CP0_EntryLo0 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
66232cad1ffSPhilippe Mathieu-Daudé }
66332cad1ffSPhilippe Mathieu-Daudé #endif
66432cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_tcstatus(CPUMIPSState * env,target_ulong arg1)66532cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
66632cad1ffSPhilippe Mathieu-Daudé {
66732cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = env->CP0_TCStatus_rw_bitmask;
66832cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
66932cad1ffSPhilippe Mathieu-Daudé 
67032cad1ffSPhilippe Mathieu-Daudé     newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
67132cad1ffSPhilippe Mathieu-Daudé 
67232cad1ffSPhilippe Mathieu-Daudé     env->active_tc.CP0_TCStatus = newval;
67332cad1ffSPhilippe Mathieu-Daudé     sync_c0_tcstatus(env, env->current_tc, newval);
67432cad1ffSPhilippe Mathieu-Daudé }
67532cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_tcstatus(CPUMIPSState * env,target_ulong arg1)67632cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
67732cad1ffSPhilippe Mathieu-Daudé {
67832cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
67932cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
68032cad1ffSPhilippe Mathieu-Daudé 
68132cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
68232cad1ffSPhilippe Mathieu-Daudé         other->active_tc.CP0_TCStatus = arg1;
68332cad1ffSPhilippe Mathieu-Daudé     } else {
68432cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCStatus = arg1;
68532cad1ffSPhilippe Mathieu-Daudé     }
68632cad1ffSPhilippe Mathieu-Daudé     sync_c0_tcstatus(other, other_tc, arg1);
68732cad1ffSPhilippe Mathieu-Daudé }
68832cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_tcbind(CPUMIPSState * env,target_ulong arg1)68932cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_tcbind(CPUMIPSState *env, target_ulong arg1)
69032cad1ffSPhilippe Mathieu-Daudé {
69132cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = (1 << CP0TCBd_TBE);
69232cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
69332cad1ffSPhilippe Mathieu-Daudé 
69432cad1ffSPhilippe Mathieu-Daudé     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) {
69532cad1ffSPhilippe Mathieu-Daudé         mask |= (1 << CP0TCBd_CurVPE);
69632cad1ffSPhilippe Mathieu-Daudé     }
69732cad1ffSPhilippe Mathieu-Daudé     newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
69832cad1ffSPhilippe Mathieu-Daudé     env->active_tc.CP0_TCBind = newval;
69932cad1ffSPhilippe Mathieu-Daudé }
70032cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_tcbind(CPUMIPSState * env,target_ulong arg1)70132cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_tcbind(CPUMIPSState *env, target_ulong arg1)
70232cad1ffSPhilippe Mathieu-Daudé {
70332cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
70432cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = (1 << CP0TCBd_TBE);
70532cad1ffSPhilippe Mathieu-Daudé     uint32_t newval;
70632cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
70732cad1ffSPhilippe Mathieu-Daudé 
70832cad1ffSPhilippe Mathieu-Daudé     if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) {
70932cad1ffSPhilippe Mathieu-Daudé         mask |= (1 << CP0TCBd_CurVPE);
71032cad1ffSPhilippe Mathieu-Daudé     }
71132cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
71232cad1ffSPhilippe Mathieu-Daudé         newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
71332cad1ffSPhilippe Mathieu-Daudé         other->active_tc.CP0_TCBind = newval;
71432cad1ffSPhilippe Mathieu-Daudé     } else {
71532cad1ffSPhilippe Mathieu-Daudé         newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
71632cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCBind = newval;
71732cad1ffSPhilippe Mathieu-Daudé     }
71832cad1ffSPhilippe Mathieu-Daudé }
71932cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_tcrestart(CPUMIPSState * env,target_ulong arg1)72032cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
72132cad1ffSPhilippe Mathieu-Daudé {
72232cad1ffSPhilippe Mathieu-Daudé     env->active_tc.PC = arg1;
72332cad1ffSPhilippe Mathieu-Daudé     env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
72432cad1ffSPhilippe Mathieu-Daudé     env->CP0_LLAddr = 0;
72532cad1ffSPhilippe Mathieu-Daudé     env->lladdr = 0;
72632cad1ffSPhilippe Mathieu-Daudé     /* MIPS16 not implemented. */
72732cad1ffSPhilippe Mathieu-Daudé }
72832cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_tcrestart(CPUMIPSState * env,target_ulong arg1)72932cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
73032cad1ffSPhilippe Mathieu-Daudé {
73132cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
73232cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
73332cad1ffSPhilippe Mathieu-Daudé 
73432cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
73532cad1ffSPhilippe Mathieu-Daudé         other->active_tc.PC = arg1;
73632cad1ffSPhilippe Mathieu-Daudé         other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
73732cad1ffSPhilippe Mathieu-Daudé         other->CP0_LLAddr = 0;
73832cad1ffSPhilippe Mathieu-Daudé         other->lladdr = 0;
73932cad1ffSPhilippe Mathieu-Daudé         /* MIPS16 not implemented. */
74032cad1ffSPhilippe Mathieu-Daudé     } else {
74132cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].PC = arg1;
74232cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
74332cad1ffSPhilippe Mathieu-Daudé         other->CP0_LLAddr = 0;
74432cad1ffSPhilippe Mathieu-Daudé         other->lladdr = 0;
74532cad1ffSPhilippe Mathieu-Daudé         /* MIPS16 not implemented. */
74632cad1ffSPhilippe Mathieu-Daudé     }
74732cad1ffSPhilippe Mathieu-Daudé }
74832cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_tchalt(CPUMIPSState * env,target_ulong arg1)74932cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_tchalt(CPUMIPSState *env, target_ulong arg1)
75032cad1ffSPhilippe Mathieu-Daudé {
75132cad1ffSPhilippe Mathieu-Daudé     MIPSCPU *cpu = env_archcpu(env);
75232cad1ffSPhilippe Mathieu-Daudé 
75332cad1ffSPhilippe Mathieu-Daudé     env->active_tc.CP0_TCHalt = arg1 & 0x1;
75432cad1ffSPhilippe Mathieu-Daudé 
75532cad1ffSPhilippe Mathieu-Daudé     /* TODO: Halt TC / Restart (if allocated+active) TC. */
75632cad1ffSPhilippe Mathieu-Daudé     if (env->active_tc.CP0_TCHalt & 1) {
75732cad1ffSPhilippe Mathieu-Daudé         mips_tc_sleep(cpu, env->current_tc);
75832cad1ffSPhilippe Mathieu-Daudé     } else {
75932cad1ffSPhilippe Mathieu-Daudé         mips_tc_wake(cpu, env->current_tc);
76032cad1ffSPhilippe Mathieu-Daudé     }
76132cad1ffSPhilippe Mathieu-Daudé }
76232cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_tchalt(CPUMIPSState * env,target_ulong arg1)76332cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1)
76432cad1ffSPhilippe Mathieu-Daudé {
76532cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
76632cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
76732cad1ffSPhilippe Mathieu-Daudé     MIPSCPU *other_cpu = env_archcpu(other);
76832cad1ffSPhilippe Mathieu-Daudé 
76932cad1ffSPhilippe Mathieu-Daudé     /* TODO: Halt TC / Restart (if allocated+active) TC. */
77032cad1ffSPhilippe Mathieu-Daudé 
77132cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
77232cad1ffSPhilippe Mathieu-Daudé         other->active_tc.CP0_TCHalt = arg1;
77332cad1ffSPhilippe Mathieu-Daudé     } else {
77432cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCHalt = arg1;
77532cad1ffSPhilippe Mathieu-Daudé     }
77632cad1ffSPhilippe Mathieu-Daudé 
77732cad1ffSPhilippe Mathieu-Daudé     if (arg1 & 1) {
77832cad1ffSPhilippe Mathieu-Daudé         mips_tc_sleep(other_cpu, other_tc);
77932cad1ffSPhilippe Mathieu-Daudé     } else {
78032cad1ffSPhilippe Mathieu-Daudé         mips_tc_wake(other_cpu, other_tc);
78132cad1ffSPhilippe Mathieu-Daudé     }
78232cad1ffSPhilippe Mathieu-Daudé }
78332cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_tccontext(CPUMIPSState * env,target_ulong arg1)78432cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_tccontext(CPUMIPSState *env, target_ulong arg1)
78532cad1ffSPhilippe Mathieu-Daudé {
78632cad1ffSPhilippe Mathieu-Daudé     env->active_tc.CP0_TCContext = arg1;
78732cad1ffSPhilippe Mathieu-Daudé }
78832cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_tccontext(CPUMIPSState * env,target_ulong arg1)78932cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_tccontext(CPUMIPSState *env, target_ulong arg1)
79032cad1ffSPhilippe Mathieu-Daudé {
79132cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
79232cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
79332cad1ffSPhilippe Mathieu-Daudé 
79432cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
79532cad1ffSPhilippe Mathieu-Daudé         other->active_tc.CP0_TCContext = arg1;
79632cad1ffSPhilippe Mathieu-Daudé     } else {
79732cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCContext = arg1;
79832cad1ffSPhilippe Mathieu-Daudé     }
79932cad1ffSPhilippe Mathieu-Daudé }
80032cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_tcschedule(CPUMIPSState * env,target_ulong arg1)80132cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
80232cad1ffSPhilippe Mathieu-Daudé {
80332cad1ffSPhilippe Mathieu-Daudé     env->active_tc.CP0_TCSchedule = arg1;
80432cad1ffSPhilippe Mathieu-Daudé }
80532cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_tcschedule(CPUMIPSState * env,target_ulong arg1)80632cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
80732cad1ffSPhilippe Mathieu-Daudé {
80832cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
80932cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
81032cad1ffSPhilippe Mathieu-Daudé 
81132cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
81232cad1ffSPhilippe Mathieu-Daudé         other->active_tc.CP0_TCSchedule = arg1;
81332cad1ffSPhilippe Mathieu-Daudé     } else {
81432cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCSchedule = arg1;
81532cad1ffSPhilippe Mathieu-Daudé     }
81632cad1ffSPhilippe Mathieu-Daudé }
81732cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_tcschefback(CPUMIPSState * env,target_ulong arg1)81832cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
81932cad1ffSPhilippe Mathieu-Daudé {
82032cad1ffSPhilippe Mathieu-Daudé     env->active_tc.CP0_TCScheFBack = arg1;
82132cad1ffSPhilippe Mathieu-Daudé }
82232cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_tcschefback(CPUMIPSState * env,target_ulong arg1)82332cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
82432cad1ffSPhilippe Mathieu-Daudé {
82532cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
82632cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
82732cad1ffSPhilippe Mathieu-Daudé 
82832cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
82932cad1ffSPhilippe Mathieu-Daudé         other->active_tc.CP0_TCScheFBack = arg1;
83032cad1ffSPhilippe Mathieu-Daudé     } else {
83132cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCScheFBack = arg1;
83232cad1ffSPhilippe Mathieu-Daudé     }
83332cad1ffSPhilippe Mathieu-Daudé }
83432cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_entrylo1(CPUMIPSState * env,target_ulong arg1)83532cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
83632cad1ffSPhilippe Mathieu-Daudé {
83732cad1ffSPhilippe Mathieu-Daudé     /* 1k pages not implemented */
83832cad1ffSPhilippe Mathieu-Daudé     target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
83932cad1ffSPhilippe Mathieu-Daudé     env->CP0_EntryLo1 = (arg1 & MTC0_ENTRYLO_MASK(env))
84032cad1ffSPhilippe Mathieu-Daudé                         | (rxi << (CP0EnLo_XI - 30));
84132cad1ffSPhilippe Mathieu-Daudé }
84232cad1ffSPhilippe Mathieu-Daudé 
84332cad1ffSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
helper_dmtc0_entrylo1(CPUMIPSState * env,uint64_t arg1)84432cad1ffSPhilippe Mathieu-Daudé void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
84532cad1ffSPhilippe Mathieu-Daudé {
84632cad1ffSPhilippe Mathieu-Daudé     uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
84732cad1ffSPhilippe Mathieu-Daudé     env->CP0_EntryLo1 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
84832cad1ffSPhilippe Mathieu-Daudé }
84932cad1ffSPhilippe Mathieu-Daudé #endif
85032cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_context(CPUMIPSState * env,target_ulong arg1)85132cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
85232cad1ffSPhilippe Mathieu-Daudé {
85332cad1ffSPhilippe Mathieu-Daudé     env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
85432cad1ffSPhilippe Mathieu-Daudé }
85532cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_memorymapid(CPUMIPSState * env,target_ulong arg1)85632cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
85732cad1ffSPhilippe Mathieu-Daudé {
85832cad1ffSPhilippe Mathieu-Daudé     int32_t old;
85932cad1ffSPhilippe Mathieu-Daudé     old = env->CP0_MemoryMapID;
86032cad1ffSPhilippe Mathieu-Daudé     env->CP0_MemoryMapID = (int32_t) arg1;
86132cad1ffSPhilippe Mathieu-Daudé     /* If the MemoryMapID changes, flush qemu's TLB.  */
86232cad1ffSPhilippe Mathieu-Daudé     if (old != env->CP0_MemoryMapID) {
86332cad1ffSPhilippe Mathieu-Daudé         cpu_mips_tlb_flush(env);
86432cad1ffSPhilippe Mathieu-Daudé     }
86532cad1ffSPhilippe Mathieu-Daudé }
86632cad1ffSPhilippe Mathieu-Daudé 
compute_pagemask(uint32_t val)867*256ba771SRichard Henderson uint32_t compute_pagemask(uint32_t val)
86832cad1ffSPhilippe Mathieu-Daudé {
86932cad1ffSPhilippe Mathieu-Daudé     /* Don't care MASKX as we don't support 1KB page */
870*256ba771SRichard Henderson     uint32_t mask = extract32(val, CP0PM_MASK, 16);
871d89b9899SRichard Henderson     int maskbits = cto32(mask);
87232cad1ffSPhilippe Mathieu-Daudé 
873d89b9899SRichard Henderson     /* Ensure no more set bit after first zero, and maskbits even. */
874d89b9899SRichard Henderson     if ((mask >> maskbits) == 0 && maskbits % 2 == 0) {
875*256ba771SRichard Henderson         return mask << CP0PM_MASK;
876d89b9899SRichard Henderson     } else {
87732cad1ffSPhilippe Mathieu-Daudé         /* When invalid, set to default target page size. */
878*256ba771SRichard Henderson         return 0;
87932cad1ffSPhilippe Mathieu-Daudé     }
880d89b9899SRichard Henderson }
88132cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_pagemask(CPUMIPSState * env,target_ulong arg1)88232cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
88332cad1ffSPhilippe Mathieu-Daudé {
884*256ba771SRichard Henderson     env->CP0_PageMask = compute_pagemask(arg1);
88532cad1ffSPhilippe Mathieu-Daudé }
88632cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_pagegrain(CPUMIPSState * env,target_ulong arg1)88732cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
88832cad1ffSPhilippe Mathieu-Daudé {
88932cad1ffSPhilippe Mathieu-Daudé     /* SmartMIPS not implemented */
89032cad1ffSPhilippe Mathieu-Daudé     /* 1k pages not implemented */
89132cad1ffSPhilippe Mathieu-Daudé     env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
89232cad1ffSPhilippe Mathieu-Daudé                          (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
89332cad1ffSPhilippe Mathieu-Daudé     compute_hflags(env);
89432cad1ffSPhilippe Mathieu-Daudé     restore_pamask(env);
89532cad1ffSPhilippe Mathieu-Daudé }
89632cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_segctl0(CPUMIPSState * env,target_ulong arg1)89732cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_segctl0(CPUMIPSState *env, target_ulong arg1)
89832cad1ffSPhilippe Mathieu-Daudé {
89932cad1ffSPhilippe Mathieu-Daudé     CPUState *cs = env_cpu(env);
90032cad1ffSPhilippe Mathieu-Daudé 
90132cad1ffSPhilippe Mathieu-Daudé     env->CP0_SegCtl0 = arg1 & CP0SC0_MASK;
90232cad1ffSPhilippe Mathieu-Daudé     tlb_flush(cs);
90332cad1ffSPhilippe Mathieu-Daudé }
90432cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_segctl1(CPUMIPSState * env,target_ulong arg1)90532cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_segctl1(CPUMIPSState *env, target_ulong arg1)
90632cad1ffSPhilippe Mathieu-Daudé {
90732cad1ffSPhilippe Mathieu-Daudé     CPUState *cs = env_cpu(env);
90832cad1ffSPhilippe Mathieu-Daudé 
90932cad1ffSPhilippe Mathieu-Daudé     env->CP0_SegCtl1 = arg1 & CP0SC1_MASK;
91032cad1ffSPhilippe Mathieu-Daudé     tlb_flush(cs);
91132cad1ffSPhilippe Mathieu-Daudé }
91232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_segctl2(CPUMIPSState * env,target_ulong arg1)91332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_segctl2(CPUMIPSState *env, target_ulong arg1)
91432cad1ffSPhilippe Mathieu-Daudé {
91532cad1ffSPhilippe Mathieu-Daudé     CPUState *cs = env_cpu(env);
91632cad1ffSPhilippe Mathieu-Daudé 
91732cad1ffSPhilippe Mathieu-Daudé     env->CP0_SegCtl2 = arg1 & CP0SC2_MASK;
91832cad1ffSPhilippe Mathieu-Daudé     tlb_flush(cs);
91932cad1ffSPhilippe Mathieu-Daudé }
92032cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_pwfield(CPUMIPSState * env,target_ulong arg1)92132cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
92232cad1ffSPhilippe Mathieu-Daudé {
92332cad1ffSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
92432cad1ffSPhilippe Mathieu-Daudé     uint64_t mask = 0x3F3FFFFFFFULL;
92532cad1ffSPhilippe Mathieu-Daudé     uint32_t old_ptei = (env->CP0_PWField >> CP0PF_PTEI) & 0x3FULL;
92632cad1ffSPhilippe Mathieu-Daudé     uint32_t new_ptei = (arg1 >> CP0PF_PTEI) & 0x3FULL;
92732cad1ffSPhilippe Mathieu-Daudé 
92832cad1ffSPhilippe Mathieu-Daudé     if ((env->insn_flags & ISA_MIPS_R6)) {
92932cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_BDI) & 0x3FULL) < 12) {
93032cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_BDI);
93132cad1ffSPhilippe Mathieu-Daudé         }
93232cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_GDI) & 0x3FULL) < 12) {
93332cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_GDI);
93432cad1ffSPhilippe Mathieu-Daudé         }
93532cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_UDI) & 0x3FULL) < 12) {
93632cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_UDI);
93732cad1ffSPhilippe Mathieu-Daudé         }
93832cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_MDI) & 0x3FULL) < 12) {
93932cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_MDI);
94032cad1ffSPhilippe Mathieu-Daudé         }
94132cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_PTI) & 0x3FULL) < 12) {
94232cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_PTI);
94332cad1ffSPhilippe Mathieu-Daudé         }
94432cad1ffSPhilippe Mathieu-Daudé     }
94532cad1ffSPhilippe Mathieu-Daudé     env->CP0_PWField = arg1 & mask;
94632cad1ffSPhilippe Mathieu-Daudé 
94732cad1ffSPhilippe Mathieu-Daudé     if ((new_ptei >= 32) ||
94832cad1ffSPhilippe Mathieu-Daudé             ((env->insn_flags & ISA_MIPS_R6) &&
94932cad1ffSPhilippe Mathieu-Daudé                     (new_ptei == 0 || new_ptei == 1))) {
95032cad1ffSPhilippe Mathieu-Daudé         env->CP0_PWField = (env->CP0_PWField & ~0x3FULL) |
95132cad1ffSPhilippe Mathieu-Daudé                 (old_ptei << CP0PF_PTEI);
95232cad1ffSPhilippe Mathieu-Daudé     }
95332cad1ffSPhilippe Mathieu-Daudé #else
95432cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = 0x3FFFFFFF;
95532cad1ffSPhilippe Mathieu-Daudé     uint32_t old_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
95632cad1ffSPhilippe Mathieu-Daudé     uint32_t new_ptew = (arg1 >> CP0PF_PTEW) & 0x3F;
95732cad1ffSPhilippe Mathieu-Daudé 
95832cad1ffSPhilippe Mathieu-Daudé     if ((env->insn_flags & ISA_MIPS_R6)) {
95932cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_GDW) & 0x3F) < 12) {
96032cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3F << CP0PF_GDW);
96132cad1ffSPhilippe Mathieu-Daudé         }
96232cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_UDW) & 0x3F) < 12) {
96332cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3F << CP0PF_UDW);
96432cad1ffSPhilippe Mathieu-Daudé         }
96532cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_MDW) & 0x3F) < 12) {
96632cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3F << CP0PF_MDW);
96732cad1ffSPhilippe Mathieu-Daudé         }
96832cad1ffSPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_PTW) & 0x3F) < 12) {
96932cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3F << CP0PF_PTW);
97032cad1ffSPhilippe Mathieu-Daudé         }
97132cad1ffSPhilippe Mathieu-Daudé     }
97232cad1ffSPhilippe Mathieu-Daudé     env->CP0_PWField = arg1 & mask;
97332cad1ffSPhilippe Mathieu-Daudé 
97432cad1ffSPhilippe Mathieu-Daudé     if ((new_ptew >= 32) ||
97532cad1ffSPhilippe Mathieu-Daudé             ((env->insn_flags & ISA_MIPS_R6) &&
97632cad1ffSPhilippe Mathieu-Daudé                     (new_ptew == 0 || new_ptew == 1))) {
97732cad1ffSPhilippe Mathieu-Daudé         env->CP0_PWField = (env->CP0_PWField & ~0x3F) |
97832cad1ffSPhilippe Mathieu-Daudé                 (old_ptew << CP0PF_PTEW);
97932cad1ffSPhilippe Mathieu-Daudé     }
98032cad1ffSPhilippe Mathieu-Daudé #endif
98132cad1ffSPhilippe Mathieu-Daudé }
98232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_pwsize(CPUMIPSState * env,target_ulong arg1)98332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_pwsize(CPUMIPSState *env, target_ulong arg1)
98432cad1ffSPhilippe Mathieu-Daudé {
98532cad1ffSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
98632cad1ffSPhilippe Mathieu-Daudé     env->CP0_PWSize = arg1 & 0x3F7FFFFFFFULL;
98732cad1ffSPhilippe Mathieu-Daudé #else
98832cad1ffSPhilippe Mathieu-Daudé     env->CP0_PWSize = arg1 & 0x3FFFFFFF;
98932cad1ffSPhilippe Mathieu-Daudé #endif
99032cad1ffSPhilippe Mathieu-Daudé }
99132cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_wired(CPUMIPSState * env,target_ulong arg1)99232cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
99332cad1ffSPhilippe Mathieu-Daudé {
99432cad1ffSPhilippe Mathieu-Daudé     if (env->insn_flags & ISA_MIPS_R6) {
99532cad1ffSPhilippe Mathieu-Daudé         if (arg1 < env->tlb->nb_tlb) {
99632cad1ffSPhilippe Mathieu-Daudé             env->CP0_Wired = arg1;
99732cad1ffSPhilippe Mathieu-Daudé         }
99832cad1ffSPhilippe Mathieu-Daudé     } else {
99932cad1ffSPhilippe Mathieu-Daudé         env->CP0_Wired = arg1 % env->tlb->nb_tlb;
100032cad1ffSPhilippe Mathieu-Daudé     }
100132cad1ffSPhilippe Mathieu-Daudé }
100232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_pwctl(CPUMIPSState * env,target_ulong arg1)100332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_pwctl(CPUMIPSState *env, target_ulong arg1)
100432cad1ffSPhilippe Mathieu-Daudé {
100532cad1ffSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
100632cad1ffSPhilippe Mathieu-Daudé     /* PWEn = 0. Hardware page table walking is not implemented. */
100732cad1ffSPhilippe Mathieu-Daudé     env->CP0_PWCtl = (env->CP0_PWCtl & 0x000000C0) | (arg1 & 0x5C00003F);
100832cad1ffSPhilippe Mathieu-Daudé #else
100932cad1ffSPhilippe Mathieu-Daudé     env->CP0_PWCtl = (arg1 & 0x800000FF);
101032cad1ffSPhilippe Mathieu-Daudé #endif
101132cad1ffSPhilippe Mathieu-Daudé }
101232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_srsconf0(CPUMIPSState * env,target_ulong arg1)101332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
101432cad1ffSPhilippe Mathieu-Daudé {
101532cad1ffSPhilippe Mathieu-Daudé     env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
101632cad1ffSPhilippe Mathieu-Daudé }
101732cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_srsconf1(CPUMIPSState * env,target_ulong arg1)101832cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_srsconf1(CPUMIPSState *env, target_ulong arg1)
101932cad1ffSPhilippe Mathieu-Daudé {
102032cad1ffSPhilippe Mathieu-Daudé     env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
102132cad1ffSPhilippe Mathieu-Daudé }
102232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_srsconf2(CPUMIPSState * env,target_ulong arg1)102332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_srsconf2(CPUMIPSState *env, target_ulong arg1)
102432cad1ffSPhilippe Mathieu-Daudé {
102532cad1ffSPhilippe Mathieu-Daudé     env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
102632cad1ffSPhilippe Mathieu-Daudé }
102732cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_srsconf3(CPUMIPSState * env,target_ulong arg1)102832cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_srsconf3(CPUMIPSState *env, target_ulong arg1)
102932cad1ffSPhilippe Mathieu-Daudé {
103032cad1ffSPhilippe Mathieu-Daudé     env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
103132cad1ffSPhilippe Mathieu-Daudé }
103232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_srsconf4(CPUMIPSState * env,target_ulong arg1)103332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_srsconf4(CPUMIPSState *env, target_ulong arg1)
103432cad1ffSPhilippe Mathieu-Daudé {
103532cad1ffSPhilippe Mathieu-Daudé     env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
103632cad1ffSPhilippe Mathieu-Daudé }
103732cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_hwrena(CPUMIPSState * env,target_ulong arg1)103832cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
103932cad1ffSPhilippe Mathieu-Daudé {
104032cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = 0x0000000F;
104132cad1ffSPhilippe Mathieu-Daudé 
104232cad1ffSPhilippe Mathieu-Daudé     if ((env->CP0_Config1 & (1 << CP0C1_PC)) &&
104332cad1ffSPhilippe Mathieu-Daudé         (env->insn_flags & ISA_MIPS_R6)) {
104432cad1ffSPhilippe Mathieu-Daudé         mask |= (1 << 4);
104532cad1ffSPhilippe Mathieu-Daudé     }
104632cad1ffSPhilippe Mathieu-Daudé     if (env->insn_flags & ISA_MIPS_R6) {
104732cad1ffSPhilippe Mathieu-Daudé         mask |= (1 << 5);
104832cad1ffSPhilippe Mathieu-Daudé     }
104932cad1ffSPhilippe Mathieu-Daudé     if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
105032cad1ffSPhilippe Mathieu-Daudé         mask |= (1 << 29);
105132cad1ffSPhilippe Mathieu-Daudé 
105232cad1ffSPhilippe Mathieu-Daudé         if (arg1 & (1 << 29)) {
105332cad1ffSPhilippe Mathieu-Daudé             env->hflags |= MIPS_HFLAG_HWRENA_ULR;
105432cad1ffSPhilippe Mathieu-Daudé         } else {
105532cad1ffSPhilippe Mathieu-Daudé             env->hflags &= ~MIPS_HFLAG_HWRENA_ULR;
105632cad1ffSPhilippe Mathieu-Daudé         }
105732cad1ffSPhilippe Mathieu-Daudé     }
105832cad1ffSPhilippe Mathieu-Daudé 
105932cad1ffSPhilippe Mathieu-Daudé     env->CP0_HWREna = arg1 & mask;
106032cad1ffSPhilippe Mathieu-Daudé }
106132cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_count(CPUMIPSState * env,target_ulong arg1)106232cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
106332cad1ffSPhilippe Mathieu-Daudé {
106432cad1ffSPhilippe Mathieu-Daudé     cpu_mips_store_count(env, arg1);
106532cad1ffSPhilippe Mathieu-Daudé }
106632cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_entryhi(CPUMIPSState * env,target_ulong arg1)106732cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
106832cad1ffSPhilippe Mathieu-Daudé {
106932cad1ffSPhilippe Mathieu-Daudé     target_ulong old, val, mask;
107032cad1ffSPhilippe Mathieu-Daudé     mask = (TARGET_PAGE_MASK << 1) | env->CP0_EntryHi_ASID_mask;
107132cad1ffSPhilippe Mathieu-Daudé     if (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) {
107232cad1ffSPhilippe Mathieu-Daudé         mask |= 1 << CP0EnHi_EHINV;
107332cad1ffSPhilippe Mathieu-Daudé     }
107432cad1ffSPhilippe Mathieu-Daudé 
107532cad1ffSPhilippe Mathieu-Daudé     /* 1k pages not implemented */
107632cad1ffSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
107732cad1ffSPhilippe Mathieu-Daudé     if (env->insn_flags & ISA_MIPS_R6) {
107832cad1ffSPhilippe Mathieu-Daudé         int entryhi_r = extract64(arg1, 62, 2);
107932cad1ffSPhilippe Mathieu-Daudé         int config0_at = extract32(env->CP0_Config0, 13, 2);
108032cad1ffSPhilippe Mathieu-Daudé         bool no_supervisor = (env->CP0_Status_rw_bitmask & 0x8) == 0;
108132cad1ffSPhilippe Mathieu-Daudé         if ((entryhi_r == 2) ||
108232cad1ffSPhilippe Mathieu-Daudé             (entryhi_r == 1 && (no_supervisor || config0_at == 1))) {
108332cad1ffSPhilippe Mathieu-Daudé             /* skip EntryHi.R field if new value is reserved */
108432cad1ffSPhilippe Mathieu-Daudé             mask &= ~(0x3ull << 62);
108532cad1ffSPhilippe Mathieu-Daudé         }
108632cad1ffSPhilippe Mathieu-Daudé     }
108732cad1ffSPhilippe Mathieu-Daudé     mask &= env->SEGMask;
108832cad1ffSPhilippe Mathieu-Daudé #endif
108932cad1ffSPhilippe Mathieu-Daudé     old = env->CP0_EntryHi;
109032cad1ffSPhilippe Mathieu-Daudé     val = (arg1 & mask) | (old & ~mask);
109132cad1ffSPhilippe Mathieu-Daudé     env->CP0_EntryHi = val;
109232cad1ffSPhilippe Mathieu-Daudé     if (ase_mt_available(env)) {
109332cad1ffSPhilippe Mathieu-Daudé         sync_c0_entryhi(env, env->current_tc);
109432cad1ffSPhilippe Mathieu-Daudé     }
109532cad1ffSPhilippe Mathieu-Daudé     /* If the ASID changes, flush qemu's TLB.  */
109632cad1ffSPhilippe Mathieu-Daudé     if ((old & env->CP0_EntryHi_ASID_mask) !=
109732cad1ffSPhilippe Mathieu-Daudé         (val & env->CP0_EntryHi_ASID_mask)) {
109832cad1ffSPhilippe Mathieu-Daudé         tlb_flush(env_cpu(env));
109932cad1ffSPhilippe Mathieu-Daudé     }
110032cad1ffSPhilippe Mathieu-Daudé }
110132cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_entryhi(CPUMIPSState * env,target_ulong arg1)110232cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1)
110332cad1ffSPhilippe Mathieu-Daudé {
110432cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
110532cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
110632cad1ffSPhilippe Mathieu-Daudé 
110732cad1ffSPhilippe Mathieu-Daudé     other->CP0_EntryHi = arg1;
110832cad1ffSPhilippe Mathieu-Daudé     sync_c0_entryhi(other, other_tc);
110932cad1ffSPhilippe Mathieu-Daudé }
111032cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_compare(CPUMIPSState * env,target_ulong arg1)111132cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1)
111232cad1ffSPhilippe Mathieu-Daudé {
111332cad1ffSPhilippe Mathieu-Daudé     cpu_mips_store_compare(env, arg1);
111432cad1ffSPhilippe Mathieu-Daudé }
111532cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_status(CPUMIPSState * env,target_ulong arg1)111632cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
111732cad1ffSPhilippe Mathieu-Daudé {
111832cad1ffSPhilippe Mathieu-Daudé     uint32_t val, old;
111932cad1ffSPhilippe Mathieu-Daudé 
112032cad1ffSPhilippe Mathieu-Daudé     old = env->CP0_Status;
112132cad1ffSPhilippe Mathieu-Daudé     cpu_mips_store_status(env, arg1);
112232cad1ffSPhilippe Mathieu-Daudé     val = env->CP0_Status;
112332cad1ffSPhilippe Mathieu-Daudé 
112432cad1ffSPhilippe Mathieu-Daudé     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
112532cad1ffSPhilippe Mathieu-Daudé         qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
112632cad1ffSPhilippe Mathieu-Daudé                 old, old & env->CP0_Cause & CP0Ca_IP_mask,
112732cad1ffSPhilippe Mathieu-Daudé                 val, val & env->CP0_Cause & CP0Ca_IP_mask,
112832cad1ffSPhilippe Mathieu-Daudé                 env->CP0_Cause);
112932cad1ffSPhilippe Mathieu-Daudé         switch (mips_env_mmu_index(env)) {
113032cad1ffSPhilippe Mathieu-Daudé         case 3:
113132cad1ffSPhilippe Mathieu-Daudé             qemu_log(", ERL\n");
113232cad1ffSPhilippe Mathieu-Daudé             break;
113332cad1ffSPhilippe Mathieu-Daudé         case MIPS_HFLAG_UM:
113432cad1ffSPhilippe Mathieu-Daudé             qemu_log(", UM\n");
113532cad1ffSPhilippe Mathieu-Daudé             break;
113632cad1ffSPhilippe Mathieu-Daudé         case MIPS_HFLAG_SM:
113732cad1ffSPhilippe Mathieu-Daudé             qemu_log(", SM\n");
113832cad1ffSPhilippe Mathieu-Daudé             break;
113932cad1ffSPhilippe Mathieu-Daudé         case MIPS_HFLAG_KM:
114032cad1ffSPhilippe Mathieu-Daudé             qemu_log("\n");
114132cad1ffSPhilippe Mathieu-Daudé             break;
114232cad1ffSPhilippe Mathieu-Daudé         default:
114332cad1ffSPhilippe Mathieu-Daudé             cpu_abort(env_cpu(env), "Invalid MMU mode!\n");
114432cad1ffSPhilippe Mathieu-Daudé             break;
114532cad1ffSPhilippe Mathieu-Daudé         }
114632cad1ffSPhilippe Mathieu-Daudé     }
114732cad1ffSPhilippe Mathieu-Daudé }
114832cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_status(CPUMIPSState * env,target_ulong arg1)114932cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_status(CPUMIPSState *env, target_ulong arg1)
115032cad1ffSPhilippe Mathieu-Daudé {
115132cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
115232cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = env->CP0_Status_rw_bitmask & ~0xf1000018;
115332cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
115432cad1ffSPhilippe Mathieu-Daudé 
115532cad1ffSPhilippe Mathieu-Daudé     other->CP0_Status = (other->CP0_Status & ~mask) | (arg1 & mask);
115632cad1ffSPhilippe Mathieu-Daudé     sync_c0_status(env, other, other_tc);
115732cad1ffSPhilippe Mathieu-Daudé }
115832cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_intctl(CPUMIPSState * env,target_ulong arg1)115932cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_intctl(CPUMIPSState *env, target_ulong arg1)
116032cad1ffSPhilippe Mathieu-Daudé {
116132cad1ffSPhilippe Mathieu-Daudé     env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000003e0) | (arg1 & 0x000003e0);
116232cad1ffSPhilippe Mathieu-Daudé }
116332cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_srsctl(CPUMIPSState * env,target_ulong arg1)116432cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1)
116532cad1ffSPhilippe Mathieu-Daudé {
116632cad1ffSPhilippe Mathieu-Daudé     uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
116732cad1ffSPhilippe Mathieu-Daudé     env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
116832cad1ffSPhilippe Mathieu-Daudé }
116932cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_cause(CPUMIPSState * env,target_ulong arg1)117032cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1)
117132cad1ffSPhilippe Mathieu-Daudé {
117232cad1ffSPhilippe Mathieu-Daudé     cpu_mips_store_cause(env, arg1);
117332cad1ffSPhilippe Mathieu-Daudé }
117432cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_cause(CPUMIPSState * env,target_ulong arg1)117532cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1)
117632cad1ffSPhilippe Mathieu-Daudé {
117732cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
117832cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
117932cad1ffSPhilippe Mathieu-Daudé 
118032cad1ffSPhilippe Mathieu-Daudé     cpu_mips_store_cause(other, arg1);
118132cad1ffSPhilippe Mathieu-Daudé }
118232cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_epc(CPUMIPSState * env)118332cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_epc(CPUMIPSState *env)
118432cad1ffSPhilippe Mathieu-Daudé {
118532cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
118632cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
118732cad1ffSPhilippe Mathieu-Daudé 
118832cad1ffSPhilippe Mathieu-Daudé     return other->CP0_EPC;
118932cad1ffSPhilippe Mathieu-Daudé }
119032cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_ebase(CPUMIPSState * env)119132cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_ebase(CPUMIPSState *env)
119232cad1ffSPhilippe Mathieu-Daudé {
119332cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
119432cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
119532cad1ffSPhilippe Mathieu-Daudé 
119632cad1ffSPhilippe Mathieu-Daudé     return other->CP0_EBase;
119732cad1ffSPhilippe Mathieu-Daudé }
119832cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_ebase(CPUMIPSState * env,target_ulong arg1)119932cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1)
120032cad1ffSPhilippe Mathieu-Daudé {
120132cad1ffSPhilippe Mathieu-Daudé     target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
120232cad1ffSPhilippe Mathieu-Daudé     if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
120332cad1ffSPhilippe Mathieu-Daudé         mask |= ~0x3FFFFFFF;
120432cad1ffSPhilippe Mathieu-Daudé     }
120532cad1ffSPhilippe Mathieu-Daudé     env->CP0_EBase = (env->CP0_EBase & ~mask) | (arg1 & mask);
120632cad1ffSPhilippe Mathieu-Daudé }
120732cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_ebase(CPUMIPSState * env,target_ulong arg1)120832cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1)
120932cad1ffSPhilippe Mathieu-Daudé {
121032cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
121132cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
121232cad1ffSPhilippe Mathieu-Daudé     target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
121332cad1ffSPhilippe Mathieu-Daudé     if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
121432cad1ffSPhilippe Mathieu-Daudé         mask |= ~0x3FFFFFFF;
121532cad1ffSPhilippe Mathieu-Daudé     }
121632cad1ffSPhilippe Mathieu-Daudé     other->CP0_EBase = (other->CP0_EBase & ~mask) | (arg1 & mask);
121732cad1ffSPhilippe Mathieu-Daudé }
121832cad1ffSPhilippe Mathieu-Daudé 
helper_mftc0_configx(CPUMIPSState * env,target_ulong idx)121932cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx)
122032cad1ffSPhilippe Mathieu-Daudé {
122132cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
122232cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
122332cad1ffSPhilippe Mathieu-Daudé 
122432cad1ffSPhilippe Mathieu-Daudé     switch (idx) {
122532cad1ffSPhilippe Mathieu-Daudé     case 0: return other->CP0_Config0;
122632cad1ffSPhilippe Mathieu-Daudé     case 1: return other->CP0_Config1;
122732cad1ffSPhilippe Mathieu-Daudé     case 2: return other->CP0_Config2;
122832cad1ffSPhilippe Mathieu-Daudé     case 3: return other->CP0_Config3;
122932cad1ffSPhilippe Mathieu-Daudé     /* 4 and 5 are reserved.  */
123032cad1ffSPhilippe Mathieu-Daudé     case 6: return other->CP0_Config6;
123132cad1ffSPhilippe Mathieu-Daudé     case 7: return other->CP0_Config7;
123232cad1ffSPhilippe Mathieu-Daudé     default:
123332cad1ffSPhilippe Mathieu-Daudé         break;
123432cad1ffSPhilippe Mathieu-Daudé     }
123532cad1ffSPhilippe Mathieu-Daudé     return 0;
123632cad1ffSPhilippe Mathieu-Daudé }
123732cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_config0(CPUMIPSState * env,target_ulong arg1)123832cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_config0(CPUMIPSState *env, target_ulong arg1)
123932cad1ffSPhilippe Mathieu-Daudé {
124032cad1ffSPhilippe Mathieu-Daudé     env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
124132cad1ffSPhilippe Mathieu-Daudé }
124232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_config2(CPUMIPSState * env,target_ulong arg1)124332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1)
124432cad1ffSPhilippe Mathieu-Daudé {
124532cad1ffSPhilippe Mathieu-Daudé     /* tertiary/secondary caches not implemented */
124632cad1ffSPhilippe Mathieu-Daudé     env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
124732cad1ffSPhilippe Mathieu-Daudé }
124832cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_config3(CPUMIPSState * env,target_ulong arg1)124932cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_config3(CPUMIPSState *env, target_ulong arg1)
125032cad1ffSPhilippe Mathieu-Daudé {
125132cad1ffSPhilippe Mathieu-Daudé     if (env->insn_flags & ASE_MICROMIPS) {
125232cad1ffSPhilippe Mathieu-Daudé         env->CP0_Config3 = (env->CP0_Config3 & ~(1 << CP0C3_ISA_ON_EXC)) |
125332cad1ffSPhilippe Mathieu-Daudé                            (arg1 & (1 << CP0C3_ISA_ON_EXC));
125432cad1ffSPhilippe Mathieu-Daudé     }
125532cad1ffSPhilippe Mathieu-Daudé }
125632cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_config4(CPUMIPSState * env,target_ulong arg1)125732cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_config4(CPUMIPSState *env, target_ulong arg1)
125832cad1ffSPhilippe Mathieu-Daudé {
125932cad1ffSPhilippe Mathieu-Daudé     env->CP0_Config4 = (env->CP0_Config4 & (~env->CP0_Config4_rw_bitmask)) |
126032cad1ffSPhilippe Mathieu-Daudé                        (arg1 & env->CP0_Config4_rw_bitmask);
126132cad1ffSPhilippe Mathieu-Daudé }
126232cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_config5(CPUMIPSState * env,target_ulong arg1)126332cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1)
126432cad1ffSPhilippe Mathieu-Daudé {
126532cad1ffSPhilippe Mathieu-Daudé     env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
126632cad1ffSPhilippe Mathieu-Daudé                        (arg1 & env->CP0_Config5_rw_bitmask);
126732cad1ffSPhilippe Mathieu-Daudé     env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
126832cad1ffSPhilippe Mathieu-Daudé             0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
126932cad1ffSPhilippe Mathieu-Daudé     compute_hflags(env);
127032cad1ffSPhilippe Mathieu-Daudé }
127132cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_lladdr(CPUMIPSState * env,target_ulong arg1)127232cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1)
127332cad1ffSPhilippe Mathieu-Daudé {
127432cad1ffSPhilippe Mathieu-Daudé     target_long mask = env->CP0_LLAddr_rw_bitmask;
127532cad1ffSPhilippe Mathieu-Daudé     arg1 = arg1 << env->CP0_LLAddr_shift;
127632cad1ffSPhilippe Mathieu-Daudé     env->CP0_LLAddr = (env->CP0_LLAddr & ~mask) | (arg1 & mask);
127732cad1ffSPhilippe Mathieu-Daudé }
127832cad1ffSPhilippe Mathieu-Daudé 
127932cad1ffSPhilippe Mathieu-Daudé #define MTC0_MAAR_MASK(env) \
128032cad1ffSPhilippe Mathieu-Daudé         ((0x1ULL << 63) | ((env->PAMask >> 4) & ~0xFFFull) | 0x3)
128132cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_maar(CPUMIPSState * env,target_ulong arg1)128232cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_maar(CPUMIPSState *env, target_ulong arg1)
128332cad1ffSPhilippe Mathieu-Daudé {
128432cad1ffSPhilippe Mathieu-Daudé     env->CP0_MAAR[env->CP0_MAARI] = arg1 & MTC0_MAAR_MASK(env);
128532cad1ffSPhilippe Mathieu-Daudé }
128632cad1ffSPhilippe Mathieu-Daudé 
helper_mthc0_maar(CPUMIPSState * env,target_ulong arg1)128732cad1ffSPhilippe Mathieu-Daudé void helper_mthc0_maar(CPUMIPSState *env, target_ulong arg1)
128832cad1ffSPhilippe Mathieu-Daudé {
128932cad1ffSPhilippe Mathieu-Daudé     env->CP0_MAAR[env->CP0_MAARI] =
129032cad1ffSPhilippe Mathieu-Daudé         (((uint64_t) arg1 << 32) & MTC0_MAAR_MASK(env)) |
129132cad1ffSPhilippe Mathieu-Daudé         (env->CP0_MAAR[env->CP0_MAARI] & 0x00000000ffffffffULL);
129232cad1ffSPhilippe Mathieu-Daudé }
129332cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_maari(CPUMIPSState * env,target_ulong arg1)129432cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_maari(CPUMIPSState *env, target_ulong arg1)
129532cad1ffSPhilippe Mathieu-Daudé {
129632cad1ffSPhilippe Mathieu-Daudé     int index = arg1 & 0x3f;
129732cad1ffSPhilippe Mathieu-Daudé     if (index == 0x3f) {
129832cad1ffSPhilippe Mathieu-Daudé         /*
129932cad1ffSPhilippe Mathieu-Daudé          * Software may write all ones to INDEX to determine the
130032cad1ffSPhilippe Mathieu-Daudé          *  maximum value supported.
130132cad1ffSPhilippe Mathieu-Daudé          */
130232cad1ffSPhilippe Mathieu-Daudé         env->CP0_MAARI = MIPS_MAAR_MAX - 1;
130332cad1ffSPhilippe Mathieu-Daudé     } else if (index < MIPS_MAAR_MAX) {
130432cad1ffSPhilippe Mathieu-Daudé         env->CP0_MAARI = index;
130532cad1ffSPhilippe Mathieu-Daudé     }
130632cad1ffSPhilippe Mathieu-Daudé     /*
130732cad1ffSPhilippe Mathieu-Daudé      * Other than the all ones, if the value written is not supported,
130832cad1ffSPhilippe Mathieu-Daudé      * then INDEX is unchanged from its previous value.
130932cad1ffSPhilippe Mathieu-Daudé      */
131032cad1ffSPhilippe Mathieu-Daudé }
131132cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_watchlo(CPUMIPSState * env,target_ulong arg1,uint32_t sel)131232cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
131332cad1ffSPhilippe Mathieu-Daudé {
131432cad1ffSPhilippe Mathieu-Daudé     /*
131532cad1ffSPhilippe Mathieu-Daudé      * Watch exceptions for instructions, data loads, data stores
131632cad1ffSPhilippe Mathieu-Daudé      * not implemented.
131732cad1ffSPhilippe Mathieu-Daudé      */
131832cad1ffSPhilippe Mathieu-Daudé     env->CP0_WatchLo[sel] = (arg1 & ~0x7);
131932cad1ffSPhilippe Mathieu-Daudé }
132032cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_watchhi(CPUMIPSState * env,target_ulong arg1,uint32_t sel)132132cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
132232cad1ffSPhilippe Mathieu-Daudé {
132332cad1ffSPhilippe Mathieu-Daudé     uint64_t mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID);
132432cad1ffSPhilippe Mathieu-Daudé     uint64_t m_bit = env->CP0_WatchHi[sel] & (1 << CP0WH_M); /* read-only */
132532cad1ffSPhilippe Mathieu-Daudé     if ((env->CP0_Config5 >> CP0C5_MI) & 1) {
132632cad1ffSPhilippe Mathieu-Daudé         mask |= 0xFFFFFFFF00000000ULL; /* MMID */
132732cad1ffSPhilippe Mathieu-Daudé     }
132832cad1ffSPhilippe Mathieu-Daudé     env->CP0_WatchHi[sel] = m_bit | (arg1 & mask);
132932cad1ffSPhilippe Mathieu-Daudé     env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
133032cad1ffSPhilippe Mathieu-Daudé }
133132cad1ffSPhilippe Mathieu-Daudé 
helper_mthc0_watchhi(CPUMIPSState * env,target_ulong arg1,uint32_t sel)133232cad1ffSPhilippe Mathieu-Daudé void helper_mthc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
133332cad1ffSPhilippe Mathieu-Daudé {
133432cad1ffSPhilippe Mathieu-Daudé     env->CP0_WatchHi[sel] = ((uint64_t) (arg1) << 32) |
133532cad1ffSPhilippe Mathieu-Daudé                             (env->CP0_WatchHi[sel] & 0x00000000ffffffffULL);
133632cad1ffSPhilippe Mathieu-Daudé }
133732cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_xcontext(CPUMIPSState * env,target_ulong arg1)133832cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1)
133932cad1ffSPhilippe Mathieu-Daudé {
134032cad1ffSPhilippe Mathieu-Daudé     target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
134132cad1ffSPhilippe Mathieu-Daudé     env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
134232cad1ffSPhilippe Mathieu-Daudé }
134332cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_framemask(CPUMIPSState * env,target_ulong arg1)134432cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_framemask(CPUMIPSState *env, target_ulong arg1)
134532cad1ffSPhilippe Mathieu-Daudé {
134632cad1ffSPhilippe Mathieu-Daudé     env->CP0_Framemask = arg1; /* XXX */
134732cad1ffSPhilippe Mathieu-Daudé }
134832cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_debug(CPUMIPSState * env,target_ulong arg1)134932cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_debug(CPUMIPSState *env, target_ulong arg1)
135032cad1ffSPhilippe Mathieu-Daudé {
135132cad1ffSPhilippe Mathieu-Daudé     env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
135232cad1ffSPhilippe Mathieu-Daudé     if (arg1 & (1 << CP0DB_DM)) {
135332cad1ffSPhilippe Mathieu-Daudé         env->hflags |= MIPS_HFLAG_DM;
135432cad1ffSPhilippe Mathieu-Daudé     } else {
135532cad1ffSPhilippe Mathieu-Daudé         env->hflags &= ~MIPS_HFLAG_DM;
135632cad1ffSPhilippe Mathieu-Daudé     }
135732cad1ffSPhilippe Mathieu-Daudé }
135832cad1ffSPhilippe Mathieu-Daudé 
helper_mttc0_debug(CPUMIPSState * env,target_ulong arg1)135932cad1ffSPhilippe Mathieu-Daudé void helper_mttc0_debug(CPUMIPSState *env, target_ulong arg1)
136032cad1ffSPhilippe Mathieu-Daudé {
136132cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
136232cad1ffSPhilippe Mathieu-Daudé     uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
136332cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
136432cad1ffSPhilippe Mathieu-Daudé 
136532cad1ffSPhilippe Mathieu-Daudé     /* XXX: Might be wrong, check with EJTAG spec. */
136632cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
136732cad1ffSPhilippe Mathieu-Daudé         other->active_tc.CP0_Debug_tcstatus = val;
136832cad1ffSPhilippe Mathieu-Daudé     } else {
136932cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_Debug_tcstatus = val;
137032cad1ffSPhilippe Mathieu-Daudé     }
137132cad1ffSPhilippe Mathieu-Daudé     other->CP0_Debug = (other->CP0_Debug &
137232cad1ffSPhilippe Mathieu-Daudé                      ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
137332cad1ffSPhilippe Mathieu-Daudé                      (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
137432cad1ffSPhilippe Mathieu-Daudé }
137532cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_performance0(CPUMIPSState * env,target_ulong arg1)137632cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1)
137732cad1ffSPhilippe Mathieu-Daudé {
137832cad1ffSPhilippe Mathieu-Daudé     env->CP0_Performance0 = arg1 & 0x000007ff;
137932cad1ffSPhilippe Mathieu-Daudé }
138032cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_errctl(CPUMIPSState * env,target_ulong arg1)138132cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_errctl(CPUMIPSState *env, target_ulong arg1)
138232cad1ffSPhilippe Mathieu-Daudé {
138332cad1ffSPhilippe Mathieu-Daudé     int32_t wst = arg1 & (1 << CP0EC_WST);
138432cad1ffSPhilippe Mathieu-Daudé     int32_t spr = arg1 & (1 << CP0EC_SPR);
138532cad1ffSPhilippe Mathieu-Daudé     int32_t itc = env->itc_tag ? (arg1 & (1 << CP0EC_ITC)) : 0;
138632cad1ffSPhilippe Mathieu-Daudé 
138732cad1ffSPhilippe Mathieu-Daudé     env->CP0_ErrCtl = wst | spr | itc;
138832cad1ffSPhilippe Mathieu-Daudé 
138932cad1ffSPhilippe Mathieu-Daudé     if (itc && !wst && !spr) {
139032cad1ffSPhilippe Mathieu-Daudé         env->hflags |= MIPS_HFLAG_ITC_CACHE;
139132cad1ffSPhilippe Mathieu-Daudé     } else {
139232cad1ffSPhilippe Mathieu-Daudé         env->hflags &= ~MIPS_HFLAG_ITC_CACHE;
139332cad1ffSPhilippe Mathieu-Daudé     }
139432cad1ffSPhilippe Mathieu-Daudé }
139532cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_taglo(CPUMIPSState * env,target_ulong arg1)139632cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1)
139732cad1ffSPhilippe Mathieu-Daudé {
139832cad1ffSPhilippe Mathieu-Daudé     if (env->hflags & MIPS_HFLAG_ITC_CACHE) {
139932cad1ffSPhilippe Mathieu-Daudé         /*
140032cad1ffSPhilippe Mathieu-Daudé          * If CACHE instruction is configured for ITC tags then make all
140132cad1ffSPhilippe Mathieu-Daudé          * CP0.TagLo bits writable. The actual write to ITC Configuration
140232cad1ffSPhilippe Mathieu-Daudé          * Tag will take care of the read-only bits.
140332cad1ffSPhilippe Mathieu-Daudé          */
140432cad1ffSPhilippe Mathieu-Daudé         env->CP0_TagLo = arg1;
140532cad1ffSPhilippe Mathieu-Daudé     } else {
140632cad1ffSPhilippe Mathieu-Daudé         env->CP0_TagLo = arg1 & 0xFFFFFCF6;
140732cad1ffSPhilippe Mathieu-Daudé     }
140832cad1ffSPhilippe Mathieu-Daudé }
140932cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_datalo(CPUMIPSState * env,target_ulong arg1)141032cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1)
141132cad1ffSPhilippe Mathieu-Daudé {
141232cad1ffSPhilippe Mathieu-Daudé     env->CP0_DataLo = arg1; /* XXX */
141332cad1ffSPhilippe Mathieu-Daudé }
141432cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_taghi(CPUMIPSState * env,target_ulong arg1)141532cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_taghi(CPUMIPSState *env, target_ulong arg1)
141632cad1ffSPhilippe Mathieu-Daudé {
141732cad1ffSPhilippe Mathieu-Daudé     env->CP0_TagHi = arg1; /* XXX */
141832cad1ffSPhilippe Mathieu-Daudé }
141932cad1ffSPhilippe Mathieu-Daudé 
helper_mtc0_datahi(CPUMIPSState * env,target_ulong arg1)142032cad1ffSPhilippe Mathieu-Daudé void helper_mtc0_datahi(CPUMIPSState *env, target_ulong arg1)
142132cad1ffSPhilippe Mathieu-Daudé {
142232cad1ffSPhilippe Mathieu-Daudé     env->CP0_DataHi = arg1; /* XXX */
142332cad1ffSPhilippe Mathieu-Daudé }
142432cad1ffSPhilippe Mathieu-Daudé 
142532cad1ffSPhilippe Mathieu-Daudé /* MIPS MT functions */
helper_mftgpr(CPUMIPSState * env,uint32_t sel)142632cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftgpr(CPUMIPSState *env, uint32_t sel)
142732cad1ffSPhilippe Mathieu-Daudé {
142832cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
142932cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
143032cad1ffSPhilippe Mathieu-Daudé 
143132cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
143232cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.gpr[sel];
143332cad1ffSPhilippe Mathieu-Daudé     } else {
143432cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].gpr[sel];
143532cad1ffSPhilippe Mathieu-Daudé     }
143632cad1ffSPhilippe Mathieu-Daudé }
143732cad1ffSPhilippe Mathieu-Daudé 
helper_mftlo(CPUMIPSState * env,uint32_t sel)143832cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftlo(CPUMIPSState *env, uint32_t sel)
143932cad1ffSPhilippe Mathieu-Daudé {
144032cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
144132cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
144232cad1ffSPhilippe Mathieu-Daudé 
144332cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
144432cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.LO[sel];
144532cad1ffSPhilippe Mathieu-Daudé     } else {
144632cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].LO[sel];
144732cad1ffSPhilippe Mathieu-Daudé     }
144832cad1ffSPhilippe Mathieu-Daudé }
144932cad1ffSPhilippe Mathieu-Daudé 
helper_mfthi(CPUMIPSState * env,uint32_t sel)145032cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mfthi(CPUMIPSState *env, uint32_t sel)
145132cad1ffSPhilippe Mathieu-Daudé {
145232cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
145332cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
145432cad1ffSPhilippe Mathieu-Daudé 
145532cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
145632cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.HI[sel];
145732cad1ffSPhilippe Mathieu-Daudé     } else {
145832cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].HI[sel];
145932cad1ffSPhilippe Mathieu-Daudé     }
146032cad1ffSPhilippe Mathieu-Daudé }
146132cad1ffSPhilippe Mathieu-Daudé 
helper_mftacx(CPUMIPSState * env,uint32_t sel)146232cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftacx(CPUMIPSState *env, uint32_t sel)
146332cad1ffSPhilippe Mathieu-Daudé {
146432cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
146532cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
146632cad1ffSPhilippe Mathieu-Daudé 
146732cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
146832cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.ACX[sel];
146932cad1ffSPhilippe Mathieu-Daudé     } else {
147032cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].ACX[sel];
147132cad1ffSPhilippe Mathieu-Daudé     }
147232cad1ffSPhilippe Mathieu-Daudé }
147332cad1ffSPhilippe Mathieu-Daudé 
helper_mftdsp(CPUMIPSState * env)147432cad1ffSPhilippe Mathieu-Daudé target_ulong helper_mftdsp(CPUMIPSState *env)
147532cad1ffSPhilippe Mathieu-Daudé {
147632cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
147732cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
147832cad1ffSPhilippe Mathieu-Daudé 
147932cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
148032cad1ffSPhilippe Mathieu-Daudé         return other->active_tc.DSPControl;
148132cad1ffSPhilippe Mathieu-Daudé     } else {
148232cad1ffSPhilippe Mathieu-Daudé         return other->tcs[other_tc].DSPControl;
148332cad1ffSPhilippe Mathieu-Daudé     }
148432cad1ffSPhilippe Mathieu-Daudé }
148532cad1ffSPhilippe Mathieu-Daudé 
helper_mttgpr(CPUMIPSState * env,target_ulong arg1,uint32_t sel)148632cad1ffSPhilippe Mathieu-Daudé void helper_mttgpr(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
148732cad1ffSPhilippe Mathieu-Daudé {
148832cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
148932cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
149032cad1ffSPhilippe Mathieu-Daudé 
149132cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
149232cad1ffSPhilippe Mathieu-Daudé         other->active_tc.gpr[sel] = arg1;
149332cad1ffSPhilippe Mathieu-Daudé     } else {
149432cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].gpr[sel] = arg1;
149532cad1ffSPhilippe Mathieu-Daudé     }
149632cad1ffSPhilippe Mathieu-Daudé }
149732cad1ffSPhilippe Mathieu-Daudé 
helper_mttlo(CPUMIPSState * env,target_ulong arg1,uint32_t sel)149832cad1ffSPhilippe Mathieu-Daudé void helper_mttlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
149932cad1ffSPhilippe Mathieu-Daudé {
150032cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
150132cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
150232cad1ffSPhilippe Mathieu-Daudé 
150332cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
150432cad1ffSPhilippe Mathieu-Daudé         other->active_tc.LO[sel] = arg1;
150532cad1ffSPhilippe Mathieu-Daudé     } else {
150632cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].LO[sel] = arg1;
150732cad1ffSPhilippe Mathieu-Daudé     }
150832cad1ffSPhilippe Mathieu-Daudé }
150932cad1ffSPhilippe Mathieu-Daudé 
helper_mtthi(CPUMIPSState * env,target_ulong arg1,uint32_t sel)151032cad1ffSPhilippe Mathieu-Daudé void helper_mtthi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
151132cad1ffSPhilippe Mathieu-Daudé {
151232cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
151332cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
151432cad1ffSPhilippe Mathieu-Daudé 
151532cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
151632cad1ffSPhilippe Mathieu-Daudé         other->active_tc.HI[sel] = arg1;
151732cad1ffSPhilippe Mathieu-Daudé     } else {
151832cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].HI[sel] = arg1;
151932cad1ffSPhilippe Mathieu-Daudé     }
152032cad1ffSPhilippe Mathieu-Daudé }
152132cad1ffSPhilippe Mathieu-Daudé 
helper_mttacx(CPUMIPSState * env,target_ulong arg1,uint32_t sel)152232cad1ffSPhilippe Mathieu-Daudé void helper_mttacx(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
152332cad1ffSPhilippe Mathieu-Daudé {
152432cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
152532cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
152632cad1ffSPhilippe Mathieu-Daudé 
152732cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
152832cad1ffSPhilippe Mathieu-Daudé         other->active_tc.ACX[sel] = arg1;
152932cad1ffSPhilippe Mathieu-Daudé     } else {
153032cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].ACX[sel] = arg1;
153132cad1ffSPhilippe Mathieu-Daudé     }
153232cad1ffSPhilippe Mathieu-Daudé }
153332cad1ffSPhilippe Mathieu-Daudé 
helper_mttdsp(CPUMIPSState * env,target_ulong arg1)153432cad1ffSPhilippe Mathieu-Daudé void helper_mttdsp(CPUMIPSState *env, target_ulong arg1)
153532cad1ffSPhilippe Mathieu-Daudé {
153632cad1ffSPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
153732cad1ffSPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
153832cad1ffSPhilippe Mathieu-Daudé 
153932cad1ffSPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
154032cad1ffSPhilippe Mathieu-Daudé         other->active_tc.DSPControl = arg1;
154132cad1ffSPhilippe Mathieu-Daudé     } else {
154232cad1ffSPhilippe Mathieu-Daudé         other->tcs[other_tc].DSPControl = arg1;
154332cad1ffSPhilippe Mathieu-Daudé     }
154432cad1ffSPhilippe Mathieu-Daudé }
154532cad1ffSPhilippe Mathieu-Daudé 
154632cad1ffSPhilippe Mathieu-Daudé /* MIPS MT functions */
helper_dmt(void)154732cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dmt(void)
154832cad1ffSPhilippe Mathieu-Daudé {
154932cad1ffSPhilippe Mathieu-Daudé     /* TODO */
155032cad1ffSPhilippe Mathieu-Daudé     return 0;
155132cad1ffSPhilippe Mathieu-Daudé }
155232cad1ffSPhilippe Mathieu-Daudé 
helper_emt(void)155332cad1ffSPhilippe Mathieu-Daudé target_ulong helper_emt(void)
155432cad1ffSPhilippe Mathieu-Daudé {
155532cad1ffSPhilippe Mathieu-Daudé     /* TODO */
155632cad1ffSPhilippe Mathieu-Daudé     return 0;
155732cad1ffSPhilippe Mathieu-Daudé }
155832cad1ffSPhilippe Mathieu-Daudé 
helper_dvpe(CPUMIPSState * env)155932cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dvpe(CPUMIPSState *env)
156032cad1ffSPhilippe Mathieu-Daudé {
156132cad1ffSPhilippe Mathieu-Daudé     CPUState *other_cs = first_cpu;
156232cad1ffSPhilippe Mathieu-Daudé     target_ulong prev = env->mvp->CP0_MVPControl;
156332cad1ffSPhilippe Mathieu-Daudé 
156432cad1ffSPhilippe Mathieu-Daudé     CPU_FOREACH(other_cs) {
156532cad1ffSPhilippe Mathieu-Daudé         MIPSCPU *other_cpu = MIPS_CPU(other_cs);
156632cad1ffSPhilippe Mathieu-Daudé         /* Turn off all VPEs except the one executing the dvpe.  */
156732cad1ffSPhilippe Mathieu-Daudé         if (&other_cpu->env != env) {
156832cad1ffSPhilippe Mathieu-Daudé             other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
156932cad1ffSPhilippe Mathieu-Daudé             mips_vpe_sleep(other_cpu);
157032cad1ffSPhilippe Mathieu-Daudé         }
157132cad1ffSPhilippe Mathieu-Daudé     }
157232cad1ffSPhilippe Mathieu-Daudé     return prev;
157332cad1ffSPhilippe Mathieu-Daudé }
157432cad1ffSPhilippe Mathieu-Daudé 
helper_evpe(CPUMIPSState * env)157532cad1ffSPhilippe Mathieu-Daudé target_ulong helper_evpe(CPUMIPSState *env)
157632cad1ffSPhilippe Mathieu-Daudé {
157732cad1ffSPhilippe Mathieu-Daudé     CPUState *other_cs = first_cpu;
157832cad1ffSPhilippe Mathieu-Daudé     target_ulong prev = env->mvp->CP0_MVPControl;
157932cad1ffSPhilippe Mathieu-Daudé 
158032cad1ffSPhilippe Mathieu-Daudé     CPU_FOREACH(other_cs) {
158132cad1ffSPhilippe Mathieu-Daudé         MIPSCPU *other_cpu = MIPS_CPU(other_cs);
158232cad1ffSPhilippe Mathieu-Daudé 
158332cad1ffSPhilippe Mathieu-Daudé         if (&other_cpu->env != env
158432cad1ffSPhilippe Mathieu-Daudé             /* If the VPE is WFI, don't disturb its sleep.  */
158532cad1ffSPhilippe Mathieu-Daudé             && !mips_vpe_is_wfi(other_cpu)) {
158632cad1ffSPhilippe Mathieu-Daudé             /* Enable the VPE.  */
158732cad1ffSPhilippe Mathieu-Daudé             other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
158832cad1ffSPhilippe Mathieu-Daudé             mips_vpe_wake(other_cpu); /* And wake it up.  */
158932cad1ffSPhilippe Mathieu-Daudé         }
159032cad1ffSPhilippe Mathieu-Daudé     }
159132cad1ffSPhilippe Mathieu-Daudé     return prev;
159232cad1ffSPhilippe Mathieu-Daudé }
159332cad1ffSPhilippe Mathieu-Daudé 
159432cad1ffSPhilippe Mathieu-Daudé /* R6 Multi-threading */
helper_dvp(CPUMIPSState * env)159532cad1ffSPhilippe Mathieu-Daudé target_ulong helper_dvp(CPUMIPSState *env)
159632cad1ffSPhilippe Mathieu-Daudé {
159732cad1ffSPhilippe Mathieu-Daudé     CPUState *other_cs = first_cpu;
159832cad1ffSPhilippe Mathieu-Daudé     target_ulong prev = env->CP0_VPControl;
159932cad1ffSPhilippe Mathieu-Daudé 
160032cad1ffSPhilippe Mathieu-Daudé     if (!((env->CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
160132cad1ffSPhilippe Mathieu-Daudé         CPU_FOREACH(other_cs) {
160232cad1ffSPhilippe Mathieu-Daudé             MIPSCPU *other_cpu = MIPS_CPU(other_cs);
160332cad1ffSPhilippe Mathieu-Daudé             /* Turn off all VPs except the one executing the dvp. */
160432cad1ffSPhilippe Mathieu-Daudé             if (&other_cpu->env != env) {
160532cad1ffSPhilippe Mathieu-Daudé                 mips_vpe_sleep(other_cpu);
160632cad1ffSPhilippe Mathieu-Daudé             }
160732cad1ffSPhilippe Mathieu-Daudé         }
160832cad1ffSPhilippe Mathieu-Daudé         env->CP0_VPControl |= (1 << CP0VPCtl_DIS);
160932cad1ffSPhilippe Mathieu-Daudé     }
161032cad1ffSPhilippe Mathieu-Daudé     return prev;
161132cad1ffSPhilippe Mathieu-Daudé }
161232cad1ffSPhilippe Mathieu-Daudé 
helper_evp(CPUMIPSState * env)161332cad1ffSPhilippe Mathieu-Daudé target_ulong helper_evp(CPUMIPSState *env)
161432cad1ffSPhilippe Mathieu-Daudé {
161532cad1ffSPhilippe Mathieu-Daudé     CPUState *other_cs = first_cpu;
161632cad1ffSPhilippe Mathieu-Daudé     target_ulong prev = env->CP0_VPControl;
161732cad1ffSPhilippe Mathieu-Daudé 
161832cad1ffSPhilippe Mathieu-Daudé     if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
161932cad1ffSPhilippe Mathieu-Daudé         CPU_FOREACH(other_cs) {
162032cad1ffSPhilippe Mathieu-Daudé             MIPSCPU *other_cpu = MIPS_CPU(other_cs);
162132cad1ffSPhilippe Mathieu-Daudé             if ((&other_cpu->env != env) && !mips_vp_is_wfi(other_cpu)) {
162232cad1ffSPhilippe Mathieu-Daudé                 /*
162332cad1ffSPhilippe Mathieu-Daudé                  * If the VP is WFI, don't disturb its sleep.
162432cad1ffSPhilippe Mathieu-Daudé                  * Otherwise, wake it up.
162532cad1ffSPhilippe Mathieu-Daudé                  */
162632cad1ffSPhilippe Mathieu-Daudé                 mips_vpe_wake(other_cpu);
162732cad1ffSPhilippe Mathieu-Daudé             }
162832cad1ffSPhilippe Mathieu-Daudé         }
162932cad1ffSPhilippe Mathieu-Daudé         env->CP0_VPControl &= ~(1 << CP0VPCtl_DIS);
163032cad1ffSPhilippe Mathieu-Daudé     }
163132cad1ffSPhilippe Mathieu-Daudé     return prev;
163232cad1ffSPhilippe Mathieu-Daudé }
1633