]>
Commit | Line | Data |
---|---|---|
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 | /* generic load/store macros */ | |
82 | ||
83 | static inline RES_TYPE | |
84 | glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) | |
85 | { | |
86 | int page_index; | |
87 | RES_TYPE res; | |
88 | target_ulong addr; | |
89 | int mmu_idx; | |
90 | ||
91 | addr = ptr; | |
92 | page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | |
93 | mmu_idx = CPU_MMU_INDEX; | |
94 | if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != | |
95 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { | |
96 | res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx); | |
97 | } else { | |
98 | uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; | |
99 | res = glue(glue(ld, USUFFIX), _raw)(hostaddr); | |
100 | } | |
101 | return res; | |
102 | } | |
103 | ||
104 | #if DATA_SIZE <= 2 | |
105 | static inline int | |
106 | glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) | |
107 | { | |
108 | int res, page_index; | |
109 | target_ulong addr; | |
110 | int mmu_idx; | |
111 | ||
112 | addr = ptr; | |
113 | page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | |
114 | mmu_idx = CPU_MMU_INDEX; | |
115 | if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != | |
116 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { | |
117 | res = (DATA_STYPE)glue(glue(helper_ld, SUFFIX), | |
118 | MMUSUFFIX)(env, addr, mmu_idx); | |
119 | } else { | |
120 | uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; | |
121 | res = glue(glue(lds, SUFFIX), _raw)(hostaddr); | |
122 | } | |
123 | return res; | |
124 | } | |
125 | #endif | |
126 | ||
127 | #if ACCESS_TYPE != (NB_MMU_MODES + 1) | |
128 | ||
129 | /* generic store macro */ | |
130 | ||
131 | static inline void | |
132 | glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr, | |
133 | RES_TYPE v) | |
134 | { | |
135 | int page_index; | |
136 | target_ulong addr; | |
137 | int mmu_idx; | |
138 | ||
139 | addr = ptr; | |
140 | page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | |
141 | mmu_idx = CPU_MMU_INDEX; | |
142 | if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write != | |
143 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { | |
144 | glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx); | |
145 | } else { | |
146 | uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; | |
147 | glue(glue(st, SUFFIX), _raw)(hostaddr, v); | |
148 | } | |
149 | } | |
150 | ||
151 | #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */ | |
152 | ||
153 | #if ACCESS_TYPE != (NB_MMU_MODES + 1) | |
154 | ||
155 | #if DATA_SIZE == 8 | |
156 | static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env, | |
157 | target_ulong ptr) | |
158 | { | |
159 | union { | |
160 | float64 d; | |
161 | uint64_t i; | |
162 | } u; | |
163 | u.i = glue(cpu_ldq, MEMSUFFIX)(env, ptr); | |
164 | return u.d; | |
165 | } | |
166 | ||
167 | static inline void glue(cpu_stfq, MEMSUFFIX)(CPUArchState *env, | |
168 | target_ulong ptr, float64 v) | |
169 | { | |
170 | union { | |
171 | float64 d; | |
172 | uint64_t i; | |
173 | } u; | |
174 | u.d = v; | |
175 | glue(cpu_stq, MEMSUFFIX)(env, ptr, u.i); | |
176 | } | |
177 | #endif /* DATA_SIZE == 8 */ | |
178 | ||
179 | #if DATA_SIZE == 4 | |
180 | static inline float32 glue(cpu_ldfl, MEMSUFFIX)(CPUArchState *env, | |
181 | target_ulong ptr) | |
182 | { | |
183 | union { | |
184 | float32 f; | |
185 | uint32_t i; | |
186 | } u; | |
187 | u.i = glue(cpu_ldl, MEMSUFFIX)(env, ptr); | |
188 | return u.f; | |
189 | } | |
190 | ||
191 | static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env, | |
192 | target_ulong ptr, float32 v) | |
193 | { | |
194 | union { | |
195 | float32 f; | |
196 | uint32_t i; | |
197 | } u; | |
198 | u.f = v; | |
199 | glue(cpu_stl, MEMSUFFIX)(env, ptr, u.i); | |
200 | } | |
201 | #endif /* DATA_SIZE == 4 */ | |
202 | ||
203 | #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */ | |
204 | ||
205 | #undef RES_TYPE | |
206 | #undef DATA_TYPE | |
207 | #undef DATA_STYPE | |
208 | #undef SUFFIX | |
209 | #undef USUFFIX | |
210 | #undef DATA_SIZE | |
211 | #undef CPU_MMU_INDEX | |
212 | #undef MMUSUFFIX | |
213 | #undef ADDR_READ |