1*d60146a9SPhilippe Mathieu-Daudé /* 2*d60146a9SPhilippe Mathieu-Daudé * QEMU MIPS emulation: Special opcode helpers 3*d60146a9SPhilippe Mathieu-Daudé * 4*d60146a9SPhilippe Mathieu-Daudé * Copyright (c) 2004-2005 Jocelyn Mayer 5*d60146a9SPhilippe Mathieu-Daudé * 6*d60146a9SPhilippe Mathieu-Daudé * This library is free software; you can redistribute it and/or 7*d60146a9SPhilippe Mathieu-Daudé * modify it under the terms of the GNU Lesser General Public 8*d60146a9SPhilippe Mathieu-Daudé * License as published by the Free Software Foundation; either 9*d60146a9SPhilippe Mathieu-Daudé * version 2.1 of the License, or (at your option) any later version. 10*d60146a9SPhilippe Mathieu-Daudé * 11*d60146a9SPhilippe Mathieu-Daudé * This library is distributed in the hope that it will be useful, 12*d60146a9SPhilippe Mathieu-Daudé * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*d60146a9SPhilippe Mathieu-Daudé * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*d60146a9SPhilippe Mathieu-Daudé * Lesser General Public License for more details. 15*d60146a9SPhilippe Mathieu-Daudé * 16*d60146a9SPhilippe Mathieu-Daudé * You should have received a copy of the GNU Lesser General Public 17*d60146a9SPhilippe Mathieu-Daudé * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18*d60146a9SPhilippe Mathieu-Daudé * 19*d60146a9SPhilippe Mathieu-Daudé */ 20*d60146a9SPhilippe Mathieu-Daudé 21*d60146a9SPhilippe Mathieu-Daudé #include "qemu/osdep.h" 22*d60146a9SPhilippe Mathieu-Daudé #include "cpu.h" 23*d60146a9SPhilippe Mathieu-Daudé #include "exec/helper-proto.h" 24*d60146a9SPhilippe Mathieu-Daudé #include "exec/exec-all.h" 25*d60146a9SPhilippe Mathieu-Daudé #include "internal.h" 26*d60146a9SPhilippe Mathieu-Daudé 27*d60146a9SPhilippe Mathieu-Daudé /* Specials */ 28*d60146a9SPhilippe Mathieu-Daudé target_ulong helper_di(CPUMIPSState *env) 29*d60146a9SPhilippe Mathieu-Daudé { 30*d60146a9SPhilippe Mathieu-Daudé target_ulong t0 = env->CP0_Status; 31*d60146a9SPhilippe Mathieu-Daudé 32*d60146a9SPhilippe Mathieu-Daudé env->CP0_Status = t0 & ~(1 << CP0St_IE); 33*d60146a9SPhilippe Mathieu-Daudé return t0; 34*d60146a9SPhilippe Mathieu-Daudé } 35*d60146a9SPhilippe Mathieu-Daudé 36*d60146a9SPhilippe Mathieu-Daudé target_ulong helper_ei(CPUMIPSState *env) 37*d60146a9SPhilippe Mathieu-Daudé { 38*d60146a9SPhilippe Mathieu-Daudé target_ulong t0 = env->CP0_Status; 39*d60146a9SPhilippe Mathieu-Daudé 40*d60146a9SPhilippe Mathieu-Daudé env->CP0_Status = t0 | (1 << CP0St_IE); 41*d60146a9SPhilippe Mathieu-Daudé return t0; 42*d60146a9SPhilippe Mathieu-Daudé } 43*d60146a9SPhilippe Mathieu-Daudé 44*d60146a9SPhilippe Mathieu-Daudé static void debug_pre_eret(CPUMIPSState *env) 45*d60146a9SPhilippe Mathieu-Daudé { 46*d60146a9SPhilippe Mathieu-Daudé if (qemu_loglevel_mask(CPU_LOG_EXEC)) { 47*d60146a9SPhilippe Mathieu-Daudé qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, 48*d60146a9SPhilippe Mathieu-Daudé env->active_tc.PC, env->CP0_EPC); 49*d60146a9SPhilippe Mathieu-Daudé if (env->CP0_Status & (1 << CP0St_ERL)) { 50*d60146a9SPhilippe Mathieu-Daudé qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); 51*d60146a9SPhilippe Mathieu-Daudé } 52*d60146a9SPhilippe Mathieu-Daudé if (env->hflags & MIPS_HFLAG_DM) { 53*d60146a9SPhilippe Mathieu-Daudé qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC); 54*d60146a9SPhilippe Mathieu-Daudé } 55*d60146a9SPhilippe Mathieu-Daudé qemu_log("\n"); 56*d60146a9SPhilippe Mathieu-Daudé } 57*d60146a9SPhilippe Mathieu-Daudé } 58*d60146a9SPhilippe Mathieu-Daudé 59*d60146a9SPhilippe Mathieu-Daudé static void debug_post_eret(CPUMIPSState *env) 60*d60146a9SPhilippe Mathieu-Daudé { 61*d60146a9SPhilippe Mathieu-Daudé if (qemu_loglevel_mask(CPU_LOG_EXEC)) { 62*d60146a9SPhilippe Mathieu-Daudé qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, 63*d60146a9SPhilippe Mathieu-Daudé env->active_tc.PC, env->CP0_EPC); 64*d60146a9SPhilippe Mathieu-Daudé if (env->CP0_Status & (1 << CP0St_ERL)) { 65*d60146a9SPhilippe Mathieu-Daudé qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); 66*d60146a9SPhilippe Mathieu-Daudé } 67*d60146a9SPhilippe Mathieu-Daudé if (env->hflags & MIPS_HFLAG_DM) { 68*d60146a9SPhilippe Mathieu-Daudé qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC); 69*d60146a9SPhilippe Mathieu-Daudé } 70*d60146a9SPhilippe Mathieu-Daudé switch (cpu_mmu_index(env, false)) { 71*d60146a9SPhilippe Mathieu-Daudé case 3: 72*d60146a9SPhilippe Mathieu-Daudé qemu_log(", ERL\n"); 73*d60146a9SPhilippe Mathieu-Daudé break; 74*d60146a9SPhilippe Mathieu-Daudé case MIPS_HFLAG_UM: 75*d60146a9SPhilippe Mathieu-Daudé qemu_log(", UM\n"); 76*d60146a9SPhilippe Mathieu-Daudé break; 77*d60146a9SPhilippe Mathieu-Daudé case MIPS_HFLAG_SM: 78*d60146a9SPhilippe Mathieu-Daudé qemu_log(", SM\n"); 79*d60146a9SPhilippe Mathieu-Daudé break; 80*d60146a9SPhilippe Mathieu-Daudé case MIPS_HFLAG_KM: 81*d60146a9SPhilippe Mathieu-Daudé qemu_log("\n"); 82*d60146a9SPhilippe Mathieu-Daudé break; 83*d60146a9SPhilippe Mathieu-Daudé default: 84*d60146a9SPhilippe Mathieu-Daudé cpu_abort(env_cpu(env), "Invalid MMU mode!\n"); 85*d60146a9SPhilippe Mathieu-Daudé break; 86*d60146a9SPhilippe Mathieu-Daudé } 87*d60146a9SPhilippe Mathieu-Daudé } 88*d60146a9SPhilippe Mathieu-Daudé } 89*d60146a9SPhilippe Mathieu-Daudé 90*d60146a9SPhilippe Mathieu-Daudé bool mips_io_recompile_replay_branch(CPUState *cs, const TranslationBlock *tb) 91*d60146a9SPhilippe Mathieu-Daudé { 92*d60146a9SPhilippe Mathieu-Daudé MIPSCPU *cpu = MIPS_CPU(cs); 93*d60146a9SPhilippe Mathieu-Daudé CPUMIPSState *env = &cpu->env; 94*d60146a9SPhilippe Mathieu-Daudé 95*d60146a9SPhilippe Mathieu-Daudé if ((env->hflags & MIPS_HFLAG_BMASK) != 0 96*d60146a9SPhilippe Mathieu-Daudé && env->active_tc.PC != tb->pc) { 97*d60146a9SPhilippe Mathieu-Daudé env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4); 98*d60146a9SPhilippe Mathieu-Daudé env->hflags &= ~MIPS_HFLAG_BMASK; 99*d60146a9SPhilippe Mathieu-Daudé return true; 100*d60146a9SPhilippe Mathieu-Daudé } 101*d60146a9SPhilippe Mathieu-Daudé return false; 102*d60146a9SPhilippe Mathieu-Daudé } 103*d60146a9SPhilippe Mathieu-Daudé 104*d60146a9SPhilippe Mathieu-Daudé static inline void exception_return(CPUMIPSState *env) 105*d60146a9SPhilippe Mathieu-Daudé { 106*d60146a9SPhilippe Mathieu-Daudé debug_pre_eret(env); 107*d60146a9SPhilippe Mathieu-Daudé if (env->CP0_Status & (1 << CP0St_ERL)) { 108*d60146a9SPhilippe Mathieu-Daudé mips_env_set_pc(env, env->CP0_ErrorEPC); 109*d60146a9SPhilippe Mathieu-Daudé env->CP0_Status &= ~(1 << CP0St_ERL); 110*d60146a9SPhilippe Mathieu-Daudé } else { 111*d60146a9SPhilippe Mathieu-Daudé mips_env_set_pc(env, env->CP0_EPC); 112*d60146a9SPhilippe Mathieu-Daudé env->CP0_Status &= ~(1 << CP0St_EXL); 113*d60146a9SPhilippe Mathieu-Daudé } 114*d60146a9SPhilippe Mathieu-Daudé compute_hflags(env); 115*d60146a9SPhilippe Mathieu-Daudé debug_post_eret(env); 116*d60146a9SPhilippe Mathieu-Daudé } 117*d60146a9SPhilippe Mathieu-Daudé 118*d60146a9SPhilippe Mathieu-Daudé void helper_eret(CPUMIPSState *env) 119*d60146a9SPhilippe Mathieu-Daudé { 120*d60146a9SPhilippe Mathieu-Daudé exception_return(env); 121*d60146a9SPhilippe Mathieu-Daudé env->CP0_LLAddr = 1; 122*d60146a9SPhilippe Mathieu-Daudé env->lladdr = 1; 123*d60146a9SPhilippe Mathieu-Daudé } 124*d60146a9SPhilippe Mathieu-Daudé 125*d60146a9SPhilippe Mathieu-Daudé void helper_eretnc(CPUMIPSState *env) 126*d60146a9SPhilippe Mathieu-Daudé { 127*d60146a9SPhilippe Mathieu-Daudé exception_return(env); 128*d60146a9SPhilippe Mathieu-Daudé } 129*d60146a9SPhilippe Mathieu-Daudé 130*d60146a9SPhilippe Mathieu-Daudé void helper_deret(CPUMIPSState *env) 131*d60146a9SPhilippe Mathieu-Daudé { 132*d60146a9SPhilippe Mathieu-Daudé debug_pre_eret(env); 133*d60146a9SPhilippe Mathieu-Daudé 134*d60146a9SPhilippe Mathieu-Daudé env->hflags &= ~MIPS_HFLAG_DM; 135*d60146a9SPhilippe Mathieu-Daudé compute_hflags(env); 136*d60146a9SPhilippe Mathieu-Daudé 137*d60146a9SPhilippe Mathieu-Daudé mips_env_set_pc(env, env->CP0_DEPC); 138*d60146a9SPhilippe Mathieu-Daudé 139*d60146a9SPhilippe Mathieu-Daudé debug_post_eret(env); 140*d60146a9SPhilippe Mathieu-Daudé } 141