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 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 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 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 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 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 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 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 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 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