]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of version 2 of the GNU General Public License as | |
6 | * published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it would be useful, but | |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
11 | * | |
12 | * Further, this software is distributed without any warranty that it is | |
13 | * free of the rightful claim of any third person regarding infringement | |
14 | * or the like. Any license provided herein, whether implied or | |
15 | * otherwise, applies only to this software file. Patent licenses, if | |
16 | * any, provided herein do not apply to combinations of this program with | |
17 | * other software, or any other product whatsoever. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License along | |
20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | |
21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
22 | * | |
23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | |
24 | * Mountain View, CA 94043, or: | |
25 | * | |
26 | * http://www.sgi.com | |
27 | * | |
28 | * For further information regarding this notice, see: | |
29 | * | |
30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | |
31 | */ | |
32 | ||
33 | #include <libxfs.h> | |
34 | #include "bit.h" | |
35 | ||
36 | #undef setbit /* defined in param.h on Linux */ | |
37 | ||
38 | static int getbit(char *ptr, int bit); | |
39 | static void setbit(char *ptr, int bit, int val); | |
40 | ||
41 | static int | |
42 | getbit( | |
43 | char *ptr, | |
44 | int bit) | |
45 | { | |
46 | int mask; | |
47 | int shift; | |
48 | ||
49 | ptr += byteize(bit); | |
50 | bit = bitoffs(bit); | |
51 | shift = 7 - bit; | |
52 | mask = 1 << shift; | |
53 | return (*ptr & mask) >> shift; | |
54 | } | |
55 | ||
56 | static void | |
57 | setbit( | |
58 | char *ptr, | |
59 | int bit, | |
60 | int val) | |
61 | { | |
62 | int mask; | |
63 | int shift; | |
64 | ||
65 | ptr += byteize(bit); | |
66 | bit = bitoffs(bit); | |
67 | shift = 7 - bit; | |
68 | mask = (1 << shift); | |
69 | if (val) { | |
70 | *ptr |= mask; | |
71 | } else { | |
72 | mask = ~mask; | |
73 | *ptr &= mask; | |
74 | } | |
75 | } | |
76 | ||
77 | __int64_t | |
78 | getbitval( | |
79 | void *obj, | |
80 | int bitoff, | |
81 | int nbits, | |
82 | int flags) | |
83 | { | |
84 | int bit; | |
85 | int i; | |
86 | char *p; | |
87 | __int64_t rval; | |
88 | int signext; | |
89 | int z1, z2, z3, z4; | |
90 | ||
91 | ASSERT(nbits<=64); | |
92 | ||
93 | p = (char *)obj + byteize(bitoff); | |
94 | bit = bitoffs(bitoff); | |
95 | signext = (flags & BVSIGNED) != 0; | |
96 | z4 = ((__psint_t)p & 0xf) == 0 && bit == 0; | |
97 | if (nbits == 64 && z4) { | |
98 | if (signext) | |
99 | return (__int64_t)INT_GET(*(__int64_t *)p, ARCH_CONVERT); | |
100 | else | |
101 | return (__int64_t)INT_GET(*(__uint64_t *)p, ARCH_CONVERT); | |
102 | } | |
103 | z3 = ((__psint_t)p & 0x7) == 0 && bit == 0; | |
104 | if (nbits == 32 && z3) { | |
105 | if (signext) | |
106 | return (__int64_t)INT_GET(*(__int32_t *)p, ARCH_CONVERT); | |
107 | else | |
108 | return (__int64_t)INT_GET(*(__uint32_t *)p, ARCH_CONVERT); | |
109 | } | |
110 | z2 = ((__psint_t)p & 0x3) == 0 && bit == 0; | |
111 | if (nbits == 16 && z2) { | |
112 | if (signext) | |
113 | return (__int64_t)INT_GET(*(__int16_t *)p, ARCH_CONVERT); | |
114 | else | |
115 | return (__int64_t)INT_GET(*(__uint16_t *)p, ARCH_CONVERT); | |
116 | } | |
117 | z1 = ((__psint_t)p & 0x1) == 0 && bit == 0; | |
118 | if (nbits == 8 && z1) { | |
119 | if (signext) | |
120 | return (__int64_t)INT_GET(*(__int8_t *)p, ARCH_CONVERT); | |
121 | else | |
122 | return (__int64_t)INT_GET(*(__uint8_t *)p, ARCH_CONVERT); | |
123 | } | |
124 | ||
125 | ||
126 | for (i = 0, rval = 0LL; i < nbits; i++) { | |
127 | if (getbit(p, bit + i)) { | |
128 | /* If the last bit is on and we care about sign | |
129 | * bits and we don't have a full 64 bit | |
130 | * container, turn all bits on between the | |
131 | * sign bit and the most sig bit. | |
132 | */ | |
133 | ||
134 | /* handle endian swap here */ | |
135 | #if __BYTE_ORDER == LITTLE_ENDIAN | |
136 | if (i == 0 && signext && nbits < 64) | |
137 | rval = -1LL << nbits; | |
138 | rval |= 1LL << (nbits - i - 1); | |
139 | #else | |
140 | if ((i == (nbits - 1)) && signext && nbits < 64) | |
141 | rval |= (-1LL << nbits); | |
142 | rval |= 1LL << (nbits - i - 1); | |
143 | #endif | |
144 | } | |
145 | } | |
146 | return rval; | |
147 | } | |
148 | ||
149 | void | |
150 | setbitval( | |
151 | void *obuf, /* buffer to write into */ | |
152 | int bitoff, /* bit offset of where to write */ | |
153 | int nbits, /* number of bits to write */ | |
154 | void *ibuf) /* source bits */ | |
155 | { | |
156 | char *in = (char *)ibuf; | |
157 | char *out = (char *)obuf; | |
158 | ||
159 | int bit; | |
160 | ||
161 | #if BYTE_ORDER == LITTLE_ENDIAN | |
162 | int big = 0; | |
163 | #else | |
164 | int big = 1; | |
165 | #endif | |
166 | ||
167 | /* only need to swap LE integers */ | |
168 | if (big || (nbits!=8 && nbits!=32 && nbits!=64) ) { | |
169 | /* We don't have type info, so we can only assume | |
170 | * that 2,4 & 8 byte values are integers. sigh. | |
171 | */ | |
172 | ||
173 | /* byte aligned ? */ | |
174 | if (bitoff%NBBY) { | |
175 | /* no - bit copy */ | |
176 | for (bit=0; bit<nbits; bit++) | |
177 | setbit(out, bit+bitoff, getbit(in, bit)); | |
178 | } else { | |
179 | /* yes - byte copy */ | |
180 | memcpy(out+byteize(bitoff), in, byteize(nbits)); | |
181 | } | |
182 | ||
183 | } else { | |
184 | int ibit; | |
185 | int obit; | |
186 | ||
187 | /* we need to endian swap this value */ | |
188 | ||
189 | out+=byteize(bitoff); | |
190 | obit=bitoffs(bitoff); | |
191 | ||
192 | ibit=nbits-NBBY; | |
193 | ||
194 | for (bit=0; bit<nbits; bit++) { | |
195 | setbit(out, bit+obit, getbit(in, ibit)); | |
196 | if (ibit%NBBY==NBBY-1) | |
197 | ibit-=NBBY*2-1; | |
198 | else | |
199 | ibit++; | |
200 | } | |
201 | } | |
202 | } |