1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2022 Oxide Computer Company
14 */
15
16 /*
17 * Various functions for manipulating regions of bits in standard sized
18 * integers. Meant to be a replacement for the extant BITX macro and provide
19 * additional functionality. See bitx64(9F), bitdel64(9F), and bitset64(9f) for
20 * more information.
21 */
22
23 #include <sys/debug.h>
24 #include <sys/stdint.h>
25
26 uint8_t
bitx8(uint8_t reg,uint_t high,uint_t low)27 bitx8(uint8_t reg, uint_t high, uint_t low)
28 {
29 uint8_t mask;
30
31 ASSERT3U(high, >=, low);
32 ASSERT3U(high, <, 8);
33 ASSERT3U(low, <, 8);
34
35 mask = (1 << (high - low + 1)) - 1;
36 return ((reg >> low) & mask);
37 }
38
39 uint16_t
bitx16(uint16_t reg,uint_t high,uint_t low)40 bitx16(uint16_t reg, uint_t high, uint_t low)
41 {
42 uint16_t mask;
43
44 ASSERT3U(high, >=, low);
45 ASSERT3U(high, <, 16);
46 ASSERT3U(low, <, 16);
47
48 mask = (1 << (high - low + 1)) - 1;
49 return ((reg >> low) & mask);
50 }
51
52
53 uint32_t
bitx32(uint32_t reg,uint_t high,uint_t low)54 bitx32(uint32_t reg, uint_t high, uint_t low)
55 {
56 uint32_t mask;
57
58 ASSERT3U(high, >=, low);
59 ASSERT3U(high, <, 32);
60 ASSERT3U(low, <, 32);
61
62 mask = (1UL << (high - low + 1)) - 1;
63
64 return ((reg >> low) & mask);
65 }
66
67 uint64_t
bitx64(uint64_t reg,uint_t high,uint_t low)68 bitx64(uint64_t reg, uint_t high, uint_t low)
69 {
70 uint64_t mask;
71
72 ASSERT3U(high, >=, low);
73 ASSERT3U(high, <, 64);
74 ASSERT3U(low, <, 64);
75
76 mask = (1ULL << (high - low + 1)) - 1ULL;
77 return ((reg >> low) & mask);
78 }
79
80 uint8_t
bitset8(uint8_t reg,uint_t high,uint_t low,uint8_t val)81 bitset8(uint8_t reg, uint_t high, uint_t low, uint8_t val)
82 {
83 uint8_t mask;
84
85 ASSERT3U(high, >=, low);
86 ASSERT3U(high, <, 8);
87 ASSERT3U(low, <, 8);
88
89 mask = (1 << (high - low + 1)) - 1;
90 ASSERT0(~mask & val);
91
92 reg &= ~(mask << low);
93 reg |= val << low;
94
95 return (reg);
96 }
97
98 uint16_t
bitset16(uint16_t reg,uint_t high,uint_t low,uint16_t val)99 bitset16(uint16_t reg, uint_t high, uint_t low, uint16_t val)
100 {
101 uint16_t mask;
102
103 ASSERT3U(high, >=, low);
104 ASSERT3U(high, <, 16);
105 ASSERT3U(low, <, 16);
106
107 mask = (1 << (high - low + 1)) - 1;
108 ASSERT0(~mask & val);
109
110 reg &= ~(mask << low);
111 reg |= val << low;
112
113 return (reg);
114 }
115
116 uint32_t
bitset32(uint32_t reg,uint_t high,uint_t low,uint32_t val)117 bitset32(uint32_t reg, uint_t high, uint_t low, uint32_t val)
118 {
119 uint32_t mask;
120
121 ASSERT3U(high, >=, low);
122 ASSERT3U(high, <, 32);
123 ASSERT3U(low, <, 32);
124
125 mask = (1UL << (high - low + 1)) - 1;
126 ASSERT0(~mask & val);
127
128 reg &= ~(mask << low);
129 reg |= val << low;
130
131 return (reg);
132 }
133
134 uint64_t
bitset64(uint64_t reg,uint_t high,uint_t low,uint64_t val)135 bitset64(uint64_t reg, uint_t high, uint_t low, uint64_t val)
136 {
137 uint64_t mask;
138
139 ASSERT3U(high, >=, low);
140 ASSERT3U(high, <, 64);
141 ASSERT3U(low, <, 64);
142
143 mask = (1ULL << (high - low + 1)) - 1ULL;
144 ASSERT0(~mask & val);
145
146 reg &= ~(mask << low);
147 reg |= val << low;
148
149 return (reg);
150 }
151
152 uint64_t
bitdel64(uint64_t val,uint_t high,uint_t low)153 bitdel64(uint64_t val, uint_t high, uint_t low)
154 {
155 uint64_t high_val = 0;
156 uint64_t low_val = 0;
157
158 ASSERT3U(high, >=, low);
159 ASSERT3U(high, <, 64);
160 ASSERT3U(low, <, 64);
161
162 if (low != 0) {
163 low_val = bitx64(val, low - 1, 0);
164 }
165
166 if (high != 63) {
167 high_val = bitx64(val, 63, high + 1);
168 }
169
170 return ((high_val << low) | low_val);
171 }
172