sync with latest
[sdk/emulator/qemu.git] / softmmu_header.h
1 /*
2  *  Software MMU support
3  *
4  * Generate inline load/store functions for one MMU mode and data
5  * size.
6  *
7  * Generate a store function as well as signed and unsigned loads. For
8  * 32 and 64 bit cases, also generate floating point functions with
9  * the same size.
10  *
11  * Not used directly but included from softmmu_exec.h and exec-all.h.
12  *
13  *  Copyright (c) 2003 Fabrice Bellard
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
27  */
28 #if DATA_SIZE == 8
29 #define SUFFIX q
30 #define USUFFIX q
31 #define DATA_TYPE uint64_t
32 #elif DATA_SIZE == 4
33 #define SUFFIX l
34 #define USUFFIX l
35 #define DATA_TYPE uint32_t
36 #elif DATA_SIZE == 2
37 #define SUFFIX w
38 #define USUFFIX uw
39 #define DATA_TYPE uint16_t
40 #define DATA_STYPE int16_t
41 #elif DATA_SIZE == 1
42 #define SUFFIX b
43 #define USUFFIX ub
44 #define DATA_TYPE uint8_t
45 #define DATA_STYPE int8_t
46 #else
47 #error unsupported data size
48 #endif
49
50 #if ACCESS_TYPE < (NB_MMU_MODES)
51
52 #define CPU_MMU_INDEX ACCESS_TYPE
53 #define MMUSUFFIX _mmu
54
55 #elif ACCESS_TYPE == (NB_MMU_MODES)
56
57 #define CPU_MMU_INDEX (cpu_mmu_index(env))
58 #define MMUSUFFIX _mmu
59
60 #elif ACCESS_TYPE == (NB_MMU_MODES + 1)
61
62 #define CPU_MMU_INDEX (cpu_mmu_index(env))
63 #define MMUSUFFIX _cmmu
64
65 #else
66 #error invalid ACCESS_TYPE
67 #endif
68
69 #if DATA_SIZE == 8
70 #define RES_TYPE uint64_t
71 #else
72 #define RES_TYPE uint32_t
73 #endif
74
75 #if ACCESS_TYPE == (NB_MMU_MODES + 1)
76 #define ADDR_READ addr_code
77 #else
78 #define ADDR_READ addr_read
79 #endif
80
81 #ifndef CONFIG_TCG_PASS_AREG0
82 #define ENV_PARAM
83 #define ENV_VAR
84 #define CPU_PREFIX
85 #define HELPER_PREFIX __
86 #else
87 #define ENV_PARAM CPUArchState *env,
88 #define ENV_VAR env,
89 #define CPU_PREFIX cpu_
90 #define HELPER_PREFIX helper_
91 #endif
92
93 /* generic load/store macros */
94
95 static inline RES_TYPE
96 glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
97                                                      target_ulong ptr)
98 {
99     int page_index;
100     RES_TYPE res;
101     target_ulong addr;
102     int mmu_idx;
103
104     addr = ptr;
105     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
106     mmu_idx = CPU_MMU_INDEX;
107     if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
108                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
109         res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR
110                                                                      addr,
111                                                                      mmu_idx);
112     } else {
113         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
114         res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
115     }
116     return res;
117 }
118
119 #if DATA_SIZE <= 2
120 static inline int
121 glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
122                                                      target_ulong ptr)
123 {
124     int res, page_index;
125     target_ulong addr;
126     int mmu_idx;
127
128     addr = ptr;
129     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
130     mmu_idx = CPU_MMU_INDEX;
131     if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
132                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
133         res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX),
134                                MMUSUFFIX)(ENV_VAR addr, mmu_idx);
135     } else {
136         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
137         res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
138     }
139     return res;
140 }
141 #endif
142
143 #if ACCESS_TYPE != (NB_MMU_MODES + 1)
144
145 /* generic store macro */
146
147 static inline void
148 glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
149                                                     RES_TYPE v)
150 {
151     int page_index;
152     target_ulong addr;
153     int mmu_idx;
154
155     addr = ptr;
156     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
157     mmu_idx = CPU_MMU_INDEX;
158     if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
159                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
160         glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v,
161                                                                mmu_idx);
162     } else {
163         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
164         glue(glue(st, SUFFIX), _raw)(hostaddr, v);
165     }
166 }
167
168 #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
169
170 #if ACCESS_TYPE != (NB_MMU_MODES + 1)
171
172 #if DATA_SIZE == 8
173 static inline float64 glue(glue(CPU_PREFIX, ldfq), MEMSUFFIX)(ENV_PARAM
174                                                               target_ulong ptr)
175 {
176     union {
177         float64 d;
178         uint64_t i;
179     } u;
180     u.i = glue(glue(CPU_PREFIX, ldq), MEMSUFFIX)(ENV_VAR ptr);
181     return u.d;
182 }
183
184 static inline void glue(glue(CPU_PREFIX, stfq), MEMSUFFIX)(ENV_PARAM
185                                                            target_ulong ptr,
186                                                            float64 v)
187 {
188     union {
189         float64 d;
190         uint64_t i;
191     } u;
192     u.d = v;
193     glue(glue(CPU_PREFIX, stq), MEMSUFFIX)(ENV_VAR ptr, u.i);
194 }
195 #endif /* DATA_SIZE == 8 */
196
197 #if DATA_SIZE == 4
198 static inline float32 glue(glue(CPU_PREFIX, ldfl), MEMSUFFIX)(ENV_PARAM
199                                                               target_ulong ptr)
200 {
201     union {
202         float32 f;
203         uint32_t i;
204     } u;
205     u.i = glue(glue(CPU_PREFIX, ldl), MEMSUFFIX)(ENV_VAR ptr);
206     return u.f;
207 }
208
209 static inline void glue(glue(CPU_PREFIX, stfl), MEMSUFFIX)(ENV_PARAM
210                                                            target_ulong ptr,
211                                                            float32 v)
212 {
213     union {
214         float32 f;
215         uint32_t i;
216     } u;
217     u.f = v;
218     glue(glue(CPU_PREFIX, stl), MEMSUFFIX)(ENV_VAR ptr, u.i);
219 }
220 #endif /* DATA_SIZE == 4 */
221
222 #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
223
224 #undef RES_TYPE
225 #undef DATA_TYPE
226 #undef DATA_STYPE
227 #undef SUFFIX
228 #undef USUFFIX
229 #undef DATA_SIZE
230 #undef CPU_MMU_INDEX
231 #undef MMUSUFFIX
232 #undef ADDR_READ
233 #undef ENV_PARAM
234 #undef ENV_VAR
235 #undef CPU_PREFIX
236 #undef HELPER_PREFIX