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