]>
Commit | Line | Data |
---|---|---|
b92e5a22 FB |
1 | /* |
2 | * Software MMU support | |
5fafdf24 | 3 | * |
efbf29b6 BS |
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 | * | |
c773828a | 11 | * Not used directly but included from cpu_ldst.h. |
efbf29b6 | 12 | * |
b92e5a22 FB |
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 | |
8167ee88 | 26 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
b92e5a22 FB |
27 | */ |
28 | #if DATA_SIZE == 8 | |
29 | #define SUFFIX q | |
61382a50 | 30 | #define USUFFIX q |
b92e5a22 FB |
31 | #define DATA_TYPE uint64_t |
32 | #elif DATA_SIZE == 4 | |
33 | #define SUFFIX l | |
61382a50 | 34 | #define USUFFIX l |
b92e5a22 FB |
35 | #define DATA_TYPE uint32_t |
36 | #elif DATA_SIZE == 2 | |
37 | #define SUFFIX w | |
61382a50 | 38 | #define USUFFIX uw |
b92e5a22 FB |
39 | #define DATA_TYPE uint16_t |
40 | #define DATA_STYPE int16_t | |
41 | #elif DATA_SIZE == 1 | |
42 | #define SUFFIX b | |
61382a50 | 43 | #define USUFFIX ub |
b92e5a22 FB |
44 | #define DATA_TYPE uint8_t |
45 | #define DATA_STYPE int8_t | |
46 | #else | |
47 | #error unsupported data size | |
48 | #endif | |
49 | ||
b92e5a22 FB |
50 | #if DATA_SIZE == 8 |
51 | #define RES_TYPE uint64_t | |
52 | #else | |
c086b783 | 53 | #define RES_TYPE uint32_t |
b92e5a22 FB |
54 | #endif |
55 | ||
859d7612 | 56 | #ifdef SOFTMMU_CODE_ACCESS |
84b7b8e7 | 57 | #define ADDR_READ addr_code |
a6c9eac0 | 58 | #define MMUSUFFIX _cmmu |
84b7b8e7 FB |
59 | #else |
60 | #define ADDR_READ addr_read | |
a6c9eac0 | 61 | #define MMUSUFFIX _mmu |
84b7b8e7 | 62 | #endif |
b92e5a22 | 63 | |
e16c53fa FB |
64 | /* generic load/store macros */ |
65 | ||
e141ab52 | 66 | static inline RES_TYPE |
89c33337 | 67 | glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) |
b92e5a22 | 68 | { |
4d7a0880 | 69 | int page_index; |
b92e5a22 | 70 | RES_TYPE res; |
c27004ec | 71 | target_ulong addr; |
6ebbf390 | 72 | int mmu_idx; |
61382a50 | 73 | |
c27004ec | 74 | addr = ptr; |
4d7a0880 | 75 | page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
6ebbf390 | 76 | mmu_idx = CPU_MMU_INDEX; |
551bd27f TS |
77 | if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != |
78 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { | |
89c33337 | 79 | res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx); |
b92e5a22 | 80 | } else { |
23ddbf08 | 81 | uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; |
b065927a | 82 | res = glue(glue(ld, USUFFIX), _raw)(hostaddr); |
b92e5a22 FB |
83 | } |
84 | return res; | |
85 | } | |
86 | ||
87 | #if DATA_SIZE <= 2 | |
e141ab52 | 88 | static inline int |
89c33337 | 89 | glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) |
b92e5a22 | 90 | { |
4d7a0880 | 91 | int res, page_index; |
c27004ec | 92 | target_ulong addr; |
6ebbf390 | 93 | int mmu_idx; |
61382a50 | 94 | |
c27004ec | 95 | addr = ptr; |
4d7a0880 | 96 | page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
6ebbf390 | 97 | mmu_idx = CPU_MMU_INDEX; |
551bd27f TS |
98 | if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != |
99 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { | |
89c33337 BS |
100 | res = (DATA_STYPE)glue(glue(helper_ld, SUFFIX), |
101 | MMUSUFFIX)(env, addr, mmu_idx); | |
b92e5a22 | 102 | } else { |
23ddbf08 | 103 | uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; |
b065927a | 104 | res = glue(glue(lds, SUFFIX), _raw)(hostaddr); |
b92e5a22 FB |
105 | } |
106 | return res; | |
107 | } | |
108 | #endif | |
109 | ||
859d7612 | 110 | #ifndef SOFTMMU_CODE_ACCESS |
84b7b8e7 | 111 | |
e16c53fa FB |
112 | /* generic store macro */ |
113 | ||
e141ab52 | 114 | static inline void |
89c33337 BS |
115 | glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr, |
116 | RES_TYPE v) | |
b92e5a22 | 117 | { |
4d7a0880 | 118 | int page_index; |
c27004ec | 119 | target_ulong addr; |
6ebbf390 | 120 | int mmu_idx; |
61382a50 | 121 | |
c27004ec | 122 | addr = ptr; |
4d7a0880 | 123 | page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
6ebbf390 | 124 | mmu_idx = CPU_MMU_INDEX; |
551bd27f TS |
125 | if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write != |
126 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { | |
89c33337 | 127 | glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx); |
b92e5a22 | 128 | } else { |
23ddbf08 | 129 | uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; |
b065927a | 130 | glue(glue(st, SUFFIX), _raw)(hostaddr, v); |
b92e5a22 FB |
131 | } |
132 | } | |
133 | ||
84b7b8e7 | 134 | |
e16c53fa | 135 | |
2d603d22 | 136 | #if DATA_SIZE == 8 |
89c33337 BS |
137 | static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env, |
138 | target_ulong ptr) | |
2d603d22 FB |
139 | { |
140 | union { | |
3f87bf69 | 141 | float64 d; |
2d603d22 FB |
142 | uint64_t i; |
143 | } u; | |
89c33337 | 144 | u.i = glue(cpu_ldq, MEMSUFFIX)(env, ptr); |
2d603d22 FB |
145 | return u.d; |
146 | } | |
147 | ||
89c33337 BS |
148 | static inline void glue(cpu_stfq, MEMSUFFIX)(CPUArchState *env, |
149 | target_ulong ptr, float64 v) | |
2d603d22 FB |
150 | { |
151 | union { | |
3f87bf69 | 152 | float64 d; |
2d603d22 FB |
153 | uint64_t i; |
154 | } u; | |
155 | u.d = v; | |
89c33337 | 156 | glue(cpu_stq, MEMSUFFIX)(env, ptr, u.i); |
2d603d22 FB |
157 | } |
158 | #endif /* DATA_SIZE == 8 */ | |
159 | ||
160 | #if DATA_SIZE == 4 | |
89c33337 BS |
161 | static inline float32 glue(cpu_ldfl, MEMSUFFIX)(CPUArchState *env, |
162 | target_ulong ptr) | |
2d603d22 FB |
163 | { |
164 | union { | |
3f87bf69 | 165 | float32 f; |
2d603d22 FB |
166 | uint32_t i; |
167 | } u; | |
89c33337 | 168 | u.i = glue(cpu_ldl, MEMSUFFIX)(env, ptr); |
2d603d22 FB |
169 | return u.f; |
170 | } | |
171 | ||
89c33337 BS |
172 | static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env, |
173 | target_ulong ptr, float32 v) | |
2d603d22 FB |
174 | { |
175 | union { | |
3f87bf69 | 176 | float32 f; |
2d603d22 FB |
177 | uint32_t i; |
178 | } u; | |
179 | u.f = v; | |
89c33337 | 180 | glue(cpu_stl, MEMSUFFIX)(env, ptr, u.i); |
2d603d22 FB |
181 | } |
182 | #endif /* DATA_SIZE == 4 */ | |
183 | ||
859d7612 | 184 | #endif /* !SOFTMMU_CODE_ACCESS */ |
84b7b8e7 | 185 | |
b92e5a22 FB |
186 | #undef RES_TYPE |
187 | #undef DATA_TYPE | |
188 | #undef DATA_STYPE | |
189 | #undef SUFFIX | |
61382a50 | 190 | #undef USUFFIX |
b92e5a22 | 191 | #undef DATA_SIZE |
61382a50 | 192 | #undef MMUSUFFIX |
84b7b8e7 | 193 | #undef ADDR_READ |