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