xref: /openbmc/qemu/include/exec/memop.h (revision 344b4a82)
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 #ifdef HOST_WORDS_BIGENDIAN
32     MO_LE    = MO_BSWAP,
33     MO_BE    = 0,
34 #else
35     MO_LE    = 0,
36     MO_BE    = MO_BSWAP,
37 #endif
38 #ifdef NEED_CPU_H
39 #ifdef TARGET_WORDS_BIGENDIAN
40     MO_TE    = MO_BE,
41 #else
42     MO_TE    = MO_LE,
43 #endif
44 #endif
45 
46     /*
47      * MO_UNALN accesses are never checked for alignment.
48      * MO_ALIGN accesses will result in a call to the CPU's
49      * do_unaligned_access hook if the guest address is not aligned.
50      * The default depends on whether the target CPU defines
51      * TARGET_ALIGNED_ONLY.
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 #ifdef NEED_CPU_H
69 #ifdef TARGET_ALIGNED_ONLY
70     MO_ALIGN = 0,
71     MO_UNALN = MO_AMASK,
72 #else
73     MO_ALIGN = MO_AMASK,
74     MO_UNALN = 0,
75 #endif
76 #endif
77     MO_ALIGN_2  = 1 << MO_ASHIFT,
78     MO_ALIGN_4  = 2 << MO_ASHIFT,
79     MO_ALIGN_8  = 3 << MO_ASHIFT,
80     MO_ALIGN_16 = 4 << MO_ASHIFT,
81     MO_ALIGN_32 = 5 << MO_ASHIFT,
82     MO_ALIGN_64 = 6 << MO_ASHIFT,
83 
84     /* Combinations of the above, for ease of use.  */
85     MO_UB    = MO_8,
86     MO_UW    = MO_16,
87     MO_UL    = MO_32,
88     MO_UQ    = MO_64,
89     MO_UO    = MO_128,
90     MO_SB    = MO_SIGN | MO_8,
91     MO_SW    = MO_SIGN | MO_16,
92     MO_SL    = MO_SIGN | MO_32,
93     MO_SQ    = MO_SIGN | MO_64,
94     MO_SO    = MO_SIGN | MO_128,
95 
96     MO_LEUW  = MO_LE | MO_UW,
97     MO_LEUL  = MO_LE | MO_UL,
98     MO_LEUQ  = MO_LE | MO_UQ,
99     MO_LESW  = MO_LE | MO_SW,
100     MO_LESL  = MO_LE | MO_SL,
101     MO_LESQ  = MO_LE | MO_SQ,
102 
103     MO_BEUW  = MO_BE | MO_UW,
104     MO_BEUL  = MO_BE | MO_UL,
105     MO_BEUQ  = MO_BE | MO_UQ,
106     MO_BESW  = MO_BE | MO_SW,
107     MO_BESL  = MO_BE | MO_SL,
108     MO_BESQ  = MO_BE | MO_SQ,
109 
110 #ifdef NEED_CPU_H
111     MO_TEUW  = MO_TE | MO_UW,
112     MO_TEUL  = MO_TE | MO_UL,
113     MO_TEUQ  = MO_TE | MO_UQ,
114     MO_TEUO  = MO_TE | MO_UO,
115     MO_TESW  = MO_TE | MO_SW,
116     MO_TESL  = MO_TE | MO_SL,
117     MO_TESQ  = MO_TE | MO_SQ,
118 #endif
119 
120     MO_SSIZE = MO_SIZE | MO_SIGN,
121 } MemOp;
122 
123 /* MemOp to size in bytes.  */
124 static inline unsigned memop_size(MemOp op)
125 {
126     return 1 << (op & MO_SIZE);
127 }
128 
129 /* Size in bytes to MemOp.  */
130 static inline MemOp size_memop(unsigned size)
131 {
132 #ifdef CONFIG_DEBUG_TCG
133     /* Power of 2 up to 8.  */
134     assert((size & (size - 1)) == 0 && size >= 1 && size <= 8);
135 #endif
136     return ctz32(size);
137 }
138 
139 /* Big endianness from MemOp.  */
140 static inline bool memop_big_endian(MemOp op)
141 {
142     return (op & MO_BSWAP) == MO_BE;
143 }
144 
145 #endif
146