qemu/include/exec/cpu_ldst_template.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 cpu_ldst.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 DATA_SIZE == 8
  51#define RES_TYPE uint64_t
  52#else
  53#define RES_TYPE uint32_t
  54#endif
  55
  56#ifdef SOFTMMU_CODE_ACCESS
  57#define ADDR_READ addr_code
  58#define MMUSUFFIX _cmmu
  59#else
  60#define ADDR_READ addr_read
  61#define MMUSUFFIX _mmu
  62#endif
  63
  64/* generic load/store macros */
  65
  66static inline RES_TYPE
  67glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
  68{
  69    int page_index;
  70    RES_TYPE res;
  71    target_ulong addr;
  72    int mmu_idx;
  73
  74    addr = ptr;
  75    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  76    mmu_idx = CPU_MMU_INDEX;
  77    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
  78                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
  79        res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx);
  80    } else {
  81        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  82        res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
  83    }
  84    return res;
  85}
  86
  87#if DATA_SIZE <= 2
  88static inline int
  89glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
  90{
  91    int res, page_index;
  92    target_ulong addr;
  93    int mmu_idx;
  94
  95    addr = ptr;
  96    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  97    mmu_idx = CPU_MMU_INDEX;
  98    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
  99                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
 100        res = (DATA_STYPE)glue(glue(helper_ld, SUFFIX),
 101                               MMUSUFFIX)(env, addr, mmu_idx);
 102    } else {
 103        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
 104        res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
 105    }
 106    return res;
 107}
 108#endif
 109
 110#ifndef SOFTMMU_CODE_ACCESS
 111
 112/* generic store macro */
 113
 114static inline void
 115glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
 116                                      RES_TYPE v)
 117{
 118    int page_index;
 119    target_ulong addr;
 120    int mmu_idx;
 121
 122    addr = ptr;
 123    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 124    mmu_idx = CPU_MMU_INDEX;
 125    if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
 126                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
 127        glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx);
 128    } else {
 129        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
 130        glue(glue(st, SUFFIX), _raw)(hostaddr, v);
 131    }
 132}
 133
 134
 135
 136#if DATA_SIZE == 8
 137static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env,
 138                                                target_ulong ptr)
 139{
 140    union {
 141        float64 d;
 142        uint64_t i;
 143    } u;
 144    u.i = glue(cpu_ldq, MEMSUFFIX)(env, ptr);
 145    return u.d;
 146}
 147
 148static inline void glue(cpu_stfq, MEMSUFFIX)(CPUArchState *env,
 149                                             target_ulong ptr, float64 v)
 150{
 151    union {
 152        float64 d;
 153        uint64_t i;
 154    } u;
 155    u.d = v;
 156    glue(cpu_stq, MEMSUFFIX)(env, ptr, u.i);
 157}
 158#endif /* DATA_SIZE == 8 */
 159
 160#if DATA_SIZE == 4
 161static inline float32 glue(cpu_ldfl, MEMSUFFIX)(CPUArchState *env,
 162                                                target_ulong ptr)
 163{
 164    union {
 165        float32 f;
 166        uint32_t i;
 167    } u;
 168    u.i = glue(cpu_ldl, MEMSUFFIX)(env, ptr);
 169    return u.f;
 170}
 171
 172static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env,
 173                                             target_ulong ptr, float32 v)
 174{
 175    union {
 176        float32 f;
 177        uint32_t i;
 178    } u;
 179    u.f = v;
 180    glue(cpu_stl, MEMSUFFIX)(env, ptr, u.i);
 181}
 182#endif /* DATA_SIZE == 4 */
 183
 184#endif /* !SOFTMMU_CODE_ACCESS */
 185
 186#undef RES_TYPE
 187#undef DATA_TYPE
 188#undef DATA_STYPE
 189#undef SUFFIX
 190#undef USUFFIX
 191#undef DATA_SIZE
 192#undef MMUSUFFIX
 193#undef ADDR_READ
 194