Statistics
| Branch: | Revision:

root / softmmu_header.h @ a74cdab4

History | View | Annotate | Download (4.8 kB)

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, see <http://www.gnu.org/licenses/>.
18
 */
19
#if DATA_SIZE == 8
20
#define SUFFIX q
21
#define USUFFIX q
22
#define DATA_TYPE uint64_t
23
#elif DATA_SIZE == 4
24
#define SUFFIX l
25
#define USUFFIX l
26
#define DATA_TYPE uint32_t
27
#elif DATA_SIZE == 2
28
#define SUFFIX w
29
#define USUFFIX uw
30
#define DATA_TYPE uint16_t
31
#define DATA_STYPE int16_t
32
#elif DATA_SIZE == 1
33
#define SUFFIX b
34
#define USUFFIX ub
35
#define DATA_TYPE uint8_t
36
#define DATA_STYPE int8_t
37
#else
38
#error unsupported data size
39
#endif
40

    
41
#if ACCESS_TYPE < (NB_MMU_MODES)
42

    
43
#define CPU_MMU_INDEX ACCESS_TYPE
44
#define MMUSUFFIX _mmu
45

    
46
#elif ACCESS_TYPE == (NB_MMU_MODES)
47

    
48
#define CPU_MMU_INDEX (cpu_mmu_index(env))
49
#define MMUSUFFIX _mmu
50

    
51
#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
52

    
53
#define CPU_MMU_INDEX (cpu_mmu_index(env))
54
#define MMUSUFFIX _cmmu
55

    
56
#else
57
#error invalid ACCESS_TYPE
58
#endif
59

    
60
#if DATA_SIZE == 8
61
#define RES_TYPE uint64_t
62
#else
63
#define RES_TYPE uint32_t
64
#endif
65

    
66
#if ACCESS_TYPE == (NB_MMU_MODES + 1)
67
#define ADDR_READ addr_code
68
#else
69
#define ADDR_READ addr_read
70
#endif
71

    
72
/* generic load/store macros */
73

    
74
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
75
{
76
    int page_index;
77
    RES_TYPE res;
78
    target_ulong addr;
79
    unsigned long physaddr;
80
    int mmu_idx;
81

    
82
    addr = ptr;
83
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
84
    mmu_idx = CPU_MMU_INDEX;
85
    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
86
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
87
        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
88
    } else {
89
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
90
        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
91
    }
92
    return res;
93
}
94

    
95
#if DATA_SIZE <= 2
96
static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
97
{
98
    int res, page_index;
99
    target_ulong addr;
100
    unsigned long physaddr;
101
    int mmu_idx;
102

    
103
    addr = ptr;
104
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
105
    mmu_idx = CPU_MMU_INDEX;
106
    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
107
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
108
        res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
109
    } else {
110
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
111
        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
112
    }
113
    return res;
114
}
115
#endif
116

    
117
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
118

    
119
/* generic store macro */
120

    
121
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
122
{
123
    int page_index;
124
    target_ulong addr;
125
    unsigned long physaddr;
126
    int mmu_idx;
127

    
128
    addr = ptr;
129
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
130
    mmu_idx = CPU_MMU_INDEX;
131
    if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
132
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
133
        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
134
    } else {
135
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
136
        glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
137
    }
138
}
139

    
140
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
141

    
142
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
143

    
144
#if DATA_SIZE == 8
145
static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
146
{
147
    union {
148
        float64 d;
149
        uint64_t i;
150
    } u;
151
    u.i = glue(ldq, MEMSUFFIX)(ptr);
152
    return u.d;
153
}
154

    
155
static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
156
{
157
    union {
158
        float64 d;
159
        uint64_t i;
160
    } u;
161
    u.d = v;
162
    glue(stq, MEMSUFFIX)(ptr, u.i);
163
}
164
#endif /* DATA_SIZE == 8 */
165

    
166
#if DATA_SIZE == 4
167
static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
168
{
169
    union {
170
        float32 f;
171
        uint32_t i;
172
    } u;
173
    u.i = glue(ldl, MEMSUFFIX)(ptr);
174
    return u.f;
175
}
176

    
177
static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
178
{
179
    union {
180
        float32 f;
181
        uint32_t i;
182
    } u;
183
    u.f = v;
184
    glue(stl, MEMSUFFIX)(ptr, u.i);
185
}
186
#endif /* DATA_SIZE == 4 */
187

    
188
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
189

    
190
#undef RES_TYPE
191
#undef DATA_TYPE
192
#undef DATA_STYPE
193
#undef SUFFIX
194
#undef USUFFIX
195
#undef DATA_SIZE
196
#undef CPU_MMU_INDEX
197
#undef MMUSUFFIX
198
#undef ADDR_READ