master
h 219 lines 6.76 KB
Raw
1 /*
2 * Constants for memory operations
3 *
4 * Authors:
5 * Richard Henderson <rth@twiddle.net>
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
9 *
10 */
11
12 #ifndef MEMOP_H
13 #define MEMOP_H
14
15 #include "qemu/host-utils.h"
16
17 typedef enum MemOp {
18 MO_8 = 0,
19 MO_16 = 1,
20 MO_32 = 2,
21 MO_64 = 3,
22 MO_128 = 4,
23 MO_256 = 5,
24 MO_512 = 6,
25 MO_1024 = 7,
26 MO_SIZE = 0x07, /* Mask for the above. */
27
28 MO_SIGN = 0x08, /* Sign-extended, otherwise zero-extended. */
29
30 MO_BSWAP = 0x10, /* Host reverse endian. */
31 #if HOST_BIG_ENDIAN
32 MO_LE = MO_BSWAP,
33 MO_BE = 0,
34 #else
35 MO_LE = 0,
36 MO_BE = MO_BSWAP,
37 #endif
38 #ifdef COMPILING_PER_TARGET
39 #ifndef TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API
40 #if TARGET_BIG_ENDIAN
41 MO_TE = MO_BE,
42 #else
43 MO_TE = MO_LE,
44 #endif
45 #endif
46 #endif
47
48 /*
49 * MO_UNALN accesses are never checked for alignment.
50 * MO_ALIGN accesses will result in a call to the CPU's
51 * do_unaligned_access hook if the guest address is not aligned.
52 *
53 * Some architectures (e.g. ARMv8) need the address which is aligned
54 * to a size more than the size of the memory access.
55 * Some architectures (e.g. SPARCv9) need an address which is aligned,
56 * but less strictly than the natural alignment.
57 *
58 * MO_ALIGN supposes the alignment size is the size of a memory access.
59 *
60 * There are three options:
61 * - unaligned access permitted (MO_UNALN).
62 * - an alignment to the size of an access (MO_ALIGN);
63 * - an alignment to a specified size, which may be more or less than
64 * the access size (MO_ALIGN_x where 'x' is a size in bytes);
65 */
66 MO_ASHIFT = 5,
67 MO_AMASK = 0x7 << MO_ASHIFT,
68 MO_UNALN = 0,
69 MO_ALIGN_2 = 1 << MO_ASHIFT,
70 MO_ALIGN_4 = 2 << MO_ASHIFT,
71 MO_ALIGN_8 = 3 << MO_ASHIFT,
72 MO_ALIGN_16 = 4 << MO_ASHIFT,
73 MO_ALIGN_32 = 5 << MO_ASHIFT,
74 MO_ALIGN_64 = 6 << MO_ASHIFT,
75 MO_ALIGN = MO_AMASK,
76
77 /*
78 * MO_ALIGN_TLB_ONLY:
79 * Apply MO_AMASK only along the TCG slow path if TLB_CHECK_ALIGNED
80 * is set; otherwise unaligned access is permitted.
81 * This is used by target/arm, where unaligned accesses are
82 * permitted for pages marked Normal but aligned accesses are
83 * required for pages marked Device.
84 */
85 MO_ALIGN_TLB_ONLY = 1 << 8,
86
87 /*
88 * MO_ATOM_* describes the atomicity requirements of the operation:
89 * MO_ATOM_IFALIGN: the operation must be single-copy atomic if it
90 * is aligned; if unaligned there is no atomicity.
91 * MO_ATOM_IFALIGN_PAIR: the entire operation may be considered to
92 * be a pair of half-sized operations which are packed together
93 * for convenience, with single-copy atomicity on each half if
94 * the half is aligned.
95 * This is the atomicity e.g. of Arm pre-FEAT_LSE2 LDP.
96 * MO_ATOM_WITHIN16: the operation is single-copy atomic, even if it
97 * is unaligned, so long as it does not cross a 16-byte boundary;
98 * if it crosses a 16-byte boundary there is no atomicity.
99 * This is the atomicity e.g. of Arm FEAT_LSE2 LDR.
100 * MO_ATOM_WITHIN16_PAIR: the entire operation is single-copy atomic,
101 * if it happens to be within a 16-byte boundary, otherwise it
102 * devolves to a pair of half-sized MO_ATOM_WITHIN16 operations.
103 * Depending on alignment, one or both will be single-copy atomic.
104 * This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
105 * MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
106 * by the alignment. E.g. if an 8-byte value is accessed at an
107 * address which is 0 mod 8, then the whole 8-byte access is
108 * single-copy atomic; otherwise, if it is accessed at 0 mod 4
109 * then each 4-byte subobject is single-copy atomic; otherwise
110 * if it is accessed at 0 mod 2 then the four 2-byte subobjects
111 * are single-copy atomic.
112 * This is the atomicity e.g. of IBM Power.
113 * MO_ATOM_NONE: the operation has no atomicity requirements.
114 *
115 * Note the default (i.e. 0) value is single-copy atomic to the
116 * size of the operation, if aligned. This retains the behaviour
117 * from before this field was introduced.
118 */
119 MO_ATOM_SHIFT = 9,
120 MO_ATOM_IFALIGN = 0 << MO_ATOM_SHIFT,
121 MO_ATOM_IFALIGN_PAIR = 1 << MO_ATOM_SHIFT,
122 MO_ATOM_WITHIN16 = 2 << MO_ATOM_SHIFT,
123 MO_ATOM_WITHIN16_PAIR = 3 << MO_ATOM_SHIFT,
124 MO_ATOM_SUBALIGN = 4 << MO_ATOM_SHIFT,
125 MO_ATOM_NONE = 5 << MO_ATOM_SHIFT,
126 MO_ATOM_MASK = 7 << MO_ATOM_SHIFT,
127
128 /* Combinations of the above, for ease of use. */
129 MO_UB = MO_8,
130 MO_UW = MO_16,
131 MO_UL = MO_32,
132 MO_UQ = MO_64,
133 MO_UO = MO_128,
134 MO_SB = MO_SIGN | MO_8,
135 MO_SW = MO_SIGN | MO_16,
136 MO_SL = MO_SIGN | MO_32,
137 MO_SQ = MO_SIGN | MO_64,
138 MO_SO = MO_SIGN | MO_128,
139
140 MO_LEUW = MO_LE | MO_UW,
141 MO_LEUL = MO_LE | MO_UL,
142 MO_LEUQ = MO_LE | MO_UQ,
143 MO_LESW = MO_LE | MO_SW,
144 MO_LESL = MO_LE | MO_SL,
145 MO_LESQ = MO_LE | MO_SQ,
146
147 MO_BEUW = MO_BE | MO_UW,
148 MO_BEUL = MO_BE | MO_UL,
149 MO_BEUQ = MO_BE | MO_UQ,
150 MO_BESW = MO_BE | MO_SW,
151 MO_BESL = MO_BE | MO_SL,
152 MO_BESQ = MO_BE | MO_SQ,
153
154 #ifdef COMPILING_PER_TARGET
155 #ifndef TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API
156 MO_TEUW = MO_TE | MO_UW,
157 MO_TEUL = MO_TE | MO_UL,
158 MO_TEUQ = MO_TE | MO_UQ,
159 MO_TEUO = MO_TE | MO_UO,
160 MO_TESW = MO_TE | MO_SW,
161 MO_TESL = MO_TE | MO_SL,
162 MO_TESQ = MO_TE | MO_SQ,
163 #endif
164 #endif
165
166 MO_SSIZE = MO_SIZE | MO_SIGN,
167 } MemOp;
168
169 /* MemOp to size in bytes. */
170 static inline unsigned memop_size(MemOp op)
171 {
172 return 1 << (op & MO_SIZE);
173 }
174
175 /* Size in bytes to MemOp. */
176 static inline MemOp size_memop(unsigned size)
177 {
178 #ifdef CONFIG_DEBUG_TCG
179 /* Power of 2 up to 1024 */
180 assert(is_power_of_2(size) && size >= 1 && size <= (1 << MO_SIZE));
181 #endif
182 return (MemOp)ctz32(size);
183 }
184
185 /**
186 * memop_tlb_alignment_bits:
187 * @memop: MemOp value
188 *
189 * Extract the alignment size for use with TLB_CHECK_ALIGNED.
190 */
191 static inline unsigned memop_tlb_alignment_bits(MemOp memop, bool tlb_check)
192 {
193 unsigned a = memop & MO_AMASK;
194
195 if (a == MO_UNALN || (!tlb_check && (memop & MO_ALIGN_TLB_ONLY))) {
196 /* No alignment required. */
197 a = 0;
198 } else if (a == MO_ALIGN) {
199 /* A natural alignment requirement. */
200 a = memop & MO_SIZE;
201 } else {
202 /* A specific alignment requirement. */
203 a = a >> MO_ASHIFT;
204 }
205 return a;
206 }
207
208 /**
209 * memop_alignment_bits:
210 * @memop: MemOp value
211 *
212 * Extract the alignment size from the memop.
213 */
214 static inline unsigned memop_alignment_bits(MemOp memop)
215 {
216 return memop_tlb_alignment_bits(memop, false);
217 }
218
219 #endif