blob: ac9b9a944a918d2f6cd4a352eb7c61e1180eee9e [file] [log] [blame]
bellardb92e5a22003-08-08 23:58:05 +00001/*
2 * Software MMU support
ths5fafdf22007-09-16 21:08:06 +00003 *
bellardb92e5a22003-08-08 23:58:05 +00004 * 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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellardb92e5a22003-08-08 23:58:05 +000018 */
19#define DATA_SIZE (1 << SHIFT)
20
21#if DATA_SIZE == 8
22#define SUFFIX q
bellard61382a52003-10-27 21:22:23 +000023#define USUFFIX q
bellardb92e5a22003-08-08 23:58:05 +000024#define DATA_TYPE uint64_t
25#elif DATA_SIZE == 4
26#define SUFFIX l
bellard61382a52003-10-27 21:22:23 +000027#define USUFFIX l
bellardb92e5a22003-08-08 23:58:05 +000028#define DATA_TYPE uint32_t
29#elif DATA_SIZE == 2
30#define SUFFIX w
bellard61382a52003-10-27 21:22:23 +000031#define USUFFIX uw
bellardb92e5a22003-08-08 23:58:05 +000032#define DATA_TYPE uint16_t
33#elif DATA_SIZE == 1
34#define SUFFIX b
bellard61382a52003-10-27 21:22:23 +000035#define USUFFIX ub
bellardb92e5a22003-08-08 23:58:05 +000036#define DATA_TYPE uint8_t
37#else
38#error unsupported data size
39#endif
40
bellardb769d8f2004-10-03 15:07:13 +000041#ifdef SOFTMMU_CODE_ACCESS
42#define READ_ACCESS_TYPE 2
bellard84b7b8e2005-11-28 21:19:04 +000043#define ADDR_READ addr_code
bellardb769d8f2004-10-03 15:07:13 +000044#else
45#define READ_ACCESS_TYPE 0
bellard84b7b8e2005-11-28 21:19:04 +000046#define ADDR_READ addr_read
bellardb769d8f2004-10-03 15:07:13 +000047#endif
48
ths5fafdf22007-09-16 21:08:06 +000049static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
j_mayer6ebbf392007-10-14 07:07:08 +000050 int mmu_idx,
bellard61382a52003-10-27 21:22:23 +000051 void *retaddr);
Anthony Liguoric227f092009-10-01 16:12:16 -050052static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
pbrook2e70f6e2008-06-29 01:03:05 +000053 target_ulong addr,
54 void *retaddr)
bellardb92e5a22003-08-08 23:58:05 +000055{
56 DATA_TYPE res;
57 int index;
pbrook0f459d12008-06-09 00:20:13 +000058 index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
59 physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
pbrook2e70f6e2008-06-29 01:03:05 +000060 env->mem_io_pc = (unsigned long)retaddr;
61 if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT)
62 && !can_do_io(env)) {
63 cpu_io_recompile(env, retaddr);
64 }
bellardb92e5a22003-08-08 23:58:05 +000065
aliguoridb8886d2008-11-18 20:09:43 +000066 env->mem_io_vaddr = addr;
bellardb92e5a22003-08-08 23:58:05 +000067#if SHIFT <= 2
bellarda4193c82004-06-03 14:01:43 +000068 res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr);
bellardb92e5a22003-08-08 23:58:05 +000069#else
70#ifdef TARGET_WORDS_BIGENDIAN
bellarda4193c82004-06-03 14:01:43 +000071 res = (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr) << 32;
72 res |= io_mem_read[index][2](io_mem_opaque[index], physaddr + 4);
bellardb92e5a22003-08-08 23:58:05 +000073#else
bellarda4193c82004-06-03 14:01:43 +000074 res = io_mem_read[index][2](io_mem_opaque[index], physaddr);
75 res |= (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr + 4) << 32;
bellardb92e5a22003-08-08 23:58:05 +000076#endif
77#endif /* SHIFT > 2 */
78 return res;
79}
80
bellardb92e5a22003-08-08 23:58:05 +000081/* handle all cases except unaligned access which span two pages */
bellardd6564692008-01-31 09:22:27 +000082DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
83 int mmu_idx)
bellardb92e5a22003-08-08 23:58:05 +000084{
85 DATA_TYPE res;
bellard61382a52003-10-27 21:22:23 +000086 int index;
bellardc27004e2005-01-03 23:35:10 +000087 target_ulong tlb_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -050088 target_phys_addr_t addend;
bellardb92e5a22003-08-08 23:58:05 +000089 void *retaddr;
ths3b46e622007-09-17 08:09:54 +000090
bellardb92e5a22003-08-08 23:58:05 +000091 /* test if there is match for unaligned or IO access */
92 /* XXX: could done more in memory macro in a non portable way */
bellardb92e5a22003-08-08 23:58:05 +000093 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
94 redo:
j_mayer6ebbf392007-10-14 07:07:08 +000095 tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
bellardb92e5a22003-08-08 23:58:05 +000096 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
bellardb92e5a22003-08-08 23:58:05 +000097 if (tlb_addr & ~TARGET_PAGE_MASK) {
98 /* IO access */
99 if ((addr & (DATA_SIZE - 1)) != 0)
100 goto do_unaligned_access;
pbrook2e70f6e2008-06-29 01:03:05 +0000101 retaddr = GETPC();
pbrook0f459d12008-06-09 00:20:13 +0000102 addend = env->iotlb[mmu_idx][index];
pbrook2e70f6e2008-06-29 01:03:05 +0000103 res = glue(io_read, SUFFIX)(addend, addr, retaddr);
bellard98699962005-11-26 10:29:22 +0000104 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
bellardb92e5a22003-08-08 23:58:05 +0000105 /* slow unaligned access (it spans two pages or IO) */
106 do_unaligned_access:
bellard61382a52003-10-27 21:22:23 +0000107 retaddr = GETPC();
bellarda64d4712005-12-05 19:57:57 +0000108#ifdef ALIGNED_ONLY
j_mayer6ebbf392007-10-14 07:07:08 +0000109 do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000110#endif
ths5fafdf22007-09-16 21:08:06 +0000111 res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
j_mayer6ebbf392007-10-14 07:07:08 +0000112 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000113 } else {
bellarda64d4712005-12-05 19:57:57 +0000114 /* unaligned/aligned access in the same page */
115#ifdef ALIGNED_ONLY
116 if ((addr & (DATA_SIZE - 1)) != 0) {
117 retaddr = GETPC();
j_mayer6ebbf392007-10-14 07:07:08 +0000118 do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000119 }
120#endif
pbrook0f459d12008-06-09 00:20:13 +0000121 addend = env->tlb_table[mmu_idx][index].addend;
122 res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend));
bellardb92e5a22003-08-08 23:58:05 +0000123 }
124 } else {
125 /* the page is not in the TLB : fill it */
bellard61382a52003-10-27 21:22:23 +0000126 retaddr = GETPC();
bellarda64d4712005-12-05 19:57:57 +0000127#ifdef ALIGNED_ONLY
128 if ((addr & (DATA_SIZE - 1)) != 0)
j_mayer6ebbf392007-10-14 07:07:08 +0000129 do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000130#endif
j_mayer6ebbf392007-10-14 07:07:08 +0000131 tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000132 goto redo;
133 }
134 return res;
135}
136
137/* handle all unaligned cases */
ths5fafdf22007-09-16 21:08:06 +0000138static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
j_mayer6ebbf392007-10-14 07:07:08 +0000139 int mmu_idx,
bellard61382a52003-10-27 21:22:23 +0000140 void *retaddr)
bellardb92e5a22003-08-08 23:58:05 +0000141{
142 DATA_TYPE res, res1, res2;
bellard61382a52003-10-27 21:22:23 +0000143 int index, shift;
Anthony Liguoric227f092009-10-01 16:12:16 -0500144 target_phys_addr_t addend;
bellardc27004e2005-01-03 23:35:10 +0000145 target_ulong tlb_addr, addr1, addr2;
bellardb92e5a22003-08-08 23:58:05 +0000146
bellardb92e5a22003-08-08 23:58:05 +0000147 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
148 redo:
j_mayer6ebbf392007-10-14 07:07:08 +0000149 tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
bellardb92e5a22003-08-08 23:58:05 +0000150 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
bellardb92e5a22003-08-08 23:58:05 +0000151 if (tlb_addr & ~TARGET_PAGE_MASK) {
152 /* IO access */
153 if ((addr & (DATA_SIZE - 1)) != 0)
154 goto do_unaligned_access;
pbrook0f459d12008-06-09 00:20:13 +0000155 addend = env->iotlb[mmu_idx][index];
pbrook2e70f6e2008-06-29 01:03:05 +0000156 res = glue(io_read, SUFFIX)(addend, addr, retaddr);
bellard98699962005-11-26 10:29:22 +0000157 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
bellardb92e5a22003-08-08 23:58:05 +0000158 do_unaligned_access:
159 /* slow unaligned access (it spans two pages) */
160 addr1 = addr & ~(DATA_SIZE - 1);
161 addr2 = addr1 + DATA_SIZE;
ths5fafdf22007-09-16 21:08:06 +0000162 res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
j_mayer6ebbf392007-10-14 07:07:08 +0000163 mmu_idx, retaddr);
ths5fafdf22007-09-16 21:08:06 +0000164 res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
j_mayer6ebbf392007-10-14 07:07:08 +0000165 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000166 shift = (addr & (DATA_SIZE - 1)) * 8;
167#ifdef TARGET_WORDS_BIGENDIAN
168 res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
169#else
170 res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
171#endif
bellard6986f882004-01-18 21:53:18 +0000172 res = (DATA_TYPE)res;
bellardb92e5a22003-08-08 23:58:05 +0000173 } else {
174 /* unaligned/aligned access in the same page */
pbrook0f459d12008-06-09 00:20:13 +0000175 addend = env->tlb_table[mmu_idx][index].addend;
176 res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend));
bellardb92e5a22003-08-08 23:58:05 +0000177 }
178 } else {
179 /* the page is not in the TLB : fill it */
j_mayer6ebbf392007-10-14 07:07:08 +0000180 tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000181 goto redo;
182 }
183 return res;
184}
185
bellardb769d8f2004-10-03 15:07:13 +0000186#ifndef SOFTMMU_CODE_ACCESS
187
ths5fafdf22007-09-16 21:08:06 +0000188static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
189 DATA_TYPE val,
j_mayer6ebbf392007-10-14 07:07:08 +0000190 int mmu_idx,
bellardb769d8f2004-10-03 15:07:13 +0000191 void *retaddr);
192
Anthony Liguoric227f092009-10-01 16:12:16 -0500193static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
bellardb769d8f2004-10-03 15:07:13 +0000194 DATA_TYPE val,
pbrook0f459d12008-06-09 00:20:13 +0000195 target_ulong addr,
bellardb769d8f2004-10-03 15:07:13 +0000196 void *retaddr)
197{
198 int index;
pbrook0f459d12008-06-09 00:20:13 +0000199 index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
200 physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
pbrook2e70f6e2008-06-29 01:03:05 +0000201 if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT)
202 && !can_do_io(env)) {
203 cpu_io_recompile(env, retaddr);
204 }
bellardb769d8f2004-10-03 15:07:13 +0000205
pbrook2e70f6e2008-06-29 01:03:05 +0000206 env->mem_io_vaddr = addr;
207 env->mem_io_pc = (unsigned long)retaddr;
bellardb769d8f2004-10-03 15:07:13 +0000208#if SHIFT <= 2
209 io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val);
210#else
211#ifdef TARGET_WORDS_BIGENDIAN
212 io_mem_write[index][2](io_mem_opaque[index], physaddr, val >> 32);
213 io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val);
214#else
215 io_mem_write[index][2](io_mem_opaque[index], physaddr, val);
216 io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val >> 32);
217#endif
218#endif /* SHIFT > 2 */
219}
bellardb92e5a22003-08-08 23:58:05 +0000220
bellardd6564692008-01-31 09:22:27 +0000221void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
222 DATA_TYPE val,
223 int mmu_idx)
bellardb92e5a22003-08-08 23:58:05 +0000224{
Anthony Liguoric227f092009-10-01 16:12:16 -0500225 target_phys_addr_t addend;
bellardc27004e2005-01-03 23:35:10 +0000226 target_ulong tlb_addr;
bellardb92e5a22003-08-08 23:58:05 +0000227 void *retaddr;
bellard61382a52003-10-27 21:22:23 +0000228 int index;
ths3b46e622007-09-17 08:09:54 +0000229
bellardb92e5a22003-08-08 23:58:05 +0000230 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
231 redo:
j_mayer6ebbf392007-10-14 07:07:08 +0000232 tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
bellardb92e5a22003-08-08 23:58:05 +0000233 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
bellardb92e5a22003-08-08 23:58:05 +0000234 if (tlb_addr & ~TARGET_PAGE_MASK) {
235 /* IO access */
236 if ((addr & (DATA_SIZE - 1)) != 0)
237 goto do_unaligned_access;
bellardd720b932004-04-25 17:57:43 +0000238 retaddr = GETPC();
pbrook0f459d12008-06-09 00:20:13 +0000239 addend = env->iotlb[mmu_idx][index];
240 glue(io_write, SUFFIX)(addend, val, addr, retaddr);
bellard98699962005-11-26 10:29:22 +0000241 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
bellardb92e5a22003-08-08 23:58:05 +0000242 do_unaligned_access:
bellard61382a52003-10-27 21:22:23 +0000243 retaddr = GETPC();
bellarda64d4712005-12-05 19:57:57 +0000244#ifdef ALIGNED_ONLY
j_mayer6ebbf392007-10-14 07:07:08 +0000245 do_unaligned_access(addr, 1, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000246#endif
ths5fafdf22007-09-16 21:08:06 +0000247 glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
j_mayer6ebbf392007-10-14 07:07:08 +0000248 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000249 } else {
250 /* aligned/unaligned access in the same page */
bellarda64d4712005-12-05 19:57:57 +0000251#ifdef ALIGNED_ONLY
252 if ((addr & (DATA_SIZE - 1)) != 0) {
253 retaddr = GETPC();
j_mayer6ebbf392007-10-14 07:07:08 +0000254 do_unaligned_access(addr, 1, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000255 }
256#endif
pbrook0f459d12008-06-09 00:20:13 +0000257 addend = env->tlb_table[mmu_idx][index].addend;
258 glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val);
bellardb92e5a22003-08-08 23:58:05 +0000259 }
260 } else {
261 /* the page is not in the TLB : fill it */
bellard61382a52003-10-27 21:22:23 +0000262 retaddr = GETPC();
bellarda64d4712005-12-05 19:57:57 +0000263#ifdef ALIGNED_ONLY
264 if ((addr & (DATA_SIZE - 1)) != 0)
j_mayer6ebbf392007-10-14 07:07:08 +0000265 do_unaligned_access(addr, 1, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000266#endif
j_mayer6ebbf392007-10-14 07:07:08 +0000267 tlb_fill(addr, 1, mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000268 goto redo;
269 }
270}
271
272/* handles all unaligned cases */
ths5fafdf22007-09-16 21:08:06 +0000273static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
bellard61382a52003-10-27 21:22:23 +0000274 DATA_TYPE val,
j_mayer6ebbf392007-10-14 07:07:08 +0000275 int mmu_idx,
bellard61382a52003-10-27 21:22:23 +0000276 void *retaddr)
bellardb92e5a22003-08-08 23:58:05 +0000277{
Anthony Liguoric227f092009-10-01 16:12:16 -0500278 target_phys_addr_t addend;
bellardc27004e2005-01-03 23:35:10 +0000279 target_ulong tlb_addr;
bellard61382a52003-10-27 21:22:23 +0000280 int index, i;
bellardb92e5a22003-08-08 23:58:05 +0000281
bellardb92e5a22003-08-08 23:58:05 +0000282 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
283 redo:
j_mayer6ebbf392007-10-14 07:07:08 +0000284 tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
bellardb92e5a22003-08-08 23:58:05 +0000285 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
bellardb92e5a22003-08-08 23:58:05 +0000286 if (tlb_addr & ~TARGET_PAGE_MASK) {
287 /* IO access */
288 if ((addr & (DATA_SIZE - 1)) != 0)
289 goto do_unaligned_access;
pbrook0f459d12008-06-09 00:20:13 +0000290 addend = env->iotlb[mmu_idx][index];
291 glue(io_write, SUFFIX)(addend, val, addr, retaddr);
bellard98699962005-11-26 10:29:22 +0000292 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
bellardb92e5a22003-08-08 23:58:05 +0000293 do_unaligned_access:
294 /* XXX: not efficient, but simple */
balrog6c41b272007-11-17 12:12:29 +0000295 /* Note: relies on the fact that tlb_fill() does not remove the
296 * previous page from the TLB cache. */
balrog7221fa92007-11-17 09:53:42 +0000297 for(i = DATA_SIZE - 1; i >= 0; i--) {
bellardb92e5a22003-08-08 23:58:05 +0000298#ifdef TARGET_WORDS_BIGENDIAN
ths5fafdf22007-09-16 21:08:06 +0000299 glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
j_mayer6ebbf392007-10-14 07:07:08 +0000300 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000301#else
ths5fafdf22007-09-16 21:08:06 +0000302 glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
j_mayer6ebbf392007-10-14 07:07:08 +0000303 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000304#endif
305 }
306 } else {
307 /* aligned/unaligned access in the same page */
pbrook0f459d12008-06-09 00:20:13 +0000308 addend = env->tlb_table[mmu_idx][index].addend;
309 glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val);
bellardb92e5a22003-08-08 23:58:05 +0000310 }
311 } else {
312 /* the page is not in the TLB : fill it */
j_mayer6ebbf392007-10-14 07:07:08 +0000313 tlb_fill(addr, 1, mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000314 goto redo;
315 }
316}
317
bellardb769d8f2004-10-03 15:07:13 +0000318#endif /* !defined(SOFTMMU_CODE_ACCESS) */
319
320#undef READ_ACCESS_TYPE
bellardb92e5a22003-08-08 23:58:05 +0000321#undef SHIFT
322#undef DATA_TYPE
323#undef SUFFIX
bellard61382a52003-10-27 21:22:23 +0000324#undef USUFFIX
bellardb92e5a22003-08-08 23:58:05 +0000325#undef DATA_SIZE
bellard84b7b8e2005-11-28 21:19:04 +0000326#undef ADDR_READ