MPX: Add test cases for MPX
[platform/upstream/nasm.git] / saa.c
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         fwrite(data, 1, 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 }