]> Git Repo - qemu.git/blob - target-ppc/helper_regs.h
ppc: POWER7 had ACOP and PID registers
[qemu.git] / target-ppc / helper_regs.h
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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #if !defined(__HELPER_REGS_H__)
21 #define __HELPER_REGS_H__
22
23 /* Swap temporary saved registers with GPRs */
24 static inline void hreg_swap_gpr_tgpr(CPUPPCState *env)
25 {
26     target_ulong tmp;
27
28     tmp = env->gpr[0];
29     env->gpr[0] = env->tgpr[0];
30     env->tgpr[0] = tmp;
31     tmp = env->gpr[1];
32     env->gpr[1] = env->tgpr[1];
33     env->tgpr[1] = tmp;
34     tmp = env->gpr[2];
35     env->gpr[2] = env->tgpr[2];
36     env->tgpr[2] = tmp;
37     tmp = env->gpr[3];
38     env->gpr[3] = env->tgpr[3];
39     env->tgpr[3] = tmp;
40 }
41
42 static inline void hreg_compute_mem_idx(CPUPPCState *env)
43 {
44     /* This is our encoding for server processors
45      *
46      *   0 = Guest User space virtual mode
47      *   1 = Guest Kernel space virtual mode
48      *   2 = Guest Kernel space real mode
49      *   3 = HV User space virtual mode
50      *   4 = HV Kernel space virtual mode
51      *   5 = HV Kernel space real mode
52      *
53      * The combination PR=1 IR&DR=0 is invalid, we will treat
54      * it as IR=DR=1
55      *
56      * For BookE, we need 8 MMU modes as follow:
57      *
58      *  0 = AS 0 HV User space
59      *  1 = AS 0 HV Kernel space
60      *  2 = AS 1 HV User space
61      *  3 = AS 1 HV Kernel space
62      *  4 = AS 0 Guest User space
63      *  5 = AS 0 Guest Kernel space
64      *  6 = AS 1 Guest User space
65      *  7 = AS 1 Guest Kernel space
66      */
67     if (env->mmu_model & POWERPC_MMU_BOOKE) {
68         env->immu_idx = env->dmmu_idx = msr_pr ? 0 : 1;
69         env->immu_idx += msr_is ? 2 : 0;
70         env->dmmu_idx += msr_ds ? 2 : 0;
71         env->immu_idx += msr_gs ? 4 : 0;
72         env->dmmu_idx += msr_gs ? 4 : 0;
73     } else {
74         /* First calucalte a base value independent of HV */
75         if (msr_pr != 0) {
76             /* User space, ignore IR and DR */
77             env->immu_idx = env->dmmu_idx = 0;
78         } else {
79             /* Kernel, setup a base I/D value */
80             env->immu_idx = msr_ir ? 1 : 2;
81             env->dmmu_idx = msr_dr ? 1 : 2;
82         }
83         /* Then offset it for HV */
84         if (msr_hv) {
85             env->immu_idx += 3;
86             env->dmmu_idx += 3;
87         }
88     }
89 }
90
91 static inline void hreg_compute_hflags(CPUPPCState *env)
92 {
93     target_ulong hflags_mask;
94
95     /* We 'forget' FE0 & FE1: we'll never generate imprecise exceptions */
96     hflags_mask = (1 << MSR_VR) | (1 << MSR_AP) | (1 << MSR_SA) |
97         (1 << MSR_PR) | (1 << MSR_FP) | (1 << MSR_SE) | (1 << MSR_BE) |
98         (1 << MSR_LE) | (1 << MSR_VSX) | (1 << MSR_IR) | (1 << MSR_DR);
99     hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF) | MSR_HVB;
100     hreg_compute_mem_idx(env);
101     env->hflags = env->msr & hflags_mask;
102     /* Merge with hflags coming from other registers */
103     env->hflags |= env->hflags_nmsr;
104 }
105
106 static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
107                                  int alter_hv)
108 {
109     int excp;
110 #if !defined(CONFIG_USER_ONLY)
111     CPUState *cs = CPU(ppc_env_get_cpu(env));
112 #endif
113
114     excp = 0;
115     value &= env->msr_mask;
116 #if !defined(CONFIG_USER_ONLY)
117     /* Neither mtmsr nor guest state can alter HV */
118     if (!alter_hv || !(env->msr & MSR_HVB)) {
119         value &= ~MSR_HVB;
120         value |= env->msr & MSR_HVB;
121     }
122     if (((value >> MSR_IR) & 1) != msr_ir ||
123         ((value >> MSR_DR) & 1) != msr_dr) {
124         cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
125     }
126     if ((env->mmu_model & POWERPC_MMU_BOOKE) &&
127         ((value >> MSR_GS) & 1) != msr_gs) {
128         cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
129     }
130     if (unlikely((env->flags & POWERPC_FLAG_TGPR) &&
131                  ((value ^ env->msr) & (1 << MSR_TGPR)))) {
132         /* Swap temporary saved registers with GPRs */
133         hreg_swap_gpr_tgpr(env);
134     }
135     if (unlikely((value >> MSR_EP) & 1) != msr_ep) {
136         /* Change the exception prefix on PowerPC 601 */
137         env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000;
138     }
139 #endif
140     env->msr = value;
141     hreg_compute_hflags(env);
142 #if !defined(CONFIG_USER_ONLY)
143     if (unlikely(msr_pow == 1)) {
144         if (!env->pending_interrupts && (*env->check_pow)(env)) {
145             cs->halted = 1;
146             excp = EXCP_HALTED;
147         }
148     }
149 #endif
150
151     return excp;
152 }
153
154 #if !defined(CONFIG_USER_ONLY)
155 static inline void check_tlb_flush(CPUPPCState *env)
156 {
157     CPUState *cs = CPU(ppc_env_get_cpu(env));
158     if (env->tlb_need_flush) {
159         env->tlb_need_flush = 0;
160         tlb_flush(cs, 1);
161     }
162 }
163 #else
164 static inline void check_tlb_flush(CPUPPCState *env) { }
165 #endif
166
167 #endif /* !defined(__HELPER_REGS_H__) */
This page took 0.032806 seconds and 4 git commands to generate.