1/*
2 * User-only accessor function support
3 *
4 * Generate inline load/store functions for one data size.
5 *
6 * Generate a store function as well as signed and unsigned loads.
7 *
8 * Not used directly but included from cpu_ldst.h.
9 *
10 * Copyright (c) 2015 Linaro Limited
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 */
25
26#if !defined(CODE_ACCESS)
27#include "trace-root.h"
28#endif
29
30#include "trace/mem.h"
31
32#if DATA_SIZE == 8
33#define SUFFIX q
34#define USUFFIX q
35#define DATA_TYPE uint64_t
36#define SHIFT 3
37#elif DATA_SIZE == 4
38#define SUFFIX l
39#define USUFFIX l
40#define DATA_TYPE uint32_t
41#define SHIFT 2
42#elif DATA_SIZE == 2
43#define SUFFIX w
44#define USUFFIX uw
45#define DATA_TYPE uint16_t
46#define DATA_STYPE int16_t
47#define SHIFT 1
48#elif DATA_SIZE == 1
49#define SUFFIX b
50#define USUFFIX ub
51#define DATA_TYPE uint8_t
52#define DATA_STYPE int8_t
53#define SHIFT 0
54#else
55#error unsupported data size
56#endif
57
58#if DATA_SIZE == 8
59#define RES_TYPE uint64_t
60#else
61#define RES_TYPE uint32_t
62#endif
63
64static inline RES_TYPE
65glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, abi_ptr ptr)
66{
67#ifdef CODE_ACCESS
68 RES_TYPE ret;
69 set_helper_retaddr(1);
70 ret = glue(glue(ld, USUFFIX), _p)(g2h(ptr));
71 clear_helper_retaddr();
72 return ret;
73#else
74 trace_guest_mem_before_exec(
75 env_cpu(env), ptr,
76 trace_mem_build_info(SHIFT, false, MO_TE, false));
77 return glue(glue(ld, USUFFIX), _p)(g2h(ptr));
78#endif
79}
80
81#ifndef CODE_ACCESS
82static inline RES_TYPE
83glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
84 abi_ptr ptr,
85 uintptr_t retaddr)
86{
87 RES_TYPE ret;
88 set_helper_retaddr(retaddr);
89 ret = glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(env, ptr);
90 clear_helper_retaddr();
91 return ret;
92}
93#endif
94
95#if DATA_SIZE <= 2
96static inline int
97glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, abi_ptr ptr)
98{
99#ifdef CODE_ACCESS
100 int ret;
101 set_helper_retaddr(1);
102 ret = glue(glue(lds, SUFFIX), _p)(g2h(ptr));
103 clear_helper_retaddr();
104 return ret;
105#else
106 trace_guest_mem_before_exec(
107 env_cpu(env), ptr,
108 trace_mem_build_info(SHIFT, true, MO_TE, false));
109 return glue(glue(lds, SUFFIX), _p)(g2h(ptr));
110#endif
111}
112
113#ifndef CODE_ACCESS
114static inline int
115glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
116 abi_ptr ptr,
117 uintptr_t retaddr)
118{
119 int ret;
120 set_helper_retaddr(retaddr);
121 ret = glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(env, ptr);
122 clear_helper_retaddr();
123 return ret;
124}
125#endif /* CODE_ACCESS */
126#endif /* DATA_SIZE <= 2 */
127
128#ifndef CODE_ACCESS
129static inline void
130glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, abi_ptr ptr,
131 RES_TYPE v)
132{
133 trace_guest_mem_before_exec(
134 env_cpu(env), ptr,
135 trace_mem_build_info(SHIFT, false, MO_TE, true));
136 glue(glue(st, SUFFIX), _p)(g2h(ptr), v);
137}
138
139static inline void
140glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
141 abi_ptr ptr,
142 RES_TYPE v,
143 uintptr_t retaddr)
144{
145 set_helper_retaddr(retaddr);
146 glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(env, ptr, v);
147 clear_helper_retaddr();
148}
149#endif
150
151#undef RES_TYPE
152#undef DATA_TYPE
153#undef DATA_STYPE
154#undef SUFFIX
155#undef USUFFIX
156#undef DATA_SIZE
157#undef SHIFT
158