qemu/softmmu_header.h
<<
>>
Prefs
   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 glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
  84{
  85    int page_index;
  86    RES_TYPE res;
  87    target_ulong addr;
  88    unsigned long physaddr;
  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(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
  97    } else {
  98        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  99        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
 100    }
 101    return res;
 102}
 103
 104#if DATA_SIZE <= 2
 105static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
 106{
 107    int res, page_index;
 108    target_ulong addr;
 109    unsigned long physaddr;
 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(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
 118    } else {
 119        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
 120        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
 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 glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
 131{
 132    int page_index;
 133    target_ulong addr;
 134    unsigned long physaddr;
 135    int mmu_idx;
 136
 137    addr = ptr;
 138    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 139    mmu_idx = CPU_MMU_INDEX;
 140    if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
 141                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
 142        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
 143    } else {
 144        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
 145        glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
 146    }
 147}
 148
 149#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
 150
 151#if ACCESS_TYPE != (NB_MMU_MODES + 1)
 152
 153#if DATA_SIZE == 8
 154static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
 155{
 156    union {
 157        float64 d;
 158        uint64_t i;
 159    } u;
 160    u.i = glue(ldq, MEMSUFFIX)(ptr);
 161    return u.d;
 162}
 163
 164static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
 165{
 166    union {
 167        float64 d;
 168        uint64_t i;
 169    } u;
 170    u.d = v;
 171    glue(stq, MEMSUFFIX)(ptr, u.i);
 172}
 173#endif /* DATA_SIZE == 8 */
 174
 175#if DATA_SIZE == 4
 176static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
 177{
 178    union {
 179        float32 f;
 180        uint32_t i;
 181    } u;
 182    u.i = glue(ldl, MEMSUFFIX)(ptr);
 183    return u.f;
 184}
 185
 186static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
 187{
 188    union {
 189        float32 f;
 190        uint32_t i;
 191    } u;
 192    u.f = v;
 193    glue(stl, MEMSUFFIX)(ptr, u.i);
 194}
 195#endif /* DATA_SIZE == 4 */
 196
 197#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
 198
 199#undef RES_TYPE
 200#undef DATA_TYPE
 201#undef DATA_STYPE
 202#undef SUFFIX
 203#undef USUFFIX
 204#undef DATA_SIZE
 205#undef CPU_MMU_INDEX
 206#undef MMUSUFFIX
 207#undef ADDR_READ
 208