blob: b8bd700325054788938e105d7f02eec79c6c16d5 [file] [log] [blame]
bellardb92e5a22003-08-08 23:58:05 +00001/*
2 * Software MMU support
ths5fafdf22007-09-16 21:08:06 +00003 *
Blue Swirlefbf29b2011-09-21 20:00:18 +00004 * 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 *
bellardb92e5a22003-08-08 23:58:05 +00009 * 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
Blue Swirl8167ee82009-07-16 20:47:01 +000022 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellardb92e5a22003-08-08 23:58:05 +000023 */
Blue Swirl29e922b2010-03-29 19:24:00 +000024#include "qemu-timer.h"
Avi Kivity0e0df1e2012-01-02 00:32:15 +020025#include "memory.h"
Blue Swirl29e922b2010-03-29 19:24:00 +000026
bellardb92e5a22003-08-08 23:58:05 +000027#define DATA_SIZE (1 << SHIFT)
28
29#if DATA_SIZE == 8
30#define SUFFIX q
bellard61382a52003-10-27 21:22:23 +000031#define USUFFIX q
bellardb92e5a22003-08-08 23:58:05 +000032#define DATA_TYPE uint64_t
33#elif DATA_SIZE == 4
34#define SUFFIX l
bellard61382a52003-10-27 21:22:23 +000035#define USUFFIX l
bellardb92e5a22003-08-08 23:58:05 +000036#define DATA_TYPE uint32_t
37#elif DATA_SIZE == 2
38#define SUFFIX w
bellard61382a52003-10-27 21:22:23 +000039#define USUFFIX uw
bellardb92e5a22003-08-08 23:58:05 +000040#define DATA_TYPE uint16_t
41#elif DATA_SIZE == 1
42#define SUFFIX b
bellard61382a52003-10-27 21:22:23 +000043#define USUFFIX ub
bellardb92e5a22003-08-08 23:58:05 +000044#define DATA_TYPE uint8_t
45#else
46#error unsupported data size
47#endif
48
bellardb769d8f2004-10-03 15:07:13 +000049#ifdef SOFTMMU_CODE_ACCESS
50#define READ_ACCESS_TYPE 2
bellard84b7b8e2005-11-28 21:19:04 +000051#define ADDR_READ addr_code
bellardb769d8f2004-10-03 15:07:13 +000052#else
53#define READ_ACCESS_TYPE 0
bellard84b7b8e2005-11-28 21:19:04 +000054#define ADDR_READ addr_read
bellardb769d8f2004-10-03 15:07:13 +000055#endif
56
Blue Swirle141ab52011-09-18 14:55:46 +000057#ifndef CONFIG_TCG_PASS_AREG0
58#define ENV_PARAM
59#define ENV_VAR
60#define CPU_PREFIX
61#define HELPER_PREFIX __
62#else
63#define ENV_PARAM CPUArchState *env,
64#define ENV_VAR env,
65#define CPU_PREFIX cpu_
66#define HELPER_PREFIX helper_
67#endif
68
69static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
70 target_ulong addr,
j_mayer6ebbf392007-10-14 07:07:08 +000071 int mmu_idx,
Blue Swirl20503962012-04-09 14:20:20 +000072 uintptr_t retaddr);
Blue Swirle141ab52011-09-18 14:55:46 +000073static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM
74 target_phys_addr_t physaddr,
pbrook2e70f6e2008-06-29 01:03:05 +000075 target_ulong addr,
Blue Swirl20503962012-04-09 14:20:20 +000076 uintptr_t retaddr)
bellardb92e5a22003-08-08 23:58:05 +000077{
78 DATA_TYPE res;
Avi Kivity37ec01d2012-03-08 18:08:35 +020079 MemoryRegion *mr = iotlb_to_region(physaddr);
80
pbrook0f459d12008-06-09 00:20:13 +000081 physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
Blue Swirl20503962012-04-09 14:20:20 +000082 env->mem_io_pc = retaddr;
Avi Kivity37ec01d2012-03-08 18:08:35 +020083 if (mr != &io_mem_ram && mr != &io_mem_rom
84 && mr != &io_mem_unassigned
85 && mr != &io_mem_notdirty
pbrook2e70f6e2008-06-29 01:03:05 +000086 && !can_do_io(env)) {
87 cpu_io_recompile(env, retaddr);
88 }
bellardb92e5a22003-08-08 23:58:05 +000089
aliguoridb8886d2008-11-18 20:09:43 +000090 env->mem_io_vaddr = addr;
bellardb92e5a22003-08-08 23:58:05 +000091#if SHIFT <= 2
Avi Kivity37ec01d2012-03-08 18:08:35 +020092 res = io_mem_read(mr, physaddr, 1 << SHIFT);
bellardb92e5a22003-08-08 23:58:05 +000093#else
94#ifdef TARGET_WORDS_BIGENDIAN
Avi Kivity37ec01d2012-03-08 18:08:35 +020095 res = io_mem_read(mr, physaddr, 4) << 32;
96 res |= io_mem_read(mr, physaddr + 4, 4);
bellardb92e5a22003-08-08 23:58:05 +000097#else
Avi Kivity37ec01d2012-03-08 18:08:35 +020098 res = io_mem_read(mr, physaddr, 4);
99 res |= io_mem_read(mr, physaddr + 4, 4) << 32;
bellardb92e5a22003-08-08 23:58:05 +0000100#endif
101#endif /* SHIFT > 2 */
102 return res;
103}
104
bellardb92e5a22003-08-08 23:58:05 +0000105/* handle all cases except unaligned access which span two pages */
Blue Swirle141ab52011-09-18 14:55:46 +0000106DATA_TYPE
107glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
108 target_ulong addr,
109 int mmu_idx)
bellardb92e5a22003-08-08 23:58:05 +0000110{
111 DATA_TYPE res;
bellard61382a52003-10-27 21:22:23 +0000112 int index;
bellardc27004e2005-01-03 23:35:10 +0000113 target_ulong tlb_addr;
Paul Brook355b1942010-04-05 00:28:53 +0100114 target_phys_addr_t ioaddr;
Blue Swirl20503962012-04-09 14:20:20 +0000115 uintptr_t retaddr;
ths3b46e622007-09-17 08:09:54 +0000116
bellardb92e5a22003-08-08 23:58:05 +0000117 /* test if there is match for unaligned or IO access */
118 /* XXX: could done more in memory macro in a non portable way */
bellardb92e5a22003-08-08 23:58:05 +0000119 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
120 redo:
j_mayer6ebbf392007-10-14 07:07:08 +0000121 tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
bellardb92e5a22003-08-08 23:58:05 +0000122 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
bellardb92e5a22003-08-08 23:58:05 +0000123 if (tlb_addr & ~TARGET_PAGE_MASK) {
124 /* IO access */
125 if ((addr & (DATA_SIZE - 1)) != 0)
126 goto do_unaligned_access;
pbrook2e70f6e2008-06-29 01:03:05 +0000127 retaddr = GETPC();
Avi Kivity37ec01d2012-03-08 18:08:35 +0200128 ioaddr = env->iotlb[mmu_idx][index];
Blue Swirle141ab52011-09-18 14:55:46 +0000129 res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr);
bellard98699962005-11-26 10:29:22 +0000130 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
bellardb92e5a22003-08-08 23:58:05 +0000131 /* slow unaligned access (it spans two pages or IO) */
132 do_unaligned_access:
bellard61382a52003-10-27 21:22:23 +0000133 retaddr = GETPC();
bellarda64d4712005-12-05 19:57:57 +0000134#ifdef ALIGNED_ONLY
Blue Swirle141ab52011-09-18 14:55:46 +0000135 do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000136#endif
Blue Swirle141ab52011-09-18 14:55:46 +0000137 res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr,
j_mayer6ebbf392007-10-14 07:07:08 +0000138 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000139 } else {
bellarda64d4712005-12-05 19:57:57 +0000140 /* unaligned/aligned access in the same page */
Stefan Weilb0659272012-04-12 14:14:51 +0200141 uintptr_t addend;
bellarda64d4712005-12-05 19:57:57 +0000142#ifdef ALIGNED_ONLY
143 if ((addr & (DATA_SIZE - 1)) != 0) {
144 retaddr = GETPC();
Blue Swirle141ab52011-09-18 14:55:46 +0000145 do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000146 }
147#endif
pbrook0f459d12008-06-09 00:20:13 +0000148 addend = env->tlb_table[mmu_idx][index].addend;
Stefan Weilb0659272012-04-12 14:14:51 +0200149 res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t)
150 (addr + addend));
bellardb92e5a22003-08-08 23:58:05 +0000151 }
152 } else {
153 /* the page is not in the TLB : fill it */
bellard61382a52003-10-27 21:22:23 +0000154 retaddr = GETPC();
bellarda64d4712005-12-05 19:57:57 +0000155#ifdef ALIGNED_ONLY
156 if ((addr & (DATA_SIZE - 1)) != 0)
Blue Swirle141ab52011-09-18 14:55:46 +0000157 do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000158#endif
Blue Swirlbccd9ec2011-07-04 20:57:05 +0000159 tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000160 goto redo;
161 }
162 return res;
163}
164
165/* handle all unaligned cases */
Blue Swirle141ab52011-09-18 14:55:46 +0000166static DATA_TYPE
167glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
168 target_ulong addr,
169 int mmu_idx,
Blue Swirl20503962012-04-09 14:20:20 +0000170 uintptr_t retaddr)
bellardb92e5a22003-08-08 23:58:05 +0000171{
172 DATA_TYPE res, res1, res2;
bellard61382a52003-10-27 21:22:23 +0000173 int index, shift;
Paul Brook355b1942010-04-05 00:28:53 +0100174 target_phys_addr_t ioaddr;
bellardc27004e2005-01-03 23:35:10 +0000175 target_ulong tlb_addr, addr1, addr2;
bellardb92e5a22003-08-08 23:58:05 +0000176
bellardb92e5a22003-08-08 23:58:05 +0000177 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
178 redo:
j_mayer6ebbf392007-10-14 07:07:08 +0000179 tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
bellardb92e5a22003-08-08 23:58:05 +0000180 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
bellardb92e5a22003-08-08 23:58:05 +0000181 if (tlb_addr & ~TARGET_PAGE_MASK) {
182 /* IO access */
183 if ((addr & (DATA_SIZE - 1)) != 0)
184 goto do_unaligned_access;
Avi Kivity37ec01d2012-03-08 18:08:35 +0200185 ioaddr = env->iotlb[mmu_idx][index];
Blue Swirle141ab52011-09-18 14:55:46 +0000186 res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr);
bellard98699962005-11-26 10:29:22 +0000187 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
bellardb92e5a22003-08-08 23:58:05 +0000188 do_unaligned_access:
189 /* slow unaligned access (it spans two pages) */
190 addr1 = addr & ~(DATA_SIZE - 1);
191 addr2 = addr1 + DATA_SIZE;
Blue Swirle141ab52011-09-18 14:55:46 +0000192 res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr1,
j_mayer6ebbf392007-10-14 07:07:08 +0000193 mmu_idx, retaddr);
Blue Swirle141ab52011-09-18 14:55:46 +0000194 res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr2,
j_mayer6ebbf392007-10-14 07:07:08 +0000195 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000196 shift = (addr & (DATA_SIZE - 1)) * 8;
197#ifdef TARGET_WORDS_BIGENDIAN
198 res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
199#else
200 res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
201#endif
bellard6986f882004-01-18 21:53:18 +0000202 res = (DATA_TYPE)res;
bellardb92e5a22003-08-08 23:58:05 +0000203 } else {
204 /* unaligned/aligned access in the same page */
Stefan Weilb0659272012-04-12 14:14:51 +0200205 uintptr_t addend = env->tlb_table[mmu_idx][index].addend;
206 res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t)
207 (addr + addend));
bellardb92e5a22003-08-08 23:58:05 +0000208 }
209 } else {
210 /* the page is not in the TLB : fill it */
Blue Swirlbccd9ec2011-07-04 20:57:05 +0000211 tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000212 goto redo;
213 }
214 return res;
215}
216
bellardb769d8f2004-10-03 15:07:13 +0000217#ifndef SOFTMMU_CODE_ACCESS
218
Blue Swirle141ab52011-09-18 14:55:46 +0000219static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
220 target_ulong addr,
ths5fafdf22007-09-16 21:08:06 +0000221 DATA_TYPE val,
j_mayer6ebbf392007-10-14 07:07:08 +0000222 int mmu_idx,
Blue Swirl20503962012-04-09 14:20:20 +0000223 uintptr_t retaddr);
bellardb769d8f2004-10-03 15:07:13 +0000224
Blue Swirle141ab52011-09-18 14:55:46 +0000225static inline void glue(io_write, SUFFIX)(ENV_PARAM
226 target_phys_addr_t physaddr,
bellardb769d8f2004-10-03 15:07:13 +0000227 DATA_TYPE val,
pbrook0f459d12008-06-09 00:20:13 +0000228 target_ulong addr,
Blue Swirl20503962012-04-09 14:20:20 +0000229 uintptr_t retaddr)
bellardb769d8f2004-10-03 15:07:13 +0000230{
Avi Kivity37ec01d2012-03-08 18:08:35 +0200231 MemoryRegion *mr = iotlb_to_region(physaddr);
232
pbrook0f459d12008-06-09 00:20:13 +0000233 physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
Avi Kivity37ec01d2012-03-08 18:08:35 +0200234 if (mr != &io_mem_ram && mr != &io_mem_rom
235 && mr != &io_mem_unassigned
236 && mr != &io_mem_notdirty
pbrook2e70f6e2008-06-29 01:03:05 +0000237 && !can_do_io(env)) {
238 cpu_io_recompile(env, retaddr);
239 }
bellardb769d8f2004-10-03 15:07:13 +0000240
pbrook2e70f6e2008-06-29 01:03:05 +0000241 env->mem_io_vaddr = addr;
Blue Swirl20503962012-04-09 14:20:20 +0000242 env->mem_io_pc = retaddr;
bellardb769d8f2004-10-03 15:07:13 +0000243#if SHIFT <= 2
Avi Kivity37ec01d2012-03-08 18:08:35 +0200244 io_mem_write(mr, physaddr, val, 1 << SHIFT);
bellardb769d8f2004-10-03 15:07:13 +0000245#else
246#ifdef TARGET_WORDS_BIGENDIAN
Avi Kivity37ec01d2012-03-08 18:08:35 +0200247 io_mem_write(mr, physaddr, (val >> 32), 4);
248 io_mem_write(mr, physaddr + 4, (uint32_t)val, 4);
bellardb769d8f2004-10-03 15:07:13 +0000249#else
Avi Kivity37ec01d2012-03-08 18:08:35 +0200250 io_mem_write(mr, physaddr, (uint32_t)val, 4);
251 io_mem_write(mr, physaddr + 4, val >> 32, 4);
bellardb769d8f2004-10-03 15:07:13 +0000252#endif
253#endif /* SHIFT > 2 */
254}
bellardb92e5a22003-08-08 23:58:05 +0000255
Blue Swirle141ab52011-09-18 14:55:46 +0000256void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
257 target_ulong addr,
258 DATA_TYPE val,
259 int mmu_idx)
bellardb92e5a22003-08-08 23:58:05 +0000260{
Paul Brook355b1942010-04-05 00:28:53 +0100261 target_phys_addr_t ioaddr;
bellardc27004e2005-01-03 23:35:10 +0000262 target_ulong tlb_addr;
Blue Swirl20503962012-04-09 14:20:20 +0000263 uintptr_t retaddr;
bellard61382a52003-10-27 21:22:23 +0000264 int index;
ths3b46e622007-09-17 08:09:54 +0000265
bellardb92e5a22003-08-08 23:58:05 +0000266 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
267 redo:
j_mayer6ebbf392007-10-14 07:07:08 +0000268 tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
bellardb92e5a22003-08-08 23:58:05 +0000269 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
bellardb92e5a22003-08-08 23:58:05 +0000270 if (tlb_addr & ~TARGET_PAGE_MASK) {
271 /* IO access */
272 if ((addr & (DATA_SIZE - 1)) != 0)
273 goto do_unaligned_access;
bellardd720b932004-04-25 17:57:43 +0000274 retaddr = GETPC();
Avi Kivity37ec01d2012-03-08 18:08:35 +0200275 ioaddr = env->iotlb[mmu_idx][index];
Blue Swirle141ab52011-09-18 14:55:46 +0000276 glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr);
bellard98699962005-11-26 10:29:22 +0000277 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
bellardb92e5a22003-08-08 23:58:05 +0000278 do_unaligned_access:
bellard61382a52003-10-27 21:22:23 +0000279 retaddr = GETPC();
bellarda64d4712005-12-05 19:57:57 +0000280#ifdef ALIGNED_ONLY
Blue Swirle141ab52011-09-18 14:55:46 +0000281 do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000282#endif
Blue Swirle141ab52011-09-18 14:55:46 +0000283 glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_VAR addr, val,
j_mayer6ebbf392007-10-14 07:07:08 +0000284 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000285 } else {
286 /* aligned/unaligned access in the same page */
Stefan Weilb0659272012-04-12 14:14:51 +0200287 uintptr_t addend;
bellarda64d4712005-12-05 19:57:57 +0000288#ifdef ALIGNED_ONLY
289 if ((addr & (DATA_SIZE - 1)) != 0) {
290 retaddr = GETPC();
Blue Swirle141ab52011-09-18 14:55:46 +0000291 do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000292 }
293#endif
pbrook0f459d12008-06-09 00:20:13 +0000294 addend = env->tlb_table[mmu_idx][index].addend;
Stefan Weilb0659272012-04-12 14:14:51 +0200295 glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t)
296 (addr + addend), val);
bellardb92e5a22003-08-08 23:58:05 +0000297 }
298 } else {
299 /* the page is not in the TLB : fill it */
bellard61382a52003-10-27 21:22:23 +0000300 retaddr = GETPC();
bellarda64d4712005-12-05 19:57:57 +0000301#ifdef ALIGNED_ONLY
302 if ((addr & (DATA_SIZE - 1)) != 0)
Blue Swirle141ab52011-09-18 14:55:46 +0000303 do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
bellarda64d4712005-12-05 19:57:57 +0000304#endif
Blue Swirlbccd9ec2011-07-04 20:57:05 +0000305 tlb_fill(env, addr, 1, mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000306 goto redo;
307 }
308}
309
310/* handles all unaligned cases */
Blue Swirle141ab52011-09-18 14:55:46 +0000311static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
312 target_ulong addr,
bellard61382a52003-10-27 21:22:23 +0000313 DATA_TYPE val,
j_mayer6ebbf392007-10-14 07:07:08 +0000314 int mmu_idx,
Blue Swirl20503962012-04-09 14:20:20 +0000315 uintptr_t retaddr)
bellardb92e5a22003-08-08 23:58:05 +0000316{
Paul Brook355b1942010-04-05 00:28:53 +0100317 target_phys_addr_t ioaddr;
bellardc27004e2005-01-03 23:35:10 +0000318 target_ulong tlb_addr;
bellard61382a52003-10-27 21:22:23 +0000319 int index, i;
bellardb92e5a22003-08-08 23:58:05 +0000320
bellardb92e5a22003-08-08 23:58:05 +0000321 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
322 redo:
j_mayer6ebbf392007-10-14 07:07:08 +0000323 tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
bellardb92e5a22003-08-08 23:58:05 +0000324 if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
bellardb92e5a22003-08-08 23:58:05 +0000325 if (tlb_addr & ~TARGET_PAGE_MASK) {
326 /* IO access */
327 if ((addr & (DATA_SIZE - 1)) != 0)
328 goto do_unaligned_access;
Avi Kivity37ec01d2012-03-08 18:08:35 +0200329 ioaddr = env->iotlb[mmu_idx][index];
Blue Swirle141ab52011-09-18 14:55:46 +0000330 glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr);
bellard98699962005-11-26 10:29:22 +0000331 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
bellardb92e5a22003-08-08 23:58:05 +0000332 do_unaligned_access:
333 /* XXX: not efficient, but simple */
balrog6c41b272007-11-17 12:12:29 +0000334 /* Note: relies on the fact that tlb_fill() does not remove the
335 * previous page from the TLB cache. */
balrog7221fa92007-11-17 09:53:42 +0000336 for(i = DATA_SIZE - 1; i >= 0; i--) {
bellardb92e5a22003-08-08 23:58:05 +0000337#ifdef TARGET_WORDS_BIGENDIAN
Blue Swirle141ab52011-09-18 14:55:46 +0000338 glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i,
339 val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
j_mayer6ebbf392007-10-14 07:07:08 +0000340 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000341#else
Blue Swirle141ab52011-09-18 14:55:46 +0000342 glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i,
343 val >> (i * 8),
j_mayer6ebbf392007-10-14 07:07:08 +0000344 mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000345#endif
346 }
347 } else {
348 /* aligned/unaligned access in the same page */
Stefan Weilb0659272012-04-12 14:14:51 +0200349 uintptr_t addend = env->tlb_table[mmu_idx][index].addend;
350 glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t)
351 (addr + addend), val);
bellardb92e5a22003-08-08 23:58:05 +0000352 }
353 } else {
354 /* the page is not in the TLB : fill it */
Blue Swirlbccd9ec2011-07-04 20:57:05 +0000355 tlb_fill(env, addr, 1, mmu_idx, retaddr);
bellardb92e5a22003-08-08 23:58:05 +0000356 goto redo;
357 }
358}
359
bellardb769d8f2004-10-03 15:07:13 +0000360#endif /* !defined(SOFTMMU_CODE_ACCESS) */
361
362#undef READ_ACCESS_TYPE
bellardb92e5a22003-08-08 23:58:05 +0000363#undef SHIFT
364#undef DATA_TYPE
365#undef SUFFIX
bellard61382a52003-10-27 21:22:23 +0000366#undef USUFFIX
bellardb92e5a22003-08-08 23:58:05 +0000367#undef DATA_SIZE
bellard84b7b8e2005-11-28 21:19:04 +0000368#undef ADDR_READ
Blue Swirle141ab52011-09-18 14:55:46 +0000369#undef ENV_PARAM
370#undef ENV_VAR
371#undef CPU_PREFIX
372#undef HELPER_PREFIX