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 214