xref: /openbmc/qemu/target/mips/tcg/sysemu/cp0_helper.c (revision d16cab541ab9217977e2a39abf3d79f914146741)
1ad520a97SPhilippe Mathieu-Daudé /*
2ad520a97SPhilippe Mathieu-Daudé  *  Helpers for emulation of CP0-related MIPS instructions.
3ad520a97SPhilippe Mathieu-Daudé  *
4ad520a97SPhilippe Mathieu-Daudé  *  Copyright (C) 2004-2005  Jocelyn Mayer
5ad520a97SPhilippe Mathieu-Daudé  *  Copyright (C) 2020  Wave Computing, Inc.
6ad520a97SPhilippe Mathieu-Daudé  *  Copyright (C) 2020  Aleksandar Markovic <amarkovic@wavecomp.com>
7ad520a97SPhilippe Mathieu-Daudé  *
8ad520a97SPhilippe Mathieu-Daudé  * This library is free software; you can redistribute it and/or
9ad520a97SPhilippe Mathieu-Daudé  * modify it under the terms of the GNU Lesser General Public
10ad520a97SPhilippe Mathieu-Daudé  * License as published by the Free Software Foundation; either
11ad520a97SPhilippe Mathieu-Daudé  * version 2.1 of the License, or (at your option) any later version.
12ad520a97SPhilippe Mathieu-Daudé  *
13ad520a97SPhilippe Mathieu-Daudé  * This library is distributed in the hope that it will be useful,
14ad520a97SPhilippe Mathieu-Daudé  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15ad520a97SPhilippe Mathieu-Daudé  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16ad520a97SPhilippe Mathieu-Daudé  * Lesser General Public License for more details.
17ad520a97SPhilippe Mathieu-Daudé  *
18ad520a97SPhilippe Mathieu-Daudé  * You should have received a copy of the GNU Lesser General Public
19ad520a97SPhilippe Mathieu-Daudé  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20ad520a97SPhilippe Mathieu-Daudé  *
21ad520a97SPhilippe Mathieu-Daudé  */
22ad520a97SPhilippe Mathieu-Daudé 
23ad520a97SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
24ad520a97SPhilippe Mathieu-Daudé #include "qemu/log.h"
25ad520a97SPhilippe Mathieu-Daudé #include "qemu/main-loop.h"
26ad520a97SPhilippe Mathieu-Daudé #include "cpu.h"
27ad520a97SPhilippe Mathieu-Daudé #include "internal.h"
28ad520a97SPhilippe Mathieu-Daudé #include "qemu/host-utils.h"
29ad520a97SPhilippe Mathieu-Daudé #include "exec/helper-proto.h"
30ad520a97SPhilippe Mathieu-Daudé #include "exec/exec-all.h"
31ad520a97SPhilippe Mathieu-Daudé 
32ad520a97SPhilippe Mathieu-Daudé 
33ad520a97SPhilippe Mathieu-Daudé /* SMP helpers.  */
mips_vpe_is_wfi(MIPSCPU * c)34ad520a97SPhilippe Mathieu-Daudé static bool mips_vpe_is_wfi(MIPSCPU *c)
35ad520a97SPhilippe Mathieu-Daudé {
36ad520a97SPhilippe Mathieu-Daudé     CPUState *cpu = CPU(c);
37ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *env = &c->env;
38ad520a97SPhilippe Mathieu-Daudé 
39ad520a97SPhilippe Mathieu-Daudé     /*
40ad520a97SPhilippe Mathieu-Daudé      * If the VPE is halted but otherwise active, it means it's waiting for
41ad520a97SPhilippe Mathieu-Daudé      * an interrupt.\
42ad520a97SPhilippe Mathieu-Daudé      */
43ad520a97SPhilippe Mathieu-Daudé     return cpu->halted && mips_vpe_active(env);
44ad520a97SPhilippe Mathieu-Daudé }
45ad520a97SPhilippe Mathieu-Daudé 
mips_vp_is_wfi(MIPSCPU * c)46ad520a97SPhilippe Mathieu-Daudé static bool mips_vp_is_wfi(MIPSCPU *c)
47ad520a97SPhilippe Mathieu-Daudé {
48ad520a97SPhilippe Mathieu-Daudé     CPUState *cpu = CPU(c);
49ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *env = &c->env;
50ad520a97SPhilippe Mathieu-Daudé 
51ad520a97SPhilippe Mathieu-Daudé     return cpu->halted && mips_vp_active(env);
52ad520a97SPhilippe Mathieu-Daudé }
53ad520a97SPhilippe Mathieu-Daudé 
mips_vpe_wake(MIPSCPU * c)54ad520a97SPhilippe Mathieu-Daudé static inline void mips_vpe_wake(MIPSCPU *c)
55ad520a97SPhilippe Mathieu-Daudé {
56ad520a97SPhilippe Mathieu-Daudé     /*
57ad520a97SPhilippe Mathieu-Daudé      * Don't set ->halted = 0 directly, let it be done via cpu_has_work
58ad520a97SPhilippe Mathieu-Daudé      * because there might be other conditions that state that c should
59ad520a97SPhilippe Mathieu-Daudé      * be sleeping.
60ad520a97SPhilippe Mathieu-Daudé      */
61195801d7SStefan Hajnoczi     bql_lock();
62ad520a97SPhilippe Mathieu-Daudé     cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
63195801d7SStefan Hajnoczi     bql_unlock();
64ad520a97SPhilippe Mathieu-Daudé }
65ad520a97SPhilippe Mathieu-Daudé 
mips_vpe_sleep(MIPSCPU * cpu)66ad520a97SPhilippe Mathieu-Daudé static inline void mips_vpe_sleep(MIPSCPU *cpu)
67ad520a97SPhilippe Mathieu-Daudé {
68ad520a97SPhilippe Mathieu-Daudé     CPUState *cs = CPU(cpu);
69ad520a97SPhilippe Mathieu-Daudé 
70ad520a97SPhilippe Mathieu-Daudé     /*
71ad520a97SPhilippe Mathieu-Daudé      * The VPE was shut off, really go to bed.
72ad520a97SPhilippe Mathieu-Daudé      * Reset any old _WAKE requests.
73ad520a97SPhilippe Mathieu-Daudé      */
74ad520a97SPhilippe Mathieu-Daudé     cs->halted = 1;
75ad520a97SPhilippe Mathieu-Daudé     cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
76ad520a97SPhilippe Mathieu-Daudé }
77ad520a97SPhilippe Mathieu-Daudé 
mips_tc_wake(MIPSCPU * cpu,int tc)78ad520a97SPhilippe Mathieu-Daudé static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
79ad520a97SPhilippe Mathieu-Daudé {
80ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *c = &cpu->env;
81ad520a97SPhilippe Mathieu-Daudé 
82ad520a97SPhilippe Mathieu-Daudé     /* FIXME: TC reschedule.  */
83ad520a97SPhilippe Mathieu-Daudé     if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
84ad520a97SPhilippe Mathieu-Daudé         mips_vpe_wake(cpu);
85ad520a97SPhilippe Mathieu-Daudé     }
86ad520a97SPhilippe Mathieu-Daudé }
87ad520a97SPhilippe Mathieu-Daudé 
mips_tc_sleep(MIPSCPU * cpu,int tc)88ad520a97SPhilippe Mathieu-Daudé static inline void mips_tc_sleep(MIPSCPU *cpu, int tc)
89ad520a97SPhilippe Mathieu-Daudé {
90ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *c = &cpu->env;
91ad520a97SPhilippe Mathieu-Daudé 
92ad520a97SPhilippe Mathieu-Daudé     /* FIXME: TC reschedule.  */
93ad520a97SPhilippe Mathieu-Daudé     if (!mips_vpe_active(c)) {
94ad520a97SPhilippe Mathieu-Daudé         mips_vpe_sleep(cpu);
95ad520a97SPhilippe Mathieu-Daudé     }
96ad520a97SPhilippe Mathieu-Daudé }
97ad520a97SPhilippe Mathieu-Daudé 
98ad520a97SPhilippe Mathieu-Daudé /**
99ad520a97SPhilippe Mathieu-Daudé  * mips_cpu_map_tc:
100ad520a97SPhilippe Mathieu-Daudé  * @env: CPU from which mapping is performed.
101ad520a97SPhilippe Mathieu-Daudé  * @tc: Should point to an int with the value of the global TC index.
102ad520a97SPhilippe Mathieu-Daudé  *
103ad520a97SPhilippe Mathieu-Daudé  * This function will transform @tc into a local index within the
104ad520a97SPhilippe Mathieu-Daudé  * returned #CPUMIPSState.
105ad520a97SPhilippe Mathieu-Daudé  */
106ad520a97SPhilippe Mathieu-Daudé 
107ad520a97SPhilippe Mathieu-Daudé /*
108ad520a97SPhilippe Mathieu-Daudé  * FIXME: This code assumes that all VPEs have the same number of TCs,
109ad520a97SPhilippe Mathieu-Daudé  *        which depends on runtime setup. Can probably be fixed by
110ad520a97SPhilippe Mathieu-Daudé  *        walking the list of CPUMIPSStates.
111ad520a97SPhilippe Mathieu-Daudé  */
mips_cpu_map_tc(CPUMIPSState * env,int * tc)112ad520a97SPhilippe Mathieu-Daudé static CPUMIPSState *mips_cpu_map_tc(CPUMIPSState *env, int *tc)
113ad520a97SPhilippe Mathieu-Daudé {
114ad520a97SPhilippe Mathieu-Daudé     MIPSCPU *cpu;
115ad520a97SPhilippe Mathieu-Daudé     CPUState *cs;
116ad520a97SPhilippe Mathieu-Daudé     CPUState *other_cs;
117ad520a97SPhilippe Mathieu-Daudé     int vpe_idx;
118ad520a97SPhilippe Mathieu-Daudé     int tc_idx = *tc;
119ad520a97SPhilippe Mathieu-Daudé 
120ad520a97SPhilippe Mathieu-Daudé     if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) {
121ad520a97SPhilippe Mathieu-Daudé         /* Not allowed to address other CPUs.  */
122ad520a97SPhilippe Mathieu-Daudé         *tc = env->current_tc;
123ad520a97SPhilippe Mathieu-Daudé         return env;
124ad520a97SPhilippe Mathieu-Daudé     }
125ad520a97SPhilippe Mathieu-Daudé 
126ad520a97SPhilippe Mathieu-Daudé     cs = env_cpu(env);
127ad520a97SPhilippe Mathieu-Daudé     vpe_idx = tc_idx / cs->nr_threads;
128ad520a97SPhilippe Mathieu-Daudé     *tc = tc_idx % cs->nr_threads;
129ad520a97SPhilippe Mathieu-Daudé     other_cs = qemu_get_cpu(vpe_idx);
130ad520a97SPhilippe Mathieu-Daudé     if (other_cs == NULL) {
131ad520a97SPhilippe Mathieu-Daudé         return env;
132ad520a97SPhilippe Mathieu-Daudé     }
133ad520a97SPhilippe Mathieu-Daudé     cpu = MIPS_CPU(other_cs);
134ad520a97SPhilippe Mathieu-Daudé     return &cpu->env;
135ad520a97SPhilippe Mathieu-Daudé }
136ad520a97SPhilippe Mathieu-Daudé 
137ad520a97SPhilippe Mathieu-Daudé /*
138ad520a97SPhilippe Mathieu-Daudé  * The per VPE CP0_Status register shares some fields with the per TC
139ad520a97SPhilippe Mathieu-Daudé  * CP0_TCStatus registers. These fields are wired to the same registers,
140ad520a97SPhilippe Mathieu-Daudé  * so changes to either of them should be reflected on both registers.
141ad520a97SPhilippe Mathieu-Daudé  *
142ad520a97SPhilippe Mathieu-Daudé  * Also, EntryHi shares the bottom 8 bit ASID with TCStauts.
143ad520a97SPhilippe Mathieu-Daudé  *
144ad520a97SPhilippe Mathieu-Daudé  * These helper call synchronizes the regs for a given cpu.
145ad520a97SPhilippe Mathieu-Daudé  */
146ad520a97SPhilippe Mathieu-Daudé 
147ad520a97SPhilippe Mathieu-Daudé /*
148ad520a97SPhilippe Mathieu-Daudé  * Called for updates to CP0_Status.  Defined in "cpu.h" for gdbstub.c.
149ad520a97SPhilippe Mathieu-Daudé  * static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu,
150ad520a97SPhilippe Mathieu-Daudé  *                                   int tc);
151ad520a97SPhilippe Mathieu-Daudé  */
152ad520a97SPhilippe Mathieu-Daudé 
153ad520a97SPhilippe Mathieu-Daudé /* Called for updates to CP0_TCStatus.  */
sync_c0_tcstatus(CPUMIPSState * cpu,int tc,target_ulong v)154ad520a97SPhilippe Mathieu-Daudé static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc,
155ad520a97SPhilippe Mathieu-Daudé                              target_ulong v)
156ad520a97SPhilippe Mathieu-Daudé {
157ad520a97SPhilippe Mathieu-Daudé     uint32_t status;
158ad520a97SPhilippe Mathieu-Daudé     uint32_t tcu, tmx, tasid, tksu;
159ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = ((1U << CP0St_CU3)
160ad520a97SPhilippe Mathieu-Daudé                        | (1 << CP0St_CU2)
161ad520a97SPhilippe Mathieu-Daudé                        | (1 << CP0St_CU1)
162ad520a97SPhilippe Mathieu-Daudé                        | (1 << CP0St_CU0)
163ad520a97SPhilippe Mathieu-Daudé                        | (1 << CP0St_MX)
164ad520a97SPhilippe Mathieu-Daudé                        | (3 << CP0St_KSU));
165ad520a97SPhilippe Mathieu-Daudé 
166ad520a97SPhilippe Mathieu-Daudé     tcu = (v >> CP0TCSt_TCU0) & 0xf;
167ad520a97SPhilippe Mathieu-Daudé     tmx = (v >> CP0TCSt_TMX) & 0x1;
168ad520a97SPhilippe Mathieu-Daudé     tasid = v & cpu->CP0_EntryHi_ASID_mask;
169ad520a97SPhilippe Mathieu-Daudé     tksu = (v >> CP0TCSt_TKSU) & 0x3;
170ad520a97SPhilippe Mathieu-Daudé 
171ad520a97SPhilippe Mathieu-Daudé     status = tcu << CP0St_CU0;
172ad520a97SPhilippe Mathieu-Daudé     status |= tmx << CP0St_MX;
173ad520a97SPhilippe Mathieu-Daudé     status |= tksu << CP0St_KSU;
174ad520a97SPhilippe Mathieu-Daudé 
175ad520a97SPhilippe Mathieu-Daudé     cpu->CP0_Status &= ~mask;
176ad520a97SPhilippe Mathieu-Daudé     cpu->CP0_Status |= status;
177ad520a97SPhilippe Mathieu-Daudé 
178ad520a97SPhilippe Mathieu-Daudé     /* Sync the TASID with EntryHi.  */
179ad520a97SPhilippe Mathieu-Daudé     cpu->CP0_EntryHi &= ~cpu->CP0_EntryHi_ASID_mask;
180ad520a97SPhilippe Mathieu-Daudé     cpu->CP0_EntryHi |= tasid;
181ad520a97SPhilippe Mathieu-Daudé 
182ad520a97SPhilippe Mathieu-Daudé     compute_hflags(cpu);
183ad520a97SPhilippe Mathieu-Daudé }
184ad520a97SPhilippe Mathieu-Daudé 
185ad520a97SPhilippe Mathieu-Daudé /* Called for updates to CP0_EntryHi.  */
sync_c0_entryhi(CPUMIPSState * cpu,int tc)186ad520a97SPhilippe Mathieu-Daudé static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
187ad520a97SPhilippe Mathieu-Daudé {
188ad520a97SPhilippe Mathieu-Daudé     int32_t *tcst;
189ad520a97SPhilippe Mathieu-Daudé     uint32_t asid, v = cpu->CP0_EntryHi;
190ad520a97SPhilippe Mathieu-Daudé 
191ad520a97SPhilippe Mathieu-Daudé     asid = v & cpu->CP0_EntryHi_ASID_mask;
192ad520a97SPhilippe Mathieu-Daudé 
193ad520a97SPhilippe Mathieu-Daudé     if (tc == cpu->current_tc) {
194ad520a97SPhilippe Mathieu-Daudé         tcst = &cpu->active_tc.CP0_TCStatus;
195ad520a97SPhilippe Mathieu-Daudé     } else {
196ad520a97SPhilippe Mathieu-Daudé         tcst = &cpu->tcs[tc].CP0_TCStatus;
197ad520a97SPhilippe Mathieu-Daudé     }
198ad520a97SPhilippe Mathieu-Daudé 
199ad520a97SPhilippe Mathieu-Daudé     *tcst &= ~cpu->CP0_EntryHi_ASID_mask;
200ad520a97SPhilippe Mathieu-Daudé     *tcst |= asid;
201ad520a97SPhilippe Mathieu-Daudé }
202ad520a97SPhilippe Mathieu-Daudé 
203ad520a97SPhilippe Mathieu-Daudé /* XXX: do not use a global */
cpu_mips_get_random(CPUMIPSState * env)204ad520a97SPhilippe Mathieu-Daudé uint32_t cpu_mips_get_random(CPUMIPSState *env)
205ad520a97SPhilippe Mathieu-Daudé {
206ad520a97SPhilippe Mathieu-Daudé     static uint32_t seed = 1;
207ad520a97SPhilippe Mathieu-Daudé     static uint32_t prev_idx;
208ad520a97SPhilippe Mathieu-Daudé     uint32_t idx;
209ad520a97SPhilippe Mathieu-Daudé     uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired;
210ad520a97SPhilippe Mathieu-Daudé 
211ad520a97SPhilippe Mathieu-Daudé     if (nb_rand_tlb == 1) {
212ad520a97SPhilippe Mathieu-Daudé         return env->tlb->nb_tlb - 1;
213ad520a97SPhilippe Mathieu-Daudé     }
214ad520a97SPhilippe Mathieu-Daudé 
215ad520a97SPhilippe Mathieu-Daudé     /* Don't return same value twice, so get another value */
216ad520a97SPhilippe Mathieu-Daudé     do {
217ad520a97SPhilippe Mathieu-Daudé         /*
218ad520a97SPhilippe Mathieu-Daudé          * Use a simple algorithm of Linear Congruential Generator
219ad520a97SPhilippe Mathieu-Daudé          * from ISO/IEC 9899 standard.
220ad520a97SPhilippe Mathieu-Daudé          */
221ad520a97SPhilippe Mathieu-Daudé         seed = 1103515245 * seed + 12345;
222ad520a97SPhilippe Mathieu-Daudé         idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired;
223ad520a97SPhilippe Mathieu-Daudé     } while (idx == prev_idx);
224ad520a97SPhilippe Mathieu-Daudé     prev_idx = idx;
225ad520a97SPhilippe Mathieu-Daudé     return idx;
226ad520a97SPhilippe Mathieu-Daudé }
227ad520a97SPhilippe Mathieu-Daudé 
228ad520a97SPhilippe Mathieu-Daudé /* CP0 helpers */
helper_mfc0_mvpcontrol(CPUMIPSState * env)229ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env)
230ad520a97SPhilippe Mathieu-Daudé {
231ad520a97SPhilippe Mathieu-Daudé     return env->mvp->CP0_MVPControl;
232ad520a97SPhilippe Mathieu-Daudé }
233ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_mvpconf0(CPUMIPSState * env)234ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_mvpconf0(CPUMIPSState *env)
235ad520a97SPhilippe Mathieu-Daudé {
236ad520a97SPhilippe Mathieu-Daudé     return env->mvp->CP0_MVPConf0;
237ad520a97SPhilippe Mathieu-Daudé }
238ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_mvpconf1(CPUMIPSState * env)239ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_mvpconf1(CPUMIPSState *env)
240ad520a97SPhilippe Mathieu-Daudé {
241ad520a97SPhilippe Mathieu-Daudé     return env->mvp->CP0_MVPConf1;
242ad520a97SPhilippe Mathieu-Daudé }
243ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_random(CPUMIPSState * env)244ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_random(CPUMIPSState *env)
245ad520a97SPhilippe Mathieu-Daudé {
246ad520a97SPhilippe Mathieu-Daudé     return (int32_t)cpu_mips_get_random(env);
247ad520a97SPhilippe Mathieu-Daudé }
248ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_tcstatus(CPUMIPSState * env)249ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcstatus(CPUMIPSState *env)
250ad520a97SPhilippe Mathieu-Daudé {
251ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCStatus;
252ad520a97SPhilippe Mathieu-Daudé }
253ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_tcstatus(CPUMIPSState * env)254ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcstatus(CPUMIPSState *env)
255ad520a97SPhilippe Mathieu-Daudé {
256ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
257ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
258ad520a97SPhilippe Mathieu-Daudé 
259ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
260ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCStatus;
261ad520a97SPhilippe Mathieu-Daudé     } else {
262ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCStatus;
263ad520a97SPhilippe Mathieu-Daudé     }
264ad520a97SPhilippe Mathieu-Daudé }
265ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_tcbind(CPUMIPSState * env)266ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcbind(CPUMIPSState *env)
267ad520a97SPhilippe Mathieu-Daudé {
268ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCBind;
269ad520a97SPhilippe Mathieu-Daudé }
270ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_tcbind(CPUMIPSState * env)271ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcbind(CPUMIPSState *env)
272ad520a97SPhilippe Mathieu-Daudé {
273ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
274ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
275ad520a97SPhilippe Mathieu-Daudé 
276ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
277ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCBind;
278ad520a97SPhilippe Mathieu-Daudé     } else {
279ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCBind;
280ad520a97SPhilippe Mathieu-Daudé     }
281ad520a97SPhilippe Mathieu-Daudé }
282ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_tcrestart(CPUMIPSState * env)283ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcrestart(CPUMIPSState *env)
284ad520a97SPhilippe Mathieu-Daudé {
285ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.PC;
286ad520a97SPhilippe Mathieu-Daudé }
287ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_tcrestart(CPUMIPSState * env)288ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcrestart(CPUMIPSState *env)
289ad520a97SPhilippe Mathieu-Daudé {
290ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
291ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
292ad520a97SPhilippe Mathieu-Daudé 
293ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
294ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.PC;
295ad520a97SPhilippe Mathieu-Daudé     } else {
296ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].PC;
297ad520a97SPhilippe Mathieu-Daudé     }
298ad520a97SPhilippe Mathieu-Daudé }
299ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_tchalt(CPUMIPSState * env)300ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_tchalt(CPUMIPSState *env)
301ad520a97SPhilippe Mathieu-Daudé {
302ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCHalt;
303ad520a97SPhilippe Mathieu-Daudé }
304ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_tchalt(CPUMIPSState * env)305ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_tchalt(CPUMIPSState *env)
306ad520a97SPhilippe Mathieu-Daudé {
307ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
308ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
309ad520a97SPhilippe Mathieu-Daudé 
310ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
311ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCHalt;
312ad520a97SPhilippe Mathieu-Daudé     } else {
313ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCHalt;
314ad520a97SPhilippe Mathieu-Daudé     }
315ad520a97SPhilippe Mathieu-Daudé }
316ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_tccontext(CPUMIPSState * env)317ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_tccontext(CPUMIPSState *env)
318ad520a97SPhilippe Mathieu-Daudé {
319ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCContext;
320ad520a97SPhilippe Mathieu-Daudé }
321ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_tccontext(CPUMIPSState * env)322ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_tccontext(CPUMIPSState *env)
323ad520a97SPhilippe Mathieu-Daudé {
324ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
325ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
326ad520a97SPhilippe Mathieu-Daudé 
327ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
328ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCContext;
329ad520a97SPhilippe Mathieu-Daudé     } else {
330ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCContext;
331ad520a97SPhilippe Mathieu-Daudé     }
332ad520a97SPhilippe Mathieu-Daudé }
333ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_tcschedule(CPUMIPSState * env)334ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcschedule(CPUMIPSState *env)
335ad520a97SPhilippe Mathieu-Daudé {
336ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCSchedule;
337ad520a97SPhilippe Mathieu-Daudé }
338ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_tcschedule(CPUMIPSState * env)339ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcschedule(CPUMIPSState *env)
340ad520a97SPhilippe Mathieu-Daudé {
341ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
342ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
343ad520a97SPhilippe Mathieu-Daudé 
344ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
345ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCSchedule;
346ad520a97SPhilippe Mathieu-Daudé     } else {
347ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCSchedule;
348ad520a97SPhilippe Mathieu-Daudé     }
349ad520a97SPhilippe Mathieu-Daudé }
350ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_tcschefback(CPUMIPSState * env)351ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_tcschefback(CPUMIPSState *env)
352ad520a97SPhilippe Mathieu-Daudé {
353ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCScheFBack;
354ad520a97SPhilippe Mathieu-Daudé }
355ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_tcschefback(CPUMIPSState * env)356ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_tcschefback(CPUMIPSState *env)
357ad520a97SPhilippe Mathieu-Daudé {
358ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
359ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
360ad520a97SPhilippe Mathieu-Daudé 
361ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
362ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.CP0_TCScheFBack;
363ad520a97SPhilippe Mathieu-Daudé     } else {
364ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].CP0_TCScheFBack;
365ad520a97SPhilippe Mathieu-Daudé     }
366ad520a97SPhilippe Mathieu-Daudé }
367ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_count(CPUMIPSState * env)368ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_count(CPUMIPSState *env)
369ad520a97SPhilippe Mathieu-Daudé {
370ad520a97SPhilippe Mathieu-Daudé     return (int32_t)cpu_mips_get_count(env);
371ad520a97SPhilippe Mathieu-Daudé }
372ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_entryhi(CPUMIPSState * env)373ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_entryhi(CPUMIPSState *env)
374ad520a97SPhilippe Mathieu-Daudé {
375ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
376ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
377ad520a97SPhilippe Mathieu-Daudé 
378ad520a97SPhilippe Mathieu-Daudé     return other->CP0_EntryHi;
379ad520a97SPhilippe Mathieu-Daudé }
380ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_cause(CPUMIPSState * env)381ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_cause(CPUMIPSState *env)
382ad520a97SPhilippe Mathieu-Daudé {
383ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
384ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
385ad520a97SPhilippe Mathieu-Daudé 
386ad520a97SPhilippe Mathieu-Daudé     return other->CP0_Cause;
387ad520a97SPhilippe Mathieu-Daudé }
388ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_status(CPUMIPSState * env)389ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_status(CPUMIPSState *env)
390ad520a97SPhilippe Mathieu-Daudé {
391ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
392ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
393ad520a97SPhilippe Mathieu-Daudé 
394ad520a97SPhilippe Mathieu-Daudé     return other->CP0_Status;
395ad520a97SPhilippe Mathieu-Daudé }
396ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_lladdr(CPUMIPSState * env)397ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_lladdr(CPUMIPSState *env)
398ad520a97SPhilippe Mathieu-Daudé {
399ad520a97SPhilippe Mathieu-Daudé     return (int32_t)(env->CP0_LLAddr >> env->CP0_LLAddr_shift);
400ad520a97SPhilippe Mathieu-Daudé }
401ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_maar(CPUMIPSState * env)402ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_maar(CPUMIPSState *env)
403ad520a97SPhilippe Mathieu-Daudé {
404ad520a97SPhilippe Mathieu-Daudé     return (int32_t) env->CP0_MAAR[env->CP0_MAARI];
405ad520a97SPhilippe Mathieu-Daudé }
406ad520a97SPhilippe Mathieu-Daudé 
helper_mfhc0_maar(CPUMIPSState * env)407ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfhc0_maar(CPUMIPSState *env)
408ad520a97SPhilippe Mathieu-Daudé {
409ad520a97SPhilippe Mathieu-Daudé     return env->CP0_MAAR[env->CP0_MAARI] >> 32;
410ad520a97SPhilippe Mathieu-Daudé }
411ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_watchlo(CPUMIPSState * env,uint32_t sel)412ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel)
413ad520a97SPhilippe Mathieu-Daudé {
414ad520a97SPhilippe Mathieu-Daudé     return (int32_t)env->CP0_WatchLo[sel];
415ad520a97SPhilippe Mathieu-Daudé }
416ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_watchhi(CPUMIPSState * env,uint32_t sel)417ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel)
418ad520a97SPhilippe Mathieu-Daudé {
419ad520a97SPhilippe Mathieu-Daudé     return (int32_t) env->CP0_WatchHi[sel];
420ad520a97SPhilippe Mathieu-Daudé }
421ad520a97SPhilippe Mathieu-Daudé 
helper_mfhc0_watchhi(CPUMIPSState * env,uint32_t sel)422ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfhc0_watchhi(CPUMIPSState *env, uint32_t sel)
423ad520a97SPhilippe Mathieu-Daudé {
424ad520a97SPhilippe Mathieu-Daudé     return env->CP0_WatchHi[sel] >> 32;
425ad520a97SPhilippe Mathieu-Daudé }
426ad520a97SPhilippe Mathieu-Daudé 
helper_mfc0_debug(CPUMIPSState * env)427ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfc0_debug(CPUMIPSState *env)
428ad520a97SPhilippe Mathieu-Daudé {
429ad520a97SPhilippe Mathieu-Daudé     target_ulong t0 = env->CP0_Debug;
430ad520a97SPhilippe Mathieu-Daudé     if (env->hflags & MIPS_HFLAG_DM) {
431ad520a97SPhilippe Mathieu-Daudé         t0 |= 1 << CP0DB_DM;
432ad520a97SPhilippe Mathieu-Daudé     }
433ad520a97SPhilippe Mathieu-Daudé 
434ad520a97SPhilippe Mathieu-Daudé     return t0;
435ad520a97SPhilippe Mathieu-Daudé }
436ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_debug(CPUMIPSState * env)437ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_debug(CPUMIPSState *env)
438ad520a97SPhilippe Mathieu-Daudé {
439ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
440ad520a97SPhilippe Mathieu-Daudé     int32_t tcstatus;
441ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
442ad520a97SPhilippe Mathieu-Daudé 
443ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
444ad520a97SPhilippe Mathieu-Daudé         tcstatus = other->active_tc.CP0_Debug_tcstatus;
445ad520a97SPhilippe Mathieu-Daudé     } else {
446ad520a97SPhilippe Mathieu-Daudé         tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus;
447ad520a97SPhilippe Mathieu-Daudé     }
448ad520a97SPhilippe Mathieu-Daudé 
449ad520a97SPhilippe Mathieu-Daudé     /* XXX: Might be wrong, check with EJTAG spec. */
450ad520a97SPhilippe Mathieu-Daudé     return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
451ad520a97SPhilippe Mathieu-Daudé             (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
452ad520a97SPhilippe Mathieu-Daudé }
453ad520a97SPhilippe Mathieu-Daudé 
454ad520a97SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
helper_dmfc0_tcrestart(CPUMIPSState * env)455ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tcrestart(CPUMIPSState *env)
456ad520a97SPhilippe Mathieu-Daudé {
457ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.PC;
458ad520a97SPhilippe Mathieu-Daudé }
459ad520a97SPhilippe Mathieu-Daudé 
helper_dmfc0_tchalt(CPUMIPSState * env)460ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tchalt(CPUMIPSState *env)
461ad520a97SPhilippe Mathieu-Daudé {
462ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCHalt;
463ad520a97SPhilippe Mathieu-Daudé }
464ad520a97SPhilippe Mathieu-Daudé 
helper_dmfc0_tccontext(CPUMIPSState * env)465ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tccontext(CPUMIPSState *env)
466ad520a97SPhilippe Mathieu-Daudé {
467ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCContext;
468ad520a97SPhilippe Mathieu-Daudé }
469ad520a97SPhilippe Mathieu-Daudé 
helper_dmfc0_tcschedule(CPUMIPSState * env)470ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tcschedule(CPUMIPSState *env)
471ad520a97SPhilippe Mathieu-Daudé {
472ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCSchedule;
473ad520a97SPhilippe Mathieu-Daudé }
474ad520a97SPhilippe Mathieu-Daudé 
helper_dmfc0_tcschefback(CPUMIPSState * env)475ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_tcschefback(CPUMIPSState *env)
476ad520a97SPhilippe Mathieu-Daudé {
477ad520a97SPhilippe Mathieu-Daudé     return env->active_tc.CP0_TCScheFBack;
478ad520a97SPhilippe Mathieu-Daudé }
479ad520a97SPhilippe Mathieu-Daudé 
helper_dmfc0_lladdr(CPUMIPSState * env)480ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_lladdr(CPUMIPSState *env)
481ad520a97SPhilippe Mathieu-Daudé {
482ad520a97SPhilippe Mathieu-Daudé     return env->CP0_LLAddr >> env->CP0_LLAddr_shift;
483ad520a97SPhilippe Mathieu-Daudé }
484ad520a97SPhilippe Mathieu-Daudé 
helper_dmfc0_maar(CPUMIPSState * env)485ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_maar(CPUMIPSState *env)
486ad520a97SPhilippe Mathieu-Daudé {
487ad520a97SPhilippe Mathieu-Daudé     return env->CP0_MAAR[env->CP0_MAARI];
488ad520a97SPhilippe Mathieu-Daudé }
489ad520a97SPhilippe Mathieu-Daudé 
helper_dmfc0_watchlo(CPUMIPSState * env,uint32_t sel)490ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
491ad520a97SPhilippe Mathieu-Daudé {
492ad520a97SPhilippe Mathieu-Daudé     return env->CP0_WatchLo[sel];
493ad520a97SPhilippe Mathieu-Daudé }
494ad520a97SPhilippe Mathieu-Daudé 
helper_dmfc0_watchhi(CPUMIPSState * env,uint32_t sel)495ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmfc0_watchhi(CPUMIPSState *env, uint32_t sel)
496ad520a97SPhilippe Mathieu-Daudé {
497ad520a97SPhilippe Mathieu-Daudé     return env->CP0_WatchHi[sel];
498ad520a97SPhilippe Mathieu-Daudé }
499ad520a97SPhilippe Mathieu-Daudé 
500ad520a97SPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */
501ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_index(CPUMIPSState * env,target_ulong arg1)502ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
503ad520a97SPhilippe Mathieu-Daudé {
504ad520a97SPhilippe Mathieu-Daudé     uint32_t index_p = env->CP0_Index & 0x80000000;
505ad520a97SPhilippe Mathieu-Daudé     uint32_t tlb_index = arg1 & 0x7fffffff;
506ad520a97SPhilippe Mathieu-Daudé     if (tlb_index < env->tlb->nb_tlb) {
507ad520a97SPhilippe Mathieu-Daudé         if (env->insn_flags & ISA_MIPS_R6) {
508ad520a97SPhilippe Mathieu-Daudé             index_p |= arg1 & 0x80000000;
509ad520a97SPhilippe Mathieu-Daudé         }
510ad520a97SPhilippe Mathieu-Daudé         env->CP0_Index = index_p | tlb_index;
511ad520a97SPhilippe Mathieu-Daudé     }
512ad520a97SPhilippe Mathieu-Daudé }
513ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_mvpcontrol(CPUMIPSState * env,target_ulong arg1)514ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
515ad520a97SPhilippe Mathieu-Daudé {
516ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = 0;
517ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
518ad520a97SPhilippe Mathieu-Daudé 
519ad520a97SPhilippe Mathieu-Daudé     if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
520ad520a97SPhilippe Mathieu-Daudé         mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
521ad520a97SPhilippe Mathieu-Daudé                 (1 << CP0MVPCo_EVP);
522ad520a97SPhilippe Mathieu-Daudé     }
523ad520a97SPhilippe Mathieu-Daudé     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) {
524ad520a97SPhilippe Mathieu-Daudé         mask |= (1 << CP0MVPCo_STLB);
525ad520a97SPhilippe Mathieu-Daudé     }
526ad520a97SPhilippe Mathieu-Daudé     newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
527ad520a97SPhilippe Mathieu-Daudé 
528ad520a97SPhilippe Mathieu-Daudé     /* TODO: Enable/disable shared TLB, enable/disable VPEs. */
529ad520a97SPhilippe Mathieu-Daudé 
530ad520a97SPhilippe Mathieu-Daudé     env->mvp->CP0_MVPControl = newval;
531ad520a97SPhilippe Mathieu-Daudé }
532ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_vpecontrol(CPUMIPSState * env,target_ulong arg1)533ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
534ad520a97SPhilippe Mathieu-Daudé {
535ad520a97SPhilippe Mathieu-Daudé     uint32_t mask;
536ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
537ad520a97SPhilippe Mathieu-Daudé 
538ad520a97SPhilippe Mathieu-Daudé     mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
539ad520a97SPhilippe Mathieu-Daudé            (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
540ad520a97SPhilippe Mathieu-Daudé     newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
541ad520a97SPhilippe Mathieu-Daudé 
542ad520a97SPhilippe Mathieu-Daudé     /*
543ad520a97SPhilippe Mathieu-Daudé      * Yield scheduler intercept not implemented.
544ad520a97SPhilippe Mathieu-Daudé      * Gating storage scheduler intercept not implemented.
545ad520a97SPhilippe Mathieu-Daudé      */
546ad520a97SPhilippe Mathieu-Daudé 
547ad520a97SPhilippe Mathieu-Daudé     /* TODO: Enable/disable TCs. */
548ad520a97SPhilippe Mathieu-Daudé 
549ad520a97SPhilippe Mathieu-Daudé     env->CP0_VPEControl = newval;
550ad520a97SPhilippe Mathieu-Daudé }
551ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_vpecontrol(CPUMIPSState * env,target_ulong arg1)552ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
553ad520a97SPhilippe Mathieu-Daudé {
554ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
555ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
556ad520a97SPhilippe Mathieu-Daudé     uint32_t mask;
557ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
558ad520a97SPhilippe Mathieu-Daudé 
559ad520a97SPhilippe Mathieu-Daudé     mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
560ad520a97SPhilippe Mathieu-Daudé            (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
561ad520a97SPhilippe Mathieu-Daudé     newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask);
562ad520a97SPhilippe Mathieu-Daudé 
563ad520a97SPhilippe Mathieu-Daudé     /* TODO: Enable/disable TCs.  */
564ad520a97SPhilippe Mathieu-Daudé 
565ad520a97SPhilippe Mathieu-Daudé     other->CP0_VPEControl = newval;
566ad520a97SPhilippe Mathieu-Daudé }
567ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_vpecontrol(CPUMIPSState * env)568ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_vpecontrol(CPUMIPSState *env)
569ad520a97SPhilippe Mathieu-Daudé {
570ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
571ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
572ad520a97SPhilippe Mathieu-Daudé     /* FIXME: Mask away return zero on read bits.  */
573ad520a97SPhilippe Mathieu-Daudé     return other->CP0_VPEControl;
574ad520a97SPhilippe Mathieu-Daudé }
575ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_vpeconf0(CPUMIPSState * env)576ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_vpeconf0(CPUMIPSState *env)
577ad520a97SPhilippe Mathieu-Daudé {
578ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
579ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
580ad520a97SPhilippe Mathieu-Daudé 
581ad520a97SPhilippe Mathieu-Daudé     return other->CP0_VPEConf0;
582ad520a97SPhilippe Mathieu-Daudé }
583ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_vpeconf0(CPUMIPSState * env,target_ulong arg1)584ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
585ad520a97SPhilippe Mathieu-Daudé {
586ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = 0;
587ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
588ad520a97SPhilippe Mathieu-Daudé 
589ad520a97SPhilippe Mathieu-Daudé     if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
590ad520a97SPhilippe Mathieu-Daudé         if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA)) {
591ad520a97SPhilippe Mathieu-Daudé             mask |= (0xff << CP0VPEC0_XTC);
592ad520a97SPhilippe Mathieu-Daudé         }
593ad520a97SPhilippe Mathieu-Daudé         mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
594ad520a97SPhilippe Mathieu-Daudé     }
595ad520a97SPhilippe Mathieu-Daudé     newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
596ad520a97SPhilippe Mathieu-Daudé 
597ad520a97SPhilippe Mathieu-Daudé     /* TODO: TC exclusive handling due to ERL/EXL. */
598ad520a97SPhilippe Mathieu-Daudé 
599ad520a97SPhilippe Mathieu-Daudé     env->CP0_VPEConf0 = newval;
600ad520a97SPhilippe Mathieu-Daudé }
601ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_vpeconf0(CPUMIPSState * env,target_ulong arg1)602ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
603ad520a97SPhilippe Mathieu-Daudé {
604ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
605ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
606ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = 0;
607ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
608ad520a97SPhilippe Mathieu-Daudé 
609ad520a97SPhilippe Mathieu-Daudé     mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
610ad520a97SPhilippe Mathieu-Daudé     newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask);
611ad520a97SPhilippe Mathieu-Daudé 
612ad520a97SPhilippe Mathieu-Daudé     /* TODO: TC exclusive handling due to ERL/EXL.  */
613ad520a97SPhilippe Mathieu-Daudé     other->CP0_VPEConf0 = newval;
614ad520a97SPhilippe Mathieu-Daudé }
615ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_vpeconf1(CPUMIPSState * env,target_ulong arg1)616ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_vpeconf1(CPUMIPSState *env, target_ulong arg1)
617ad520a97SPhilippe Mathieu-Daudé {
618ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = 0;
619ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
620ad520a97SPhilippe Mathieu-Daudé 
621ad520a97SPhilippe Mathieu-Daudé     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
622ad520a97SPhilippe Mathieu-Daudé         mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
623ad520a97SPhilippe Mathieu-Daudé                 (0xff << CP0VPEC1_NCP1);
624ad520a97SPhilippe Mathieu-Daudé     newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
625ad520a97SPhilippe Mathieu-Daudé 
626ad520a97SPhilippe Mathieu-Daudé     /* UDI not implemented. */
627ad520a97SPhilippe Mathieu-Daudé     /* CP2 not implemented. */
628ad520a97SPhilippe Mathieu-Daudé 
629ad520a97SPhilippe Mathieu-Daudé     /* TODO: Handle FPU (CP1) binding. */
630ad520a97SPhilippe Mathieu-Daudé 
631ad520a97SPhilippe Mathieu-Daudé     env->CP0_VPEConf1 = newval;
632ad520a97SPhilippe Mathieu-Daudé }
633ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_yqmask(CPUMIPSState * env,target_ulong arg1)634ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_yqmask(CPUMIPSState *env, target_ulong arg1)
635ad520a97SPhilippe Mathieu-Daudé {
636ad520a97SPhilippe Mathieu-Daudé     /* Yield qualifier inputs not implemented. */
637ad520a97SPhilippe Mathieu-Daudé     env->CP0_YQMask = 0x00000000;
638ad520a97SPhilippe Mathieu-Daudé }
639ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_vpeopt(CPUMIPSState * env,target_ulong arg1)640ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
641ad520a97SPhilippe Mathieu-Daudé {
642ad520a97SPhilippe Mathieu-Daudé     env->CP0_VPEOpt = arg1 & 0x0000ffff;
643ad520a97SPhilippe Mathieu-Daudé }
644ad520a97SPhilippe Mathieu-Daudé 
645ad520a97SPhilippe Mathieu-Daudé #define MTC0_ENTRYLO_MASK(env) ((env->PAMask >> 6) & 0x3FFFFFFF)
646ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_entrylo0(CPUMIPSState * env,target_ulong arg1)647ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
648ad520a97SPhilippe Mathieu-Daudé {
649ad520a97SPhilippe Mathieu-Daudé     /* 1k pages not implemented */
650ad520a97SPhilippe Mathieu-Daudé     target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
651ad520a97SPhilippe Mathieu-Daudé     env->CP0_EntryLo0 = (arg1 & MTC0_ENTRYLO_MASK(env))
652ad520a97SPhilippe Mathieu-Daudé                         | (rxi << (CP0EnLo_XI - 30));
653ad520a97SPhilippe Mathieu-Daudé }
654ad520a97SPhilippe Mathieu-Daudé 
655ad520a97SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
656ad520a97SPhilippe Mathieu-Daudé #define DMTC0_ENTRYLO_MASK(env) (env->PAMask >> 6)
657ad520a97SPhilippe Mathieu-Daudé 
helper_dmtc0_entrylo0(CPUMIPSState * env,uint64_t arg1)658ad520a97SPhilippe Mathieu-Daudé void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
659ad520a97SPhilippe Mathieu-Daudé {
660ad520a97SPhilippe Mathieu-Daudé     uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
661ad520a97SPhilippe Mathieu-Daudé     env->CP0_EntryLo0 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
662ad520a97SPhilippe Mathieu-Daudé }
663ad520a97SPhilippe Mathieu-Daudé #endif
664ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_tcstatus(CPUMIPSState * env,target_ulong arg1)665ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
666ad520a97SPhilippe Mathieu-Daudé {
667ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = env->CP0_TCStatus_rw_bitmask;
668ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
669ad520a97SPhilippe Mathieu-Daudé 
670ad520a97SPhilippe Mathieu-Daudé     newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
671ad520a97SPhilippe Mathieu-Daudé 
672ad520a97SPhilippe Mathieu-Daudé     env->active_tc.CP0_TCStatus = newval;
673ad520a97SPhilippe Mathieu-Daudé     sync_c0_tcstatus(env, env->current_tc, newval);
674ad520a97SPhilippe Mathieu-Daudé }
675ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_tcstatus(CPUMIPSState * env,target_ulong arg1)676ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
677ad520a97SPhilippe Mathieu-Daudé {
678ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
679ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
680ad520a97SPhilippe Mathieu-Daudé 
681ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
682ad520a97SPhilippe Mathieu-Daudé         other->active_tc.CP0_TCStatus = arg1;
683ad520a97SPhilippe Mathieu-Daudé     } else {
684ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCStatus = arg1;
685ad520a97SPhilippe Mathieu-Daudé     }
686ad520a97SPhilippe Mathieu-Daudé     sync_c0_tcstatus(other, other_tc, arg1);
687ad520a97SPhilippe Mathieu-Daudé }
688ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_tcbind(CPUMIPSState * env,target_ulong arg1)689ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_tcbind(CPUMIPSState *env, target_ulong arg1)
690ad520a97SPhilippe Mathieu-Daudé {
691ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = (1 << CP0TCBd_TBE);
692ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
693ad520a97SPhilippe Mathieu-Daudé 
694ad520a97SPhilippe Mathieu-Daudé     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) {
695ad520a97SPhilippe Mathieu-Daudé         mask |= (1 << CP0TCBd_CurVPE);
696ad520a97SPhilippe Mathieu-Daudé     }
697ad520a97SPhilippe Mathieu-Daudé     newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
698ad520a97SPhilippe Mathieu-Daudé     env->active_tc.CP0_TCBind = newval;
699ad520a97SPhilippe Mathieu-Daudé }
700ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_tcbind(CPUMIPSState * env,target_ulong arg1)701ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_tcbind(CPUMIPSState *env, target_ulong arg1)
702ad520a97SPhilippe Mathieu-Daudé {
703ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
704ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = (1 << CP0TCBd_TBE);
705ad520a97SPhilippe Mathieu-Daudé     uint32_t newval;
706ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
707ad520a97SPhilippe Mathieu-Daudé 
708ad520a97SPhilippe Mathieu-Daudé     if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) {
709ad520a97SPhilippe Mathieu-Daudé         mask |= (1 << CP0TCBd_CurVPE);
710ad520a97SPhilippe Mathieu-Daudé     }
711ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
712ad520a97SPhilippe Mathieu-Daudé         newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
713ad520a97SPhilippe Mathieu-Daudé         other->active_tc.CP0_TCBind = newval;
714ad520a97SPhilippe Mathieu-Daudé     } else {
715ad520a97SPhilippe Mathieu-Daudé         newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
716ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCBind = newval;
717ad520a97SPhilippe Mathieu-Daudé     }
718ad520a97SPhilippe Mathieu-Daudé }
719ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_tcrestart(CPUMIPSState * env,target_ulong arg1)720ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
721ad520a97SPhilippe Mathieu-Daudé {
722ad520a97SPhilippe Mathieu-Daudé     env->active_tc.PC = arg1;
723ad520a97SPhilippe Mathieu-Daudé     env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
724ad520a97SPhilippe Mathieu-Daudé     env->CP0_LLAddr = 0;
725ad520a97SPhilippe Mathieu-Daudé     env->lladdr = 0;
726ad520a97SPhilippe Mathieu-Daudé     /* MIPS16 not implemented. */
727ad520a97SPhilippe Mathieu-Daudé }
728ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_tcrestart(CPUMIPSState * env,target_ulong arg1)729ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
730ad520a97SPhilippe Mathieu-Daudé {
731ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
732ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
733ad520a97SPhilippe Mathieu-Daudé 
734ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
735ad520a97SPhilippe Mathieu-Daudé         other->active_tc.PC = arg1;
736ad520a97SPhilippe Mathieu-Daudé         other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
737ad520a97SPhilippe Mathieu-Daudé         other->CP0_LLAddr = 0;
738ad520a97SPhilippe Mathieu-Daudé         other->lladdr = 0;
739ad520a97SPhilippe Mathieu-Daudé         /* MIPS16 not implemented. */
740ad520a97SPhilippe Mathieu-Daudé     } else {
741ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].PC = arg1;
742ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
743ad520a97SPhilippe Mathieu-Daudé         other->CP0_LLAddr = 0;
744ad520a97SPhilippe Mathieu-Daudé         other->lladdr = 0;
745ad520a97SPhilippe Mathieu-Daudé         /* MIPS16 not implemented. */
746ad520a97SPhilippe Mathieu-Daudé     }
747ad520a97SPhilippe Mathieu-Daudé }
748ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_tchalt(CPUMIPSState * env,target_ulong arg1)749ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_tchalt(CPUMIPSState *env, target_ulong arg1)
750ad520a97SPhilippe Mathieu-Daudé {
751ad520a97SPhilippe Mathieu-Daudé     MIPSCPU *cpu = env_archcpu(env);
752ad520a97SPhilippe Mathieu-Daudé 
753ad520a97SPhilippe Mathieu-Daudé     env->active_tc.CP0_TCHalt = arg1 & 0x1;
754ad520a97SPhilippe Mathieu-Daudé 
755ad520a97SPhilippe Mathieu-Daudé     /* TODO: Halt TC / Restart (if allocated+active) TC. */
756ad520a97SPhilippe Mathieu-Daudé     if (env->active_tc.CP0_TCHalt & 1) {
757ad520a97SPhilippe Mathieu-Daudé         mips_tc_sleep(cpu, env->current_tc);
758ad520a97SPhilippe Mathieu-Daudé     } else {
759ad520a97SPhilippe Mathieu-Daudé         mips_tc_wake(cpu, env->current_tc);
760ad520a97SPhilippe Mathieu-Daudé     }
761ad520a97SPhilippe Mathieu-Daudé }
762ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_tchalt(CPUMIPSState * env,target_ulong arg1)763ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1)
764ad520a97SPhilippe Mathieu-Daudé {
765ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
766ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
767ad520a97SPhilippe Mathieu-Daudé     MIPSCPU *other_cpu = env_archcpu(other);
768ad520a97SPhilippe Mathieu-Daudé 
769ad520a97SPhilippe Mathieu-Daudé     /* TODO: Halt TC / Restart (if allocated+active) TC. */
770ad520a97SPhilippe Mathieu-Daudé 
771ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
772ad520a97SPhilippe Mathieu-Daudé         other->active_tc.CP0_TCHalt = arg1;
773ad520a97SPhilippe Mathieu-Daudé     } else {
774ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCHalt = arg1;
775ad520a97SPhilippe Mathieu-Daudé     }
776ad520a97SPhilippe Mathieu-Daudé 
777ad520a97SPhilippe Mathieu-Daudé     if (arg1 & 1) {
778ad520a97SPhilippe Mathieu-Daudé         mips_tc_sleep(other_cpu, other_tc);
779ad520a97SPhilippe Mathieu-Daudé     } else {
780ad520a97SPhilippe Mathieu-Daudé         mips_tc_wake(other_cpu, other_tc);
781ad520a97SPhilippe Mathieu-Daudé     }
782ad520a97SPhilippe Mathieu-Daudé }
783ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_tccontext(CPUMIPSState * env,target_ulong arg1)784ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_tccontext(CPUMIPSState *env, target_ulong arg1)
785ad520a97SPhilippe Mathieu-Daudé {
786ad520a97SPhilippe Mathieu-Daudé     env->active_tc.CP0_TCContext = arg1;
787ad520a97SPhilippe Mathieu-Daudé }
788ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_tccontext(CPUMIPSState * env,target_ulong arg1)789ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_tccontext(CPUMIPSState *env, target_ulong arg1)
790ad520a97SPhilippe Mathieu-Daudé {
791ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
792ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
793ad520a97SPhilippe Mathieu-Daudé 
794ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
795ad520a97SPhilippe Mathieu-Daudé         other->active_tc.CP0_TCContext = arg1;
796ad520a97SPhilippe Mathieu-Daudé     } else {
797ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCContext = arg1;
798ad520a97SPhilippe Mathieu-Daudé     }
799ad520a97SPhilippe Mathieu-Daudé }
800ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_tcschedule(CPUMIPSState * env,target_ulong arg1)801ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
802ad520a97SPhilippe Mathieu-Daudé {
803ad520a97SPhilippe Mathieu-Daudé     env->active_tc.CP0_TCSchedule = arg1;
804ad520a97SPhilippe Mathieu-Daudé }
805ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_tcschedule(CPUMIPSState * env,target_ulong arg1)806ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
807ad520a97SPhilippe Mathieu-Daudé {
808ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
809ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
810ad520a97SPhilippe Mathieu-Daudé 
811ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
812ad520a97SPhilippe Mathieu-Daudé         other->active_tc.CP0_TCSchedule = arg1;
813ad520a97SPhilippe Mathieu-Daudé     } else {
814ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCSchedule = arg1;
815ad520a97SPhilippe Mathieu-Daudé     }
816ad520a97SPhilippe Mathieu-Daudé }
817ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_tcschefback(CPUMIPSState * env,target_ulong arg1)818ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
819ad520a97SPhilippe Mathieu-Daudé {
820ad520a97SPhilippe Mathieu-Daudé     env->active_tc.CP0_TCScheFBack = arg1;
821ad520a97SPhilippe Mathieu-Daudé }
822ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_tcschefback(CPUMIPSState * env,target_ulong arg1)823ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
824ad520a97SPhilippe Mathieu-Daudé {
825ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
826ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
827ad520a97SPhilippe Mathieu-Daudé 
828ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
829ad520a97SPhilippe Mathieu-Daudé         other->active_tc.CP0_TCScheFBack = arg1;
830ad520a97SPhilippe Mathieu-Daudé     } else {
831ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_TCScheFBack = arg1;
832ad520a97SPhilippe Mathieu-Daudé     }
833ad520a97SPhilippe Mathieu-Daudé }
834ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_entrylo1(CPUMIPSState * env,target_ulong arg1)835ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
836ad520a97SPhilippe Mathieu-Daudé {
837ad520a97SPhilippe Mathieu-Daudé     /* 1k pages not implemented */
838ad520a97SPhilippe Mathieu-Daudé     target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
839ad520a97SPhilippe Mathieu-Daudé     env->CP0_EntryLo1 = (arg1 & MTC0_ENTRYLO_MASK(env))
840ad520a97SPhilippe Mathieu-Daudé                         | (rxi << (CP0EnLo_XI - 30));
841ad520a97SPhilippe Mathieu-Daudé }
842ad520a97SPhilippe Mathieu-Daudé 
843ad520a97SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
helper_dmtc0_entrylo1(CPUMIPSState * env,uint64_t arg1)844ad520a97SPhilippe Mathieu-Daudé void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
845ad520a97SPhilippe Mathieu-Daudé {
846ad520a97SPhilippe Mathieu-Daudé     uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
847ad520a97SPhilippe Mathieu-Daudé     env->CP0_EntryLo1 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
848ad520a97SPhilippe Mathieu-Daudé }
849ad520a97SPhilippe Mathieu-Daudé #endif
850ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_context(CPUMIPSState * env,target_ulong arg1)851ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
852ad520a97SPhilippe Mathieu-Daudé {
853ad520a97SPhilippe Mathieu-Daudé     env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
854ad520a97SPhilippe Mathieu-Daudé }
855ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_memorymapid(CPUMIPSState * env,target_ulong arg1)856ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
857ad520a97SPhilippe Mathieu-Daudé {
858ad520a97SPhilippe Mathieu-Daudé     int32_t old;
859ad520a97SPhilippe Mathieu-Daudé     old = env->CP0_MemoryMapID;
860ad520a97SPhilippe Mathieu-Daudé     env->CP0_MemoryMapID = (int32_t) arg1;
861ad520a97SPhilippe Mathieu-Daudé     /* If the MemoryMapID changes, flush qemu's TLB.  */
862ad520a97SPhilippe Mathieu-Daudé     if (old != env->CP0_MemoryMapID) {
863ad520a97SPhilippe Mathieu-Daudé         cpu_mips_tlb_flush(env);
864ad520a97SPhilippe Mathieu-Daudé     }
865ad520a97SPhilippe Mathieu-Daudé }
866ad520a97SPhilippe Mathieu-Daudé 
update_pagemask(CPUMIPSState * env,target_ulong arg1,int32_t * pagemask)867ad520a97SPhilippe Mathieu-Daudé void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
868ad520a97SPhilippe Mathieu-Daudé {
869ad520a97SPhilippe Mathieu-Daudé     uint32_t mask;
870ad520a97SPhilippe Mathieu-Daudé     int maskbits;
871ad520a97SPhilippe Mathieu-Daudé 
872ad520a97SPhilippe Mathieu-Daudé     /* Don't care MASKX as we don't support 1KB page */
873ad520a97SPhilippe Mathieu-Daudé     mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);
874ad520a97SPhilippe Mathieu-Daudé     maskbits = cto32(mask);
875ad520a97SPhilippe Mathieu-Daudé 
876ad520a97SPhilippe Mathieu-Daudé     /* Ensure no more set bit after first zero */
877ad520a97SPhilippe Mathieu-Daudé     if ((mask >> maskbits) != 0) {
878ad520a97SPhilippe Mathieu-Daudé         goto invalid;
879ad520a97SPhilippe Mathieu-Daudé     }
880ad520a97SPhilippe Mathieu-Daudé     /* We don't support VTLB entry smaller than target page */
881ad520a97SPhilippe Mathieu-Daudé     if ((maskbits + TARGET_PAGE_BITS_MIN) < TARGET_PAGE_BITS) {
882ad520a97SPhilippe Mathieu-Daudé         goto invalid;
883ad520a97SPhilippe Mathieu-Daudé     }
884ad520a97SPhilippe Mathieu-Daudé     env->CP0_PageMask = mask << CP0PM_MASK;
885ad520a97SPhilippe Mathieu-Daudé 
886ad520a97SPhilippe Mathieu-Daudé     return;
887ad520a97SPhilippe Mathieu-Daudé 
888ad520a97SPhilippe Mathieu-Daudé invalid:
889ad520a97SPhilippe Mathieu-Daudé     /* When invalid, set to default target page size. */
890ad520a97SPhilippe Mathieu-Daudé     mask = (~TARGET_PAGE_MASK >> TARGET_PAGE_BITS_MIN);
891ad520a97SPhilippe Mathieu-Daudé     env->CP0_PageMask = mask << CP0PM_MASK;
892ad520a97SPhilippe Mathieu-Daudé }
893ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_pagemask(CPUMIPSState * env,target_ulong arg1)894ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
895ad520a97SPhilippe Mathieu-Daudé {
896ad520a97SPhilippe Mathieu-Daudé     update_pagemask(env, arg1, &env->CP0_PageMask);
897ad520a97SPhilippe Mathieu-Daudé }
898ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_pagegrain(CPUMIPSState * env,target_ulong arg1)899ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
900ad520a97SPhilippe Mathieu-Daudé {
901ad520a97SPhilippe Mathieu-Daudé     /* SmartMIPS not implemented */
902ad520a97SPhilippe Mathieu-Daudé     /* 1k pages not implemented */
903ad520a97SPhilippe Mathieu-Daudé     env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
904ad520a97SPhilippe Mathieu-Daudé                          (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
905ad520a97SPhilippe Mathieu-Daudé     compute_hflags(env);
906ad520a97SPhilippe Mathieu-Daudé     restore_pamask(env);
907ad520a97SPhilippe Mathieu-Daudé }
908ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_segctl0(CPUMIPSState * env,target_ulong arg1)909ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_segctl0(CPUMIPSState *env, target_ulong arg1)
910ad520a97SPhilippe Mathieu-Daudé {
911ad520a97SPhilippe Mathieu-Daudé     CPUState *cs = env_cpu(env);
912ad520a97SPhilippe Mathieu-Daudé 
913ad520a97SPhilippe Mathieu-Daudé     env->CP0_SegCtl0 = arg1 & CP0SC0_MASK;
914ad520a97SPhilippe Mathieu-Daudé     tlb_flush(cs);
915ad520a97SPhilippe Mathieu-Daudé }
916ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_segctl1(CPUMIPSState * env,target_ulong arg1)917ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_segctl1(CPUMIPSState *env, target_ulong arg1)
918ad520a97SPhilippe Mathieu-Daudé {
919ad520a97SPhilippe Mathieu-Daudé     CPUState *cs = env_cpu(env);
920ad520a97SPhilippe Mathieu-Daudé 
921ad520a97SPhilippe Mathieu-Daudé     env->CP0_SegCtl1 = arg1 & CP0SC1_MASK;
922ad520a97SPhilippe Mathieu-Daudé     tlb_flush(cs);
923ad520a97SPhilippe Mathieu-Daudé }
924ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_segctl2(CPUMIPSState * env,target_ulong arg1)925ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_segctl2(CPUMIPSState *env, target_ulong arg1)
926ad520a97SPhilippe Mathieu-Daudé {
927ad520a97SPhilippe Mathieu-Daudé     CPUState *cs = env_cpu(env);
928ad520a97SPhilippe Mathieu-Daudé 
929ad520a97SPhilippe Mathieu-Daudé     env->CP0_SegCtl2 = arg1 & CP0SC2_MASK;
930ad520a97SPhilippe Mathieu-Daudé     tlb_flush(cs);
931ad520a97SPhilippe Mathieu-Daudé }
932ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_pwfield(CPUMIPSState * env,target_ulong arg1)933ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
934ad520a97SPhilippe Mathieu-Daudé {
935ad520a97SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
936ad520a97SPhilippe Mathieu-Daudé     uint64_t mask = 0x3F3FFFFFFFULL;
937ad520a97SPhilippe Mathieu-Daudé     uint32_t old_ptei = (env->CP0_PWField >> CP0PF_PTEI) & 0x3FULL;
938ad520a97SPhilippe Mathieu-Daudé     uint32_t new_ptei = (arg1 >> CP0PF_PTEI) & 0x3FULL;
939ad520a97SPhilippe Mathieu-Daudé 
940ad520a97SPhilippe Mathieu-Daudé     if ((env->insn_flags & ISA_MIPS_R6)) {
941ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_BDI) & 0x3FULL) < 12) {
942ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_BDI);
943ad520a97SPhilippe Mathieu-Daudé         }
944ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_GDI) & 0x3FULL) < 12) {
945ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_GDI);
946ad520a97SPhilippe Mathieu-Daudé         }
947ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_UDI) & 0x3FULL) < 12) {
948ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_UDI);
949ad520a97SPhilippe Mathieu-Daudé         }
950ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_MDI) & 0x3FULL) < 12) {
951ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_MDI);
952ad520a97SPhilippe Mathieu-Daudé         }
953ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_PTI) & 0x3FULL) < 12) {
954ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3FULL << CP0PF_PTI);
955ad520a97SPhilippe Mathieu-Daudé         }
956ad520a97SPhilippe Mathieu-Daudé     }
957ad520a97SPhilippe Mathieu-Daudé     env->CP0_PWField = arg1 & mask;
958ad520a97SPhilippe Mathieu-Daudé 
959ad520a97SPhilippe Mathieu-Daudé     if ((new_ptei >= 32) ||
960ad520a97SPhilippe Mathieu-Daudé             ((env->insn_flags & ISA_MIPS_R6) &&
961ad520a97SPhilippe Mathieu-Daudé                     (new_ptei == 0 || new_ptei == 1))) {
962ad520a97SPhilippe Mathieu-Daudé         env->CP0_PWField = (env->CP0_PWField & ~0x3FULL) |
963ad520a97SPhilippe Mathieu-Daudé                 (old_ptei << CP0PF_PTEI);
964ad520a97SPhilippe Mathieu-Daudé     }
965ad520a97SPhilippe Mathieu-Daudé #else
966ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = 0x3FFFFFFF;
967ad520a97SPhilippe Mathieu-Daudé     uint32_t old_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
968ad520a97SPhilippe Mathieu-Daudé     uint32_t new_ptew = (arg1 >> CP0PF_PTEW) & 0x3F;
969ad520a97SPhilippe Mathieu-Daudé 
970ad520a97SPhilippe Mathieu-Daudé     if ((env->insn_flags & ISA_MIPS_R6)) {
971ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_GDW) & 0x3F) < 12) {
972ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3F << CP0PF_GDW);
973ad520a97SPhilippe Mathieu-Daudé         }
974ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_UDW) & 0x3F) < 12) {
975ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3F << CP0PF_UDW);
976ad520a97SPhilippe Mathieu-Daudé         }
977ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_MDW) & 0x3F) < 12) {
978ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3F << CP0PF_MDW);
979ad520a97SPhilippe Mathieu-Daudé         }
980ad520a97SPhilippe Mathieu-Daudé         if (((arg1 >> CP0PF_PTW) & 0x3F) < 12) {
981ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3F << CP0PF_PTW);
982ad520a97SPhilippe Mathieu-Daudé         }
983ad520a97SPhilippe Mathieu-Daudé     }
984ad520a97SPhilippe Mathieu-Daudé     env->CP0_PWField = arg1 & mask;
985ad520a97SPhilippe Mathieu-Daudé 
986ad520a97SPhilippe Mathieu-Daudé     if ((new_ptew >= 32) ||
987ad520a97SPhilippe Mathieu-Daudé             ((env->insn_flags & ISA_MIPS_R6) &&
988ad520a97SPhilippe Mathieu-Daudé                     (new_ptew == 0 || new_ptew == 1))) {
989ad520a97SPhilippe Mathieu-Daudé         env->CP0_PWField = (env->CP0_PWField & ~0x3F) |
990ad520a97SPhilippe Mathieu-Daudé                 (old_ptew << CP0PF_PTEW);
991ad520a97SPhilippe Mathieu-Daudé     }
992ad520a97SPhilippe Mathieu-Daudé #endif
993ad520a97SPhilippe Mathieu-Daudé }
994ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_pwsize(CPUMIPSState * env,target_ulong arg1)995ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_pwsize(CPUMIPSState *env, target_ulong arg1)
996ad520a97SPhilippe Mathieu-Daudé {
997ad520a97SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
998ad520a97SPhilippe Mathieu-Daudé     env->CP0_PWSize = arg1 & 0x3F7FFFFFFFULL;
999ad520a97SPhilippe Mathieu-Daudé #else
1000ad520a97SPhilippe Mathieu-Daudé     env->CP0_PWSize = arg1 & 0x3FFFFFFF;
1001ad520a97SPhilippe Mathieu-Daudé #endif
1002ad520a97SPhilippe Mathieu-Daudé }
1003ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_wired(CPUMIPSState * env,target_ulong arg1)1004ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
1005ad520a97SPhilippe Mathieu-Daudé {
1006ad520a97SPhilippe Mathieu-Daudé     if (env->insn_flags & ISA_MIPS_R6) {
1007ad520a97SPhilippe Mathieu-Daudé         if (arg1 < env->tlb->nb_tlb) {
1008ad520a97SPhilippe Mathieu-Daudé             env->CP0_Wired = arg1;
1009ad520a97SPhilippe Mathieu-Daudé         }
1010ad520a97SPhilippe Mathieu-Daudé     } else {
1011ad520a97SPhilippe Mathieu-Daudé         env->CP0_Wired = arg1 % env->tlb->nb_tlb;
1012ad520a97SPhilippe Mathieu-Daudé     }
1013ad520a97SPhilippe Mathieu-Daudé }
1014ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_pwctl(CPUMIPSState * env,target_ulong arg1)1015ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_pwctl(CPUMIPSState *env, target_ulong arg1)
1016ad520a97SPhilippe Mathieu-Daudé {
1017ad520a97SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
1018ad520a97SPhilippe Mathieu-Daudé     /* PWEn = 0. Hardware page table walking is not implemented. */
1019ad520a97SPhilippe Mathieu-Daudé     env->CP0_PWCtl = (env->CP0_PWCtl & 0x000000C0) | (arg1 & 0x5C00003F);
1020ad520a97SPhilippe Mathieu-Daudé #else
1021ad520a97SPhilippe Mathieu-Daudé     env->CP0_PWCtl = (arg1 & 0x800000FF);
1022ad520a97SPhilippe Mathieu-Daudé #endif
1023ad520a97SPhilippe Mathieu-Daudé }
1024ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_srsconf0(CPUMIPSState * env,target_ulong arg1)1025ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
1026ad520a97SPhilippe Mathieu-Daudé {
1027ad520a97SPhilippe Mathieu-Daudé     env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
1028ad520a97SPhilippe Mathieu-Daudé }
1029ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_srsconf1(CPUMIPSState * env,target_ulong arg1)1030ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_srsconf1(CPUMIPSState *env, target_ulong arg1)
1031ad520a97SPhilippe Mathieu-Daudé {
1032ad520a97SPhilippe Mathieu-Daudé     env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
1033ad520a97SPhilippe Mathieu-Daudé }
1034ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_srsconf2(CPUMIPSState * env,target_ulong arg1)1035ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_srsconf2(CPUMIPSState *env, target_ulong arg1)
1036ad520a97SPhilippe Mathieu-Daudé {
1037ad520a97SPhilippe Mathieu-Daudé     env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
1038ad520a97SPhilippe Mathieu-Daudé }
1039ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_srsconf3(CPUMIPSState * env,target_ulong arg1)1040ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_srsconf3(CPUMIPSState *env, target_ulong arg1)
1041ad520a97SPhilippe Mathieu-Daudé {
1042ad520a97SPhilippe Mathieu-Daudé     env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
1043ad520a97SPhilippe Mathieu-Daudé }
1044ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_srsconf4(CPUMIPSState * env,target_ulong arg1)1045ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_srsconf4(CPUMIPSState *env, target_ulong arg1)
1046ad520a97SPhilippe Mathieu-Daudé {
1047ad520a97SPhilippe Mathieu-Daudé     env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
1048ad520a97SPhilippe Mathieu-Daudé }
1049ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_hwrena(CPUMIPSState * env,target_ulong arg1)1050ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
1051ad520a97SPhilippe Mathieu-Daudé {
1052ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = 0x0000000F;
1053ad520a97SPhilippe Mathieu-Daudé 
1054ad520a97SPhilippe Mathieu-Daudé     if ((env->CP0_Config1 & (1 << CP0C1_PC)) &&
1055ad520a97SPhilippe Mathieu-Daudé         (env->insn_flags & ISA_MIPS_R6)) {
1056ad520a97SPhilippe Mathieu-Daudé         mask |= (1 << 4);
1057ad520a97SPhilippe Mathieu-Daudé     }
1058ad520a97SPhilippe Mathieu-Daudé     if (env->insn_flags & ISA_MIPS_R6) {
1059ad520a97SPhilippe Mathieu-Daudé         mask |= (1 << 5);
1060ad520a97SPhilippe Mathieu-Daudé     }
1061ad520a97SPhilippe Mathieu-Daudé     if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
1062ad520a97SPhilippe Mathieu-Daudé         mask |= (1 << 29);
1063ad520a97SPhilippe Mathieu-Daudé 
1064ad520a97SPhilippe Mathieu-Daudé         if (arg1 & (1 << 29)) {
1065ad520a97SPhilippe Mathieu-Daudé             env->hflags |= MIPS_HFLAG_HWRENA_ULR;
1066ad520a97SPhilippe Mathieu-Daudé         } else {
1067ad520a97SPhilippe Mathieu-Daudé             env->hflags &= ~MIPS_HFLAG_HWRENA_ULR;
1068ad520a97SPhilippe Mathieu-Daudé         }
1069ad520a97SPhilippe Mathieu-Daudé     }
1070ad520a97SPhilippe Mathieu-Daudé 
1071ad520a97SPhilippe Mathieu-Daudé     env->CP0_HWREna = arg1 & mask;
1072ad520a97SPhilippe Mathieu-Daudé }
1073ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_count(CPUMIPSState * env,target_ulong arg1)1074ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
1075ad520a97SPhilippe Mathieu-Daudé {
1076ad520a97SPhilippe Mathieu-Daudé     cpu_mips_store_count(env, arg1);
1077ad520a97SPhilippe Mathieu-Daudé }
1078ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_entryhi(CPUMIPSState * env,target_ulong arg1)1079ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
1080ad520a97SPhilippe Mathieu-Daudé {
1081ad520a97SPhilippe Mathieu-Daudé     target_ulong old, val, mask;
1082ad520a97SPhilippe Mathieu-Daudé     mask = (TARGET_PAGE_MASK << 1) | env->CP0_EntryHi_ASID_mask;
1083ad520a97SPhilippe Mathieu-Daudé     if (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) {
1084ad520a97SPhilippe Mathieu-Daudé         mask |= 1 << CP0EnHi_EHINV;
1085ad520a97SPhilippe Mathieu-Daudé     }
1086ad520a97SPhilippe Mathieu-Daudé 
1087ad520a97SPhilippe Mathieu-Daudé     /* 1k pages not implemented */
1088ad520a97SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
1089ad520a97SPhilippe Mathieu-Daudé     if (env->insn_flags & ISA_MIPS_R6) {
1090ad520a97SPhilippe Mathieu-Daudé         int entryhi_r = extract64(arg1, 62, 2);
1091ad520a97SPhilippe Mathieu-Daudé         int config0_at = extract32(env->CP0_Config0, 13, 2);
1092ad520a97SPhilippe Mathieu-Daudé         bool no_supervisor = (env->CP0_Status_rw_bitmask & 0x8) == 0;
1093ad520a97SPhilippe Mathieu-Daudé         if ((entryhi_r == 2) ||
1094ad520a97SPhilippe Mathieu-Daudé             (entryhi_r == 1 && (no_supervisor || config0_at == 1))) {
1095ad520a97SPhilippe Mathieu-Daudé             /* skip EntryHi.R field if new value is reserved */
1096ad520a97SPhilippe Mathieu-Daudé             mask &= ~(0x3ull << 62);
1097ad520a97SPhilippe Mathieu-Daudé         }
1098ad520a97SPhilippe Mathieu-Daudé     }
1099ad520a97SPhilippe Mathieu-Daudé     mask &= env->SEGMask;
1100ad520a97SPhilippe Mathieu-Daudé #endif
1101ad520a97SPhilippe Mathieu-Daudé     old = env->CP0_EntryHi;
1102ad520a97SPhilippe Mathieu-Daudé     val = (arg1 & mask) | (old & ~mask);
1103ad520a97SPhilippe Mathieu-Daudé     env->CP0_EntryHi = val;
1104ad520a97SPhilippe Mathieu-Daudé     if (ase_mt_available(env)) {
1105ad520a97SPhilippe Mathieu-Daudé         sync_c0_entryhi(env, env->current_tc);
1106ad520a97SPhilippe Mathieu-Daudé     }
1107ad520a97SPhilippe Mathieu-Daudé     /* If the ASID changes, flush qemu's TLB.  */
1108ad520a97SPhilippe Mathieu-Daudé     if ((old & env->CP0_EntryHi_ASID_mask) !=
1109ad520a97SPhilippe Mathieu-Daudé         (val & env->CP0_EntryHi_ASID_mask)) {
1110ad520a97SPhilippe Mathieu-Daudé         tlb_flush(env_cpu(env));
1111ad520a97SPhilippe Mathieu-Daudé     }
1112ad520a97SPhilippe Mathieu-Daudé }
1113ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_entryhi(CPUMIPSState * env,target_ulong arg1)1114ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1)
1115ad520a97SPhilippe Mathieu-Daudé {
1116ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1117ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1118ad520a97SPhilippe Mathieu-Daudé 
1119ad520a97SPhilippe Mathieu-Daudé     other->CP0_EntryHi = arg1;
1120ad520a97SPhilippe Mathieu-Daudé     sync_c0_entryhi(other, other_tc);
1121ad520a97SPhilippe Mathieu-Daudé }
1122ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_compare(CPUMIPSState * env,target_ulong arg1)1123ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1)
1124ad520a97SPhilippe Mathieu-Daudé {
1125ad520a97SPhilippe Mathieu-Daudé     cpu_mips_store_compare(env, arg1);
1126ad520a97SPhilippe Mathieu-Daudé }
1127ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_status(CPUMIPSState * env,target_ulong arg1)1128ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
1129ad520a97SPhilippe Mathieu-Daudé {
1130ad520a97SPhilippe Mathieu-Daudé     uint32_t val, old;
1131ad520a97SPhilippe Mathieu-Daudé 
1132ad520a97SPhilippe Mathieu-Daudé     old = env->CP0_Status;
1133ad520a97SPhilippe Mathieu-Daudé     cpu_mips_store_status(env, arg1);
1134ad520a97SPhilippe Mathieu-Daudé     val = env->CP0_Status;
1135ad520a97SPhilippe Mathieu-Daudé 
1136ad520a97SPhilippe Mathieu-Daudé     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1137ad520a97SPhilippe Mathieu-Daudé         qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
1138ad520a97SPhilippe Mathieu-Daudé                 old, old & env->CP0_Cause & CP0Ca_IP_mask,
1139ad520a97SPhilippe Mathieu-Daudé                 val, val & env->CP0_Cause & CP0Ca_IP_mask,
1140ad520a97SPhilippe Mathieu-Daudé                 env->CP0_Cause);
1141*6ebf33c5SRichard Henderson         switch (mips_env_mmu_index(env)) {
1142ad520a97SPhilippe Mathieu-Daudé         case 3:
1143ad520a97SPhilippe Mathieu-Daudé             qemu_log(", ERL\n");
1144ad520a97SPhilippe Mathieu-Daudé             break;
1145ad520a97SPhilippe Mathieu-Daudé         case MIPS_HFLAG_UM:
1146ad520a97SPhilippe Mathieu-Daudé             qemu_log(", UM\n");
1147ad520a97SPhilippe Mathieu-Daudé             break;
1148ad520a97SPhilippe Mathieu-Daudé         case MIPS_HFLAG_SM:
1149ad520a97SPhilippe Mathieu-Daudé             qemu_log(", SM\n");
1150ad520a97SPhilippe Mathieu-Daudé             break;
1151ad520a97SPhilippe Mathieu-Daudé         case MIPS_HFLAG_KM:
1152ad520a97SPhilippe Mathieu-Daudé             qemu_log("\n");
1153ad520a97SPhilippe Mathieu-Daudé             break;
1154ad520a97SPhilippe Mathieu-Daudé         default:
1155ad520a97SPhilippe Mathieu-Daudé             cpu_abort(env_cpu(env), "Invalid MMU mode!\n");
1156ad520a97SPhilippe Mathieu-Daudé             break;
1157ad520a97SPhilippe Mathieu-Daudé         }
1158ad520a97SPhilippe Mathieu-Daudé     }
1159ad520a97SPhilippe Mathieu-Daudé }
1160ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_status(CPUMIPSState * env,target_ulong arg1)1161ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_status(CPUMIPSState *env, target_ulong arg1)
1162ad520a97SPhilippe Mathieu-Daudé {
1163ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1164ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = env->CP0_Status_rw_bitmask & ~0xf1000018;
1165ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1166ad520a97SPhilippe Mathieu-Daudé 
1167ad520a97SPhilippe Mathieu-Daudé     other->CP0_Status = (other->CP0_Status & ~mask) | (arg1 & mask);
1168ad520a97SPhilippe Mathieu-Daudé     sync_c0_status(env, other, other_tc);
1169ad520a97SPhilippe Mathieu-Daudé }
1170ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_intctl(CPUMIPSState * env,target_ulong arg1)1171ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_intctl(CPUMIPSState *env, target_ulong arg1)
1172ad520a97SPhilippe Mathieu-Daudé {
1173ad520a97SPhilippe Mathieu-Daudé     env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000003e0) | (arg1 & 0x000003e0);
1174ad520a97SPhilippe Mathieu-Daudé }
1175ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_srsctl(CPUMIPSState * env,target_ulong arg1)1176ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1)
1177ad520a97SPhilippe Mathieu-Daudé {
1178ad520a97SPhilippe Mathieu-Daudé     uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1179ad520a97SPhilippe Mathieu-Daudé     env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
1180ad520a97SPhilippe Mathieu-Daudé }
1181ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_cause(CPUMIPSState * env,target_ulong arg1)1182ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1)
1183ad520a97SPhilippe Mathieu-Daudé {
1184ad520a97SPhilippe Mathieu-Daudé     cpu_mips_store_cause(env, arg1);
1185ad520a97SPhilippe Mathieu-Daudé }
1186ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_cause(CPUMIPSState * env,target_ulong arg1)1187ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1)
1188ad520a97SPhilippe Mathieu-Daudé {
1189ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1190ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1191ad520a97SPhilippe Mathieu-Daudé 
1192ad520a97SPhilippe Mathieu-Daudé     cpu_mips_store_cause(other, arg1);
1193ad520a97SPhilippe Mathieu-Daudé }
1194ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_epc(CPUMIPSState * env)1195ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_epc(CPUMIPSState *env)
1196ad520a97SPhilippe Mathieu-Daudé {
1197ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1198ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1199ad520a97SPhilippe Mathieu-Daudé 
1200ad520a97SPhilippe Mathieu-Daudé     return other->CP0_EPC;
1201ad520a97SPhilippe Mathieu-Daudé }
1202ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_ebase(CPUMIPSState * env)1203ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_ebase(CPUMIPSState *env)
1204ad520a97SPhilippe Mathieu-Daudé {
1205ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1206ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1207ad520a97SPhilippe Mathieu-Daudé 
1208ad520a97SPhilippe Mathieu-Daudé     return other->CP0_EBase;
1209ad520a97SPhilippe Mathieu-Daudé }
1210ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_ebase(CPUMIPSState * env,target_ulong arg1)1211ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1)
1212ad520a97SPhilippe Mathieu-Daudé {
1213ad520a97SPhilippe Mathieu-Daudé     target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
1214ad520a97SPhilippe Mathieu-Daudé     if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
1215ad520a97SPhilippe Mathieu-Daudé         mask |= ~0x3FFFFFFF;
1216ad520a97SPhilippe Mathieu-Daudé     }
1217ad520a97SPhilippe Mathieu-Daudé     env->CP0_EBase = (env->CP0_EBase & ~mask) | (arg1 & mask);
1218ad520a97SPhilippe Mathieu-Daudé }
1219ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_ebase(CPUMIPSState * env,target_ulong arg1)1220ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1)
1221ad520a97SPhilippe Mathieu-Daudé {
1222ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1223ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1224ad520a97SPhilippe Mathieu-Daudé     target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
1225ad520a97SPhilippe Mathieu-Daudé     if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
1226ad520a97SPhilippe Mathieu-Daudé         mask |= ~0x3FFFFFFF;
1227ad520a97SPhilippe Mathieu-Daudé     }
1228ad520a97SPhilippe Mathieu-Daudé     other->CP0_EBase = (other->CP0_EBase & ~mask) | (arg1 & mask);
1229ad520a97SPhilippe Mathieu-Daudé }
1230ad520a97SPhilippe Mathieu-Daudé 
helper_mftc0_configx(CPUMIPSState * env,target_ulong idx)1231ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx)
1232ad520a97SPhilippe Mathieu-Daudé {
1233ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1234ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1235ad520a97SPhilippe Mathieu-Daudé 
1236ad520a97SPhilippe Mathieu-Daudé     switch (idx) {
1237ad520a97SPhilippe Mathieu-Daudé     case 0: return other->CP0_Config0;
1238ad520a97SPhilippe Mathieu-Daudé     case 1: return other->CP0_Config1;
1239ad520a97SPhilippe Mathieu-Daudé     case 2: return other->CP0_Config2;
1240ad520a97SPhilippe Mathieu-Daudé     case 3: return other->CP0_Config3;
1241ad520a97SPhilippe Mathieu-Daudé     /* 4 and 5 are reserved.  */
1242ad520a97SPhilippe Mathieu-Daudé     case 6: return other->CP0_Config6;
1243ad520a97SPhilippe Mathieu-Daudé     case 7: return other->CP0_Config7;
1244ad520a97SPhilippe Mathieu-Daudé     default:
1245ad520a97SPhilippe Mathieu-Daudé         break;
1246ad520a97SPhilippe Mathieu-Daudé     }
1247ad520a97SPhilippe Mathieu-Daudé     return 0;
1248ad520a97SPhilippe Mathieu-Daudé }
1249ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_config0(CPUMIPSState * env,target_ulong arg1)1250ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_config0(CPUMIPSState *env, target_ulong arg1)
1251ad520a97SPhilippe Mathieu-Daudé {
1252ad520a97SPhilippe Mathieu-Daudé     env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
1253ad520a97SPhilippe Mathieu-Daudé }
1254ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_config2(CPUMIPSState * env,target_ulong arg1)1255ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1)
1256ad520a97SPhilippe Mathieu-Daudé {
1257ad520a97SPhilippe Mathieu-Daudé     /* tertiary/secondary caches not implemented */
1258ad520a97SPhilippe Mathieu-Daudé     env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1259ad520a97SPhilippe Mathieu-Daudé }
1260ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_config3(CPUMIPSState * env,target_ulong arg1)1261ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_config3(CPUMIPSState *env, target_ulong arg1)
1262ad520a97SPhilippe Mathieu-Daudé {
1263ad520a97SPhilippe Mathieu-Daudé     if (env->insn_flags & ASE_MICROMIPS) {
1264ad520a97SPhilippe Mathieu-Daudé         env->CP0_Config3 = (env->CP0_Config3 & ~(1 << CP0C3_ISA_ON_EXC)) |
1265ad520a97SPhilippe Mathieu-Daudé                            (arg1 & (1 << CP0C3_ISA_ON_EXC));
1266ad520a97SPhilippe Mathieu-Daudé     }
1267ad520a97SPhilippe Mathieu-Daudé }
1268ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_config4(CPUMIPSState * env,target_ulong arg1)1269ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_config4(CPUMIPSState *env, target_ulong arg1)
1270ad520a97SPhilippe Mathieu-Daudé {
1271ad520a97SPhilippe Mathieu-Daudé     env->CP0_Config4 = (env->CP0_Config4 & (~env->CP0_Config4_rw_bitmask)) |
1272ad520a97SPhilippe Mathieu-Daudé                        (arg1 & env->CP0_Config4_rw_bitmask);
1273ad520a97SPhilippe Mathieu-Daudé }
1274ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_config5(CPUMIPSState * env,target_ulong arg1)1275ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1)
1276ad520a97SPhilippe Mathieu-Daudé {
1277ad520a97SPhilippe Mathieu-Daudé     env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
1278ad520a97SPhilippe Mathieu-Daudé                        (arg1 & env->CP0_Config5_rw_bitmask);
1279ad520a97SPhilippe Mathieu-Daudé     env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
1280ad520a97SPhilippe Mathieu-Daudé             0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
1281ad520a97SPhilippe Mathieu-Daudé     compute_hflags(env);
1282ad520a97SPhilippe Mathieu-Daudé }
1283ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_lladdr(CPUMIPSState * env,target_ulong arg1)1284ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1)
1285ad520a97SPhilippe Mathieu-Daudé {
1286ad520a97SPhilippe Mathieu-Daudé     target_long mask = env->CP0_LLAddr_rw_bitmask;
1287ad520a97SPhilippe Mathieu-Daudé     arg1 = arg1 << env->CP0_LLAddr_shift;
1288ad520a97SPhilippe Mathieu-Daudé     env->CP0_LLAddr = (env->CP0_LLAddr & ~mask) | (arg1 & mask);
1289ad520a97SPhilippe Mathieu-Daudé }
1290ad520a97SPhilippe Mathieu-Daudé 
1291ad520a97SPhilippe Mathieu-Daudé #define MTC0_MAAR_MASK(env) \
1292ad520a97SPhilippe Mathieu-Daudé         ((0x1ULL << 63) | ((env->PAMask >> 4) & ~0xFFFull) | 0x3)
1293ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_maar(CPUMIPSState * env,target_ulong arg1)1294ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_maar(CPUMIPSState *env, target_ulong arg1)
1295ad520a97SPhilippe Mathieu-Daudé {
1296ad520a97SPhilippe Mathieu-Daudé     env->CP0_MAAR[env->CP0_MAARI] = arg1 & MTC0_MAAR_MASK(env);
1297ad520a97SPhilippe Mathieu-Daudé }
1298ad520a97SPhilippe Mathieu-Daudé 
helper_mthc0_maar(CPUMIPSState * env,target_ulong arg1)1299ad520a97SPhilippe Mathieu-Daudé void helper_mthc0_maar(CPUMIPSState *env, target_ulong arg1)
1300ad520a97SPhilippe Mathieu-Daudé {
1301ad520a97SPhilippe Mathieu-Daudé     env->CP0_MAAR[env->CP0_MAARI] =
1302ad520a97SPhilippe Mathieu-Daudé         (((uint64_t) arg1 << 32) & MTC0_MAAR_MASK(env)) |
1303ad520a97SPhilippe Mathieu-Daudé         (env->CP0_MAAR[env->CP0_MAARI] & 0x00000000ffffffffULL);
1304ad520a97SPhilippe Mathieu-Daudé }
1305ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_maari(CPUMIPSState * env,target_ulong arg1)1306ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_maari(CPUMIPSState *env, target_ulong arg1)
1307ad520a97SPhilippe Mathieu-Daudé {
1308ad520a97SPhilippe Mathieu-Daudé     int index = arg1 & 0x3f;
1309ad520a97SPhilippe Mathieu-Daudé     if (index == 0x3f) {
1310ad520a97SPhilippe Mathieu-Daudé         /*
1311ad520a97SPhilippe Mathieu-Daudé          * Software may write all ones to INDEX to determine the
1312ad520a97SPhilippe Mathieu-Daudé          *  maximum value supported.
1313ad520a97SPhilippe Mathieu-Daudé          */
1314ad520a97SPhilippe Mathieu-Daudé         env->CP0_MAARI = MIPS_MAAR_MAX - 1;
1315ad520a97SPhilippe Mathieu-Daudé     } else if (index < MIPS_MAAR_MAX) {
1316ad520a97SPhilippe Mathieu-Daudé         env->CP0_MAARI = index;
1317ad520a97SPhilippe Mathieu-Daudé     }
1318ad520a97SPhilippe Mathieu-Daudé     /*
1319ad520a97SPhilippe Mathieu-Daudé      * Other than the all ones, if the value written is not supported,
1320ad520a97SPhilippe Mathieu-Daudé      * then INDEX is unchanged from its previous value.
1321ad520a97SPhilippe Mathieu-Daudé      */
1322ad520a97SPhilippe Mathieu-Daudé }
1323ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_watchlo(CPUMIPSState * env,target_ulong arg1,uint32_t sel)1324ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1325ad520a97SPhilippe Mathieu-Daudé {
1326ad520a97SPhilippe Mathieu-Daudé     /*
1327ad520a97SPhilippe Mathieu-Daudé      * Watch exceptions for instructions, data loads, data stores
1328ad520a97SPhilippe Mathieu-Daudé      * not implemented.
1329ad520a97SPhilippe Mathieu-Daudé      */
1330ad520a97SPhilippe Mathieu-Daudé     env->CP0_WatchLo[sel] = (arg1 & ~0x7);
1331ad520a97SPhilippe Mathieu-Daudé }
1332ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_watchhi(CPUMIPSState * env,target_ulong arg1,uint32_t sel)1333ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1334ad520a97SPhilippe Mathieu-Daudé {
1335ad520a97SPhilippe Mathieu-Daudé     uint64_t mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID);
1336a6bc80f7SMarcin Nowakowski     uint64_t m_bit = env->CP0_WatchHi[sel] & (1 << CP0WH_M); /* read-only */
1337ad520a97SPhilippe Mathieu-Daudé     if ((env->CP0_Config5 >> CP0C5_MI) & 1) {
1338ad520a97SPhilippe Mathieu-Daudé         mask |= 0xFFFFFFFF00000000ULL; /* MMID */
1339ad520a97SPhilippe Mathieu-Daudé     }
1340a6bc80f7SMarcin Nowakowski     env->CP0_WatchHi[sel] = m_bit | (arg1 & mask);
1341ad520a97SPhilippe Mathieu-Daudé     env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
1342ad520a97SPhilippe Mathieu-Daudé }
1343ad520a97SPhilippe Mathieu-Daudé 
helper_mthc0_watchhi(CPUMIPSState * env,target_ulong arg1,uint32_t sel)1344ad520a97SPhilippe Mathieu-Daudé void helper_mthc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1345ad520a97SPhilippe Mathieu-Daudé {
1346ad520a97SPhilippe Mathieu-Daudé     env->CP0_WatchHi[sel] = ((uint64_t) (arg1) << 32) |
1347ad520a97SPhilippe Mathieu-Daudé                             (env->CP0_WatchHi[sel] & 0x00000000ffffffffULL);
1348ad520a97SPhilippe Mathieu-Daudé }
1349ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_xcontext(CPUMIPSState * env,target_ulong arg1)1350ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1)
1351ad520a97SPhilippe Mathieu-Daudé {
1352ad520a97SPhilippe Mathieu-Daudé     target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1353ad520a97SPhilippe Mathieu-Daudé     env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
1354ad520a97SPhilippe Mathieu-Daudé }
1355ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_framemask(CPUMIPSState * env,target_ulong arg1)1356ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_framemask(CPUMIPSState *env, target_ulong arg1)
1357ad520a97SPhilippe Mathieu-Daudé {
1358ad520a97SPhilippe Mathieu-Daudé     env->CP0_Framemask = arg1; /* XXX */
1359ad520a97SPhilippe Mathieu-Daudé }
1360ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_debug(CPUMIPSState * env,target_ulong arg1)1361ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_debug(CPUMIPSState *env, target_ulong arg1)
1362ad520a97SPhilippe Mathieu-Daudé {
1363ad520a97SPhilippe Mathieu-Daudé     env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
1364ad520a97SPhilippe Mathieu-Daudé     if (arg1 & (1 << CP0DB_DM)) {
1365ad520a97SPhilippe Mathieu-Daudé         env->hflags |= MIPS_HFLAG_DM;
1366ad520a97SPhilippe Mathieu-Daudé     } else {
1367ad520a97SPhilippe Mathieu-Daudé         env->hflags &= ~MIPS_HFLAG_DM;
1368ad520a97SPhilippe Mathieu-Daudé     }
1369ad520a97SPhilippe Mathieu-Daudé }
1370ad520a97SPhilippe Mathieu-Daudé 
helper_mttc0_debug(CPUMIPSState * env,target_ulong arg1)1371ad520a97SPhilippe Mathieu-Daudé void helper_mttc0_debug(CPUMIPSState *env, target_ulong arg1)
1372ad520a97SPhilippe Mathieu-Daudé {
1373ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1374ad520a97SPhilippe Mathieu-Daudé     uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1375ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1376ad520a97SPhilippe Mathieu-Daudé 
1377ad520a97SPhilippe Mathieu-Daudé     /* XXX: Might be wrong, check with EJTAG spec. */
1378ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1379ad520a97SPhilippe Mathieu-Daudé         other->active_tc.CP0_Debug_tcstatus = val;
1380ad520a97SPhilippe Mathieu-Daudé     } else {
1381ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].CP0_Debug_tcstatus = val;
1382ad520a97SPhilippe Mathieu-Daudé     }
1383ad520a97SPhilippe Mathieu-Daudé     other->CP0_Debug = (other->CP0_Debug &
1384ad520a97SPhilippe Mathieu-Daudé                      ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1385ad520a97SPhilippe Mathieu-Daudé                      (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1386ad520a97SPhilippe Mathieu-Daudé }
1387ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_performance0(CPUMIPSState * env,target_ulong arg1)1388ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1)
1389ad520a97SPhilippe Mathieu-Daudé {
1390ad520a97SPhilippe Mathieu-Daudé     env->CP0_Performance0 = arg1 & 0x000007ff;
1391ad520a97SPhilippe Mathieu-Daudé }
1392ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_errctl(CPUMIPSState * env,target_ulong arg1)1393ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_errctl(CPUMIPSState *env, target_ulong arg1)
1394ad520a97SPhilippe Mathieu-Daudé {
1395ad520a97SPhilippe Mathieu-Daudé     int32_t wst = arg1 & (1 << CP0EC_WST);
1396ad520a97SPhilippe Mathieu-Daudé     int32_t spr = arg1 & (1 << CP0EC_SPR);
1397ad520a97SPhilippe Mathieu-Daudé     int32_t itc = env->itc_tag ? (arg1 & (1 << CP0EC_ITC)) : 0;
1398ad520a97SPhilippe Mathieu-Daudé 
1399ad520a97SPhilippe Mathieu-Daudé     env->CP0_ErrCtl = wst | spr | itc;
1400ad520a97SPhilippe Mathieu-Daudé 
1401ad520a97SPhilippe Mathieu-Daudé     if (itc && !wst && !spr) {
1402ad520a97SPhilippe Mathieu-Daudé         env->hflags |= MIPS_HFLAG_ITC_CACHE;
1403ad520a97SPhilippe Mathieu-Daudé     } else {
1404ad520a97SPhilippe Mathieu-Daudé         env->hflags &= ~MIPS_HFLAG_ITC_CACHE;
1405ad520a97SPhilippe Mathieu-Daudé     }
1406ad520a97SPhilippe Mathieu-Daudé }
1407ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_taglo(CPUMIPSState * env,target_ulong arg1)1408ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1)
1409ad520a97SPhilippe Mathieu-Daudé {
1410ad520a97SPhilippe Mathieu-Daudé     if (env->hflags & MIPS_HFLAG_ITC_CACHE) {
1411ad520a97SPhilippe Mathieu-Daudé         /*
1412ad520a97SPhilippe Mathieu-Daudé          * If CACHE instruction is configured for ITC tags then make all
1413ad520a97SPhilippe Mathieu-Daudé          * CP0.TagLo bits writable. The actual write to ITC Configuration
1414ad520a97SPhilippe Mathieu-Daudé          * Tag will take care of the read-only bits.
1415ad520a97SPhilippe Mathieu-Daudé          */
1416ad520a97SPhilippe Mathieu-Daudé         env->CP0_TagLo = arg1;
1417ad520a97SPhilippe Mathieu-Daudé     } else {
1418ad520a97SPhilippe Mathieu-Daudé         env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1419ad520a97SPhilippe Mathieu-Daudé     }
1420ad520a97SPhilippe Mathieu-Daudé }
1421ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_datalo(CPUMIPSState * env,target_ulong arg1)1422ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1)
1423ad520a97SPhilippe Mathieu-Daudé {
1424ad520a97SPhilippe Mathieu-Daudé     env->CP0_DataLo = arg1; /* XXX */
1425ad520a97SPhilippe Mathieu-Daudé }
1426ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_taghi(CPUMIPSState * env,target_ulong arg1)1427ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_taghi(CPUMIPSState *env, target_ulong arg1)
1428ad520a97SPhilippe Mathieu-Daudé {
1429ad520a97SPhilippe Mathieu-Daudé     env->CP0_TagHi = arg1; /* XXX */
1430ad520a97SPhilippe Mathieu-Daudé }
1431ad520a97SPhilippe Mathieu-Daudé 
helper_mtc0_datahi(CPUMIPSState * env,target_ulong arg1)1432ad520a97SPhilippe Mathieu-Daudé void helper_mtc0_datahi(CPUMIPSState *env, target_ulong arg1)
1433ad520a97SPhilippe Mathieu-Daudé {
1434ad520a97SPhilippe Mathieu-Daudé     env->CP0_DataHi = arg1; /* XXX */
1435ad520a97SPhilippe Mathieu-Daudé }
1436ad520a97SPhilippe Mathieu-Daudé 
1437ad520a97SPhilippe Mathieu-Daudé /* MIPS MT functions */
helper_mftgpr(CPUMIPSState * env,uint32_t sel)1438ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftgpr(CPUMIPSState *env, uint32_t sel)
1439ad520a97SPhilippe Mathieu-Daudé {
1440ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1441ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1442ad520a97SPhilippe Mathieu-Daudé 
1443ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1444ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.gpr[sel];
1445ad520a97SPhilippe Mathieu-Daudé     } else {
1446ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].gpr[sel];
1447ad520a97SPhilippe Mathieu-Daudé     }
1448ad520a97SPhilippe Mathieu-Daudé }
1449ad520a97SPhilippe Mathieu-Daudé 
helper_mftlo(CPUMIPSState * env,uint32_t sel)1450ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftlo(CPUMIPSState *env, uint32_t sel)
1451ad520a97SPhilippe Mathieu-Daudé {
1452ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1453ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1454ad520a97SPhilippe Mathieu-Daudé 
1455ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1456ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.LO[sel];
1457ad520a97SPhilippe Mathieu-Daudé     } else {
1458ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].LO[sel];
1459ad520a97SPhilippe Mathieu-Daudé     }
1460ad520a97SPhilippe Mathieu-Daudé }
1461ad520a97SPhilippe Mathieu-Daudé 
helper_mfthi(CPUMIPSState * env,uint32_t sel)1462ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mfthi(CPUMIPSState *env, uint32_t sel)
1463ad520a97SPhilippe Mathieu-Daudé {
1464ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1465ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1466ad520a97SPhilippe Mathieu-Daudé 
1467ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1468ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.HI[sel];
1469ad520a97SPhilippe Mathieu-Daudé     } else {
1470ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].HI[sel];
1471ad520a97SPhilippe Mathieu-Daudé     }
1472ad520a97SPhilippe Mathieu-Daudé }
1473ad520a97SPhilippe Mathieu-Daudé 
helper_mftacx(CPUMIPSState * env,uint32_t sel)1474ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftacx(CPUMIPSState *env, uint32_t sel)
1475ad520a97SPhilippe Mathieu-Daudé {
1476ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1477ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1478ad520a97SPhilippe Mathieu-Daudé 
1479ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1480ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.ACX[sel];
1481ad520a97SPhilippe Mathieu-Daudé     } else {
1482ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].ACX[sel];
1483ad520a97SPhilippe Mathieu-Daudé     }
1484ad520a97SPhilippe Mathieu-Daudé }
1485ad520a97SPhilippe Mathieu-Daudé 
helper_mftdsp(CPUMIPSState * env)1486ad520a97SPhilippe Mathieu-Daudé target_ulong helper_mftdsp(CPUMIPSState *env)
1487ad520a97SPhilippe Mathieu-Daudé {
1488ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1489ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1490ad520a97SPhilippe Mathieu-Daudé 
1491ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1492ad520a97SPhilippe Mathieu-Daudé         return other->active_tc.DSPControl;
1493ad520a97SPhilippe Mathieu-Daudé     } else {
1494ad520a97SPhilippe Mathieu-Daudé         return other->tcs[other_tc].DSPControl;
1495ad520a97SPhilippe Mathieu-Daudé     }
1496ad520a97SPhilippe Mathieu-Daudé }
1497ad520a97SPhilippe Mathieu-Daudé 
helper_mttgpr(CPUMIPSState * env,target_ulong arg1,uint32_t sel)1498ad520a97SPhilippe Mathieu-Daudé void helper_mttgpr(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1499ad520a97SPhilippe Mathieu-Daudé {
1500ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1501ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1502ad520a97SPhilippe Mathieu-Daudé 
1503ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1504ad520a97SPhilippe Mathieu-Daudé         other->active_tc.gpr[sel] = arg1;
1505ad520a97SPhilippe Mathieu-Daudé     } else {
1506ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].gpr[sel] = arg1;
1507ad520a97SPhilippe Mathieu-Daudé     }
1508ad520a97SPhilippe Mathieu-Daudé }
1509ad520a97SPhilippe Mathieu-Daudé 
helper_mttlo(CPUMIPSState * env,target_ulong arg1,uint32_t sel)1510ad520a97SPhilippe Mathieu-Daudé void helper_mttlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1511ad520a97SPhilippe Mathieu-Daudé {
1512ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1513ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1514ad520a97SPhilippe Mathieu-Daudé 
1515ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1516ad520a97SPhilippe Mathieu-Daudé         other->active_tc.LO[sel] = arg1;
1517ad520a97SPhilippe Mathieu-Daudé     } else {
1518ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].LO[sel] = arg1;
1519ad520a97SPhilippe Mathieu-Daudé     }
1520ad520a97SPhilippe Mathieu-Daudé }
1521ad520a97SPhilippe Mathieu-Daudé 
helper_mtthi(CPUMIPSState * env,target_ulong arg1,uint32_t sel)1522ad520a97SPhilippe Mathieu-Daudé void helper_mtthi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1523ad520a97SPhilippe Mathieu-Daudé {
1524ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1525ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1526ad520a97SPhilippe Mathieu-Daudé 
1527ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1528ad520a97SPhilippe Mathieu-Daudé         other->active_tc.HI[sel] = arg1;
1529ad520a97SPhilippe Mathieu-Daudé     } else {
1530ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].HI[sel] = arg1;
1531ad520a97SPhilippe Mathieu-Daudé     }
1532ad520a97SPhilippe Mathieu-Daudé }
1533ad520a97SPhilippe Mathieu-Daudé 
helper_mttacx(CPUMIPSState * env,target_ulong arg1,uint32_t sel)1534ad520a97SPhilippe Mathieu-Daudé void helper_mttacx(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1535ad520a97SPhilippe Mathieu-Daudé {
1536ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1537ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1538ad520a97SPhilippe Mathieu-Daudé 
1539ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1540ad520a97SPhilippe Mathieu-Daudé         other->active_tc.ACX[sel] = arg1;
1541ad520a97SPhilippe Mathieu-Daudé     } else {
1542ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].ACX[sel] = arg1;
1543ad520a97SPhilippe Mathieu-Daudé     }
1544ad520a97SPhilippe Mathieu-Daudé }
1545ad520a97SPhilippe Mathieu-Daudé 
helper_mttdsp(CPUMIPSState * env,target_ulong arg1)1546ad520a97SPhilippe Mathieu-Daudé void helper_mttdsp(CPUMIPSState *env, target_ulong arg1)
1547ad520a97SPhilippe Mathieu-Daudé {
1548ad520a97SPhilippe Mathieu-Daudé     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1549ad520a97SPhilippe Mathieu-Daudé     CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1550ad520a97SPhilippe Mathieu-Daudé 
1551ad520a97SPhilippe Mathieu-Daudé     if (other_tc == other->current_tc) {
1552ad520a97SPhilippe Mathieu-Daudé         other->active_tc.DSPControl = arg1;
1553ad520a97SPhilippe Mathieu-Daudé     } else {
1554ad520a97SPhilippe Mathieu-Daudé         other->tcs[other_tc].DSPControl = arg1;
1555ad520a97SPhilippe Mathieu-Daudé     }
1556ad520a97SPhilippe Mathieu-Daudé }
1557ad520a97SPhilippe Mathieu-Daudé 
1558ad520a97SPhilippe Mathieu-Daudé /* MIPS MT functions */
helper_dmt(void)1559ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dmt(void)
1560ad520a97SPhilippe Mathieu-Daudé {
1561ad520a97SPhilippe Mathieu-Daudé     /* TODO */
1562ad520a97SPhilippe Mathieu-Daudé     return 0;
1563ad520a97SPhilippe Mathieu-Daudé }
1564ad520a97SPhilippe Mathieu-Daudé 
helper_emt(void)1565ad520a97SPhilippe Mathieu-Daudé target_ulong helper_emt(void)
1566ad520a97SPhilippe Mathieu-Daudé {
1567ad520a97SPhilippe Mathieu-Daudé     /* TODO */
1568ad520a97SPhilippe Mathieu-Daudé     return 0;
1569ad520a97SPhilippe Mathieu-Daudé }
1570ad520a97SPhilippe Mathieu-Daudé 
helper_dvpe(CPUMIPSState * env)1571ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dvpe(CPUMIPSState *env)
1572ad520a97SPhilippe Mathieu-Daudé {
1573ad520a97SPhilippe Mathieu-Daudé     CPUState *other_cs = first_cpu;
1574ad520a97SPhilippe Mathieu-Daudé     target_ulong prev = env->mvp->CP0_MVPControl;
1575ad520a97SPhilippe Mathieu-Daudé 
1576ad520a97SPhilippe Mathieu-Daudé     CPU_FOREACH(other_cs) {
1577ad520a97SPhilippe Mathieu-Daudé         MIPSCPU *other_cpu = MIPS_CPU(other_cs);
1578ad520a97SPhilippe Mathieu-Daudé         /* Turn off all VPEs except the one executing the dvpe.  */
1579ad520a97SPhilippe Mathieu-Daudé         if (&other_cpu->env != env) {
1580ad520a97SPhilippe Mathieu-Daudé             other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
1581ad520a97SPhilippe Mathieu-Daudé             mips_vpe_sleep(other_cpu);
1582ad520a97SPhilippe Mathieu-Daudé         }
1583ad520a97SPhilippe Mathieu-Daudé     }
1584ad520a97SPhilippe Mathieu-Daudé     return prev;
1585ad520a97SPhilippe Mathieu-Daudé }
1586ad520a97SPhilippe Mathieu-Daudé 
helper_evpe(CPUMIPSState * env)1587ad520a97SPhilippe Mathieu-Daudé target_ulong helper_evpe(CPUMIPSState *env)
1588ad520a97SPhilippe Mathieu-Daudé {
1589ad520a97SPhilippe Mathieu-Daudé     CPUState *other_cs = first_cpu;
1590ad520a97SPhilippe Mathieu-Daudé     target_ulong prev = env->mvp->CP0_MVPControl;
1591ad520a97SPhilippe Mathieu-Daudé 
1592ad520a97SPhilippe Mathieu-Daudé     CPU_FOREACH(other_cs) {
1593ad520a97SPhilippe Mathieu-Daudé         MIPSCPU *other_cpu = MIPS_CPU(other_cs);
1594ad520a97SPhilippe Mathieu-Daudé 
1595ad520a97SPhilippe Mathieu-Daudé         if (&other_cpu->env != env
1596ad520a97SPhilippe Mathieu-Daudé             /* If the VPE is WFI, don't disturb its sleep.  */
1597ad520a97SPhilippe Mathieu-Daudé             && !mips_vpe_is_wfi(other_cpu)) {
1598ad520a97SPhilippe Mathieu-Daudé             /* Enable the VPE.  */
1599ad520a97SPhilippe Mathieu-Daudé             other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
1600ad520a97SPhilippe Mathieu-Daudé             mips_vpe_wake(other_cpu); /* And wake it up.  */
1601ad520a97SPhilippe Mathieu-Daudé         }
1602ad520a97SPhilippe Mathieu-Daudé     }
1603ad520a97SPhilippe Mathieu-Daudé     return prev;
1604ad520a97SPhilippe Mathieu-Daudé }
1605ad520a97SPhilippe Mathieu-Daudé 
1606ad520a97SPhilippe Mathieu-Daudé /* R6 Multi-threading */
helper_dvp(CPUMIPSState * env)1607ad520a97SPhilippe Mathieu-Daudé target_ulong helper_dvp(CPUMIPSState *env)
1608ad520a97SPhilippe Mathieu-Daudé {
1609ad520a97SPhilippe Mathieu-Daudé     CPUState *other_cs = first_cpu;
1610ad520a97SPhilippe Mathieu-Daudé     target_ulong prev = env->CP0_VPControl;
1611ad520a97SPhilippe Mathieu-Daudé 
1612ad520a97SPhilippe Mathieu-Daudé     if (!((env->CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
1613ad520a97SPhilippe Mathieu-Daudé         CPU_FOREACH(other_cs) {
1614ad520a97SPhilippe Mathieu-Daudé             MIPSCPU *other_cpu = MIPS_CPU(other_cs);
1615ad520a97SPhilippe Mathieu-Daudé             /* Turn off all VPs except the one executing the dvp. */
1616ad520a97SPhilippe Mathieu-Daudé             if (&other_cpu->env != env) {
1617ad520a97SPhilippe Mathieu-Daudé                 mips_vpe_sleep(other_cpu);
1618ad520a97SPhilippe Mathieu-Daudé             }
1619ad520a97SPhilippe Mathieu-Daudé         }
1620ad520a97SPhilippe Mathieu-Daudé         env->CP0_VPControl |= (1 << CP0VPCtl_DIS);
1621ad520a97SPhilippe Mathieu-Daudé     }
1622ad520a97SPhilippe Mathieu-Daudé     return prev;
1623ad520a97SPhilippe Mathieu-Daudé }
1624ad520a97SPhilippe Mathieu-Daudé 
helper_evp(CPUMIPSState * env)1625ad520a97SPhilippe Mathieu-Daudé target_ulong helper_evp(CPUMIPSState *env)
1626ad520a97SPhilippe Mathieu-Daudé {
1627ad520a97SPhilippe Mathieu-Daudé     CPUState *other_cs = first_cpu;
1628ad520a97SPhilippe Mathieu-Daudé     target_ulong prev = env->CP0_VPControl;
1629ad520a97SPhilippe Mathieu-Daudé 
1630ad520a97SPhilippe Mathieu-Daudé     if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
1631ad520a97SPhilippe Mathieu-Daudé         CPU_FOREACH(other_cs) {
1632ad520a97SPhilippe Mathieu-Daudé             MIPSCPU *other_cpu = MIPS_CPU(other_cs);
1633ad520a97SPhilippe Mathieu-Daudé             if ((&other_cpu->env != env) && !mips_vp_is_wfi(other_cpu)) {
1634ad520a97SPhilippe Mathieu-Daudé                 /*
1635ad520a97SPhilippe Mathieu-Daudé                  * If the VP is WFI, don't disturb its sleep.
1636ad520a97SPhilippe Mathieu-Daudé                  * Otherwise, wake it up.
1637ad520a97SPhilippe Mathieu-Daudé                  */
1638ad520a97SPhilippe Mathieu-Daudé                 mips_vpe_wake(other_cpu);
1639ad520a97SPhilippe Mathieu-Daudé             }
1640ad520a97SPhilippe Mathieu-Daudé         }
1641ad520a97SPhilippe Mathieu-Daudé         env->CP0_VPControl &= ~(1 << CP0VPCtl_DIS);
1642ad520a97SPhilippe Mathieu-Daudé     }
1643ad520a97SPhilippe Mathieu-Daudé     return prev;
1644ad520a97SPhilippe Mathieu-Daudé }
1645