fix for sanitizer errors in left shifts
[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, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
21
22 #ifndef OPENOCD_HELPER_BINARYBUFFER_H
23 #define OPENOCD_HELPER_BINARYBUFFER_H
24
25 #include "list.h"
26
27 /** @file
28 * Support functions to access arbitrary bits in a byte array
29 */
30
31 /**
32 * Sets @c num bits in @c _buffer, starting at the @c first bit,
33 * using the bits in @c value. This routine fast-paths writes
34 * of little-endian, byte-aligned, 32-bit words.
35 * @param _buffer The buffer whose bits will be set.
36 * @param first The bit offset in @c _buffer to start writing (0-31).
37 * @param num The number of bits from @c value to copy (1-32).
38 * @param value Up to 32 bits that will be copied to _buffer.
39 */
40 static inline void buf_set_u32(uint8_t *_buffer,
41 unsigned first, unsigned num, uint32_t value)
42 {
43 uint8_t *buffer = _buffer;
44
45 if ((num == 32) && (first == 0)) {
46 buffer[3] = (value >> 24) & 0xff;
47 buffer[2] = (value >> 16) & 0xff;
48 buffer[1] = (value >> 8) & 0xff;
49 buffer[0] = (value >> 0) & 0xff;
50 } else {
51 for (unsigned i = first; i < first + num; i++) {
52 if (((value >> (i - first)) & 1) == 1)
53 buffer[i / 8] |= 1 << (i % 8);
54 else
55 buffer[i / 8] &= ~(1 << (i % 8));
56 }
57 }
58 }
59
60 /**
61 * Sets @c num bits in @c _buffer, starting at the @c first bit,
62 * using the bits in @c value. This routine fast-paths writes
63 * of little-endian, byte-aligned, 64-bit words.
64 * @param _buffer The buffer whose bits will be set.
65 * @param first The bit offset in @c _buffer to start writing (0-63).
66 * @param num The number of bits from @c value to copy (1-64).
67 * @param value Up to 64 bits that will be copied to _buffer.
68 */
69 static inline void buf_set_u64(uint8_t *_buffer,
70 unsigned first, unsigned num, uint64_t value)
71 {
72 uint8_t *buffer = _buffer;
73
74 if ((num == 32) && (first == 0)) {
75 buffer[3] = (value >> 24) & 0xff;
76 buffer[2] = (value >> 16) & 0xff;
77 buffer[1] = (value >> 8) & 0xff;
78 buffer[0] = (value >> 0) & 0xff;
79 } else if ((num == 64) && (first == 0)) {
80 buffer[7] = (value >> 56) & 0xff;
81 buffer[6] = (value >> 48) & 0xff;
82 buffer[5] = (value >> 40) & 0xff;
83 buffer[4] = (value >> 32) & 0xff;
84 buffer[3] = (value >> 24) & 0xff;
85 buffer[2] = (value >> 16) & 0xff;
86 buffer[1] = (value >> 8) & 0xff;
87 buffer[0] = (value >> 0) & 0xff;
88 } else {
89 for (unsigned i = first; i < first + num; i++) {
90 if (((value >> (i - first)) & 1) == 1)
91 buffer[i / 8] |= 1 << (i % 8);
92 else
93 buffer[i / 8] &= ~(1 << (i % 8));
94 }
95 }
96 }
97
98 /**
99 * Retrieves @c num bits from @c _buffer, starting at the @c first bit,
100 * returning the bits in a 32-bit word. This routine fast-paths reads
101 * of little-endian, byte-aligned, 32-bit words.
102 * @param _buffer The buffer whose bits will be read.
103 * @param first The bit offset in @c _buffer to start reading (0-31).
104 * @param num The number of bits from @c _buffer to read (1-32).
105 * @returns Up to 32-bits that were read from @c _buffer.
106 */
107 static inline uint32_t buf_get_u32(const uint8_t *_buffer,
108 unsigned first, unsigned num)
109 {
110 const uint8_t *buffer = _buffer;
111
112 if ((num == 32) && (first == 0)) {
113 return (((uint32_t)buffer[3]) << 24) |
114 (((uint32_t)buffer[2]) << 16) |
115 (((uint32_t)buffer[1]) << 8) |
116 (((uint32_t)buffer[0]) << 0);
117 } else {
118 uint32_t result = 0;
119 for (unsigned i = first; i < first + num; i++) {
120 if (((buffer[i / 8] >> (i % 8)) & 1) == 1)
121 result |= 1U << (i - first);
122 }
123 return result;
124 }
125 }
126
127 /**
128 * Retrieves @c num bits from @c _buffer, starting at the @c first bit,
129 * returning the bits in a 64-bit word. This routine fast-paths reads
130 * of little-endian, byte-aligned, 64-bit words.
131 * @param _buffer The buffer whose bits will be read.
132 * @param first The bit offset in @c _buffer to start reading (0-63).
133 * @param num The number of bits from @c _buffer to read (1-64).
134 * @returns Up to 64-bits that were read from @c _buffer.
135 */
136 static inline uint64_t buf_get_u64(const uint8_t *_buffer,
137 unsigned first, unsigned num)
138 {
139 const uint8_t *buffer = _buffer;
140
141 if ((num == 32) && (first == 0)) {
142 return 0 + ((((uint32_t)buffer[3]) << 24) | /* Note - zero plus is to avoid a checkpatch bug */
143 (((uint32_t)buffer[2]) << 16) |
144 (((uint32_t)buffer[1]) << 8) |
145 (((uint32_t)buffer[0]) << 0));
146 } else if ((num == 64) && (first == 0)) {
147 return 0 + ((((uint64_t)buffer[7]) << 56) | /* Note - zero plus is to avoid a checkpatch bug */
148 (((uint64_t)buffer[6]) << 48) |
149 (((uint64_t)buffer[5]) << 40) |
150 (((uint64_t)buffer[4]) << 32) |
151 (((uint64_t)buffer[3]) << 24) |
152 (((uint64_t)buffer[2]) << 16) |
153 (((uint64_t)buffer[1]) << 8) |
154 (((uint64_t)buffer[0]) << 0));
155 } else {
156 uint64_t result = 0;
157 for (unsigned i = first; i < first + num; i++) {
158 if (((buffer[i / 8] >> (i % 8)) & 1) == 1)
159 result = result | ((uint64_t)1 << (uint64_t)(i - first));
160 }
161 return result;
162 }
163 }
164
165
166 /**
167 * Inverts the ordering of bits inside a 32-bit word (e.g. 31..0 -> 0..31).
168 * This routine can be used to flip smaller data types by using smaller
169 * values for @c width.
170 * @param value The word to flip.
171 * @param width The number of bits in value (2-32).
172 * @returns A 32-bit word with @c value in reversed bit-order.
173 */
174 uint32_t flip_u32(uint32_t value, unsigned width);
175
176 bool buf_cmp(const void *buf1, const void *buf2, unsigned size);
177 bool buf_cmp_mask(const void *buf1, const void *buf2,
178 const void *mask, unsigned size);
179
180 /**
181 * Copies @c size bits out of @c from and into @c to. Any extra
182 * bits in the final byte will be set to zero.
183 * @param from The buffer to copy into @c to.
184 * @param to The buffer that will receive the copy of @c from.
185 * @param size The number of bits to copy.
186 */
187 void *buf_cpy(const void *from, void *to, unsigned size);
188
189 /**
190 * Set the contents of @c buf with @c count bits, all set to 1.
191 * @param buf The buffer to fill with ones.
192 * @param size The number of bits.
193 * @returns The original buffer (@c buf).
194 */
195 void *buf_set_ones(void *buf, unsigned size);
196
197 void *buf_set_buf(const void *src, unsigned src_start,
198 void *dst, unsigned dst_start, unsigned len);
199
200 int str_to_buf(const char *str, unsigned len,
201 void *bin_buf, unsigned buf_size, unsigned radix);
202 char *buf_to_str(const void *buf, unsigned size, unsigned radix);
203
204 /* read a uint32_t from a buffer in target memory endianness */
205 static inline uint32_t fast_target_buffer_get_u32(const void *p, bool le)
206 {
207 return le ? le_to_h_u32(p) : be_to_h_u32(p);
208 }
209
210 static inline void bit_copy(uint8_t *dst, unsigned dst_offset, const uint8_t *src,
211 unsigned src_offset, unsigned bit_count)
212 {
213 buf_set_buf(src, src_offset, dst, dst_offset, bit_count);
214 }
215
216 struct bit_copy_queue {
217 struct list_head list;
218 };
219
220 struct bit_copy_queue_entry {
221 uint8_t *dst;
222 unsigned dst_offset;
223 const uint8_t *src;
224 unsigned src_offset;
225 unsigned bit_count;
226 struct list_head list;
227 };
228
229 void bit_copy_queue_init(struct bit_copy_queue *q);
230 int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src,
231 unsigned src_offset, unsigned bit_count);
232 void bit_copy_execute(struct bit_copy_queue *q);
233 void bit_copy_discard(struct bit_copy_queue *q);
234
235 /* functions to convert to/from hex encoded buffer
236 * used in ti-icdi driver and gdb server */
237 size_t unhexify(uint8_t *bin, const char *hex, size_t count);
238 size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t out_maxlen);
239 void buffer_shr(void *_buf, unsigned buf_len, unsigned count);
240
241 #endif /* OPENOCD_HELPER_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)