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