18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Software MMU support 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2003 Fabrice Bellard 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is free software; you can redistribute it and/or 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modify it under the terms of the GNU Lesser General Public 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * License as published by the Free Software Foundation; either 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * version 2 of the License, or (at your option) any later version. 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is distributed in the hope that it will be useful, 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lesser General Public License for more details. 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU Lesser General Public 172910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>. 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DATA_SIZE == 8 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUFFIX q 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define USUFFIX q 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DATA_TYPE uint64_t 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif DATA_SIZE == 4 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUFFIX l 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define USUFFIX l 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DATA_TYPE uint32_t 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif DATA_SIZE == 2 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUFFIX w 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define USUFFIX uw 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DATA_TYPE uint16_t 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DATA_STYPE int16_t 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif DATA_SIZE == 1 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUFFIX b 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define USUFFIX ub 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DATA_TYPE uint8_t 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DATA_STYPE int8_t 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error unsupported data size 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if ACCESS_TYPE < (NB_MMU_MODES) 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#if defined(OUTSIDE_JIT) 445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Dispatch calls to __ldx_outside_jit / __stx_outside_jit, which don't 455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * expect CPU environment. to be cached in ebp register, but rather uses 465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * cpu_single_env variable for that purpose. 475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#define MMUSUFFIX _outside_jit 495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#else // OUTSIDE_JIT 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MMUSUFFIX _mmu 515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif // OUTSIDE_JIT 525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#define CPU_MMU_INDEX ACCESS_TYPE 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif ACCESS_TYPE == (NB_MMU_MODES) 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CPU_MMU_INDEX (cpu_mmu_index(env)) 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MMUSUFFIX _mmu 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif ACCESS_TYPE == (NB_MMU_MODES + 1) 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CPU_MMU_INDEX (cpu_mmu_index(env)) 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MMUSUFFIX _cmmu 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error invalid ACCESS_TYPE 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DATA_SIZE == 8 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define RES_TYPE uint64_t 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 711275f06d57fc62754e3b1abd4748e943ded966e5David Turner#define RES_TYPE uint32_t 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if ACCESS_TYPE == (NB_MMU_MODES + 1) 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADDR_READ addr_code 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADDR_READ addr_read 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* generic load/store macros */ 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int page_index; 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project RES_TYPE res; 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project target_ulong addr; 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned long physaddr; 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int mmu_idx; 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = ptr; 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mmu_idx = CPU_MMU_INDEX; 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx); 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr); 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return res; 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DATA_SIZE <= 2 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr) 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int res, page_index; 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project target_ulong addr; 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned long physaddr; 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int mmu_idx; 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = ptr; 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mmu_idx = CPU_MMU_INDEX; 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx); 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr); 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return res; 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if ACCESS_TYPE != (NB_MMU_MODES + 1) 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* generic store macro */ 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v) 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int page_index; 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project target_ulong addr; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned long physaddr; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int mmu_idx; 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = ptr; 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mmu_idx = CPU_MMU_INDEX; 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write != 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx); 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v); 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */ 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if ACCESS_TYPE != (NB_MMU_MODES + 1) 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DATA_SIZE == 8 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr) 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project float64 d; 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint64_t i; 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } u; 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u.i = glue(ldq, MEMSUFFIX)(ptr); 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return u.d; 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v) 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project float64 d; 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint64_t i; 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } u; 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u.d = v; 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project glue(stq, MEMSUFFIX)(ptr, u.i); 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* DATA_SIZE == 8 */ 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DATA_SIZE == 4 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr) 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project float32 f; 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t i; 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } u; 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u.i = glue(ldl, MEMSUFFIX)(ptr); 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return u.f; 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v) 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project float32 f; 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t i; 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } u; 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u.f = v; 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project glue(stl, MEMSUFFIX)(ptr, u.i); 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* DATA_SIZE == 4 */ 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */ 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef RES_TYPE 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef DATA_TYPE 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef DATA_STYPE 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef SUFFIX 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef USUFFIX 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef DATA_SIZE 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef CPU_MMU_INDEX 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef MMUSUFFIX 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ADDR_READ 207