-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitops.c
145 lines (123 loc) · 4.83 KB
/
bitops.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#ifndef bitops_c_included
#define bitops_c_included
#include <linux/kernel.h>
#include "bitops.h"
uint8_t u8ReadBits (uint8_t source, int bitStart, int bitEnd)
{
if (bitStart > bitEnd || bitStart < 0 || bitStart > 7 ||
bitEnd < 0 || bitEnd > 7)
{
printk ("%s(): invalid bitStart and/or bitEnd: %d -> %d\n",
__FUNCTION__, bitStart, bitEnd);
return source;
}
return (source & (0x00ff >> (7 - bitEnd))) >> bitStart;
}
uint8_t u8ReadBit (uint8_t source, int bitnum)
{
if (bitnum > 7 || bitnum < 0) {
printk ("%s(): invalid bitnum: %d\n", __FUNCTION__, bitnum);
return source;
}
return u8ReadBits(source, bitnum, bitnum);
}
uint8_t u8WriteBits (uint8_t source, int bitStart, int bitEnd, uint8_t value)
{
uint8_t top, middle, bottom;
if (bitStart > bitEnd || bitStart < 0 || bitStart > 7 ||
bitEnd < 0 || bitEnd > 7)
{
printk ("%s(): invalid bitStart and/or bitEnd: %d -> %d\n",
__FUNCTION__, bitStart, bitEnd);
return source;
}
/* power == bitEnd - bitStart, 0x00ff >> (7 - (bitEnd - bitStart)) */
if (value > (0x00ff >> (7 - (bitEnd - bitStart)))) {
printk ("%s(): value (0x%x) too big for range (%d -> %d)\n",
__FUNCTION__, value, bitStart, bitEnd);
return source;
}
/* ex: u8WriteBits (source = ssss ssss,
* bitStart = 2,
* bitEnd = 5,
* value = vvvv)
* ssss ssss == source
* vvvv == value
* ssvv vvss == result
*
* ss00 0000 == top
* 00vv vv00 == middle
* 0000 00ss == bottom
*/
top = (source & (0x00ff << (bitEnd + 1))) & 0x00ff;
middle = value << bitStart;
bottom = source & (0x00ff >> (7 - bitStart + 1));
return top | middle | bottom;
}
uint8_t u8WriteBit (uint8_t source, int bitnum, int value)
{
if (bitnum > 7 || bitnum < 0 || value > 1 || value < 0) {
printk ("%s(): invalid bitnum and/or value: %d %d\n",
__FUNCTION__, bitnum, value);
return source;
}
return u8WriteBits(source, bitnum, bitnum, value);
}
uint32_t u32ReadBits (uint32_t source, int bitStart, int bitEnd)
{
if (bitStart > bitEnd || bitStart < 0 || bitStart > 31 ||
bitEnd < 0 || bitEnd > 31)
{
printk ("%s(): invalid bitStart and/or bitEnd: %d -> %d\n",
__FUNCTION__, bitStart, bitEnd);
return source;
}
return (source & (0xffffffff >> (31 - bitEnd))) >> bitStart;
}
uint32_t u32ReadBit (uint32_t source, int bitnum)
{
if (bitnum > 31 || bitnum < 0) {
printk ("%s(): invalid bitnum %d\n", __FUNCTION__, bitnum);
return source;
}
return u32ReadBits(source, bitnum, bitnum);
}
uint32_t u32WriteBits (uint32_t source, int bitStart, int bitEnd,
uint32_t value)
{
uint32_t top, middle, bottom;
if (bitStart > bitEnd ||
bitStart < 0 ||
bitStart > 31 ||
bitEnd < 0 ||
bitEnd > 31)
{
printk ("%s(): invalid bitStart and/or bitEnd: %d -> %d\n",
__FUNCTION__, bitStart, bitEnd);
return source;
}
/* power = bitEnd - bitStart, 0xffffffff >> (31 - (bitEnd - bitStart)) */
if (value > (0xffffffff >> (31 - (bitEnd - bitStart)))) {
printk ("%s(): value (0x%x) too big for range (%d -> %d)\n",
__FUNCTION__, value, bitStart, bitEnd);
return source;
}
/* ex: u32WriteBits (source = ssss ssss ssss ssss ssss ssss ssss ssss,
* bitStart = 17,
* bitEnd = 26,
* value = vv vvvv vvvv)
*
* ssss ssss ssss ssss ssss ssss ssss ssss
* vv vvvv vvvv
* ssss svvv vvvv vvvs ssss ssss ssss ssss
*
* ssss s000 0000 0000 0000 0000 0000 0000 top
* 0000 0vvv vvvv vvv0 0000 0000 0000 0000 middle
* 0000 0000 0000 000s ssss ssss ssss ssss
*/
top = (source & (0xffffffff << (bitEnd + 1))) & 0xffffffff;
middle = value << bitStart;
bottom = source & (0xffffffff >> (31 - bitStart + 1));
return top | middle | bottom;
}
#endif /* bitops_c_included */