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