xref: /qemu/include/hw/registerfields.h (revision 8f9abdf5)
1 /*
2  * Register Definition API: field macros
3  *
4  * Copyright (c) 2016 Xilinx Inc.
5  * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
6  *
7  * This work is licensed under the terms of the GNU GPL, version 2.  See
8  * the COPYING file in the top-level directory.
9  */
10 
11 #ifndef REGISTERFIELDS_H
12 #define REGISTERFIELDS_H
13 
14 #include "qemu/bitops.h"
15 
16 /* Define constants for a 32 bit register */
17 
18 /* This macro will define A_FOO, for the byte address of a register
19  * as well as R_FOO for the uint32_t[] register number (A_FOO / 4).
20  */
21 #define REG32(reg, addr)                                                  \
22     enum { A_ ## reg = (addr) };                                          \
23     enum { R_ ## reg = (addr) / 4 };
24 
25 #define REG8(reg, addr)                                                   \
26     enum { A_ ## reg = (addr) };                                          \
27     enum { R_ ## reg = (addr) };
28 
29 #define REG16(reg, addr)                                                  \
30     enum { A_ ## reg = (addr) };                                          \
31     enum { R_ ## reg = (addr) / 2 };
32 
33 #define REG64(reg, addr)                                                  \
34     enum { A_ ## reg = (addr) };                                          \
35     enum { R_ ## reg = (addr) / 8 };
36 
37 /* Define SHIFT, LENGTH and MASK constants for a field within a register */
38 
39 /* This macro will define R_FOO_BAR_MASK, R_FOO_BAR_SHIFT and R_FOO_BAR_LENGTH
40  * constants for field BAR in register FOO.
41  */
42 #define FIELD(reg, field, shift, length)                                  \
43     enum { R_ ## reg ## _ ## field ## _SHIFT = (shift)};                  \
44     enum { R_ ## reg ## _ ## field ## _LENGTH = (length)};                \
45     enum { R_ ## reg ## _ ## field ## _MASK =                             \
46                                         MAKE_64BIT_MASK(shift, length)};
47 
48 /* Extract a field from a register */
49 #define FIELD_EX8(storage, reg, field)                                    \
50     extract8((storage), R_ ## reg ## _ ## field ## _SHIFT,                \
51               R_ ## reg ## _ ## field ## _LENGTH)
52 #define FIELD_EX16(storage, reg, field)                                   \
53     extract16((storage), R_ ## reg ## _ ## field ## _SHIFT,               \
54               R_ ## reg ## _ ## field ## _LENGTH)
55 #define FIELD_EX32(storage, reg, field)                                   \
56     extract32((storage), R_ ## reg ## _ ## field ## _SHIFT,               \
57               R_ ## reg ## _ ## field ## _LENGTH)
58 #define FIELD_EX64(storage, reg, field)                                   \
59     extract64((storage), R_ ## reg ## _ ## field ## _SHIFT,               \
60               R_ ## reg ## _ ## field ## _LENGTH)
61 
62 #define FIELD_SEX8(storage, reg, field)                                   \
63     sextract8((storage), R_ ## reg ## _ ## field ## _SHIFT,               \
64               R_ ## reg ## _ ## field ## _LENGTH)
65 #define FIELD_SEX16(storage, reg, field)                                  \
66     sextract16((storage), R_ ## reg ## _ ## field ## _SHIFT,              \
67                R_ ## reg ## _ ## field ## _LENGTH)
68 #define FIELD_SEX32(storage, reg, field)                                  \
69     sextract32((storage), R_ ## reg ## _ ## field ## _SHIFT,              \
70                R_ ## reg ## _ ## field ## _LENGTH)
71 #define FIELD_SEX64(storage, reg, field)                                  \
72     sextract64((storage), R_ ## reg ## _ ## field ## _SHIFT,              \
73                R_ ## reg ## _ ## field ## _LENGTH)
74 
75 /* Extract a field from an array of registers */
76 #define ARRAY_FIELD_EX32(regs, reg, field)                                \
77     FIELD_EX32((regs)[R_ ## reg], reg, field)
78 #define ARRAY_FIELD_EX64(regs, reg, field)                                \
79     FIELD_EX64((regs)[R_ ## reg], reg, field)
80 
81 /* Deposit a register field.
82  * Assigning values larger then the target field will result in
83  * compilation warnings.
84  */
85 #define FIELD_DP8(storage, reg, field, val) ({                            \
86     struct {                                                              \
87         unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;                \
88     } _v = { .v = val };                                                  \
89     uint8_t _d;                                                           \
90     _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,          \
91                   R_ ## reg ## _ ## field ## _LENGTH, _v.v);              \
92     _d; })
93 #define FIELD_DP16(storage, reg, field, val) ({                           \
94     struct {                                                              \
95         unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;                \
96     } _v = { .v = val };                                                  \
97     uint16_t _d;                                                          \
98     _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,          \
99                   R_ ## reg ## _ ## field ## _LENGTH, _v.v);              \
100     _d; })
101 #define FIELD_DP32(storage, reg, field, val) ({                           \
102     struct {                                                              \
103         unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;                \
104     } _v = { .v = val };                                                  \
105     uint32_t _d;                                                          \
106     _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,          \
107                   R_ ## reg ## _ ## field ## _LENGTH, _v.v);              \
108     _d; })
109 #define FIELD_DP64(storage, reg, field, val) ({                           \
110     struct {                                                              \
111         uint64_t v:R_ ## reg ## _ ## field ## _LENGTH;                    \
112     } _v = { .v = val };                                                  \
113     uint64_t _d;                                                          \
114     _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT,          \
115                   R_ ## reg ## _ ## field ## _LENGTH, _v.v);              \
116     _d; })
117 
118 #define FIELD_SDP8(storage, reg, field, val) ({                           \
119     struct {                                                              \
120         signed int v:R_ ## reg ## _ ## field ## _LENGTH;                  \
121     } _v = { .v = val };                                                  \
122     uint8_t _d;                                                           \
123     _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,          \
124                   R_ ## reg ## _ ## field ## _LENGTH, _v.v);              \
125     _d; })
126 #define FIELD_SDP16(storage, reg, field, val) ({                          \
127     struct {                                                              \
128         signed int v:R_ ## reg ## _ ## field ## _LENGTH;                  \
129     } _v = { .v = val };                                                  \
130     uint16_t _d;                                                          \
131     _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,          \
132                   R_ ## reg ## _ ## field ## _LENGTH, _v.v);              \
133     _d; })
134 #define FIELD_SDP32(storage, reg, field, val) ({                          \
135     struct {                                                              \
136         signed int v:R_ ## reg ## _ ## field ## _LENGTH;                  \
137     } _v = { .v = val };                                                  \
138     uint32_t _d;                                                          \
139     _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,          \
140                   R_ ## reg ## _ ## field ## _LENGTH, _v.v);              \
141     _d; })
142 #define FIELD_SDP64(storage, reg, field, val) ({                          \
143     struct {                                                              \
144         int64_t v:R_ ## reg ## _ ## field ## _LENGTH;                     \
145     } _v = { .v = val };                                                  \
146     uint64_t _d;                                                          \
147     _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT,          \
148                   R_ ## reg ## _ ## field ## _LENGTH, _v.v);              \
149     _d; })
150 
151 /* Deposit a field to array of registers.  */
152 #define ARRAY_FIELD_DP32(regs, reg, field, val)                           \
153     (regs)[R_ ## reg] = FIELD_DP32((regs)[R_ ## reg], reg, field, val);
154 #define ARRAY_FIELD_DP64(regs, reg, field, val)                           \
155     (regs)[R_ ## reg] = FIELD_DP64((regs)[R_ ## reg], reg, field, val);
156 
157 
158 /*
159  * These macros can be used for defining and extracting fields that have the
160  * same bit position across multiple registers.
161  */
162 
163 /* Define shared SHIFT, LENGTH, and MASK constants */
164 #define SHARED_FIELD(name, shift, length)   \
165     enum { name ## _ ## SHIFT = (shift)};   \
166     enum { name ## _ ## LENGTH = (length)}; \
167     enum { name ## _ ## MASK = MAKE_64BIT_MASK(shift, length)};
168 
169 /* Extract a shared field */
170 #define SHARED_FIELD_EX8(storage, field) \
171     extract8((storage), field ## _SHIFT, field ## _LENGTH)
172 
173 #define SHARED_FIELD_EX16(storage, field) \
174     extract16((storage), field ## _SHIFT, field ## _LENGTH)
175 
176 #define SHARED_FIELD_EX32(storage, field) \
177     extract32((storage), field ## _SHIFT, field ## _LENGTH)
178 
179 #define SHARED_FIELD_EX64(storage, field) \
180     extract64((storage), field ## _SHIFT, field ## _LENGTH)
181 
182 /* Extract a shared field from a register array */
183 #define SHARED_ARRAY_FIELD_EX32(regs, offset, field) \
184     SHARED_FIELD_EX32((regs)[(offset)], field)
185 #define SHARED_ARRAY_FIELD_EX64(regs, offset, field) \
186     SHARED_FIELD_EX64((regs)[(offset)], field)
187 
188 /* Deposit a shared field */
189 #define SHARED_FIELD_DP8(storage, field, val) ({                        \
190     struct {                                                            \
191         unsigned int v:field ## _LENGTH;                                \
192     } _v = { .v = val };                                                \
193     uint8_t _d;                                                         \
194     _d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
195     _d; })
196 
197 #define SHARED_FIELD_DP16(storage, field, val) ({                       \
198     struct {                                                            \
199         unsigned int v:field ## _LENGTH;                                \
200     } _v = { .v = val };                                                \
201     uint16_t _d;                                                        \
202     _d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
203     _d; })
204 
205 #define SHARED_FIELD_DP32(storage, field, val) ({                       \
206     struct {                                                            \
207         unsigned int v:field ## _LENGTH;                                \
208     } _v = { .v = val };                                                \
209     uint32_t _d;                                                        \
210     _d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
211     _d; })
212 
213 #define SHARED_FIELD_DP64(storage, field, val) ({                       \
214     struct {                                                            \
215         uint64_t v:field ## _LENGTH;                                    \
216     } _v = { .v = val };                                                \
217     uint64_t _d;                                                        \
218     _d = deposit64((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
219     _d; })
220 
221 /* Deposit a shared field to a register array */
222 #define SHARED_ARRAY_FIELD_DP32(regs, offset, field, val) \
223     (regs)[(offset)] = SHARED_FIELD_DP32((regs)[(offset)], field, val);
224 #define SHARED_ARRAY_FIELD_DP64(regs, offset, field, val) \
225     (regs)[(offset)] = SHARED_FIELD_DP64((regs)[(offset)], field, val);
226 
227 #endif
228