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