1package volatile
2
3// This file defines Register{8,16,32,64} types, which are convenience types for
4// volatile register accesses.
5
6// Special types that causes loads/stores to be volatile (necessary for
7// memory-mapped registers).
8type Register8 struct {
9	Reg uint8
10}
11
12// Get returns the value in the register. It is the volatile equivalent of:
13//
14//     *r.Reg
15//
16//go:inline
17func (r *Register8) Get() uint8 {
18	return LoadUint8(&r.Reg)
19}
20
21// Set updates the register value. It is the volatile equivalent of:
22//
23//     *r.Reg = value
24//
25//go:inline
26func (r *Register8) Set(value uint8) {
27	StoreUint8(&r.Reg, value)
28}
29
30// SetBits reads the register, sets the given bits, and writes it back. It is
31// the volatile equivalent of:
32//
33//     r.Reg |= value
34//
35//go:inline
36func (r *Register8) SetBits(value uint8) {
37	StoreUint8(&r.Reg, LoadUint8(&r.Reg)|value)
38}
39
40// ClearBits reads the register, clears the given bits, and writes it back. It
41// is the volatile equivalent of:
42//
43//     r.Reg &^= value
44//
45//go:inline
46func (r *Register8) ClearBits(value uint8) {
47	StoreUint8(&r.Reg, LoadUint8(&r.Reg)&^value)
48}
49
50// HasBits reads the register and then checks to see if the passed bits are set. It
51// is the volatile equivalent of:
52//
53//     (*r.Reg & value) > 0
54//
55//go:inline
56func (r *Register8) HasBits(value uint8) bool {
57	return (r.Get() & value) > 0
58}
59
60// ReplaceBits is a helper to simplify setting multiple bits high and/or low at
61// once. It is the volatile equivalent of:
62//
63//     r.Reg = (r.Reg & ^(mask << pos)) | value << pos
64//
65// go:inline
66func (r *Register8) ReplaceBits(value uint8, mask uint8, pos uint8) {
67	StoreUint8(&r.Reg, LoadUint8(&r.Reg)&^(mask<<pos)|value<<pos)
68}
69
70type Register16 struct {
71	Reg uint16
72}
73
74// Get returns the value in the register. It is the volatile equivalent of:
75//
76//     *r.Reg
77//
78//go:inline
79func (r *Register16) Get() uint16 {
80	return LoadUint16(&r.Reg)
81}
82
83// Set updates the register value. It is the volatile equivalent of:
84//
85//     *r.Reg = value
86//
87//go:inline
88func (r *Register16) Set(value uint16) {
89	StoreUint16(&r.Reg, value)
90}
91
92// SetBits reads the register, sets the given bits, and writes it back. It is
93// the volatile equivalent of:
94//
95//     r.Reg |= value
96//
97//go:inline
98func (r *Register16) SetBits(value uint16) {
99	StoreUint16(&r.Reg, LoadUint16(&r.Reg)|value)
100}
101
102// ClearBits reads the register, clears the given bits, and writes it back. It
103// is the volatile equivalent of:
104//
105//     r.Reg &^= value
106//
107//go:inline
108func (r *Register16) ClearBits(value uint16) {
109	StoreUint16(&r.Reg, LoadUint16(&r.Reg)&^value)
110}
111
112// HasBits reads the register and then checks to see if the passed bits are set. It
113// is the volatile equivalent of:
114//
115//     (*r.Reg & value) > 0
116//
117//go:inline
118func (r *Register16) HasBits(value uint16) bool {
119	return (r.Get() & value) > 0
120}
121
122// ReplaceBits is a helper to simplify setting multiple bits high and/or low at
123// once. It is the volatile equivalent of:
124//
125//     r.Reg = (r.Reg & ^(mask << pos)) | value << pos
126//
127// go:inline
128func (r *Register16) ReplaceBits(value uint16, mask uint16, pos uint8) {
129	StoreUint16(&r.Reg, LoadUint16(&r.Reg)&^(mask<<pos)|value<<pos)
130}
131
132type Register32 struct {
133	Reg uint32
134}
135
136// Get returns the value in the register. It is the volatile equivalent of:
137//
138//     *r.Reg
139//
140//go:inline
141func (r *Register32) Get() uint32 {
142	return LoadUint32(&r.Reg)
143}
144
145// Set updates the register value. It is the volatile equivalent of:
146//
147//     *r.Reg = value
148//
149//go:inline
150func (r *Register32) Set(value uint32) {
151	StoreUint32(&r.Reg, value)
152}
153
154// SetBits reads the register, sets the given bits, and writes it back. It is
155// the volatile equivalent of:
156//
157//     r.Reg |= value
158//
159//go:inline
160func (r *Register32) SetBits(value uint32) {
161	StoreUint32(&r.Reg, LoadUint32(&r.Reg)|value)
162}
163
164// ClearBits reads the register, clears the given bits, and writes it back. It
165// is the volatile equivalent of:
166//
167//     r.Reg &^= value
168//
169//go:inline
170func (r *Register32) ClearBits(value uint32) {
171	StoreUint32(&r.Reg, LoadUint32(&r.Reg)&^value)
172}
173
174// HasBits reads the register and then checks to see if the passed bits are set. It
175// is the volatile equivalent of:
176//
177//     (*r.Reg & value) > 0
178//
179//go:inline
180func (r *Register32) HasBits(value uint32) bool {
181	return (r.Get() & value) > 0
182}
183
184// ReplaceBits is a helper to simplify setting multiple bits high and/or low at
185// once. It is the volatile equivalent of:
186//
187//     r.Reg = (r.Reg & ^(mask << pos)) | value << pos
188//
189// go:inline
190func (r *Register32) ReplaceBits(value uint32, mask uint32, pos uint8) {
191	StoreUint32(&r.Reg, LoadUint32(&r.Reg)&^(mask<<pos)|value<<pos)
192}
193
194type Register64 struct {
195	Reg uint64
196}
197
198// Get returns the value in the register. It is the volatile equivalent of:
199//
200//     *r.Reg
201//
202//go:inline
203func (r *Register64) Get() uint64 {
204	return LoadUint64(&r.Reg)
205}
206
207// Set updates the register value. It is the volatile equivalent of:
208//
209//     *r.Reg = value
210//
211//go:inline
212func (r *Register64) Set(value uint64) {
213	StoreUint64(&r.Reg, value)
214}
215
216// SetBits reads the register, sets the given bits, and writes it back. It is
217// the volatile equivalent of:
218//
219//     r.Reg |= value
220//
221//go:inline
222func (r *Register64) SetBits(value uint64) {
223	StoreUint64(&r.Reg, LoadUint64(&r.Reg)|value)
224}
225
226// ClearBits reads the register, clears the given bits, and writes it back. It
227// is the volatile equivalent of:
228//
229//     r.Reg &^= value
230//
231//go:inline
232func (r *Register64) ClearBits(value uint64) {
233	StoreUint64(&r.Reg, LoadUint64(&r.Reg)&^value)
234}
235
236// HasBits reads the register and then checks to see if the passed bits are set. It
237// is the volatile equivalent of:
238//
239//     (*r.Reg & value) > 0
240//
241//go:inline
242func (r *Register64) HasBits(value uint64) bool {
243	return (r.Get() & value) > 0
244}
245
246// ReplaceBits is a helper to simplify setting multiple bits high and/or low at
247// once. It is the volatile equivalent of:
248//
249//     r.Reg = (r.Reg & ^(mask << pos)) | value << pos
250//
251// go:inline
252func (r *Register64) ReplaceBits(value uint64, mask uint64, pos uint8) {
253	StoreUint64(&r.Reg, LoadUint64(&r.Reg)&^(mask<<pos)|value<<pos)
254}
255