binarybuffer: Remove unnecessary cast and fix hidden "bug"
[openocd.git] / src / helper / binarybuffer.h
1 /***************************************************************************
2 * Copyright (C) 2004, 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
23
24 #ifndef BINARYBUFFER_H
25 #define BINARYBUFFER_H
26
27 #include "list.h"
28
29 /** @file
30 * Support functions to access arbitrary bits in a byte array
31 */
32
33 /**
34 * Sets @c num bits in @c _buffer, starting at the @c first bit,
35 * using the bits in @c value. This routine fast-paths writes
36 * of little-endian, byte-aligned, 32-bit words.
37 * @param _buffer The buffer whose bits will be set.
38 * @param first The bit offset in @c _buffer to start writing (0-31).
39 * @param num The number of bits from @c value to copy (1-32).
40 * @param value Up to 32 bits that will be copied to _buffer.
41 */
42 static inline void buf_set_u32(void *_buffer,
43 unsigned first, unsigned num, uint32_t value)
44 {
45 uint8_t *buffer = _buffer;
46
47 if ((num == 32) && (first == 0)) {
48 buffer[3] = (value >> 24) & 0xff;
49 buffer[2] = (value >> 16) & 0xff;
50 buffer[1] = (value >> 8) & 0xff;
51 buffer[0] = (value >> 0) & 0xff;
52 } else {
53 for (unsigned i = first; i < first + num; i++) {
54 if (((value >> (i - first)) & 1) == 1)
55 buffer[i / 8] |= 1 << (i % 8);
56 else
57 buffer[i / 8] &= ~(1 << (i % 8));
58 }
59 }
60 }
61
62 /**
63 * Sets @c num bits in @c _buffer, starting at the @c first bit,
64 * using the bits in @c value. This routine fast-paths writes
65 * of little-endian, byte-aligned, 64-bit words.
66 * @param _buffer The buffer whose bits will be set.
67 * @param first The bit offset in @c _buffer to start writing (0-63).
68 * @param num The number of bits from @c value to copy (1-64).
69 * @param value Up to 64 bits that will be copied to _buffer.
70 */
71 static inline void buf_set_u64(void *_buffer,
72 unsigned first, unsigned num, uint64_t value)
73 {
74 uint8_t *buffer = _buffer;
75
76 if ((num == 32) && (first == 0)) {
77 buffer[3] = (value >> 24) & 0xff;
78 buffer[2] = (value >> 16) & 0xff;
79 buffer[1] = (value >> 8) & 0xff;
80 buffer[0] = (value >> 0) & 0xff;
81 } else if ((num == 64) && (first == 0)) {
82 buffer[7] = (value >> 56) & 0xff;
83 buffer[6] = (value >> 48) & 0xff;
84 buffer[5] = (value >> 40) & 0xff;
85 buffer[4] = (value >> 32) & 0xff;
86 buffer[3] = (value >> 24) & 0xff;
87 buffer[2] = (value >> 16) & 0xff;
88 buffer[1] = (value >> 8) & 0xff;
89 buffer[0] = (value >> 0) & 0xff;
90 } else {
91 for (unsigned i = first; i < first + num; i++) {
92 if (((value >> (i - first)) & 1) == 1)
93 buffer[i / 8] |= 1 << (i % 8);
94 else
95 buffer[i / 8] &= ~(1 << (i % 8));
96 }
97 }
98 }
99
100 /**
101 * Retrieves @c num bits from @c _buffer, starting at the @c first bit,
102 * returning the bits in a 32-bit word. This routine fast-paths reads
103 * of little-endian, byte-aligned, 32-bit words.
104 * @param _buffer The buffer whose bits will be read.
105 * @param first The bit offset in @c _buffer to start reading (0-31).
106 * @param num The number of bits from @c _buffer to read (1-32).
107 * @returns Up to 32-bits that were read from @c _buffer.
108 */
109 static inline uint32_t buf_get_u32(const void *_buffer,
110 unsigned first, unsigned num)
111 {
112 const uint8_t *buffer = _buffer;
113
114 if ((num == 32) && (first == 0)) {
115 return (((uint32_t)buffer[3]) << 24) |
116 (((uint32_t)buffer[2]) << 16) |
117 (((uint32_t)buffer[1]) << 8) |
118 (((uint32_t)buffer[0]) << 0);
119 } else {
120 uint32_t result = 0;
121 for (unsigned i = first; i < first + num; i++) {
122 if (((buffer[i / 8] >> (i % 8)) & 1) == 1)
123 result |= 1 << (i - first);
124 }
125 return result;
126 }
127 }
128
129 /**
130 * Retrieves @c num bits from @c _buffer, starting at the @c first bit,
131 * returning the bits in a 64-bit word. This routine fast-paths reads
132 * of little-endian, byte-aligned, 64-bit words.
133 * @param _buffer The buffer whose bits will be read.
134 * @param first The bit offset in @c _buffer to start reading (0-63).
135 * @param num The number of bits from @c _buffer to read (1-64).
136 * @returns Up to 64-bits that were read from @c _buffer.
137 */
138 static inline uint64_t buf_get_u64(const void *_buffer,
139 unsigned first, unsigned num)
140 {
141 const uint8_t *buffer = _buffer;
142
143 if ((num == 32) && (first == 0)) {
144 return 0 + ((((uint32_t)buffer[3]) << 24) | /* Note - zero plus is to avoid a checkpatch bug */
145 (((uint32_t)buffer[2]) << 16) |
146 (((uint32_t)buffer[1]) << 8) |
147 (((uint32_t)buffer[0]) << 0));
148 } else if ((num == 64) && (first == 0)) {
149 return 0 + ((((uint64_t)buffer[7]) << 56) | /* Note - zero plus is to avoid a checkpatch bug */
150 (((uint64_t)buffer[6]) << 48) |
151 (((uint64_t)buffer[5]) << 40) |
152 (((uint64_t)buffer[4]) << 32) |
153 (((uint64_t)buffer[3]) << 24) |
154 (((uint64_t)buffer[2]) << 16) |
155 (((uint64_t)buffer[1]) << 8) |
156 (((uint64_t)buffer[0]) << 0));
157 } else {
158 uint64_t result = 0;
159 for (unsigned i = first; i < first + num; i++) {
160 if (((buffer[i / 8] >> (i % 8)) & 1) == 1)
161 result = result | ((uint64_t)1 << (uint64_t)(i - first));
162 }
163 return result;
164 }
165 }
166
167
168 /**
169 * Inverts the ordering of bits inside a 32-bit word (e.g. 31..0 -> 0..31).
170 * This routine can be used to flip smaller data types by using smaller
171 * values for @c width.
172 * @param value The word to flip.
173 * @param width The number of bits in value (2-32).
174 * @returns A 32-bit word with @c value in reversed bit-order.
175 */
176 uint32_t flip_u32(uint32_t value, unsigned width);
177
178 bool buf_cmp(const void *buf1, const void *buf2, unsigned size);
179 bool buf_cmp_mask(const void *buf1, const void *buf2,
180 const void *mask, unsigned size);
181
182 /**
183 * Copies @c size bits out of @c from and into @c to. Any extra
184 * bits in the final byte will be set to zero.
185 * @param from The buffer to copy into @c to.
186 * @param to The buffer that will receive the copy of @c from.
187 * @param size The number of bits to copy.
188 */
189 void *buf_cpy(const void *from, void *to, unsigned size);
190
191 /**
192 * Set the contents of @c buf with @c count bits, all set to 1.
193 * @param buf The buffer to fill with ones.
194 * @param size The number of bits.
195 * @returns The original buffer (@c buf).
196 */
197 void *buf_set_ones(void *buf, unsigned size);
198
199 void *buf_set_buf(const void *src, unsigned src_start,
200 void *dst, unsigned dst_start, unsigned len);
201
202 int str_to_buf(const char *str, unsigned len,
203 void *bin_buf, unsigned buf_size, unsigned radix);
204 char *buf_to_str(const void *buf, unsigned size, unsigned radix);
205
206 /* read a uint32_t from a buffer in target memory endianness */
207 static inline uint32_t fast_target_buffer_get_u32(const void *p, bool le)
208 {
209 return le ? le_to_h_u32(p) : be_to_h_u32(p);
210 }
211
212 static inline void bit_copy(uint8_t *dst, unsigned dst_offset, const uint8_t *src,
213 unsigned src_offset, unsigned bit_count)
214 {
215 buf_set_buf(src, src_offset, dst, dst_offset, bit_count);
216 }
217
218 struct bit_copy_queue {
219 struct list_head list;
220 };
221
222 struct bit_copy_queue_entry {
223 uint8_t *dst;
224 unsigned dst_offset;
225 const uint8_t *src;
226 unsigned src_offset;
227 unsigned bit_count;
228 struct list_head list;
229 };
230
231 void bit_copy_queue_init(struct bit_copy_queue *q);
232 int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src,
233 unsigned src_offset, unsigned bit_count);
234 void bit_copy_execute(struct bit_copy_queue *q);
235 void bit_copy_discard(struct bit_copy_queue *q);
236
237 /* functions to convert to/from hex encoded buffer
238 * used in ti-icdi driver and gdb server */
239 int unhexify(char *bin, const char *hex, int count);
240 int hexify(char *hex, const char *bin, int count, int out_maxlen);
241 void buffer_shr(void *_buf, unsigned buf_len, unsigned count);
242
243 #endif /* BINARYBUFFER_H */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)