xref: /illumos-gate/usr/src/common/bitext/bitext.c (revision 71815ce7)
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