File:  [Qemu by Fabrice Bellard] / qemu / softmmu_header.h
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:37 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    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, write to the Free Software
   18:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
   19:  */
   20: #if DATA_SIZE == 8
   21: #define SUFFIX q
   22: #define USUFFIX q
   23: #define DATA_TYPE uint64_t
   24: #elif DATA_SIZE == 4
   25: #define SUFFIX l
   26: #define USUFFIX l
   27: #define DATA_TYPE uint32_t
   28: #elif DATA_SIZE == 2
   29: #define SUFFIX w
   30: #define USUFFIX uw
   31: #define DATA_TYPE uint16_t
   32: #define DATA_STYPE int16_t
   33: #elif DATA_SIZE == 1
   34: #define SUFFIX b
   35: #define USUFFIX ub
   36: #define DATA_TYPE uint8_t
   37: #define DATA_STYPE int8_t
   38: #else
   39: #error unsupported data size
   40: #endif
   41: 
   42: #if ACCESS_TYPE < (NB_MMU_MODES)
   43: 
   44: #define CPU_MMU_INDEX ACCESS_TYPE
   45: #define MMUSUFFIX _mmu
   46: 
   47: #elif ACCESS_TYPE == (NB_MMU_MODES)
   48: 
   49: #define CPU_MMU_INDEX (cpu_mmu_index(env))
   50: #define MMUSUFFIX _mmu
   51: 
   52: #elif ACCESS_TYPE == (NB_MMU_MODES + 1)
   53: 
   54: #define CPU_MMU_INDEX (cpu_mmu_index(env))
   55: #define MMUSUFFIX _cmmu
   56: 
   57: #else
   58: #error invalid ACCESS_TYPE
   59: #endif
   60: 
   61: #if DATA_SIZE == 8
   62: #define RES_TYPE uint64_t
   63: #else
   64: #define RES_TYPE int
   65: #endif
   66: 
   67: #if ACCESS_TYPE == (NB_MMU_MODES + 1)
   68: #define ADDR_READ addr_code
   69: #else
   70: #define ADDR_READ addr_read
   71: #endif
   72: 
   73: #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
   74:     (ACCESS_TYPE < NB_MMU_MODES) && defined(ASM_SOFTMMU)
   75: 
   76: static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
   77: {
   78:     int res;
   79: 
   80:     asm volatile ("movl %1, %%edx\n"
   81:                   "movl %1, %%eax\n"
   82:                   "shrl %3, %%edx\n"
   83:                   "andl %4, %%eax\n"
   84:                   "andl %2, %%edx\n"
   85:                   "leal %5(%%edx, %%ebp), %%edx\n"
   86:                   "cmpl (%%edx), %%eax\n"
   87:                   "movl %1, %%eax\n"
   88:                   "je 1f\n"
   89:                   "movl %6, %%edx\n"
   90:                   "call %7\n"
   91:                   "movl %%eax, %0\n"
   92:                   "jmp 2f\n"
   93:                   "1:\n"
   94:                   "addl 12(%%edx), %%eax\n"
   95: #if DATA_SIZE == 1
   96:                   "movzbl (%%eax), %0\n"
   97: #elif DATA_SIZE == 2
   98:                   "movzwl (%%eax), %0\n"
   99: #elif DATA_SIZE == 4
  100:                   "movl (%%eax), %0\n"
  101: #else
  102: #error unsupported size
  103: #endif
  104:                   "2:\n"
  105:                   : "=r" (res)
  106:                   : "r" (ptr),
  107:                   "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
  108:                   "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
  109:                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
  110:                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
  111:                   "i" (CPU_MMU_INDEX),
  112:                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
  113:                   : "%eax", "%ecx", "%edx", "memory", "cc");
  114:     return res;
  115: }
  116: 
  117: #if DATA_SIZE <= 2
  118: static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
  119: {
  120:     int res;
  121: 
  122:     asm volatile ("movl %1, %%edx\n"
  123:                   "movl %1, %%eax\n"
  124:                   "shrl %3, %%edx\n"
  125:                   "andl %4, %%eax\n"
  126:                   "andl %2, %%edx\n"
  127:                   "leal %5(%%edx, %%ebp), %%edx\n"
  128:                   "cmpl (%%edx), %%eax\n"
  129:                   "movl %1, %%eax\n"
  130:                   "je 1f\n"
  131:                   "movl %6, %%edx\n"
  132:                   "call %7\n"
  133: #if DATA_SIZE == 1
  134:                   "movsbl %%al, %0\n"
  135: #elif DATA_SIZE == 2
  136:                   "movswl %%ax, %0\n"
  137: #else
  138: #error unsupported size
  139: #endif
  140:                   "jmp 2f\n"
  141:                   "1:\n"
  142:                   "addl 12(%%edx), %%eax\n"
  143: #if DATA_SIZE == 1
  144:                   "movsbl (%%eax), %0\n"
  145: #elif DATA_SIZE == 2
  146:                   "movswl (%%eax), %0\n"
  147: #else
  148: #error unsupported size
  149: #endif
  150:                   "2:\n"
  151:                   : "=r" (res)
  152:                   : "r" (ptr),
  153:                   "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
  154:                   "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
  155:                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
  156:                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
  157:                   "i" (CPU_MMU_INDEX),
  158:                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
  159:                   : "%eax", "%ecx", "%edx", "memory", "cc");
  160:     return res;
  161: }
  162: #endif
  163: 
  164: static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
  165: {
  166:     asm volatile ("movl %0, %%edx\n"
  167:                   "movl %0, %%eax\n"
  168:                   "shrl %3, %%edx\n"
  169:                   "andl %4, %%eax\n"
  170:                   "andl %2, %%edx\n"
  171:                   "leal %5(%%edx, %%ebp), %%edx\n"
  172:                   "cmpl (%%edx), %%eax\n"
  173:                   "movl %0, %%eax\n"
  174:                   "je 1f\n"
  175: #if DATA_SIZE == 1
  176:                   "movzbl %b1, %%edx\n"
  177: #elif DATA_SIZE == 2
  178:                   "movzwl %w1, %%edx\n"
  179: #elif DATA_SIZE == 4
  180:                   "movl %1, %%edx\n"
  181: #else
  182: #error unsupported size
  183: #endif
  184:                   "movl %6, %%ecx\n"
  185:                   "call %7\n"
  186:                   "jmp 2f\n"
  187:                   "1:\n"
  188:                   "addl 8(%%edx), %%eax\n"
  189: #if DATA_SIZE == 1
  190:                   "movb %b1, (%%eax)\n"
  191: #elif DATA_SIZE == 2
  192:                   "movw %w1, (%%eax)\n"
  193: #elif DATA_SIZE == 4
  194:                   "movl %1, (%%eax)\n"
  195: #else
  196: #error unsupported size
  197: #endif
  198:                   "2:\n"
  199:                   :
  200:                   : "r" (ptr),
  201: #if DATA_SIZE == 1
  202:                   "q" (v),
  203: #else
  204:                   "r" (v),
  205: #endif
  206:                   "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
  207:                   "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
  208:                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
  209:                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_write)),
  210:                   "i" (CPU_MMU_INDEX),
  211:                   "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
  212:                   : "%eax", "%ecx", "%edx", "memory", "cc");
  213: }
  214: 
  215: #else
  216: 
  217: /* generic load/store macros */
  218: 
  219: static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
  220: {
  221:     int page_index;
  222:     RES_TYPE res;
  223:     target_ulong addr;
  224:     unsigned long physaddr;
  225:     int mmu_idx;
  226: 
  227:     addr = ptr;
  228:     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  229:     mmu_idx = CPU_MMU_INDEX;
  230:     if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
  231:                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
  232:         res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
  233:     } else {
  234:         physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  235:         res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
  236:     }
  237:     return res;
  238: }
  239: 
  240: #if DATA_SIZE <= 2
  241: static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
  242: {
  243:     int res, page_index;
  244:     target_ulong addr;
  245:     unsigned long physaddr;
  246:     int mmu_idx;
  247: 
  248:     addr = ptr;
  249:     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  250:     mmu_idx = CPU_MMU_INDEX;
  251:     if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
  252:                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
  253:         res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
  254:     } else {
  255:         physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  256:         res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
  257:     }
  258:     return res;
  259: }
  260: #endif
  261: 
  262: #if ACCESS_TYPE != (NB_MMU_MODES + 1)
  263: 
  264: /* generic store macro */
  265: 
  266: static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
  267: {
  268:     int page_index;
  269:     target_ulong addr;
  270:     unsigned long physaddr;
  271:     int mmu_idx;
  272: 
  273:     addr = ptr;
  274:     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  275:     mmu_idx = CPU_MMU_INDEX;
  276:     if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
  277:                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
  278:         glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
  279:     } else {
  280:         physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  281:         glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
  282:     }
  283: }
  284: 
  285: #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
  286: 
  287: #endif /* !asm */
  288: 
  289: #if ACCESS_TYPE != (NB_MMU_MODES + 1)
  290: 
  291: #if DATA_SIZE == 8
  292: static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
  293: {
  294:     union {
  295:         float64 d;
  296:         uint64_t i;
  297:     } u;
  298:     u.i = glue(ldq, MEMSUFFIX)(ptr);
  299:     return u.d;
  300: }
  301: 
  302: static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
  303: {
  304:     union {
  305:         float64 d;
  306:         uint64_t i;
  307:     } u;
  308:     u.d = v;
  309:     glue(stq, MEMSUFFIX)(ptr, u.i);
  310: }
  311: #endif /* DATA_SIZE == 8 */
  312: 
  313: #if DATA_SIZE == 4
  314: static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
  315: {
  316:     union {
  317:         float32 f;
  318:         uint32_t i;
  319:     } u;
  320:     u.i = glue(ldl, MEMSUFFIX)(ptr);
  321:     return u.f;
  322: }
  323: 
  324: static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
  325: {
  326:     union {
  327:         float32 f;
  328:         uint32_t i;
  329:     } u;
  330:     u.f = v;
  331:     glue(stl, MEMSUFFIX)(ptr, u.i);
  332: }
  333: #endif /* DATA_SIZE == 4 */
  334: 
  335: #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
  336: 
  337: #undef RES_TYPE
  338: #undef DATA_TYPE
  339: #undef DATA_STYPE
  340: #undef SUFFIX
  341: #undef USUFFIX
  342: #undef DATA_SIZE
  343: #undef CPU_MMU_INDEX
  344: #undef MMUSUFFIX
  345: #undef ADDR_READ

unix.superglobalmegacorp.com