10554
|
1 /* ----------------------------------------------------------------------- *
|
|
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
|
|
34 #include "compiler.h"
|
|
35 #include "nasmlib.h"
|
|
36 #include "saa.h"
|
|
37
|
|
38 /* Aggregate SAA components smaller than this */
|
|
39 #define SAA_BLKSHIFT 16
|
|
40 #define SAA_BLKLEN ((size_t)1 << SAA_BLKSHIFT)
|
|
41
|
|
42 struct 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)
|
|
50 s->blk_len = elem_len;
|
|
51 else
|
|
52 s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len);
|
|
53
|
|
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
|
|
65 void 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--)
|
|
71 nasm_free(*p);
|
|
72
|
|
73 nasm_free(s->blk_ptrs);
|
|
74 nasm_free(s);
|
|
75 }
|
|
76
|
|
77 /* Add one allocation block to an SAA */
|
|
78 static void saa_extend(struct SAA *s)
|
|
79 {
|
|
80 size_t blkn = s->nblks++;
|
|
81
|
|
82 if (blkn >= s->nblkptrs) {
|
|
83 size_t rindex = s->rblk - s->blk_ptrs;
|
|
84 size_t windex = s->wblk - s->blk_ptrs;
|
|
85
|
|
86 s->nblkptrs <<= 1;
|
|
87 s->blk_ptrs =
|
|
88 nasm_realloc(s->blk_ptrs, s->nblkptrs * sizeof(char *));
|
|
89
|
|
90 s->rblk = s->blk_ptrs + rindex;
|
|
91 s->wblk = s->blk_ptrs + windex;
|
|
92 }
|
|
93
|
|
94 s->blk_ptrs[blkn] = nasm_malloc(s->blk_len);
|
|
95 s->length += s->blk_len;
|
|
96 }
|
|
97
|
|
98 void *saa_wstruct(struct SAA *s)
|
|
99 {
|
|
100 void *p;
|
|
101
|
|
102 nasm_assert((s->wpos % s->elem_len) == 0);
|
|
103
|
|
104 if (s->wpos + s->elem_len > s->blk_len) {
|
|
105 nasm_assert(s->wpos == s->blk_len);
|
|
106 if (s->wptr + s->elem_len > s->length)
|
|
107 saa_extend(s);
|
|
108 s->wblk++;
|
|
109 s->wpos = 0;
|
|
110 }
|
|
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)
|
|
117 s->datalen = s->wptr;
|
|
118
|
|
119 return p;
|
|
120 }
|
|
121
|
|
122 void 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;
|
|
137 s->wptr += l;
|
|
138 len -= l;
|
|
139
|
|
140 if (s->datalen < s->wptr)
|
|
141 s->datalen = s->wptr;
|
|
142 }
|
|
143 if (len) {
|
|
144 if (s->wptr >= s->length)
|
|
145 saa_extend(s);
|
|
146 s->wblk++;
|
|
147 s->wpos = 0;
|
|
148 }
|
|
149 }
|
|
150 }
|
|
151
|
|
152 void saa_rewind(struct SAA *s)
|
|
153 {
|
|
154 s->rblk = s->blk_ptrs;
|
|
155 s->rpos = s->rptr = 0;
|
|
156 }
|
|
157
|
|
158 void *saa_rstruct(struct SAA *s)
|
|
159 {
|
|
160 void *p;
|
|
161
|
|
162 if (s->rptr + s->elem_len > s->datalen)
|
|
163 return NULL;
|
|
164
|
|
165 nasm_assert((s->rpos % s->elem_len) == 0);
|
|
166
|
|
167 if (s->rpos + s->elem_len > s->blk_len) {
|
|
168 s->rblk++;
|
|
169 s->rpos = 0;
|
|
170 }
|
|
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
|
|
179 const void *saa_rbytes(struct SAA *s, size_t * lenp)
|
|
180 {
|
|
181 const void *p;
|
|
182 size_t len;
|
|
183
|
|
184 if (s->rptr >= s->datalen) {
|
|
185 *lenp = 0;
|
|
186 return NULL;
|
|
187 }
|
|
188
|
|
189 if (s->rpos >= s->blk_len) {
|
|
190 s->rblk++;
|
|
191 s->rpos = 0;
|
|
192 }
|
|
193
|
|
194 len = *lenp;
|
|
195 if (len > s->datalen - s->rptr)
|
|
196 len = s->datalen - s->rptr;
|
|
197 if (len > s->blk_len - s->rpos)
|
|
198 len = s->blk_len - s->rpos;
|
|
199
|
|
200 *lenp = len;
|
|
201 p = *s->rblk + s->rpos;
|
|
202
|
|
203 s->rpos += len;
|
|
204 s->rptr += len;
|
|
205
|
|
206 return p;
|
|
207 }
|
|
208
|
|
209 void saa_rnbytes(struct SAA *s, void *data, size_t len)
|
|
210 {
|
|
211 char *d = data;
|
|
212
|
|
213 nasm_assert(s->rptr + len <= s->datalen);
|
|
214
|
|
215 while (len) {
|
|
216 size_t l;
|
|
217 const void *p;
|
|
218
|
|
219 l = len;
|
|
220 p = saa_rbytes(s, &l);
|
|
221
|
|
222 memcpy(d, p, l);
|
|
223 d += l;
|
|
224 len -= l;
|
|
225 }
|
|
226 }
|
|
227
|
|
228 /* Same as saa_rnbytes, except position the counter first */
|
|
229 void saa_fread(struct SAA *s, size_t posn, void *data, size_t len)
|
|
230 {
|
|
231 size_t ix;
|
|
232
|
|
233 nasm_assert(posn + len <= s->datalen);
|
|
234
|
|
235 if (likely(s->blk_len == SAA_BLKLEN)) {
|
|
236 ix = posn >> SAA_BLKSHIFT;
|
|
237 s->rpos = posn & (SAA_BLKLEN - 1);
|
|
238 } else {
|
|
239 ix = posn / s->blk_len;
|
|
240 s->rpos = posn % s->blk_len;
|
|
241 }
|
|
242 s->rptr = posn;
|
|
243 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 */
|
|
249 void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len)
|
|
250 {
|
|
251 size_t ix;
|
|
252
|
|
253 /* Seek beyond the end of the existing array not supported */
|
|
254 nasm_assert(posn <= s->datalen);
|
|
255
|
|
256 if (likely(s->blk_len == SAA_BLKLEN)) {
|
|
257 ix = posn >> SAA_BLKSHIFT;
|
|
258 s->wpos = posn & (SAA_BLKLEN - 1);
|
|
259 } else {
|
|
260 ix = posn / s->blk_len;
|
|
261 s->wpos = posn % s->blk_len;
|
|
262 }
|
|
263 s->wptr = posn;
|
|
264 s->wblk = &s->blk_ptrs[ix];
|
|
265
|
|
266 if (!s->wpos) {
|
|
267 s->wpos = s->blk_len;
|
|
268 s->wblk--;
|
|
269 }
|
|
270
|
|
271 saa_wbytes(s, data, len);
|
|
272 }
|
|
273
|
|
274 void 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 nasm_write(data, len, fp);
|
|
282 }
|
|
283
|
|
284 void saa_write8(struct SAA *s, uint8_t v)
|
|
285 {
|
|
286 saa_wbytes(s, &v, 1);
|
|
287 }
|
|
288
|
|
289 #ifdef WORDS_LITTEENDIAN
|
|
290
|
|
291 void saa_write16(struct SAA *s, uint16_t v)
|
|
292 {
|
|
293 saa_wbytes(s, &v, 2);
|
|
294 }
|
|
295
|
|
296 void saa_write32(struct SAA *s, uint32_t v)
|
|
297 {
|
|
298 saa_wbytes(s, &v, 4);
|
|
299 }
|
|
300
|
|
301 void saa_write64(struct SAA *s, uint64_t v)
|
|
302 {
|
|
303 saa_wbytes(s, &v, 8);
|
|
304 }
|
|
305
|
|
306 void saa_writeaddr(struct SAA *s, uint64_t v, size_t len)
|
|
307 {
|
|
308 saa_wbytes(s, &v, len);
|
|
309 }
|
|
310
|
|
311 #else /* not WORDS_LITTLEENDIAN */
|
|
312
|
|
313 void 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
|
|
322 void 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
|
|
333 void 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;
|
|
345
|
|
346 saa_wbytes(s, b, 8);
|
|
347 }
|
|
348
|
|
349 void 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
|
|
362 saa_wbytes(s, b, len);
|
|
363 }
|
|
364
|
|
365 #endif /* WORDS_LITTLEENDIAN */
|
|
366
|
|
367 /* write unsigned LEB128 value to SAA */
|
|
368 void saa_wleb128u(struct SAA *psaa, int value)
|
|
369 {
|
|
370 char temp[64], *ptemp;
|
|
371 uint8_t byte;
|
|
372 int len;
|
|
373
|
|
374 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);
|
|
386 }
|
|
387
|
|
388 /* write signed LEB128 value to SAA */
|
|
389 void saa_wleb128s(struct SAA *psaa, int value)
|
|
390 {
|
|
391 char temp[64], *ptemp;
|
|
392 uint8_t byte;
|
|
393 bool more, negative;
|
|
394 int size, len;
|
|
395
|
|
396 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);
|
|
418 }
|