target/arm: Convert Neon 3-reg-diff narrowing ops to decodetree
[qemu/ar7.git] / memory_ldst.inc.c
blobc54aee4a951fcd4c0b00e23faf9224b42e8f0370
1 /*
2 * Physical memory access templates
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2015 Linaro, Inc.
6 * Copyright (c) 2016 Red Hat, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 /* warning: addr must be aligned */
23 static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL,
24 hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
25 enum device_endian endian)
27 uint8_t *ptr;
28 uint64_t val;
29 MemoryRegion *mr;
30 hwaddr l = 4;
31 hwaddr addr1;
32 MemTxResult r;
33 bool release_lock = false;
35 RCU_READ_LOCK();
36 mr = TRANSLATE(addr, &addr1, &l, false, attrs);
37 if (l < 4 || !memory_access_is_direct(mr, false)) {
38 release_lock |= prepare_mmio_access(mr);
40 /* I/O case */
41 r = memory_region_dispatch_read(mr, addr1, &val,
42 MO_32 | devend_memop(endian), attrs);
43 } else {
44 /* RAM case */
45 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
46 switch (endian) {
47 case DEVICE_LITTLE_ENDIAN:
48 val = ldl_le_p(ptr);
49 break;
50 case DEVICE_BIG_ENDIAN:
51 val = ldl_be_p(ptr);
52 break;
53 default:
54 val = ldl_p(ptr);
55 break;
57 r = MEMTX_OK;
59 if (result) {
60 *result = r;
62 if (release_lock) {
63 qemu_mutex_unlock_iothread();
65 RCU_READ_UNLOCK();
66 return val;
69 uint32_t glue(address_space_ldl, SUFFIX)(ARG1_DECL,
70 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
72 return glue(address_space_ldl_internal, SUFFIX)(ARG1, addr, attrs, result,
73 DEVICE_NATIVE_ENDIAN);
76 uint32_t glue(address_space_ldl_le, SUFFIX)(ARG1_DECL,
77 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
79 return glue(address_space_ldl_internal, SUFFIX)(ARG1, addr, attrs, result,
80 DEVICE_LITTLE_ENDIAN);
83 uint32_t glue(address_space_ldl_be, SUFFIX)(ARG1_DECL,
84 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
86 return glue(address_space_ldl_internal, SUFFIX)(ARG1, addr, attrs, result,
87 DEVICE_BIG_ENDIAN);
90 /* warning: addr must be aligned */
91 static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL,
92 hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
93 enum device_endian endian)
95 uint8_t *ptr;
96 uint64_t val;
97 MemoryRegion *mr;
98 hwaddr l = 8;
99 hwaddr addr1;
100 MemTxResult r;
101 bool release_lock = false;
103 RCU_READ_LOCK();
104 mr = TRANSLATE(addr, &addr1, &l, false, attrs);
105 if (l < 8 || !memory_access_is_direct(mr, false)) {
106 release_lock |= prepare_mmio_access(mr);
108 /* I/O case */
109 r = memory_region_dispatch_read(mr, addr1, &val,
110 MO_64 | devend_memop(endian), attrs);
111 } else {
112 /* RAM case */
113 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
114 switch (endian) {
115 case DEVICE_LITTLE_ENDIAN:
116 val = ldq_le_p(ptr);
117 break;
118 case DEVICE_BIG_ENDIAN:
119 val = ldq_be_p(ptr);
120 break;
121 default:
122 val = ldq_p(ptr);
123 break;
125 r = MEMTX_OK;
127 if (result) {
128 *result = r;
130 if (release_lock) {
131 qemu_mutex_unlock_iothread();
133 RCU_READ_UNLOCK();
134 return val;
137 uint64_t glue(address_space_ldq, SUFFIX)(ARG1_DECL,
138 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
140 return glue(address_space_ldq_internal, SUFFIX)(ARG1, addr, attrs, result,
141 DEVICE_NATIVE_ENDIAN);
144 uint64_t glue(address_space_ldq_le, SUFFIX)(ARG1_DECL,
145 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
147 return glue(address_space_ldq_internal, SUFFIX)(ARG1, addr, attrs, result,
148 DEVICE_LITTLE_ENDIAN);
151 uint64_t glue(address_space_ldq_be, SUFFIX)(ARG1_DECL,
152 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
154 return glue(address_space_ldq_internal, SUFFIX)(ARG1, addr, attrs, result,
155 DEVICE_BIG_ENDIAN);
158 uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
159 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
161 uint8_t *ptr;
162 uint64_t val;
163 MemoryRegion *mr;
164 hwaddr l = 1;
165 hwaddr addr1;
166 MemTxResult r;
167 bool release_lock = false;
169 RCU_READ_LOCK();
170 mr = TRANSLATE(addr, &addr1, &l, false, attrs);
171 if (!memory_access_is_direct(mr, false)) {
172 release_lock |= prepare_mmio_access(mr);
174 /* I/O case */
175 r = memory_region_dispatch_read(mr, addr1, &val, MO_8, attrs);
176 } else {
177 /* RAM case */
178 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
179 val = ldub_p(ptr);
180 r = MEMTX_OK;
182 if (result) {
183 *result = r;
185 if (release_lock) {
186 qemu_mutex_unlock_iothread();
188 RCU_READ_UNLOCK();
189 return val;
192 /* warning: addr must be aligned */
193 static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
194 hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
195 enum device_endian endian)
197 uint8_t *ptr;
198 uint64_t val;
199 MemoryRegion *mr;
200 hwaddr l = 2;
201 hwaddr addr1;
202 MemTxResult r;
203 bool release_lock = false;
205 RCU_READ_LOCK();
206 mr = TRANSLATE(addr, &addr1, &l, false, attrs);
207 if (l < 2 || !memory_access_is_direct(mr, false)) {
208 release_lock |= prepare_mmio_access(mr);
210 /* I/O case */
211 r = memory_region_dispatch_read(mr, addr1, &val,
212 MO_16 | devend_memop(endian), attrs);
213 } else {
214 /* RAM case */
215 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
216 switch (endian) {
217 case DEVICE_LITTLE_ENDIAN:
218 val = lduw_le_p(ptr);
219 break;
220 case DEVICE_BIG_ENDIAN:
221 val = lduw_be_p(ptr);
222 break;
223 default:
224 val = lduw_p(ptr);
225 break;
227 r = MEMTX_OK;
229 if (result) {
230 *result = r;
232 if (release_lock) {
233 qemu_mutex_unlock_iothread();
235 RCU_READ_UNLOCK();
236 return val;
239 uint32_t glue(address_space_lduw, SUFFIX)(ARG1_DECL,
240 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
242 return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
243 DEVICE_NATIVE_ENDIAN);
246 uint32_t glue(address_space_lduw_le, SUFFIX)(ARG1_DECL,
247 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
249 return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
250 DEVICE_LITTLE_ENDIAN);
253 uint32_t glue(address_space_lduw_be, SUFFIX)(ARG1_DECL,
254 hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
256 return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
257 DEVICE_BIG_ENDIAN);
260 /* warning: addr must be aligned. The ram page is not masked as dirty
261 and the code inside is not invalidated. It is useful if the dirty
262 bits are used to track modified PTEs */
263 void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL,
264 hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
266 uint8_t *ptr;
267 MemoryRegion *mr;
268 hwaddr l = 4;
269 hwaddr addr1;
270 MemTxResult r;
271 uint8_t dirty_log_mask;
272 bool release_lock = false;
274 RCU_READ_LOCK();
275 mr = TRANSLATE(addr, &addr1, &l, true, attrs);
276 if (l < 4 || !memory_access_is_direct(mr, true)) {
277 release_lock |= prepare_mmio_access(mr);
279 r = memory_region_dispatch_write(mr, addr1, val, MO_32, attrs);
280 } else {
281 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
282 stl_p(ptr, val);
284 dirty_log_mask = memory_region_get_dirty_log_mask(mr);
285 dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
286 cpu_physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr,
287 4, dirty_log_mask);
288 r = MEMTX_OK;
290 if (result) {
291 *result = r;
293 if (release_lock) {
294 qemu_mutex_unlock_iothread();
296 RCU_READ_UNLOCK();
299 /* warning: addr must be aligned */
300 static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
301 hwaddr addr, uint32_t val, MemTxAttrs attrs,
302 MemTxResult *result, enum device_endian endian)
304 uint8_t *ptr;
305 MemoryRegion *mr;
306 hwaddr l = 4;
307 hwaddr addr1;
308 MemTxResult r;
309 bool release_lock = false;
311 RCU_READ_LOCK();
312 mr = TRANSLATE(addr, &addr1, &l, true, attrs);
313 if (l < 4 || !memory_access_is_direct(mr, true)) {
314 release_lock |= prepare_mmio_access(mr);
315 r = memory_region_dispatch_write(mr, addr1, val,
316 MO_32 | devend_memop(endian), attrs);
317 } else {
318 /* RAM case */
319 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
320 switch (endian) {
321 case DEVICE_LITTLE_ENDIAN:
322 stl_le_p(ptr, val);
323 break;
324 case DEVICE_BIG_ENDIAN:
325 stl_be_p(ptr, val);
326 break;
327 default:
328 stl_p(ptr, val);
329 break;
331 invalidate_and_set_dirty(mr, addr1, 4);
332 r = MEMTX_OK;
334 if (result) {
335 *result = r;
337 if (release_lock) {
338 qemu_mutex_unlock_iothread();
340 RCU_READ_UNLOCK();
343 void glue(address_space_stl, SUFFIX)(ARG1_DECL,
344 hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
346 glue(address_space_stl_internal, SUFFIX)(ARG1, addr, val, attrs,
347 result, DEVICE_NATIVE_ENDIAN);
350 void glue(address_space_stl_le, SUFFIX)(ARG1_DECL,
351 hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
353 glue(address_space_stl_internal, SUFFIX)(ARG1, addr, val, attrs,
354 result, DEVICE_LITTLE_ENDIAN);
357 void glue(address_space_stl_be, SUFFIX)(ARG1_DECL,
358 hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
360 glue(address_space_stl_internal, SUFFIX)(ARG1, addr, val, attrs,
361 result, DEVICE_BIG_ENDIAN);
364 void glue(address_space_stb, SUFFIX)(ARG1_DECL,
365 hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
367 uint8_t *ptr;
368 MemoryRegion *mr;
369 hwaddr l = 1;
370 hwaddr addr1;
371 MemTxResult r;
372 bool release_lock = false;
374 RCU_READ_LOCK();
375 mr = TRANSLATE(addr, &addr1, &l, true, attrs);
376 if (!memory_access_is_direct(mr, true)) {
377 release_lock |= prepare_mmio_access(mr);
378 r = memory_region_dispatch_write(mr, addr1, val, MO_8, attrs);
379 } else {
380 /* RAM case */
381 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
382 stb_p(ptr, val);
383 invalidate_and_set_dirty(mr, addr1, 1);
384 r = MEMTX_OK;
386 if (result) {
387 *result = r;
389 if (release_lock) {
390 qemu_mutex_unlock_iothread();
392 RCU_READ_UNLOCK();
395 /* warning: addr must be aligned */
396 static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
397 hwaddr addr, uint32_t val, MemTxAttrs attrs,
398 MemTxResult *result, enum device_endian endian)
400 uint8_t *ptr;
401 MemoryRegion *mr;
402 hwaddr l = 2;
403 hwaddr addr1;
404 MemTxResult r;
405 bool release_lock = false;
407 RCU_READ_LOCK();
408 mr = TRANSLATE(addr, &addr1, &l, true, attrs);
409 if (l < 2 || !memory_access_is_direct(mr, true)) {
410 release_lock |= prepare_mmio_access(mr);
411 r = memory_region_dispatch_write(mr, addr1, val,
412 MO_16 | devend_memop(endian), attrs);
413 } else {
414 /* RAM case */
415 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
416 switch (endian) {
417 case DEVICE_LITTLE_ENDIAN:
418 stw_le_p(ptr, val);
419 break;
420 case DEVICE_BIG_ENDIAN:
421 stw_be_p(ptr, val);
422 break;
423 default:
424 stw_p(ptr, val);
425 break;
427 invalidate_and_set_dirty(mr, addr1, 2);
428 r = MEMTX_OK;
430 if (result) {
431 *result = r;
433 if (release_lock) {
434 qemu_mutex_unlock_iothread();
436 RCU_READ_UNLOCK();
439 void glue(address_space_stw, SUFFIX)(ARG1_DECL,
440 hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
442 glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
443 DEVICE_NATIVE_ENDIAN);
446 void glue(address_space_stw_le, SUFFIX)(ARG1_DECL,
447 hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
449 glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
450 DEVICE_LITTLE_ENDIAN);
453 void glue(address_space_stw_be, SUFFIX)(ARG1_DECL,
454 hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
456 glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
457 DEVICE_BIG_ENDIAN);
460 static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
461 hwaddr addr, uint64_t val, MemTxAttrs attrs,
462 MemTxResult *result, enum device_endian endian)
464 uint8_t *ptr;
465 MemoryRegion *mr;
466 hwaddr l = 8;
467 hwaddr addr1;
468 MemTxResult r;
469 bool release_lock = false;
471 RCU_READ_LOCK();
472 mr = TRANSLATE(addr, &addr1, &l, true, attrs);
473 if (l < 8 || !memory_access_is_direct(mr, true)) {
474 release_lock |= prepare_mmio_access(mr);
475 r = memory_region_dispatch_write(mr, addr1, val,
476 MO_64 | devend_memop(endian), attrs);
477 } else {
478 /* RAM case */
479 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
480 switch (endian) {
481 case DEVICE_LITTLE_ENDIAN:
482 stq_le_p(ptr, val);
483 break;
484 case DEVICE_BIG_ENDIAN:
485 stq_be_p(ptr, val);
486 break;
487 default:
488 stq_p(ptr, val);
489 break;
491 invalidate_and_set_dirty(mr, addr1, 8);
492 r = MEMTX_OK;
494 if (result) {
495 *result = r;
497 if (release_lock) {
498 qemu_mutex_unlock_iothread();
500 RCU_READ_UNLOCK();
503 void glue(address_space_stq, SUFFIX)(ARG1_DECL,
504 hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result)
506 glue(address_space_stq_internal, SUFFIX)(ARG1, addr, val, attrs, result,
507 DEVICE_NATIVE_ENDIAN);
510 void glue(address_space_stq_le, SUFFIX)(ARG1_DECL,
511 hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result)
513 glue(address_space_stq_internal, SUFFIX)(ARG1, addr, val, attrs, result,
514 DEVICE_LITTLE_ENDIAN);
517 void glue(address_space_stq_be, SUFFIX)(ARG1_DECL,
518 hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result)
520 glue(address_space_stq_internal, SUFFIX)(ARG1, addr, val, attrs, result,
521 DEVICE_BIG_ENDIAN);
524 #undef ARG1_DECL
525 #undef ARG1
526 #undef SUFFIX
527 #undef TRANSLATE
528 #undef RCU_READ_LOCK
529 #undef RCU_READ_UNLOCK