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