123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /*
- * Software MMU support
- *
- * Generate inline load/store functions for one MMU mode and data
- * size.
- *
- * Generate a store function as well as signed and unsigned loads. For
- * 32 and 64 bit cases, also generate floating point functions with
- * the same size.
- *
- * Not used directly but included from softmmu_exec.h and exec-all.h.
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
- #if DATA_SIZE == 8
- #define SUFFIX q
- #define USUFFIX q
- #define DATA_TYPE uint64_t
- #elif DATA_SIZE == 4
- #define SUFFIX l
- #define USUFFIX l
- #define DATA_TYPE uint32_t
- #elif DATA_SIZE == 2
- #define SUFFIX w
- #define USUFFIX uw
- #define DATA_TYPE uint16_t
- #define DATA_STYPE int16_t
- #elif DATA_SIZE == 1
- #define SUFFIX b
- #define USUFFIX ub
- #define DATA_TYPE uint8_t
- #define DATA_STYPE int8_t
- #else
- #error unsupported data size
- #endif
- #if ACCESS_TYPE < (NB_MMU_MODES)
- #define CPU_MMU_INDEX ACCESS_TYPE
- #define MMUSUFFIX _mmu
- #elif ACCESS_TYPE == (NB_MMU_MODES)
- #define CPU_MMU_INDEX (cpu_mmu_index(env))
- #define MMUSUFFIX _mmu
- #elif ACCESS_TYPE == (NB_MMU_MODES + 1)
- #define CPU_MMU_INDEX (cpu_mmu_index(env))
- #define MMUSUFFIX _cmmu
- #else
- #error invalid ACCESS_TYPE
- #endif
- #if DATA_SIZE == 8
- #define RES_TYPE uint64_t
- #else
- #define RES_TYPE uint32_t
- #endif
- #if ACCESS_TYPE == (NB_MMU_MODES + 1)
- #define ADDR_READ addr_code
- #else
- #define ADDR_READ addr_read
- #endif
- #ifndef CONFIG_TCG_PASS_AREG0
- #define ENV_PARAM
- #define ENV_VAR
- #define CPU_PREFIX
- #define HELPER_PREFIX __
- #else
- #define ENV_PARAM CPUArchState *env,
- #define ENV_VAR env,
- #define CPU_PREFIX cpu_
- #define HELPER_PREFIX helper_
- #endif
- /* generic load/store macros */
- static inline RES_TYPE
- glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
- target_ulong ptr)
- {
- int page_index;
- RES_TYPE res;
- target_ulong addr;
- int mmu_idx;
- addr = ptr;
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- mmu_idx = CPU_MMU_INDEX;
- if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
- (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
- res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR
- addr,
- mmu_idx);
- } else {
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
- res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
- }
- return res;
- }
- #if DATA_SIZE <= 2
- static inline int
- glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
- target_ulong ptr)
- {
- int res, page_index;
- target_ulong addr;
- int mmu_idx;
- addr = ptr;
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- mmu_idx = CPU_MMU_INDEX;
- if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
- (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
- res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX),
- MMUSUFFIX)(ENV_VAR addr, mmu_idx);
- } else {
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
- res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
- }
- return res;
- }
- #endif
- #if ACCESS_TYPE != (NB_MMU_MODES + 1)
- /* generic store macro */
- static inline void
- glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
- RES_TYPE v)
- {
- int page_index;
- target_ulong addr;
- int mmu_idx;
- addr = ptr;
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- mmu_idx = CPU_MMU_INDEX;
- if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
- (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
- glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v,
- mmu_idx);
- } else {
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
- glue(glue(st, SUFFIX), _raw)(hostaddr, v);
- }
- }
- #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
- #if ACCESS_TYPE != (NB_MMU_MODES + 1)
- #if DATA_SIZE == 8
- static inline float64 glue(glue(CPU_PREFIX, ldfq), MEMSUFFIX)(ENV_PARAM
- target_ulong ptr)
- {
- union {
- float64 d;
- uint64_t i;
- } u;
- u.i = glue(glue(CPU_PREFIX, ldq), MEMSUFFIX)(ENV_VAR ptr);
- return u.d;
- }
- static inline void glue(glue(CPU_PREFIX, stfq), MEMSUFFIX)(ENV_PARAM
- target_ulong ptr,
- float64 v)
- {
- union {
- float64 d;
- uint64_t i;
- } u;
- u.d = v;
- glue(glue(CPU_PREFIX, stq), MEMSUFFIX)(ENV_VAR ptr, u.i);
- }
- #endif /* DATA_SIZE == 8 */
- #if DATA_SIZE == 4
- static inline float32 glue(glue(CPU_PREFIX, ldfl), MEMSUFFIX)(ENV_PARAM
- target_ulong ptr)
- {
- union {
- float32 f;
- uint32_t i;
- } u;
- u.i = glue(glue(CPU_PREFIX, ldl), MEMSUFFIX)(ENV_VAR ptr);
- return u.f;
- }
- static inline void glue(glue(CPU_PREFIX, stfl), MEMSUFFIX)(ENV_PARAM
- target_ulong ptr,
- float32 v)
- {
- union {
- float32 f;
- uint32_t i;
- } u;
- u.f = v;
- glue(glue(CPU_PREFIX, stl), MEMSUFFIX)(ENV_VAR ptr, u.i);
- }
- #endif /* DATA_SIZE == 4 */
- #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
- #undef RES_TYPE
- #undef DATA_TYPE
- #undef DATA_STYPE
- #undef SUFFIX
- #undef USUFFIX
- #undef DATA_SIZE
- #undef CPU_MMU_INDEX
- #undef MMUSUFFIX
- #undef ADDR_READ
- #undef ENV_PARAM
- #undef ENV_VAR
- #undef CPU_PREFIX
- #undef HELPER_PREFIX
|