blob: 6719584aa462c079c4778bbb37513d19e3e37326 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * ----------------------------------------------------------------------- */
33
H. Peter Anvin1803ded2008-06-09 17:32:43 -070034#include "compiler.h"
35#include "nasmlib.h"
36#include "saa.h"
37
38/* Aggregate SAA components smaller than this */
H. Peter Anvin1cff81e2008-06-10 09:29:20 -070039#define SAA_BLKSHIFT 16
40#define SAA_BLKLEN ((size_t)1 << SAA_BLKSHIFT)
H. Peter Anvin1803ded2008-06-09 17:32:43 -070041
42struct SAA *saa_init(size_t elem_len)
43{
44 struct SAA *s;
45 char *data;
46
47 s = nasm_zalloc(sizeof(struct SAA));
48
49 if (elem_len >= SAA_BLKLEN)
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -070050 s->blk_len = elem_len;
H. Peter Anvin1803ded2008-06-09 17:32:43 -070051 else
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -070052 s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len);
H. Peter Anvin1803ded2008-06-09 17:32:43 -070053
54 s->elem_len = elem_len;
55 s->length = s->blk_len;
56 data = nasm_malloc(s->blk_len);
57 s->nblkptrs = s->nblks = 1;
58 s->blk_ptrs = nasm_malloc(sizeof(char *));
59 s->blk_ptrs[0] = data;
60 s->wblk = s->rblk = &s->blk_ptrs[0];
61
62 return s;
63}
64
65void saa_free(struct SAA *s)
66{
67 char **p;
68 size_t n;
69
70 for (p = s->blk_ptrs, n = s->nblks; n; p++, n--)
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -070071 nasm_free(*p);
H. Peter Anvin1803ded2008-06-09 17:32:43 -070072
73 nasm_free(s->blk_ptrs);
74 nasm_free(s);
75}
76
77/* Add one allocation block to an SAA */
78static void saa_extend(struct SAA *s)
79{
80 size_t blkn = s->nblks++;
81
82 if (blkn >= s->nblkptrs) {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -070083 size_t rindex = s->rblk - s->blk_ptrs;
84 size_t windex = s->wblk - s->blk_ptrs;
H. Peter Anvin1803ded2008-06-09 17:32:43 -070085
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -070086 s->nblkptrs <<= 1;
87 s->blk_ptrs =
88 nasm_realloc(s->blk_ptrs, s->nblkptrs * sizeof(char *));
H. Peter Anvin1803ded2008-06-09 17:32:43 -070089
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -070090 s->rblk = s->blk_ptrs + rindex;
91 s->wblk = s->blk_ptrs + windex;
H. Peter Anvin1803ded2008-06-09 17:32:43 -070092 }
93
94 s->blk_ptrs[blkn] = nasm_malloc(s->blk_len);
95 s->length += s->blk_len;
96}
97
98void *saa_wstruct(struct SAA *s)
99{
100 void *p;
101
H. Peter Anvin9bd15062009-07-18 21:07:17 -0400102 nasm_assert((s->wpos % s->elem_len) == 0);
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700103
104 if (s->wpos + s->elem_len > s->blk_len) {
H. Peter Anvin9bd15062009-07-18 21:07:17 -0400105 nasm_assert(s->wpos == s->blk_len);
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700106 if (s->wptr + s->elem_len > s->length)
107 saa_extend(s);
108 s->wblk++;
109 s->wpos = 0;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700110 }
111
112 p = *s->wblk + s->wpos;
113 s->wpos += s->elem_len;
114 s->wptr += s->elem_len;
115
116 if (s->wptr > s->datalen)
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700117 s->datalen = s->wptr;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700118
119 return p;
120}
121
122void saa_wbytes(struct SAA *s, const void *data, size_t len)
123{
124 const char *d = data;
125
126 while (len) {
127 size_t l = s->blk_len - s->wpos;
128 if (l > len)
129 l = len;
130 if (l) {
131 if (d) {
132 memcpy(*s->wblk + s->wpos, d, l);
133 d += l;
134 } else
135 memset(*s->wblk + s->wpos, 0, l);
136 s->wpos += l;
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700137 s->wptr += l;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700138 len -= l;
139
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700140 if (s->datalen < s->wptr)
141 s->datalen = s->wptr;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700142 }
143 if (len) {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700144 if (s->wptr >= s->length)
145 saa_extend(s);
146 s->wblk++;
147 s->wpos = 0;
148 }
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700149 }
150}
151
152void saa_rewind(struct SAA *s)
153{
154 s->rblk = s->blk_ptrs;
155 s->rpos = s->rptr = 0;
156}
157
158void *saa_rstruct(struct SAA *s)
159{
160 void *p;
161
162 if (s->rptr + s->elem_len > s->datalen)
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700163 return NULL;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700164
H. Peter Anvin9bd15062009-07-18 21:07:17 -0400165 nasm_assert((s->rpos % s->elem_len) == 0);
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700166
167 if (s->rpos + s->elem_len > s->blk_len) {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700168 s->rblk++;
169 s->rpos = 0;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700170 }
171
172 p = *s->rblk + s->rpos;
173 s->rpos += s->elem_len;
174 s->rptr += s->elem_len;
175
176 return p;
177}
178
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700179const void *saa_rbytes(struct SAA *s, size_t * lenp)
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700180{
181 const void *p;
182 size_t len;
183
184 if (s->rptr >= s->datalen) {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700185 *lenp = 0;
186 return NULL;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700187 }
188
189 if (s->rpos >= s->blk_len) {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700190 s->rblk++;
191 s->rpos = 0;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700192 }
193
194 len = *lenp;
195 if (len > s->datalen - s->rptr)
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700196 len = s->datalen - s->rptr;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700197 if (len > s->blk_len - s->rpos)
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700198 len = s->blk_len - s->rpos;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700199
200 *lenp = len;
201 p = *s->rblk + s->rpos;
202
203 s->rpos += len;
204 s->rptr += len;
205
206 return p;
207}
208
209void saa_rnbytes(struct SAA *s, void *data, size_t len)
210{
211 char *d = data;
212
H. Peter Anvin9bd15062009-07-18 21:07:17 -0400213 nasm_assert(s->rptr + len <= s->datalen);
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700214
215 while (len) {
216 size_t l;
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700217 const void *p;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700218
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700219 l = len;
220 p = saa_rbytes(s, &l);
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700221
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700222 memcpy(d, p, l);
223 d += l;
224 len -= l;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700225 }
226}
227
228/* Same as saa_rnbytes, except position the counter first */
229void saa_fread(struct SAA *s, size_t posn, void *data, size_t len)
230{
231 size_t ix;
232
H. Peter Anvin9bd15062009-07-18 21:07:17 -0400233 nasm_assert(posn + len <= s->datalen);
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700234
H. Peter Anvin51997d32008-06-10 09:35:26 -0700235 if (likely(s->blk_len == SAA_BLKLEN)) {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700236 ix = posn >> SAA_BLKSHIFT;
237 s->rpos = posn & (SAA_BLKLEN - 1);
H. Peter Anvin1cff81e2008-06-10 09:29:20 -0700238 } else {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700239 ix = posn / s->blk_len;
240 s->rpos = posn % s->blk_len;
H. Peter Anvin1cff81e2008-06-10 09:29:20 -0700241 }
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700242 s->rptr = posn;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700243 s->rblk = &s->blk_ptrs[ix];
244
245 saa_rnbytes(s, data, len);
246}
247
248/* Same as saa_wbytes, except position the counter first */
249void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len)
250{
251 size_t ix;
252
H. Peter Anvin9bd15062009-07-18 21:07:17 -0400253 /* Seek beyond the end of the existing array not supported */
254 nasm_assert(posn <= s->datalen);
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700255
H. Peter Anvin51997d32008-06-10 09:35:26 -0700256 if (likely(s->blk_len == SAA_BLKLEN)) {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700257 ix = posn >> SAA_BLKSHIFT;
258 s->wpos = posn & (SAA_BLKLEN - 1);
H. Peter Anvin1cff81e2008-06-10 09:29:20 -0700259 } else {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700260 ix = posn / s->blk_len;
261 s->wpos = posn % s->blk_len;
H. Peter Anvin1cff81e2008-06-10 09:29:20 -0700262 }
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700263 s->wptr = posn;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700264 s->wblk = &s->blk_ptrs[ix];
265
266 if (!s->wpos) {
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700267 s->wpos = s->blk_len;
268 s->wblk--;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700269 }
270
271 saa_wbytes(s, data, len);
272}
273
274void saa_fpwrite(struct SAA *s, FILE * fp)
275{
276 const char *data;
277 size_t len;
278
279 saa_rewind(s);
280 while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL)
281 fwrite(data, 1, len, fp);
282}
283
284void saa_write8(struct SAA *s, uint8_t v)
285{
286 saa_wbytes(s, &v, 1);
287}
288
289#ifdef WORDS_LITTEENDIAN
290
291void saa_write16(struct SAA *s, uint16_t v)
292{
293 saa_wbytes(s, &v, 2);
294}
295
296void saa_write32(struct SAA *s, uint32_t v)
297{
298 saa_wbytes(s, &v, 4);
299}
300
301void saa_write64(struct SAA *s, uint64_t v)
302{
303 saa_wbytes(s, &v, 8);
304}
305
H. Peter Anvinedb58f72008-10-17 19:30:34 -0700306void saa_writeaddr(struct SAA *s, uint64_t v, size_t len)
307{
308 saa_wbytes(s, &v, len);
309}
310
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700311#else /* not WORDS_LITTLEENDIAN */
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700312
313void saa_write16(struct SAA *s, uint16_t v)
314{
315 uint8_t b[2];
316
317 b[0] = v;
318 b[1] = v >> 8;
319 saa_wbytes(s, b, 2);
320}
321
322void saa_write32(struct SAA *s, uint32_t v)
323{
324 uint8_t b[4];
325
326 b[0] = v;
327 b[1] = v >> 8;
328 b[2] = v >> 16;
329 b[3] = v >> 24;
330 saa_wbytes(s, b, 4);
331}
332
333void saa_write64(struct SAA *s, uint64_t v)
334{
335 uint8_t b[8];
336
337 b[0] = v;
338 b[1] = v >> 8;
339 b[2] = v >> 16;
340 b[3] = v >> 24;
341 b[4] = v >> 32;
342 b[5] = v >> 40;
343 b[6] = v >> 48;
344 b[7] = v >> 56;
Cyrill Gorcunov0aa9bdf2011-07-17 13:59:13 +0400345
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700346 saa_wbytes(s, b, 8);
347}
348
H. Peter Anvinedb58f72008-10-17 19:30:34 -0700349void saa_writeaddr(struct SAA *s, uint64_t v, size_t len)
350{
351 uint8_t b[8];
352
353 b[0] = v;
354 b[1] = v >> 8;
355 b[2] = v >> 16;
356 b[3] = v >> 24;
357 b[4] = v >> 32;
358 b[5] = v >> 40;
359 b[6] = v >> 48;
360 b[7] = v >> 56;
361
Cyrill Gorcunov0aa9bdf2011-07-17 13:59:13 +0400362 saa_wbytes(s, b, len);
H. Peter Anvinedb58f72008-10-17 19:30:34 -0700363}
364
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700365#endif /* WORDS_LITTLEENDIAN */
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700366
367/* write unsigned LEB128 value to SAA */
368void saa_wleb128u(struct SAA *psaa, int value)
369{
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700370 char temp[64], *ptemp;
371 uint8_t byte;
372 int len;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700373
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700374 ptemp = temp;
375 len = 0;
376 do {
377 byte = value & 127;
378 value >>= 7;
379 if (value != 0) /* more bytes to come */
380 byte |= 0x80;
381 *ptemp = byte;
382 ptemp++;
383 len++;
384 } while (value != 0);
385 saa_wbytes(psaa, temp, len);
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700386}
387
388/* write signed LEB128 value to SAA */
389void saa_wleb128s(struct SAA *psaa, int value)
390{
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700391 char temp[64], *ptemp;
392 uint8_t byte;
393 bool more, negative;
394 int size, len;
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700395
H. Peter Anvin3c7e6b32008-06-19 23:09:11 -0700396 ptemp = temp;
397 more = 1;
398 negative = (value < 0);
399 size = sizeof(int) * 8;
400 len = 0;
401 while (more) {
402 byte = value & 0x7f;
403 value >>= 7;
404 if (negative)
405 /* sign extend */
406 value |= -(1 << (size - 7));
407 /* sign bit of byte is second high order bit (0x40) */
408 if ((value == 0 && !(byte & 0x40)) ||
409 ((value == -1) && (byte & 0x40)))
410 more = 0;
411 else
412 byte |= 0x80;
413 *ptemp = byte;
414 ptemp++;
415 len++;
416 }
417 saa_wbytes(psaa, temp, len);
H. Peter Anvin1803ded2008-06-09 17:32:43 -0700418}