]> git.proxmox.com Git - qemu.git/blame - softmmu_template.h
rtl8139: remove unused marco
[qemu.git] / softmmu_template.h
CommitLineData
b92e5a22
FB
1/*
2 * Software MMU support
5fafdf24 3 *
efbf29b6
BS
4 * Generate helpers used by TCG for qemu_ld/st ops and code load
5 * functions.
6 *
7 * Included from target op helpers and exec.c.
8 *
b92e5a22
FB
9 * Copyright (c) 2003 Fabrice Bellard
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
8167ee88 22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
b92e5a22 23 */
29e922b6 24#include "qemu-timer.h"
0e0df1e2 25#include "memory.h"
29e922b6 26
b92e5a22
FB
27#define DATA_SIZE (1 << SHIFT)
28
29#if DATA_SIZE == 8
30#define SUFFIX q
61382a50 31#define USUFFIX q
b92e5a22
FB
32#define DATA_TYPE uint64_t
33#elif DATA_SIZE == 4
34#define SUFFIX l
61382a50 35#define USUFFIX l
b92e5a22
FB
36#define DATA_TYPE uint32_t
37#elif DATA_SIZE == 2
38#define SUFFIX w
61382a50 39#define USUFFIX uw
b92e5a22
FB
40#define DATA_TYPE uint16_t
41#elif DATA_SIZE == 1
42#define SUFFIX b
61382a50 43#define USUFFIX ub
b92e5a22
FB
44#define DATA_TYPE uint8_t
45#else
46#error unsupported data size
47#endif
48
b769d8fe
FB
49#ifdef SOFTMMU_CODE_ACCESS
50#define READ_ACCESS_TYPE 2
84b7b8e7 51#define ADDR_READ addr_code
b769d8fe
FB
52#else
53#define READ_ACCESS_TYPE 0
84b7b8e7 54#define ADDR_READ addr_read
b769d8fe
FB
55#endif
56
5fafdf24 57static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
6ebbf390 58 int mmu_idx,
61382a50 59 void *retaddr);
c227f099 60static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
2e70f6ef
PB
61 target_ulong addr,
62 void *retaddr)
b92e5a22
FB
63{
64 DATA_TYPE res;
37ec01d4
AK
65 MemoryRegion *mr = iotlb_to_region(physaddr);
66
0f459d16 67 physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
2e70f6ef 68 env->mem_io_pc = (unsigned long)retaddr;
37ec01d4
AK
69 if (mr != &io_mem_ram && mr != &io_mem_rom
70 && mr != &io_mem_unassigned
71 && mr != &io_mem_notdirty
2e70f6ef
PB
72 && !can_do_io(env)) {
73 cpu_io_recompile(env, retaddr);
74 }
b92e5a22 75
db8886d3 76 env->mem_io_vaddr = addr;
b92e5a22 77#if SHIFT <= 2
37ec01d4 78 res = io_mem_read(mr, physaddr, 1 << SHIFT);
b92e5a22
FB
79#else
80#ifdef TARGET_WORDS_BIGENDIAN
37ec01d4
AK
81 res = io_mem_read(mr, physaddr, 4) << 32;
82 res |= io_mem_read(mr, physaddr + 4, 4);
b92e5a22 83#else
37ec01d4
AK
84 res = io_mem_read(mr, physaddr, 4);
85 res |= io_mem_read(mr, physaddr + 4, 4) << 32;
b92e5a22
FB
86#endif
87#endif /* SHIFT > 2 */
88 return res;
89}
90
b92e5a22 91/* handle all cases except unaligned access which span two pages */
d656469f
FB
92DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
93 int mmu_idx)
b92e5a22
FB
94{
95 DATA_TYPE res;
61382a50 96 int index;
c27004ec 97 target_ulong tlb_addr;
355b1943
PB
98 target_phys_addr_t ioaddr;
99 unsigned long addend;
b92e5a22 100 void *retaddr;
3b46e624 101
b92e5a22
FB
102 /* test if there is match for unaligned or IO access */
103 /* XXX: could done more in memory macro in a non portable way */
b92e5a22
FB
104 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
105 redo:
6ebbf390 106 tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
b92e5a22 107 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
b92e5a22
FB
108 if (tlb_addr & ~TARGET_PAGE_MASK) {
109 /* IO access */
110 if ((addr & (DATA_SIZE - 1)) != 0)
111 goto do_unaligned_access;
2e70f6ef 112 retaddr = GETPC();
37ec01d4 113 ioaddr = env->iotlb[mmu_idx][index];
355b1943 114 res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
98699967 115 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
b92e5a22
FB
116 /* slow unaligned access (it spans two pages or IO) */
117 do_unaligned_access:
61382a50 118 retaddr = GETPC();
a64d4718 119#ifdef ALIGNED_ONLY
6ebbf390 120 do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
a64d4718 121#endif
5fafdf24 122 res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
6ebbf390 123 mmu_idx, retaddr);
b92e5a22 124 } else {
a64d4718
FB
125 /* unaligned/aligned access in the same page */
126#ifdef ALIGNED_ONLY
127 if ((addr & (DATA_SIZE - 1)) != 0) {
128 retaddr = GETPC();
6ebbf390 129 do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
a64d4718
FB
130 }
131#endif
0f459d16
PB
132 addend = env->tlb_table[mmu_idx][index].addend;
133 res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend));
b92e5a22
FB
134 }
135 } else {
136 /* the page is not in the TLB : fill it */
61382a50 137 retaddr = GETPC();
a64d4718
FB
138#ifdef ALIGNED_ONLY
139 if ((addr & (DATA_SIZE - 1)) != 0)
6ebbf390 140 do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
a64d4718 141#endif
bccd9ec5 142 tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
b92e5a22
FB
143 goto redo;
144 }
145 return res;
146}
147
148/* handle all unaligned cases */
5fafdf24 149static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
6ebbf390 150 int mmu_idx,
61382a50 151 void *retaddr)
b92e5a22
FB
152{
153 DATA_TYPE res, res1, res2;
61382a50 154 int index, shift;
355b1943
PB
155 target_phys_addr_t ioaddr;
156 unsigned long addend;
c27004ec 157 target_ulong tlb_addr, addr1, addr2;
b92e5a22 158
b92e5a22
FB
159 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
160 redo:
6ebbf390 161 tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
b92e5a22 162 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
b92e5a22
FB
163 if (tlb_addr & ~TARGET_PAGE_MASK) {
164 /* IO access */
165 if ((addr & (DATA_SIZE - 1)) != 0)
166 goto do_unaligned_access;
37ec01d4 167 ioaddr = env->iotlb[mmu_idx][index];
355b1943 168 res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
98699967 169 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
b92e5a22
FB
170 do_unaligned_access:
171 /* slow unaligned access (it spans two pages) */
172 addr1 = addr & ~(DATA_SIZE - 1);
173 addr2 = addr1 + DATA_SIZE;
5fafdf24 174 res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
6ebbf390 175 mmu_idx, retaddr);
5fafdf24 176 res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
6ebbf390 177 mmu_idx, retaddr);
b92e5a22
FB
178 shift = (addr & (DATA_SIZE - 1)) * 8;
179#ifdef TARGET_WORDS_BIGENDIAN
180 res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
181#else
182 res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
183#endif
6986f88c 184 res = (DATA_TYPE)res;
b92e5a22
FB
185 } else {
186 /* unaligned/aligned access in the same page */
0f459d16
PB
187 addend = env->tlb_table[mmu_idx][index].addend;
188 res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend));
b92e5a22
FB
189 }
190 } else {
191 /* the page is not in the TLB : fill it */
bccd9ec5 192 tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
b92e5a22
FB
193 goto redo;
194 }
195 return res;
196}
197
b769d8fe
FB
198#ifndef SOFTMMU_CODE_ACCESS
199
5fafdf24
TS
200static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
201 DATA_TYPE val,
6ebbf390 202 int mmu_idx,
b769d8fe
FB
203 void *retaddr);
204
c227f099 205static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
b769d8fe 206 DATA_TYPE val,
0f459d16 207 target_ulong addr,
b769d8fe
FB
208 void *retaddr)
209{
37ec01d4
AK
210 MemoryRegion *mr = iotlb_to_region(physaddr);
211
0f459d16 212 physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
37ec01d4
AK
213 if (mr != &io_mem_ram && mr != &io_mem_rom
214 && mr != &io_mem_unassigned
215 && mr != &io_mem_notdirty
2e70f6ef
PB
216 && !can_do_io(env)) {
217 cpu_io_recompile(env, retaddr);
218 }
b769d8fe 219
2e70f6ef
PB
220 env->mem_io_vaddr = addr;
221 env->mem_io_pc = (unsigned long)retaddr;
b769d8fe 222#if SHIFT <= 2
37ec01d4 223 io_mem_write(mr, physaddr, val, 1 << SHIFT);
b769d8fe
FB
224#else
225#ifdef TARGET_WORDS_BIGENDIAN
37ec01d4
AK
226 io_mem_write(mr, physaddr, (val >> 32), 4);
227 io_mem_write(mr, physaddr + 4, (uint32_t)val, 4);
b769d8fe 228#else
37ec01d4
AK
229 io_mem_write(mr, physaddr, (uint32_t)val, 4);
230 io_mem_write(mr, physaddr + 4, val >> 32, 4);
b769d8fe
FB
231#endif
232#endif /* SHIFT > 2 */
233}
b92e5a22 234
d656469f
FB
235void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
236 DATA_TYPE val,
237 int mmu_idx)
b92e5a22 238{
355b1943
PB
239 target_phys_addr_t ioaddr;
240 unsigned long addend;
c27004ec 241 target_ulong tlb_addr;
b92e5a22 242 void *retaddr;
61382a50 243 int index;
3b46e624 244
b92e5a22
FB
245 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
246 redo:
6ebbf390 247 tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
b92e5a22 248 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
b92e5a22
FB
249 if (tlb_addr & ~TARGET_PAGE_MASK) {
250 /* IO access */
251 if ((addr & (DATA_SIZE - 1)) != 0)
252 goto do_unaligned_access;
d720b93d 253 retaddr = GETPC();
37ec01d4 254 ioaddr = env->iotlb[mmu_idx][index];
355b1943 255 glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
98699967 256 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
b92e5a22 257 do_unaligned_access:
61382a50 258 retaddr = GETPC();
a64d4718 259#ifdef ALIGNED_ONLY
6ebbf390 260 do_unaligned_access(addr, 1, mmu_idx, retaddr);
a64d4718 261#endif
5fafdf24 262 glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
6ebbf390 263 mmu_idx, retaddr);
b92e5a22
FB
264 } else {
265 /* aligned/unaligned access in the same page */
a64d4718
FB
266#ifdef ALIGNED_ONLY
267 if ((addr & (DATA_SIZE - 1)) != 0) {
268 retaddr = GETPC();
6ebbf390 269 do_unaligned_access(addr, 1, mmu_idx, retaddr);
a64d4718
FB
270 }
271#endif
0f459d16
PB
272 addend = env->tlb_table[mmu_idx][index].addend;
273 glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val);
b92e5a22
FB
274 }
275 } else {
276 /* the page is not in the TLB : fill it */
61382a50 277 retaddr = GETPC();
a64d4718
FB
278#ifdef ALIGNED_ONLY
279 if ((addr & (DATA_SIZE - 1)) != 0)
6ebbf390 280 do_unaligned_access(addr, 1, mmu_idx, retaddr);
a64d4718 281#endif
bccd9ec5 282 tlb_fill(env, addr, 1, mmu_idx, retaddr);
b92e5a22
FB
283 goto redo;
284 }
285}
286
287/* handles all unaligned cases */
5fafdf24 288static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
61382a50 289 DATA_TYPE val,
6ebbf390 290 int mmu_idx,
61382a50 291 void *retaddr)
b92e5a22 292{
355b1943
PB
293 target_phys_addr_t ioaddr;
294 unsigned long addend;
c27004ec 295 target_ulong tlb_addr;
61382a50 296 int index, i;
b92e5a22 297
b92e5a22
FB
298 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
299 redo:
6ebbf390 300 tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
b92e5a22 301 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
b92e5a22
FB
302 if (tlb_addr & ~TARGET_PAGE_MASK) {
303 /* IO access */
304 if ((addr & (DATA_SIZE - 1)) != 0)
305 goto do_unaligned_access;
37ec01d4 306 ioaddr = env->iotlb[mmu_idx][index];
355b1943 307 glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
98699967 308 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
b92e5a22
FB
309 do_unaligned_access:
310 /* XXX: not efficient, but simple */
6c41b272
AZ
311 /* Note: relies on the fact that tlb_fill() does not remove the
312 * previous page from the TLB cache. */
7221fa98 313 for(i = DATA_SIZE - 1; i >= 0; i--) {
b92e5a22 314#ifdef TARGET_WORDS_BIGENDIAN
5fafdf24 315 glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
6ebbf390 316 mmu_idx, retaddr);
b92e5a22 317#else
5fafdf24 318 glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
6ebbf390 319 mmu_idx, retaddr);
b92e5a22
FB
320#endif
321 }
322 } else {
323 /* aligned/unaligned access in the same page */
0f459d16
PB
324 addend = env->tlb_table[mmu_idx][index].addend;
325 glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val);
b92e5a22
FB
326 }
327 } else {
328 /* the page is not in the TLB : fill it */
bccd9ec5 329 tlb_fill(env, addr, 1, mmu_idx, retaddr);
b92e5a22
FB
330 goto redo;
331 }
332}
333
b769d8fe
FB
334#endif /* !defined(SOFTMMU_CODE_ACCESS) */
335
336#undef READ_ACCESS_TYPE
b92e5a22
FB
337#undef SHIFT
338#undef DATA_TYPE
339#undef SUFFIX
61382a50 340#undef USUFFIX
b92e5a22 341#undef DATA_SIZE
84b7b8e7 342#undef ADDR_READ