39
39
#error unsupported data size
42
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(unsigned long addr,
42
#ifdef SOFTMMU_CODE_ACCESS
43
#define READ_ACCESS_TYPE 2
44
#define ADDR_READ addr_code
46
#define READ_ACCESS_TYPE 0
47
#define ADDR_READ addr_read
50
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
45
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(unsigned long addr,
50
static inline DATA_TYPE glue(io_read, SUFFIX)(unsigned long physaddr,
51
unsigned long tlb_addr)
53
static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
54
target_ulong tlb_addr)
56
59
index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
58
res = io_mem_read[index][SHIFT](physaddr);
61
res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr);
60
63
#ifdef TARGET_WORDS_BIGENDIAN
61
res = (uint64_t)io_mem_read[index][2](physaddr) << 32;
62
res |= io_mem_read[index][2](physaddr + 4);
64
res = (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr) << 32;
65
res |= io_mem_read[index][2](io_mem_opaque[index], physaddr + 4);
64
res = io_mem_read[index][2](physaddr);
65
res |= (uint64_t)io_mem_read[index][2](physaddr + 4) << 32;
67
res = io_mem_read[index][2](io_mem_opaque[index], physaddr);
68
res |= (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr + 4) << 32;
67
70
#endif /* SHIFT > 2 */
72
env->last_io_time = cpu_get_time_fast();
71
static inline void glue(io_write, SUFFIX)(unsigned long physaddr,
73
unsigned long tlb_addr,
78
index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
79
env->mem_write_vaddr = tlb_addr;
80
env->mem_write_pc = (unsigned long)retaddr;
82
io_mem_write[index][SHIFT](physaddr, val);
84
#ifdef TARGET_WORDS_BIGENDIAN
85
io_mem_write[index][2](physaddr, val >> 32);
86
io_mem_write[index][2](physaddr + 4, val);
88
io_mem_write[index][2](physaddr, val);
89
io_mem_write[index][2](physaddr + 4, val >> 32);
91
#endif /* SHIFT > 2 */
94
77
/* handle all cases except unaligned access which span two pages */
95
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(unsigned long addr,
78
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
100
unsigned long physaddr, tlb_addr;
83
target_ulong tlb_addr;
84
target_phys_addr_t physaddr;
103
87
/* test if there is match for unaligned or IO access */
104
88
/* XXX: could done more in memory macro in a non portable way */
105
89
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
107
tlb_addr = env->tlb_read[is_user][index].address;
91
tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
108
92
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
109
physaddr = addr + env->tlb_read[is_user][index].addend;
93
physaddr = addr + env->tlb_table[mmu_idx][index].addend;
110
94
if (tlb_addr & ~TARGET_PAGE_MASK) {
112
96
if ((addr & (DATA_SIZE - 1)) != 0)
113
97
goto do_unaligned_access;
114
98
res = glue(io_read, SUFFIX)(physaddr, tlb_addr);
115
} else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
99
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
116
100
/* slow unaligned access (it spans two pages or IO) */
117
101
do_unaligned_access:
118
102
retaddr = GETPC();
119
res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
104
do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
106
res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
122
/* unaligned access in the same page */
123
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
109
/* unaligned/aligned access in the same page */
111
if ((addr & (DATA_SIZE - 1)) != 0) {
113
do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
116
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)physaddr);
126
119
/* the page is not in the TLB : fill it */
127
120
retaddr = GETPC();
128
tlb_fill(addr, 0, is_user, retaddr);
122
if ((addr & (DATA_SIZE - 1)) != 0)
123
do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
125
tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
134
131
/* handle all unaligned cases */
135
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(unsigned long addr,
132
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
139
136
DATA_TYPE res, res1, res2;
140
137
int index, shift;
141
unsigned long physaddr, tlb_addr, addr1, addr2;
138
target_phys_addr_t physaddr;
139
target_ulong tlb_addr, addr1, addr2;
143
141
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
145
tlb_addr = env->tlb_read[is_user][index].address;
143
tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
146
144
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
147
physaddr = addr + env->tlb_read[is_user][index].addend;
145
physaddr = addr + env->tlb_table[mmu_idx][index].addend;
148
146
if (tlb_addr & ~TARGET_PAGE_MASK) {
150
148
if ((addr & (DATA_SIZE - 1)) != 0)
151
149
goto do_unaligned_access;
152
150
res = glue(io_read, SUFFIX)(physaddr, tlb_addr);
153
} else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
151
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
154
152
do_unaligned_access:
155
153
/* slow unaligned access (it spans two pages) */
156
154
addr1 = addr & ~(DATA_SIZE - 1);
157
155
addr2 = addr1 + DATA_SIZE;
158
res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
160
res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
156
res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
158
res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
162
160
shift = (addr & (DATA_SIZE - 1)) * 8;
163
161
#ifdef TARGET_WORDS_BIGENDIAN
164
162
res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
168
166
res = (DATA_TYPE)res;
170
168
/* unaligned/aligned access in the same page */
171
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
169
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)physaddr);
174
172
/* the page is not in the TLB : fill it */
175
tlb_fill(addr, 0, is_user, retaddr);
173
tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
182
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(unsigned long addr,
179
#ifndef SOFTMMU_CODE_ACCESS
181
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
186
static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
188
target_ulong tlb_addr,
193
index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
194
env->mem_write_vaddr = tlb_addr;
195
env->mem_write_pc = (unsigned long)retaddr;
197
io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val);
199
#ifdef TARGET_WORDS_BIGENDIAN
200
io_mem_write[index][2](io_mem_opaque[index], physaddr, val >> 32);
201
io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val);
203
io_mem_write[index][2](io_mem_opaque[index], physaddr, val);
204
io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val >> 32);
206
#endif /* SHIFT > 2 */
208
env->last_io_time = cpu_get_time_fast();
212
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
186
unsigned long physaddr, tlb_addr;
216
target_phys_addr_t physaddr;
217
target_ulong tlb_addr;
190
221
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
192
tlb_addr = env->tlb_write[is_user][index].address;
223
tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
193
224
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
194
physaddr = addr + env->tlb_write[is_user][index].addend;
225
physaddr = addr + env->tlb_table[mmu_idx][index].addend;
195
226
if (tlb_addr & ~TARGET_PAGE_MASK) {
197
228
if ((addr & (DATA_SIZE - 1)) != 0)
198
229
goto do_unaligned_access;
199
230
retaddr = GETPC();
200
231
glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr);
201
} else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
232
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
202
233
do_unaligned_access:
203
234
retaddr = GETPC();
204
glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
236
do_unaligned_access(addr, 1, mmu_idx, retaddr);
238
glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
207
241
/* aligned/unaligned access in the same page */
208
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, val);
243
if ((addr & (DATA_SIZE - 1)) != 0) {
245
do_unaligned_access(addr, 1, mmu_idx, retaddr);
248
glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)physaddr, val);
211
251
/* the page is not in the TLB : fill it */
212
252
retaddr = GETPC();
213
tlb_fill(addr, 1, is_user, retaddr);
254
if ((addr & (DATA_SIZE - 1)) != 0)
255
do_unaligned_access(addr, 1, mmu_idx, retaddr);
257
tlb_fill(addr, 1, mmu_idx, retaddr);
218
262
/* handles all unaligned cases */
219
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(unsigned long addr,
263
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
224
unsigned long physaddr, tlb_addr;
268
target_phys_addr_t physaddr;
269
target_ulong tlb_addr;
227
272
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
229
tlb_addr = env->tlb_write[is_user][index].address;
274
tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
230
275
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
231
physaddr = addr + env->tlb_write[is_user][index].addend;
276
physaddr = addr + env->tlb_table[mmu_idx][index].addend;
232
277
if (tlb_addr & ~TARGET_PAGE_MASK) {
234
279
if ((addr & (DATA_SIZE - 1)) != 0)
235
280
goto do_unaligned_access;
236
281
glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr);
237
} else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
282
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
238
283
do_unaligned_access:
239
284
/* XXX: not efficient, but simple */
240
for(i = 0;i < DATA_SIZE; i++) {
285
/* Note: relies on the fact that tlb_fill() does not remove the
286
* previous page from the TLB cache. */
287
for(i = DATA_SIZE - 1; i >= 0; i--) {
241
288
#ifdef TARGET_WORDS_BIGENDIAN
242
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
289
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
245
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
292
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
250
297
/* aligned/unaligned access in the same page */
251
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, val);
298
glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)physaddr, val);
254
301
/* the page is not in the TLB : fill it */
255
tlb_fill(addr, 1, is_user, retaddr);
302
tlb_fill(addr, 1, mmu_idx, retaddr);
307
#endif /* !defined(SOFTMMU_CODE_ACCESS) */
309
#undef READ_ACCESS_TYPE