qemu/softmmu_header.h
<<
>>
Prefs
   1/*
   2 *  Software MMU support
   3 *
   4 *  Copyright (c) 2003 Fabrice Bellard
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19#if DATA_SIZE == 8
  20#define SUFFIX q
  21#define USUFFIX q
  22#define DATA_TYPE uint64_t
  23#elif DATA_SIZE == 4
  24#define SUFFIX l
  25#define USUFFIX l
  26#define DATA_TYPE uint32_t
  27#elif DATA_SIZE == 2
  28#define SUFFIX w
  29#define USUFFIX uw
  30#define DATA_TYPE uint16_t
  31#define DATA_STYPE int16_t
  32#elif DATA_SIZE == 1
  33#define SUFFIX b
  34#define USUFFIX ub
  35#define DATA_TYPE uint8_t
  36#define DATA_STYPE int8_t
  37#else
  38#error unsupported data size
  39#endif
  40
  41#if ACCESS_TYPE < (NB_MMU_MODES)
  42
  43#define CPU_MMU_INDEX ACCESS_TYPE
  44#define MMUSUFFIX _mmu
  45
  46#elif ACCESS_TYPE == (NB_MMU_MODES)
  47
  48#define CPU_MMU_INDEX (cpu_mmu_index(env))
  49#define MMUSUFFIX _mmu
  50
  51#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
  52
  53#define CPU_MMU_INDEX (cpu_mmu_index(env))
  54#define MMUSUFFIX _cmmu
  55
  56#else
  57#error invalid ACCESS_TYPE
  58#endif
  59
  60#if DATA_SIZE == 8
  61#define RES_TYPE uint64_t
  62#else
  63#define RES_TYPE uint32_t
  64#endif
  65
  66#if ACCESS_TYPE == (NB_MMU_MODES + 1)
  67#define ADDR_READ addr_code
  68#else
  69#define ADDR_READ addr_read
  70#endif
  71
  72/* generic load/store macros */
  73
  74static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
  75{
  76    int page_index;
  77    RES_TYPE res;
  78    target_ulong addr;
  79    unsigned long physaddr;
  80    int mmu_idx;
  81
  82    addr = ptr;
  83    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  84    mmu_idx = CPU_MMU_INDEX;
  85    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
  86                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
  87        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
  88    } else {
  89        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  90        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
  91    }
  92    return res;
  93}
  94
  95#if DATA_SIZE <= 2
  96static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
  97{
  98    int res, page_index;
  99    target_ulong addr;
 100    unsigned long physaddr;
 101    int mmu_idx;
 102
 103    addr = ptr;
 104    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 105    mmu_idx = CPU_MMU_INDEX;
 106    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
 107                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
 108        res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
 109    } else {
 110        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
 111        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
 112    }
 113    return res;
 114}
 115#endif
 116
 117#if ACCESS_TYPE != (NB_MMU_MODES + 1)
 118
 119/* generic store macro */
 120
 121static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
 122{
 123    int page_index;
 124    target_ulong addr;
 125    unsigned long physaddr;
 126    int mmu_idx;
 127
 128    addr = ptr;
 129    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 130    mmu_idx = CPU_MMU_INDEX;
 131    if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
 132                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
 133        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
 134    } else {
 135        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
 136        glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
 137    }
 138}
 139
 140#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
 141
 142#if ACCESS_TYPE != (NB_MMU_MODES + 1)
 143
 144#if DATA_SIZE == 8
 145static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
 146{
 147    union {
 148        float64 d;
 149        uint64_t i;
 150    } u;
 151    u.i = glue(ldq, MEMSUFFIX)(ptr);
 152    return u.d;
 153}
 154
 155static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
 156{
 157    union {
 158        float64 d;
 159        uint64_t i;
 160    } u;
 161    u.d = v;
 162    glue(stq, MEMSUFFIX)(ptr, u.i);
 163}
 164#endif /* DATA_SIZE == 8 */
 165
 166#if DATA_SIZE == 4
 167static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
 168{
 169    union {
 170        float32 f;
 171        uint32_t i;
 172    } u;
 173    u.i = glue(ldl, MEMSUFFIX)(ptr);
 174    return u.f;
 175}
 176
 177static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
 178{
 179    union {
 180        float32 f;
 181        uint32_t i;
 182    } u;
 183    u.f = v;
 184    glue(stl, MEMSUFFIX)(ptr, u.i);
 185}
 186#endif /* DATA_SIZE == 4 */
 187
 188#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
 189
 190#undef RES_TYPE
 191#undef DATA_TYPE
 192#undef DATA_STYPE
 193#undef SUFFIX
 194#undef USUFFIX
 195#undef DATA_SIZE
 196#undef CPU_MMU_INDEX
 197#undef MMUSUFFIX
 198#undef ADDR_READ
 199