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