|
|
1.1 ! root 1: /* ! 2: * PowerPC emulation special registers manipulation helpers for qemu. ! 3: * ! 4: * Copyright (c) 2003-2007 Jocelyn Mayer ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, write to the Free Software ! 18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 19: */ ! 20: ! 21: #if !defined(__HELPER_REGS_H__) ! 22: #define __HELPER_REGS_H__ ! 23: ! 24: static always_inline target_ulong hreg_load_xer (CPUPPCState *env) ! 25: { ! 26: return (xer_so << XER_SO) | ! 27: (xer_ov << XER_OV) | ! 28: (xer_ca << XER_CA) | ! 29: (xer_bc << XER_BC) | ! 30: (xer_cmp << XER_CMP); ! 31: } ! 32: ! 33: static always_inline void hreg_store_xer (CPUPPCState *env, target_ulong value) ! 34: { ! 35: xer_so = (value >> XER_SO) & 0x01; ! 36: xer_ov = (value >> XER_OV) & 0x01; ! 37: xer_ca = (value >> XER_CA) & 0x01; ! 38: xer_cmp = (value >> XER_CMP) & 0xFF; ! 39: xer_bc = (value >> XER_BC) & 0x7F; ! 40: } ! 41: ! 42: /* Swap temporary saved registers with GPRs */ ! 43: static always_inline void hreg_swap_gpr_tgpr (CPUPPCState *env) ! 44: { ! 45: ppc_gpr_t tmp; ! 46: ! 47: tmp = env->gpr[0]; ! 48: env->gpr[0] = env->tgpr[0]; ! 49: env->tgpr[0] = tmp; ! 50: tmp = env->gpr[1]; ! 51: env->gpr[1] = env->tgpr[1]; ! 52: env->tgpr[1] = tmp; ! 53: tmp = env->gpr[2]; ! 54: env->gpr[2] = env->tgpr[2]; ! 55: env->tgpr[2] = tmp; ! 56: tmp = env->gpr[3]; ! 57: env->gpr[3] = env->tgpr[3]; ! 58: env->tgpr[3] = tmp; ! 59: } ! 60: ! 61: static always_inline void hreg_compute_mem_idx (CPUPPCState *env) ! 62: { ! 63: /* Precompute MMU index */ ! 64: if (msr_pr == 0 && msr_hv != 0) { ! 65: env->mmu_idx = 2; ! 66: } else { ! 67: env->mmu_idx = 1 - msr_pr; ! 68: } ! 69: } ! 70: ! 71: static always_inline void hreg_compute_hflags (CPUPPCState *env) ! 72: { ! 73: target_ulong hflags_mask; ! 74: ! 75: /* We 'forget' FE0 & FE1: we'll never generate imprecise exceptions */ ! 76: hflags_mask = (1 << MSR_VR) | (1 << MSR_AP) | (1 << MSR_SA) | ! 77: (1 << MSR_PR) | (1 << MSR_FP) | (1 << MSR_SE) | (1 << MSR_BE) | ! 78: (1 << MSR_LE); ! 79: hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF) | MSR_HVB; ! 80: hreg_compute_mem_idx(env); ! 81: env->hflags = env->msr & hflags_mask; ! 82: /* Merge with hflags coming from other registers */ ! 83: env->hflags |= env->hflags_nmsr; ! 84: } ! 85: ! 86: static always_inline int hreg_store_msr (CPUPPCState *env, target_ulong value, ! 87: int alter_hv) ! 88: { ! 89: int excp; ! 90: ! 91: excp = 0; ! 92: value &= env->msr_mask; ! 93: #if !defined (CONFIG_USER_ONLY) ! 94: if (!alter_hv) { ! 95: /* mtmsr cannot alter the hypervisor state */ ! 96: value &= ~MSR_HVB; ! 97: value |= env->msr & MSR_HVB; ! 98: } ! 99: if (((value >> MSR_IR) & 1) != msr_ir || ! 100: ((value >> MSR_DR) & 1) != msr_dr) { ! 101: /* Flush all tlb when changing translation mode */ ! 102: tlb_flush(env, 1); ! 103: excp = POWERPC_EXCP_NONE; ! 104: env->interrupt_request |= CPU_INTERRUPT_EXITTB; ! 105: } ! 106: if (unlikely((env->flags & POWERPC_FLAG_TGPR) && ! 107: ((value ^ env->msr) & (1 << MSR_TGPR)))) { ! 108: /* Swap temporary saved registers with GPRs */ ! 109: hreg_swap_gpr_tgpr(env); ! 110: } ! 111: if (unlikely((value >> MSR_EP) & 1) != msr_ep) { ! 112: /* Change the exception prefix on PowerPC 601 */ ! 113: env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000; ! 114: } ! 115: #endif ! 116: env->msr = value; ! 117: hreg_compute_hflags(env); ! 118: #if !defined (CONFIG_USER_ONLY) ! 119: if (unlikely(msr_pow == 1)) { ! 120: if ((*env->check_pow)(env)) { ! 121: env->halted = 1; ! 122: excp = EXCP_HALTED; ! 123: } ! 124: } ! 125: #endif ! 126: ! 127: return excp; ! 128: } ! 129: ! 130: #endif /* !defined(__HELPER_REGS_H__) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.