1 /*
2 Copyright (C) 2001-2015, Parrot Foundation.
3
4 =head1 NAME
5
6 src/packfile/pf_items.c - Fetch/store packfile data
7
8 =head1 DESCRIPTION
9
10 Low level packfile functions to fetch and store Parrot data, i.e.
11 C<INTVAL>, C<FLOATVAL>, C<STRING> ...
12
13 C<< PF_fetch_<item>() >> functions retrieve the datatype item from the
14 opcode stream and convert byteordering or binary format on the fly,
15 depending on the packfile header.
16
17 C<< PF_store_<item>() >> functions write the datatype item to the stream
18 as is. These functions don't check the available size.
19
20 C<< PF_size_<item>() >> functions return the store size of item in
21 C<opcode_t> units.
22
23 C<BE> and C<be> are short for "Big-endian", while C<LE> and C<le> are short
24 for "little endian".
25
26 =head2 Functions
27
28 =over 4
29
30 =cut
31
32 */
33
34 #include "parrot/parrot.h"
35 #include "pf_items.str"
36
37 /* HEADERIZER HFILE: include/parrot/packfile.h */
38
39 /* HEADERIZER BEGIN: static */
40 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
41
42 static void cvt_num12_num16(
43 ARGOUT(unsigned char *dest),
44 ARGIN(const unsigned char *src))
45 __attribute__nonnull__(1)
46 __attribute__nonnull__(2)
47 FUNC_MODIFIES(*dest);
48
49 static void cvt_num12_num16_le(
50 ARGOUT(unsigned char *dest),
51 ARGIN(const unsigned char *src))
52 __attribute__nonnull__(1)
53 __attribute__nonnull__(2)
54 FUNC_MODIFIES(*dest);
55
56 static void cvt_num12_num8(
57 ARGOUT(unsigned char *dest),
58 ARGIN(const unsigned char *src))
59 __attribute__nonnull__(1)
60 __attribute__nonnull__(2)
61 FUNC_MODIFIES(*dest);
62
63 static void cvt_num12_num8_le(
64 ARGOUT(unsigned char *dest),
65 ARGIN(const unsigned char *src))
66 __attribute__nonnull__(1)
67 __attribute__nonnull__(2)
68 FUNC_MODIFIES(*dest);
69
70 static void cvt_num16_num12(
71 ARGOUT(unsigned char *dest),
72 ARGIN(const unsigned char *src))
73 __attribute__nonnull__(1)
74 __attribute__nonnull__(2)
75 FUNC_MODIFIES(*dest);
76
77 static void cvt_num16_num12_be(
78 ARGOUT(unsigned char *dest),
79 ARGIN(const unsigned char *src))
80 __attribute__nonnull__(1)
81 __attribute__nonnull__(2)
82 FUNC_MODIFIES(*dest);
83
84 static void cvt_num16_num8(
85 ARGOUT(unsigned char *dest),
86 ARGIN(const unsigned char *src))
87 __attribute__nonnull__(1)
88 __attribute__nonnull__(2)
89 FUNC_MODIFIES(*dest);
90
91 static void cvt_num16_num8_be(
92 ARGOUT(unsigned char *dest),
93 ARGIN(const unsigned char *src))
94 __attribute__nonnull__(1)
95 __attribute__nonnull__(2)
96 FUNC_MODIFIES(*dest);
97
98 static void cvt_num16_num8_le(
99 ARGOUT(unsigned char *dest),
100 ARGIN(const unsigned char *src))
101 __attribute__nonnull__(1)
102 __attribute__nonnull__(2)
103 FUNC_MODIFIES(*dest);
104
105 static void cvt_num8_num12(
106 ARGOUT(unsigned char *dest),
107 ARGIN(const unsigned char *src))
108 __attribute__nonnull__(1)
109 __attribute__nonnull__(2)
110 FUNC_MODIFIES(*dest);
111
112 static void cvt_num8_num12_be(
113 ARGOUT(unsigned char *dest),
114 ARGIN(const unsigned char *src))
115 __attribute__nonnull__(1)
116 __attribute__nonnull__(2)
117 FUNC_MODIFIES(*dest);
118
119 static void cvt_num8_num16(
120 ARGOUT(unsigned char *dest),
121 ARGIN(const unsigned char *src))
122 __attribute__nonnull__(1)
123 __attribute__nonnull__(2)
124 FUNC_MODIFIES(*dest);
125
126 static void cvt_num8_num16_be(
127 ARGOUT(unsigned char *dest),
128 ARGIN(const unsigned char *src))
129 __attribute__nonnull__(1)
130 __attribute__nonnull__(2)
131 FUNC_MODIFIES(*dest);
132
133 static void cvt_num8_num16_le(
134 ARGOUT(unsigned char *dest),
135 ARGIN(const unsigned char *src))
136 __attribute__nonnull__(1)
137 __attribute__nonnull__(2)
138 FUNC_MODIFIES(*dest);
139
140 PARROT_INLINE
141 static void fetch_buf_be_12(
142 ARGOUT(unsigned char *rb),
143 ARGIN(const unsigned char *b))
144 __attribute__nonnull__(1)
145 __attribute__nonnull__(2)
146 FUNC_MODIFIES(*rb);
147
148 PARROT_INLINE
149 static void fetch_buf_be_16(
150 ARGOUT(unsigned char *rb),
151 ARGIN(const unsigned char *b))
152 __attribute__nonnull__(1)
153 __attribute__nonnull__(2)
154 FUNC_MODIFIES(*rb);
155
156 PARROT_INLINE
157 static void fetch_buf_be_32(
158 ARGOUT(unsigned char *rb),
159 ARGIN(const unsigned char *b))
160 __attribute__nonnull__(1)
161 __attribute__nonnull__(2)
162 FUNC_MODIFIES(*rb);
163
164 PARROT_INLINE
165 static void fetch_buf_be_4(
166 ARGOUT(unsigned char *rb),
167 ARGIN(const unsigned char *b))
168 __attribute__nonnull__(1)
169 __attribute__nonnull__(2)
170 FUNC_MODIFIES(*rb);
171
172 PARROT_INLINE
173 static void fetch_buf_be_8(
174 ARGOUT(unsigned char *rb),
175 ARGIN(const unsigned char *b))
176 __attribute__nonnull__(1)
177 __attribute__nonnull__(2)
178 FUNC_MODIFIES(*rb);
179
180 PARROT_INLINE
181 static void fetch_buf_le_12(
182 ARGOUT(unsigned char *rb),
183 ARGIN(const unsigned char *b))
184 __attribute__nonnull__(1)
185 __attribute__nonnull__(2)
186 FUNC_MODIFIES(*rb);
187
188 PARROT_INLINE
189 static void fetch_buf_le_16(
190 ARGOUT(unsigned char *rb),
191 ARGIN(const unsigned char *b))
192 __attribute__nonnull__(1)
193 __attribute__nonnull__(2)
194 FUNC_MODIFIES(*rb);
195
196 PARROT_INLINE
197 static void fetch_buf_le_32(
198 ARGOUT(unsigned char *rb),
199 ARGIN(const unsigned char *b))
200 __attribute__nonnull__(1)
201 __attribute__nonnull__(2)
202 FUNC_MODIFIES(*rb);
203
204 PARROT_INLINE
205 static void fetch_buf_le_4(
206 ARGOUT(unsigned char *rb),
207 ARGIN(const unsigned char *b))
208 __attribute__nonnull__(1)
209 __attribute__nonnull__(2)
210 FUNC_MODIFIES(*rb);
211
212 PARROT_INLINE
213 static void fetch_buf_le_8(
214 ARGOUT(unsigned char *rb),
215 ARGIN(const unsigned char *b))
216 __attribute__nonnull__(1)
217 __attribute__nonnull__(2)
218 FUNC_MODIFIES(*rb);
219
220 PARROT_INLINE
221 PARROT_WARN_UNUSED_RESULT
222 PARROT_CONST_FUNCTION
223 static INTVAL fetch_iv_be(INTVAL w);
224
225 PARROT_INLINE
226 PARROT_WARN_UNUSED_RESULT
227 PARROT_CONST_FUNCTION
228 static INTVAL fetch_iv_le(INTVAL w);
229
230 PARROT_INLINE
231 PARROT_WARN_UNUSED_RESULT
232 PARROT_CONST_FUNCTION
233 static opcode_t fetch_op_be(opcode_t w);
234
235 PARROT_WARN_UNUSED_RESULT
236 static opcode_t fetch_op_be_4(ARGIN(const unsigned char *b))
237 __attribute__nonnull__(1);
238
239 PARROT_WARN_UNUSED_RESULT
240 static opcode_t fetch_op_be_8(ARGIN(const unsigned char *b))
241 __attribute__nonnull__(1);
242
243 PARROT_INLINE
244 PARROT_WARN_UNUSED_RESULT
245 PARROT_CONST_FUNCTION
246 static opcode_t fetch_op_le(opcode_t w);
247
248 PARROT_WARN_UNUSED_RESULT
249 static opcode_t fetch_op_le_4(ARGIN(const unsigned char *b))
250 __attribute__nonnull__(1);
251
252 PARROT_WARN_UNUSED_RESULT
253 static opcode_t fetch_op_le_8(ARGIN(const unsigned char *b))
254 __attribute__nonnull__(1);
255
256 #define ASSERT_ARGS_cvt_num12_num16 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
257 PARROT_ASSERT_ARG(dest) \
258 , PARROT_ASSERT_ARG(src))
259 #define ASSERT_ARGS_cvt_num12_num16_le __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
260 PARROT_ASSERT_ARG(dest) \
261 , PARROT_ASSERT_ARG(src))
262 #define ASSERT_ARGS_cvt_num12_num8 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
263 PARROT_ASSERT_ARG(dest) \
264 , PARROT_ASSERT_ARG(src))
265 #define ASSERT_ARGS_cvt_num12_num8_le __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
266 PARROT_ASSERT_ARG(dest) \
267 , PARROT_ASSERT_ARG(src))
268 #define ASSERT_ARGS_cvt_num16_num12 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
269 PARROT_ASSERT_ARG(dest) \
270 , PARROT_ASSERT_ARG(src))
271 #define ASSERT_ARGS_cvt_num16_num12_be __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
272 PARROT_ASSERT_ARG(dest) \
273 , PARROT_ASSERT_ARG(src))
274 #define ASSERT_ARGS_cvt_num16_num8 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
275 PARROT_ASSERT_ARG(dest) \
276 , PARROT_ASSERT_ARG(src))
277 #define ASSERT_ARGS_cvt_num16_num8_be __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
278 PARROT_ASSERT_ARG(dest) \
279 , PARROT_ASSERT_ARG(src))
280 #define ASSERT_ARGS_cvt_num16_num8_le __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
281 PARROT_ASSERT_ARG(dest) \
282 , PARROT_ASSERT_ARG(src))
283 #define ASSERT_ARGS_cvt_num8_num12 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
284 PARROT_ASSERT_ARG(dest) \
285 , PARROT_ASSERT_ARG(src))
286 #define ASSERT_ARGS_cvt_num8_num12_be __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
287 PARROT_ASSERT_ARG(dest) \
288 , PARROT_ASSERT_ARG(src))
289 #define ASSERT_ARGS_cvt_num8_num16 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
290 PARROT_ASSERT_ARG(dest) \
291 , PARROT_ASSERT_ARG(src))
292 #define ASSERT_ARGS_cvt_num8_num16_be __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
293 PARROT_ASSERT_ARG(dest) \
294 , PARROT_ASSERT_ARG(src))
295 #define ASSERT_ARGS_cvt_num8_num16_le __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
296 PARROT_ASSERT_ARG(dest) \
297 , PARROT_ASSERT_ARG(src))
298 #define ASSERT_ARGS_fetch_buf_be_12 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
299 PARROT_ASSERT_ARG(rb) \
300 , PARROT_ASSERT_ARG(b))
301 #define ASSERT_ARGS_fetch_buf_be_16 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
302 PARROT_ASSERT_ARG(rb) \
303 , PARROT_ASSERT_ARG(b))
304 #define ASSERT_ARGS_fetch_buf_be_32 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
305 PARROT_ASSERT_ARG(rb) \
306 , PARROT_ASSERT_ARG(b))
307 #define ASSERT_ARGS_fetch_buf_be_4 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
308 PARROT_ASSERT_ARG(rb) \
309 , PARROT_ASSERT_ARG(b))
310 #define ASSERT_ARGS_fetch_buf_be_8 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
311 PARROT_ASSERT_ARG(rb) \
312 , PARROT_ASSERT_ARG(b))
313 #define ASSERT_ARGS_fetch_buf_le_12 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
314 PARROT_ASSERT_ARG(rb) \
315 , PARROT_ASSERT_ARG(b))
316 #define ASSERT_ARGS_fetch_buf_le_16 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
317 PARROT_ASSERT_ARG(rb) \
318 , PARROT_ASSERT_ARG(b))
319 #define ASSERT_ARGS_fetch_buf_le_32 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
320 PARROT_ASSERT_ARG(rb) \
321 , PARROT_ASSERT_ARG(b))
322 #define ASSERT_ARGS_fetch_buf_le_4 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
323 PARROT_ASSERT_ARG(rb) \
324 , PARROT_ASSERT_ARG(b))
325 #define ASSERT_ARGS_fetch_buf_le_8 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
326 PARROT_ASSERT_ARG(rb) \
327 , PARROT_ASSERT_ARG(b))
328 #define ASSERT_ARGS_fetch_iv_be __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
329 #define ASSERT_ARGS_fetch_iv_le __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
330 #define ASSERT_ARGS_fetch_op_be __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
331 #define ASSERT_ARGS_fetch_op_be_4 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
332 PARROT_ASSERT_ARG(b))
333 #define ASSERT_ARGS_fetch_op_be_8 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
334 PARROT_ASSERT_ARG(b))
335 #define ASSERT_ARGS_fetch_op_le __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
336 #define ASSERT_ARGS_fetch_op_le_4 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
337 PARROT_ASSERT_ARG(b))
338 #define ASSERT_ARGS_fetch_op_le_8 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
339 PARROT_ASSERT_ARG(b))
340 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
341 /* HEADERIZER END: static */
342
343 /*
344 * round val up to whole size, return result in bytes
345 */
346 #define ROUND_UP_B(val, size) ((((val) + ((size) - 1))/(size)) * (size))
347
348 /*
349 * round val up to whole opcode_t, return result in opcodes
350 */
351 #define ROUND_UP(val, size) (((val) + ((size) - 1))/(size))
352
353 /*
354 * offset not in ptr diff, but in byte
355 */
356 #define OFFS(pf, cursor) ((pf) ? ((const char *)(cursor) - (const char *)((pf)->src)) : 0)
357
358 /*
359 * low level FLOATVAL fetch and convert functions
360 *
361 * Floattype 0 = IEEE-754 8 byte double
362 * Floattype 1 = x86 little endian 12 byte long double
363 * Floattype 2 = IEEE-754 16 byte long double
364 *
365 */
366
367 /*
368
369 =item C<static void cvt_num12_num8(unsigned char *dest, const unsigned char
370 *src)>
371
372 Converts i386 LE 12-byte long double to IEEE 754 8-byte double.
373
374 Tested ok.
375
376 =cut
377
378 */
379
380 #if (NUMVAL_SIZE == 8)
381 static void
cvt_num12_num8(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))382 cvt_num12_num8(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
383 {
384 ASSERT_ARGS(cvt_num12_num8)
385 int expo, i, s;
386 # ifdef __LCC__
387 int expo2;
388 # endif
389
390 /*
391 12-byte double (96 bits):
392 sign 1 bit 95
393 exp 15 bits 94-80
394 man 80 bits 79-0
395 to 8-byte double (64 bits):
396 sign 1 bit 63
397 exp 11 bits 62-52
398 man 52 bits 51-0
399
400 +-------+-------+-------+-------+-------+-------+--...--+-------+
401 |src[11]|src[10]|src[9] |src[8] |src[7] |src[6] | ... |src[0] |
402 S| E | F |
403 +-------+-------+-------+-------+-------+-------+--...--+-------+
404 1|<-----15----->|<----------------80 bits---------------------->|
405 <----------------------------96 bits---------------------------->
406
407 +-------+-------+-------+-------+-------+-------+-------+-------+
408 |dest[7]|dest[6]|dest[5]|dest[4]|dest[3]|dest[2]|dest[1]|dest[0]|
409 S| E | F |
410 +-------+-------+-------+-------+-------+-------+-------+-------+
411 1|<---11-->|<---------------------52 bits---------------------->|
412 <----------------------------64 bits---------------------------->
413 8-byte DOUBLE FLOATING-POINT
414 */
415
416 memset(dest, 0, 8);
417 /* exponents 15 -> 11 bits */
418 s = src[9] & 0x80; /* sign */
419 expo = ((src[9] & 0x7f)<< 8 | src[8]);
420 if (expo == 0) {
421 nul:
422 if (s)
423 dest[7] |= 0x80;
424 return;
425 }
426 # ifdef __LCC__
427 /* Yet again, LCC blows up mysteriously until a temporary variable is
428 * added. */
429 expo2 = expo - 16383;
430 expo = expo2;
431 # else
432 expo -= 16383; /* - bias */
433 # endif
434 expo += 1023; /* + bias 8byte */
435 if (expo <= 0) /* underflow */
436 goto nul;
437 if (expo > 0x7ff) { /* inf/nan */
438 dest[7] = 0x7f;
439 dest[6] = src[7] == 0xc0 ? 0xf8 : 0xf0 ;
440 goto nul;
441 }
442 expo <<= 4;
443 dest[6] = (expo & 0xff);
444 dest[7] = (expo & 0x7f00) >> 8;
445 if (s)
446 dest[7] |= 0x80;
447 /* long double frac 63 bits => 52 bits
448 src[7] &= 0x7f; reset integer bit */
449 for (i = 0; i < 6; ++i) {
450 dest[i+1] |= (i==5 ? src[7]&0x7f : src[i+2]) >> 3;
451 dest[i] |= (src[i+2] & 0x1f) << 5;
452 }
453 dest[0] |= src[1] >> 3;
454 }
455 #endif
456
457 /*
458
459 =item C<static void cvt_num16_num12(unsigned char *dest, const unsigned char
460 *src)>
461
462 Converts IEEE 754 LE 16-byte long double to i386 LE 12-byte long double.
463 See http://babbage.cs.qc.cuny.edu/IEEE-754/References.xhtml
464
465 Tested ok.
466
467 =cut
468
469 */
470
471 #if (NUMVAL_SIZE == 12)
472 static void
cvt_num16_num12(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))473 cvt_num16_num12(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
474 {
475 ASSERT_ARGS(cvt_num16_num12)
476
477 /*
478 16-byte double (128 bits):
479 sign 1 bit 127
480 exp 15 bits 126-112
481 man 112 bits 111-0
482 to 12-byte double (96 bits):
483 sign 1 bit 95
484 exp 15 bits 94-80
485 man 80 bits 79-0
486
487 +-------+-------+-------+-------+-------+-------+--...--+-------+
488 |src[15]|src[14]|src[13]|src[12]|src[11]|src[10]| ... |src[0] |
489 S| E | F |
490 +-------+-------+-------+-------+-------+-------+--...--+-------+
491 1|<-----15----->|<----------------112 bits--------------------->|
492 <---------------------------128 bits---------------------------->
493 16-byte LONG DOUBLE FLOATING-POINT (IA64 or BE 64-bit)
494
495 +-------+-------+-------+-------+-------+-------+--...--+-------+
496 |dest[11]dest[10]dest[9]|dest[8]|dest[7]|dest[6]| ... |dest[0]|
497 S| E | F |
498 +-------+-------+-------+-------+-------+-------+--...--+-------+
499 1|<-----15----->|<----------------80 bits---------------------->|
500 <----------------------------96 bits---------------------------->
501 12-byte LONG DOUBLE FLOATING-POINT (i386 special)
502
503 */
504
505 memset(dest, 0, 12);
506 /* simply copy over sign + exp */
507 dest[10] = src[15];
508 dest[11] = src[14];
509 /* and copy the rest */
510 memcpy(&dest[0], &src[0], 10);
511 }
512 #endif
513
514 /*
515
516 =item C<static void cvt_num12_num16(unsigned char *dest, const unsigned char
517 *src)>
518
519 Converts i386 LE 12-byte long double to IEEE 754 LE 16-byte long double.
520
521 Tested ok.
522 Fallback 12->8->16 disabled.
523
524 =cut
525
526 */
527
528 #if (NUMVAL_SIZE == 16)
529 static void
cvt_num12_num16(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))530 cvt_num12_num16(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
531 {
532 ASSERT_ARGS(cvt_num12_num16)
533 # if 0
534 unsigned char b[8];
535 cvt_num12_num8(b, src);
536 cvt_num8_num16(dest, b);
537 # endif
538 /*
539 12-byte double (96 bits):
540 sign 1 bit 95
541 exp 15 bits 94-80
542 man 80 bits 79-0
543 to 16-byte double (128 bits):
544 sign 1 bit 127
545 exp 15 bits 126-112
546 man 112 bits 111-0
547
548 +-------+-------+-------+-------+-------+-------+--...--+-------+
549 |src[11]|src[10]| src[9]| src[8]| src[7]| src[6]| ... | src[0]|
550 S| E | F |
551 +-------+-------+-------+-------+-------+-------+--...--+-------+
552 1|<-----15----->|<----------------80 bits---------------------->|
553 <----------------------------96 bits---------------------------->
554 12-byte LONG DOUBLE FLOATING-POINT (i386 special)
555
556 +-------+-------+-------+-------+-------+-------+--...--+-------+
557 |dest[15]dest[14]dest[13]dest[12]dest[11]dest[10] ... |dest[0]|
558 S| E | F |
559 +-------+-------+-------+-------+-------+-------+--...--+-------+
560 1|<-----15----->|<----------------112 bits--------------------->|
561 <---------------------------128 bits---------------------------->
562 16-byte LONG DOUBLE FLOATING-POINT (x86_64 or BE 64-bit)
563
564 */
565
566 memset(dest, 0, 16);
567 /* simply copy over sign + exp */
568 dest[15] = src[11];
569 dest[14] = src[10];
570 /* and copy the rest */
571 memcpy(&dest[0], &src[0], 10);
572 }
573 #endif
574 /*
575
576 =item C<static void cvt_num16_num8(unsigned char *dest, const unsigned char
577 *src)>
578
579 Converts IEEE 754 16-byte long double to IEEE 754 8 byte double.
580
581 First variant ok, 2nd not ok.
582
583 =cut
584
585 */
586
587 #if (NUMVAL_SIZE == 8)
588 static void
cvt_num16_num8(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))589 cvt_num16_num8(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
590 {
591 ASSERT_ARGS(cvt_num16_num8)
592
593 if ((sizeof (long double) == 16) && (sizeof (double) == 8)) {
594
595 long double ld;
596 double d;
597
598 memcpy(&ld, src, 16);
599 d = (double)ld; /* compiler cast */
600 memcpy(dest, &d, 8);
601
602 }
603 else {
604 # if !PARROT_BIGENDIAN
605 /* assume intel 10-byte padded to 16 byte, not a true __float128 */
606 cvt_num12_num8(dest, src);
607 return;
608 # endif
609 Parrot_x_force_error_exit(NULL, 1, "cvt_num16_num8: long double conversion unsupported");
610 }
611 }
612 #endif
613
614 /*
615
616 =item C<static void cvt_num8_num16(unsigned char *dest, const unsigned char
617 *src)>
618
619 Converts IEEE 754 8-byte double to IEEE 754 16 byte long double.
620
621 Tested ok.
622
623 =cut
624
625 */
626
627 #if (NUMVAL_SIZE == 16)
628 static void
cvt_num8_num16(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))629 cvt_num8_num16(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
630 {
631 ASSERT_ARGS(cvt_num8_num16)
632 /* The compiler can do this for us */
633 long double ld;
634 double d;
635 memcpy(&d, src, 8);
636 ld = (long double)d; /* TODO: test compiler cast */
637 memcpy(dest, &ld, 16);
638 }
639 #endif
640
641 /*
642
643 =item C<static void cvt_num8_num12(unsigned char *dest, const unsigned char
644 *src)>
645
646 Converts i386 8-byte double to i386 12 byte long double.
647
648 Tested ok.
649
650 =cut
651
652 */
653
654 #if (NUMVAL_SIZE == 12) && !PARROT_BIGENDIAN
655 static void
cvt_num8_num12(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))656 cvt_num8_num12(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
657 {
658 ASSERT_ARGS(cvt_num8_num12)
659 long double ld;
660 double d;
661 memcpy(&d, src, 8);
662 ld = (long double)d; /* compiler cast */
663 memcpy(dest, &ld, 12);
664 }
665 #endif
666
667
668 /*
669
670 =item C<static void cvt_num8_num12_be(unsigned char *dest, const unsigned char
671 *src)>
672
673 Converts a big-endian IEEE 754 8-byte double to i386 LE 12-byte long double.
674
675 Tested ok.
676
677 =cut
678
679 */
680
681 #if (NUMVAL_SIZE == 12) && !PARROT_BIGENDIAN
682 static void
cvt_num8_num12_be(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))683 cvt_num8_num12_be(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
684 {
685 ASSERT_ARGS(cvt_num8_num12_be)
686 unsigned char b[8];
687 fetch_buf_be_8(b, src);
688 cvt_num8_num12(dest, b);
689 }
690 #endif
691
692 /*
693
694 =item C<static void cvt_num8_num16_le(unsigned char *dest, const unsigned char
695 *src)>
696
697 Converts a little-endian IEEE 754 8-byte double to big-endian 16-byte long double.
698
699 Yet untested.
700
701 =cut
702
703 */
704
705 #if (NUMVAL_SIZE == 16) && PARROT_BIGENDIAN
706 static void
cvt_num8_num16_le(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))707 cvt_num8_num16_le(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
708 {
709 ASSERT_ARGS(cvt_num8_num16_le)
710 unsigned char b[8];
711 fetch_buf_be_8(b, src); /* TODO test endianize */
712 cvt_num8_num16(dest, b);
713 }
714 #endif
715
716 /*
717
718 =item C<static void cvt_num12_num16_le(unsigned char *dest, const unsigned char
719 *src)>
720
721 Converts a little-endian 12-byte double to big-endian 16-byte long double.
722
723 Tested nok.
724
725 =cut
726
727 */
728
729 #if (NUMVAL_SIZE == 16) && PARROT_BIGENDIAN
730 static void
cvt_num12_num16_le(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))731 cvt_num12_num16_le(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
732 {
733 ASSERT_ARGS(cvt_num12_num16_le)
734 unsigned char b[12];
735 fetch_buf_be_12(b, src); /* TODO test endianize */
736 cvt_num12_num16(dest, b);
737 }
738 #endif
739
740 /*
741
742 =item C<static void cvt_num12_num8_le(unsigned char *dest, const unsigned char
743 *src)>
744
745 Converts a little-endian 12-byte i386 long double into a big-endian IEEE 754 8-byte double.
746
747 =cut
748
749 */
750
751 #if (NUMVAL_SIZE == 8) && PARROT_BIGENDIAN
752 static void
cvt_num12_num8_le(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))753 cvt_num12_num8_le(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
754 {
755 ASSERT_ARGS(cvt_num12_num8_le)
756 unsigned char b[12];
757 fetch_buf_le_12(b, src); /* TODO test endianize */
758 cvt_num12_num8(dest, b);
759 }
760 #endif
761
762 /*
763
764 =item C<static void cvt_num16_num8_le(unsigned char *dest, const unsigned char
765 *src)>
766
767 Converts a little-endian intel 16-byte long double (i.e. 10-byte)
768 into a big-endian IEEE 754 8-byte double.
769
770 For a true little-endian __float128, see C<cvt_num16_num8_be()>.
771
772 =cut
773
774 */
775
776 #if (NUMVAL_SIZE == 8) && PARROT_BIGENDIAN
777 static void
cvt_num16_num8_le(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))778 cvt_num16_num8_le(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
779 {
780 ASSERT_ARGS(cvt_num16_num8_le)
781 unsigned char b[16];
782 fetch_buf_le_16(b, src);
783 cvt_num16_num8(dest, b);
784 }
785 #endif
786
787 /*
788
789 =item C<static void cvt_num16_num8_be(unsigned char *dest, const unsigned char
790 *src)>
791
792 Converts a big-endian IEEE 754 16-byte __float128 (not a powerpc double-double)
793 into a little-endian IEEE 754 8-byte double.
794
795 Untested.
796
797 =cut
798
799 */
800
801 #if (NUMVAL_SIZE == 8) && !PARROT_BIGENDIAN
802 static void
cvt_num16_num8_be(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))803 cvt_num16_num8_be(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
804 {
805 ASSERT_ARGS(cvt_num16_num8_be)
806 unsigned char b[16];
807 int expo, i, s;
808 # ifdef __LCC__
809 int expo2;
810 # endif
811
812 fetch_buf_be_16(b, src);
813
814 /*
815 16-byte double (128 bits):
816 sign 1 bit 127
817 exp 15 bits 126-112
818 man 112 bits 111-0
819 to 8-byte double (64 bits):
820 sign 1 bit 63
821 exp 11 bits 62-52
822 man 52 bits 51-0
823
824 +-------+-------+-------+-------+-------+-------+--...--+-------+
825 |src[15]|src[14]|src[13]|src[12]|src[11]|src[10]| ... |src[0] |
826 S| E | F |
827 +-------+-------+-------+-------+-------+-------+--...--+-------+
828 1|<-----15----->|<----------------112 bits--------------------->|
829 <---------------------------128 bits---------------------------->
830 16-byte __float128 (BE 64-bit)
831
832 +-------+-------+-------+-------+-------+-------+-------+-------+
833 |dest[7]|dest[6]|dest[5]|dest[4]|dest[3]|dest[2]|dest[1]|dest[0]|
834 S| E | F |
835 +-------+-------+-------+-------+-------+-------+-------+-------+
836 1|<---11-->|<---------------------52 bits---------------------->|
837 <----------------------------64 bits---------------------------->
838 8-byte DOUBLE FLOATING-POINT
839
840 */
841
842 memset(dest, 0, 8);
843 s = b[15] & 0x80; /* 10000000 */
844 /* 15->11 exponents bits */
845 expo = ((b[15] & 0x7f)<< 8 | b[14]);
846 if (expo == 0) {
847 nul:
848 if (s)
849 dest[7] |= 0x80;
850 return;
851 }
852 # ifdef __LCC__
853 /* LCC blows up mysteriously until a temporary variable is
854 * added. */
855 expo2 = expo - 16383;
856 expo = expo2;
857 # else
858 expo -= 16383; /* - same bias as with 12-byte */
859 # endif
860 expo += 1023; /* + bias 8byte */
861 if (expo <= 0) /* underflow */
862 goto nul;
863 if (expo > 0x7ff) { /* inf/nan */
864 dest[7] = 0x7f;
865 dest[6] = b[7] == 0xc0 ? 0xf8 : 0xf0 ;
866 goto nul;
867 }
868 expo <<= 4;
869 dest[6] = (expo & 0xff);
870 dest[7] = (expo & 0x7f00) >> 8;
871 if (s)
872 dest[7] |= 0x80;
873 /* long double frac 112 bits => 52 bits
874 b[13] &= 0x7f; reset integer bit */
875 for (i = 0; i < 6; ++i) {
876 dest[i+1] |= (i==5 ? b[13]&0x7f : b[i+7]) >> 3;
877 dest[i] |= (b[i+7] & 0x1f) << 5;
878 }
879 dest[0] |= b[1] >> 3;
880 }
881 #endif
882
883 /*
884
885 =item C<static void cvt_num16_num12_be(unsigned char *dest, const unsigned char
886 *src)>
887
888 Converts a big-endian IEEE 754 16-byte long double into a 12-byte i386 long double.
889
890 Untested.
891
892 =cut
893
894 */
895
896 #if (NUMVAL_SIZE == 12) && !PARROT_BIGENDIAN
897 static void
cvt_num16_num12_be(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))898 cvt_num16_num12_be(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
899 {
900 ASSERT_ARGS(cvt_num16_num12_be)
901 unsigned char b[16];
902 fetch_buf_be_16(b, src);
903 cvt_num16_num12(dest, b);
904 }
905 #endif
906
907 /*
908
909 =item C<static void cvt_num8_num16_be(unsigned char *dest, const unsigned char
910 *src)>
911
912 Converts a big-endian IEEE 754 8-byte double to little-endian IEEE 754 16 byte
913 long double.
914
915 Untested.
916
917 =cut
918
919 */
920
921 #if (NUMVAL_SIZE == 16) && !PARROT_BIGENDIAN
922 static void
cvt_num8_num16_be(ARGOUT (unsigned char * dest),ARGIN (const unsigned char * src))923 cvt_num8_num16_be(ARGOUT(unsigned char *dest), ARGIN(const unsigned char *src))
924 {
925 ASSERT_ARGS(cvt_num8_num16_be)
926 unsigned char b[8];
927 fetch_buf_be_8(b, src);
928 cvt_num8_num16(dest, b);
929 }
930 #endif
931
932 /*
933
934 =item C<static opcode_t fetch_op_be_4(const unsigned char *b)>
935
936 Fetches a 4-byte big-endian opcode.
937
938 =cut
939
940 */
941
942 PARROT_WARN_UNUSED_RESULT
943 static opcode_t
fetch_op_be_4(ARGIN (const unsigned char * b))944 fetch_op_be_4(ARGIN(const unsigned char *b))
945 {
946 ASSERT_ARGS(fetch_op_be_4)
947 union {
948 unsigned char buf[4];
949 opcode_t o;
950 } u;
951 fetch_buf_be_4(u.buf, b);
952 #if PARROT_BIGENDIAN
953 # if OPCODE_T_SIZE == 8
954 return (Parrot_Int4)(u.o >> 32);
955 # else
956 return u.o;
957 # endif
958 #else
959 # if OPCODE_T_SIZE == 8
960 return (Parrot_Int4)(fetch_iv_le(u.o) & 0xffffffff);
961 # else
962 return (opcode_t) fetch_iv_le(u.o);
963 # endif
964 #endif
965 }
966
967 /*
968
969 =item C<static opcode_t fetch_op_be_8(const unsigned char *b)>
970
971 Fetches an 8-byte big-endian opcode.
972
973 =cut
974
975 */
976
977 PARROT_WARN_UNUSED_RESULT
978 static opcode_t
fetch_op_be_8(ARGIN (const unsigned char * b))979 fetch_op_be_8(ARGIN(const unsigned char *b))
980 {
981 ASSERT_ARGS(fetch_op_be_8)
982 union {
983 unsigned char buf[8];
984 opcode_t o[2];
985 } u;
986 fetch_buf_be_8(u.buf, b);
987 #if PARROT_BIGENDIAN
988 # if OPCODE_T_SIZE == 8
989 return u.o[0];
990 # else
991 return u.o[1];
992 # endif
993 #else
994 return (opcode_t) fetch_iv_le((INTVAL)u.o[0]);
995 #endif
996 }
997
998 /*
999
1000 =item C<static opcode_t fetch_op_le_4(const unsigned char *b)>
1001
1002 Fetches a 4-byte little-endian opcode
1003
1004 =cut
1005
1006 */
1007
1008 PARROT_WARN_UNUSED_RESULT
1009 static opcode_t
fetch_op_le_4(ARGIN (const unsigned char * b))1010 fetch_op_le_4(ARGIN(const unsigned char *b))
1011 {
1012 ASSERT_ARGS(fetch_op_le_4)
1013 union {
1014 unsigned char buf[4];
1015 opcode_t o;
1016 } u;
1017 fetch_buf_le_4(u.buf, b);
1018 #if PARROT_BIGENDIAN
1019 # if OPCODE_T_SIZE == 8
1020 return (Parrot_Int4)(u.o >> 32);
1021 # else
1022 return (opcode_t) fetch_iv_be((INTVAL)u.o);
1023 # endif
1024 #else
1025 # if OPCODE_T_SIZE == 8
1026 /* without the cast we would not get a negative int, the vtable indices */
1027 return (Parrot_Int4)(u.o & 0xffffffff);
1028 # else
1029 return u.o;
1030 # endif
1031 #endif
1032 }
1033
1034 /*
1035
1036 =item C<static opcode_t fetch_op_le_8(const unsigned char *b)>
1037
1038 Fetches an 8-byte little-endian opcode
1039
1040 =cut
1041
1042 */
1043
1044 PARROT_WARN_UNUSED_RESULT
1045 static opcode_t
fetch_op_le_8(ARGIN (const unsigned char * b))1046 fetch_op_le_8(ARGIN(const unsigned char *b))
1047 {
1048 ASSERT_ARGS(fetch_op_le_8)
1049 union {
1050 unsigned char buf[8];
1051 opcode_t o[2];
1052 } u;
1053 fetch_buf_le_8(u.buf, b);
1054 #if PARROT_BIGENDIAN
1055 # if OPCODE_T_SIZE == 8
1056 return u.o[0];
1057 # else
1058 return (opcode_t) fetch_op_be((INTVAL)u.o[1]);
1059 # endif
1060 #else
1061 return u.o[0];
1062 #endif
1063 }
1064
1065 /*
1066
1067 =item C<opcode_t PF_fetch_opcode(const PackFile *pf, const opcode_t **stream)>
1068
1069 Fetches an C<opcode_t> from the stream, converting byteorder if needed.
1070
1071 When used for freeze/thaw the C<pf> argument might be NULL.
1072
1073 =cut
1074
1075 */
1076
1077 opcode_t
PF_fetch_opcode(ARGIN_NULLOK (const PackFile * pf),ARGMOD (const opcode_t ** stream))1078 PF_fetch_opcode(ARGIN_NULLOK(const PackFile *pf), ARGMOD(const opcode_t **stream))
1079 {
1080 ASSERT_ARGS(PF_fetch_opcode)
1081 if (!pf || !pf->fetch_op) {
1082 return *(*stream)++;
1083 }
1084 else {
1085 const unsigned char *ucstream = *(const unsigned char **)stream;
1086 opcode_t o = (pf->fetch_op)(ucstream);
1087 ucstream += pf->header->wordsize;
1088 /* XXX -Wcast-align Need to check alignment for RISC, or memcpy */
1089 *stream = (const opcode_t *)ucstream;
1090 return o;
1091 }
1092 }
1093
1094 /*
1095
1096 =item C<opcode_t* PF_store_opcode(opcode_t *cursor, opcode_t val)>
1097
1098 Stores an C<opcode_t> to stream as-is.
1099
1100 =cut
1101
1102 */
1103
1104 PARROT_WARN_UNUSED_RESULT
1105 PARROT_CANNOT_RETURN_NULL
1106 opcode_t*
PF_store_opcode(ARGOUT (opcode_t * cursor),opcode_t val)1107 PF_store_opcode(ARGOUT(opcode_t *cursor), opcode_t val)
1108 {
1109 ASSERT_ARGS(PF_store_opcode)
1110 *cursor++ = val;
1111 return cursor;
1112 }
1113
1114 /*
1115
1116 =item C<size_t PF_size_opcode(void)>
1117
1118 Returns the size of an item in C<opcode_t> units. The size of C<opcode_t>
1119 is 1 I<per definition>.
1120
1121 =cut
1122
1123 */
1124
1125 PARROT_CONST_FUNCTION
1126 PARROT_WARN_UNUSED_RESULT
1127 size_t
PF_size_opcode(void)1128 PF_size_opcode(void)
1129 {
1130 ASSERT_ARGS(PF_size_opcode)
1131 return 1;
1132 }
1133
1134 /*
1135
1136 =item C<INTVAL PF_fetch_integer(PackFile *pf, const opcode_t **stream)>
1137
1138 Fetches an C<INTVAL> from the stream, converting byteorder if needed.
1139
1140 XXX assumes C<sizeof (INTVAL) == sizeof (opcode_t)> - we don't have
1141 C<INTVAL> size in the PackFile header. See TT #1047 or RT #56810.
1142
1143 =cut
1144
1145 */
1146
1147 PARROT_WARN_UNUSED_RESULT
1148 INTVAL
PF_fetch_integer(ARGIN (PackFile * pf),ARGIN (const opcode_t ** stream))1149 PF_fetch_integer(ARGIN(PackFile *pf), ARGIN(const opcode_t **stream))
1150 {
1151 ASSERT_ARGS(PF_fetch_integer)
1152 INTVAL i;
1153
1154 if (!pf->fetch_iv)
1155 return *(*stream)++;
1156 i = (pf->fetch_iv)(*((const unsigned char **)stream));
1157
1158 /* XXX assume sizeof (opcode_t) == sizeof (INTVAL) on the
1159 * machine producing this PBC.
1160 *
1161 * TODO GH #415 on Sparc 64bit: On pbc wordsize=4 but native ptrsize=8 and
1162 * ptr_alignment=8 the advance by 4 will signal BUS (invalid address alignment)
1163 * in PF_fetch_integer and elsewhere.
1164 */
1165 *((const unsigned char **) (stream)) += pf->header->wordsize;
1166 return i;
1167 }
1168
1169
1170 /*
1171
1172 =item C<opcode_t* PF_store_integer(opcode_t *cursor, INTVAL val)>
1173
1174 Stores an C<INTVAL> to stream as is.
1175
1176 =cut
1177
1178 */
1179
1180 PARROT_WARN_UNUSED_RESULT
1181 PARROT_CANNOT_RETURN_NULL
1182 opcode_t*
PF_store_integer(ARGOUT (opcode_t * cursor),INTVAL val)1183 PF_store_integer(ARGOUT(opcode_t *cursor), INTVAL val)
1184 {
1185 ASSERT_ARGS(PF_store_integer)
1186 *cursor++ = (opcode_t)val; /* XXX */
1187 return cursor;
1188 }
1189
1190 /*
1191
1192 =item C<size_t PF_size_integer(void)>
1193
1194 Returns stored size of C<INTVAL> in C<opcode_t> units.
1195
1196 =cut
1197
1198 */
1199
1200 PARROT_CONST_FUNCTION
1201 size_t
PF_size_integer(void)1202 PF_size_integer(void)
1203 {
1204 ASSERT_ARGS(PF_size_integer)
1205 return sizeof (INTVAL) / sizeof (opcode_t);
1206 }
1207
1208 /*
1209
1210 =item C<FLOATVAL PF_fetch_number(PackFile *pf, const opcode_t **stream)>
1211
1212 Fetches a C<FLOATVAL> from the stream, converting byteorder if needed.
1213 Then advances the stream pointer by the packfile float size.
1214
1215 =cut
1216
1217 */
1218
1219 PARROT_WARN_UNUSED_RESULT
1220 FLOATVAL
PF_fetch_number(ARGIN_NULLOK (PackFile * pf),ARGIN (const opcode_t ** stream))1221 PF_fetch_number(ARGIN_NULLOK(PackFile *pf), ARGIN(const opcode_t **stream))
1222 {
1223 ASSERT_ARGS(PF_fetch_number)
1224 /* When we have alignment all squared away we don't need
1225 * to use memcpy() for native byteorder. */
1226 FLOATVAL f;
1227 double d;
1228 if (!pf || !pf->fetch_nv) {
1229 memcpy(&f, (const char *)*stream, sizeof (FLOATVAL));
1230 (*stream) += (sizeof (FLOATVAL) + sizeof (opcode_t) - 1)/
1231 sizeof (opcode_t);
1232 return f;
1233 }
1234 f = (FLOATVAL) 0;
1235 /* 12->8 has a messy cast. */
1236 if (NUMVAL_SIZE == 8 && pf->header->floattype == FLOATTYPE_12) {
1237 (pf->fetch_nv)((unsigned char *)&d, (const unsigned char *) *stream);
1238 f = d;
1239 }
1240 else {
1241 (pf->fetch_nv)((unsigned char *)&f, (const unsigned char *) *stream);
1242 }
1243 if (pf->header->floattype == FLOATTYPE_8) {
1244 *((const unsigned char **) (stream)) += 8;
1245 }
1246 else if (pf->header->floattype == FLOATTYPE_12) {
1247 *((const unsigned char **) (stream)) += 12;
1248 }
1249 else if (pf->header->floattype == FLOATTYPE_16) {
1250 *((const unsigned char **) (stream)) += 16;
1251 }
1252 else if (pf->header->floattype == FLOATTYPE_16MIPS) {
1253 *((const unsigned char **) (stream)) += 16;
1254 }
1255 else if (pf->header->floattype == FLOATTYPE_16AIX) {
1256 *((const unsigned char **) (stream)) += 16;
1257 }
1258 else if (pf->header->floattype == FLOATTYPE_4) {
1259 *((const unsigned char **) (stream)) += 4;
1260 }
1261 return f;
1262 }
1263
1264 /*
1265
1266 =item C<opcode_t* PF_store_number(opcode_t *cursor, const FLOATVAL *val)>
1267
1268 Writes a C<FLOATVAL> to the opcode stream as-is.
1269
1270 =cut
1271
1272 */
1273
1274 PARROT_WARN_UNUSED_RESULT
1275 PARROT_CANNOT_RETURN_NULL
1276 opcode_t*
PF_store_number(ARGOUT (opcode_t * cursor),ARGIN (const FLOATVAL * val))1277 PF_store_number(ARGOUT(opcode_t *cursor), ARGIN(const FLOATVAL *val))
1278 {
1279 ASSERT_ARGS(PF_store_number)
1280 opcode_t padded_size = (sizeof (FLOATVAL) + sizeof (opcode_t) - 1) /
1281 sizeof (opcode_t);
1282 memcpy(cursor, val, sizeof (FLOATVAL));
1283 cursor += padded_size;
1284 return cursor;
1285 }
1286
1287 /*
1288
1289 =item C<size_t PF_size_number(void)>
1290
1291 Returns stored size of FLOATVAL in C<opcode_t> units.
1292
1293 =cut
1294
1295 */
1296
1297 PARROT_CONST_FUNCTION
1298 size_t
PF_size_number(void)1299 PF_size_number(void)
1300 {
1301 ASSERT_ARGS(PF_size_number)
1302 return ROUND_UP(sizeof (FLOATVAL), sizeof (opcode_t));
1303 }
1304
1305 /*
1306
1307 =item C<STRING * PF_fetch_buf(PARROT_INTERP, PackFile *pf, const opcode_t
1308 **cursor)>
1309
1310 Fetches a buffer (fixed_8 encoded temporary C<STRING>) from bytecode.
1311
1312 Opcode format is:
1313
1314 opcode_t size
1315 * data
1316
1317 When used for freeze/thaw, the C<pf> argument might be C<NULL>.
1318
1319 The returned buffer points to the underlying packfile. It should be used and
1320 discarded immediately to avoid things changing underneath you.
1321
1322 =cut
1323
1324 */
1325
1326
1327 PARROT_WARN_UNUSED_RESULT
1328 PARROT_CANNOT_RETURN_NULL
1329 STRING *
PF_fetch_buf(PARROT_INTERP,ARGIN_NULLOK (PackFile * pf),ARGIN (const opcode_t ** cursor))1330 PF_fetch_buf(PARROT_INTERP, ARGIN_NULLOK(PackFile *pf), ARGIN(const opcode_t **cursor))
1331 {
1332 ASSERT_ARGS(PF_fetch_buf)
1333 const int wordsize = pf ? pf->header->wordsize : sizeof (opcode_t);
1334 size_t size = PF_fetch_opcode(pf, cursor);
1335 STRING *s = Parrot_str_new_init(interp, (const char *)*cursor, size,
1336 Parrot_binary_encoding_ptr,
1337 PObj_external_FLAG);
1338 *((const unsigned char **)(cursor)) += ROUND_UP_B(size, wordsize);
1339 return s;
1340 }
1341
1342
1343 /*
1344
1345 =item C<opcode_t* PF_store_buf(opcode_t *cursor, const STRING *s)>
1346
1347 Write a buffer (fixed_8 encoded, binary string) to the opcode stream. These
1348 are encoded more compactly and read more efficiently than normal strings, but
1349 have limitations (see C<PF_fetch_buf>).
1350
1351 =cut
1352
1353 */
1354
1355 PARROT_WARN_UNUSED_RESULT
1356 PARROT_CANNOT_RETURN_NULL
1357 opcode_t*
PF_store_buf(ARGOUT (opcode_t * cursor),ARGIN (const STRING * s))1358 PF_store_buf(ARGOUT(opcode_t *cursor), ARGIN(const STRING *s))
1359 {
1360 ASSERT_ARGS(PF_store_buf)
1361 const int wordsize = sizeof (opcode_t);
1362
1363 PARROT_ASSERT(s->encoding == Parrot_binary_encoding_ptr);
1364
1365 *cursor++ = s->bufused;
1366
1367 if (s->strstart) {
1368 char *charcursor = (char *) cursor;
1369 memcpy(charcursor, s->strstart, s->bufused);
1370 charcursor += s->bufused;
1371
1372 /* Pad up to wordsize boundary. */
1373 while ((charcursor - (char *)cursor) % wordsize)
1374 *charcursor++ = 0;
1375
1376 cursor += (charcursor - (char *)cursor) / wordsize;
1377 }
1378
1379 return cursor;
1380 }
1381
1382
1383 /*
1384
1385 =item C<size_t PF_size_buf(const STRING *s)>
1386
1387 Reports the stored size of a buffer in C<opcode_t> units.
1388
1389 =cut
1390
1391 */
1392
1393 PARROT_PURE_FUNCTION
1394 size_t
PF_size_buf(ARGIN (const STRING * s))1395 PF_size_buf(ARGIN(const STRING *s))
1396 {
1397 ASSERT_ARGS(PF_size_buf)
1398 if (STRING_IS_NULL(s))
1399 return 1;
1400 else
1401 return PF_size_strlen(s->bufused) - 1;
1402 }
1403
1404
1405 /*
1406
1407 =item C<STRING * PF_fetch_string(PARROT_INTERP, PackFile *pf, const opcode_t
1408 **cursor)>
1409
1410 Fetches a C<STRING> from bytecode and return a new C<STRING>.
1411
1412 Opcode format is:
1413
1414 opcode_t flags8 | encoding
1415 opcode_t size
1416 * data
1417
1418 When used for freeze/thaw the C<pf> argument might be NULL.
1419
1420 =cut
1421
1422 */
1423
1424 PARROT_WARN_UNUSED_RESULT
1425 PARROT_CANNOT_RETURN_NULL
1426 STRING *
PF_fetch_string(PARROT_INTERP,ARGIN_NULLOK (PackFile * pf),ARGIN (const opcode_t ** cursor))1427 PF_fetch_string(PARROT_INTERP, ARGIN_NULLOK(PackFile *pf), ARGIN(const opcode_t **cursor))
1428 {
1429 ASSERT_ARGS(PF_fetch_string)
1430 STRING *s;
1431 UINTVAL flags;
1432 UINTVAL encoding_nr;
1433 const STR_VTABLE *encoding;
1434 size_t size;
1435 const int wordsize = pf ? pf->header->wordsize : sizeof (opcode_t);
1436 opcode_t flag_charset_word = PF_fetch_opcode(pf, cursor);
1437
1438 if (flag_charset_word == -1)
1439 return STRINGNULL;
1440
1441 /* decode flags, charset and encoding */
1442 flags = (flag_charset_word & 0x1 ? PObj_constant_FLAG : 0) |
1443 (flag_charset_word & 0x2 ? PObj_private7_FLAG : 0) ;
1444 encoding_nr = (flag_charset_word >> 8) & 0xFF;
1445
1446 size = (size_t)PF_fetch_opcode(pf, cursor);
1447
1448 encoding = Parrot_get_encoding(interp, encoding_nr);
1449 if (!encoding)
1450 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
1451 "Invalid encoding number '%d' specified", encoding_nr);
1452
1453 if (size || (encoding != CONST_STRING(interp, "")->encoding))
1454 s = Parrot_str_new_init(interp, (const char *)*cursor, size,
1455 encoding, flags);
1456 else
1457 s = CONST_STRING(interp, "");
1458
1459 size = ROUND_UP_B(size, wordsize);
1460 *((const unsigned char **) (cursor)) += size;
1461
1462 return s;
1463 }
1464
1465
1466 /*
1467
1468 =item C<opcode_t* PF_store_string(opcode_t *cursor, const STRING *s)>
1469
1470 Writes a C<STRING> to the opcode stream.
1471
1472 =cut
1473
1474 */
1475
1476 PARROT_WARN_UNUSED_RESULT
1477 PARROT_CANNOT_RETURN_NULL
1478 opcode_t*
PF_store_string(ARGOUT (opcode_t * cursor),ARGIN (const STRING * s))1479 PF_store_string(ARGOUT(opcode_t *cursor), ARGIN(const STRING *s))
1480 {
1481 ASSERT_ARGS(PF_store_string)
1482 opcode_t padded_size = s->bufused;
1483 char *charcursor;
1484
1485 if (padded_size % sizeof (opcode_t)) {
1486 padded_size += sizeof (opcode_t) - (padded_size % sizeof (opcode_t));
1487 }
1488
1489 if (STRING_IS_NULL(s)) {
1490 /* preserve NULL-ness of strings */
1491 *cursor++ = -1;
1492 return cursor;
1493 }
1494
1495 /*
1496 * TODO as soon as we have dynamically loadable charsets
1497 * we have to store the charset name, not the number
1498 *
1499 * TODO encoding
1500 *
1501 * see also PF_fetch_string
1502 */
1503
1504 /* encode charset_nr, encoding_nr and flags into the same word */
1505 *cursor++ = (Parrot_encoding_number_of_str(NULL, s) << 8) |
1506 (PObj_get_FLAGS(s) & PObj_constant_FLAG ? 0x1 : 0x0) |
1507 (PObj_get_FLAGS(s) & PObj_private7_FLAG ? 0x2 : 0x0) ;
1508 *cursor++ = s->bufused;
1509
1510 /* Switch to char * since rest of string is addressed by
1511 * characters to ensure padding. */
1512 charcursor = (char *)cursor;
1513
1514 if (s->strstart) {
1515 memcpy(charcursor, s->strstart, s->bufused);
1516 charcursor += s->bufused;
1517 /* Pad up to sizeof (opcode_t) boundary. */
1518 while ((unsigned long) (charcursor - (char *) cursor) % sizeof (opcode_t)) {
1519 *charcursor++ = 0;
1520 }
1521 }
1522 PARROT_ASSERT(((unsigned long) (charcursor - (char *) cursor) % sizeof (opcode_t)) == 0);
1523 cursor += (charcursor - (char *) cursor) / sizeof (opcode_t);
1524
1525 return cursor;
1526 }
1527
1528 /*
1529
1530 =item C<size_t PF_size_string(const STRING *s)>
1531
1532 Reports stored size of C<STRING> in C<opcode_t> units.
1533
1534 =cut
1535
1536 */
1537
1538 PARROT_PURE_FUNCTION
1539 size_t
PF_size_string(ARGIN (const STRING * s))1540 PF_size_string(ARGIN(const STRING *s))
1541 {
1542 ASSERT_ARGS(PF_size_string)
1543 /* TODO: don't break encapsulation on strings */
1544 const UINTVAL len = s->bufused;
1545 if (STRING_IS_NULL(s))
1546 return 1;
1547 else
1548 return PF_size_strlen(len);
1549 }
1550
1551 /*
1552
1553 =item C<size_t PF_size_strlen(const UINTVAL len)>
1554
1555 Reports stored size of C<STRING> in C<opcode_t> units given its in-memory byte length.
1556
1557 =cut
1558
1559 */
1560
1561 PARROT_CONST_FUNCTION
1562 PARROT_WARN_UNUSED_RESULT
1563 size_t
PF_size_strlen(const UINTVAL len)1564 PF_size_strlen(const UINTVAL len)
1565 {
1566 ASSERT_ARGS(PF_size_strlen)
1567 opcode_t padded_size = len;
1568
1569 if (padded_size % sizeof (opcode_t)) {
1570 padded_size += sizeof (opcode_t) - (padded_size % sizeof (opcode_t));
1571 }
1572
1573 /* Include space for flags, representation, and size fields. */
1574 return 2 + (size_t)padded_size / sizeof (opcode_t);
1575 }
1576
1577 /*
1578
1579 =item C<char * PF_fetch_cstring(PARROT_INTERP, PackFile *pf, const opcode_t
1580 **cursor)>
1581
1582 Fetches a cstring from bytecode and returns an allocated copy
1583
1584 =cut
1585
1586 */
1587
1588 PARROT_MALLOC
1589 PARROT_CANNOT_RETURN_NULL
1590 char *
PF_fetch_cstring(PARROT_INTERP,ARGIN (PackFile * pf),ARGIN (const opcode_t ** cursor))1591 PF_fetch_cstring(PARROT_INTERP, ARGIN(PackFile *pf), ARGIN(const opcode_t **cursor))
1592 {
1593 ASSERT_ARGS(PF_fetch_cstring)
1594 const size_t str_len = strlen((const char *)(*cursor)) + 1;
1595 char * const p = mem_gc_allocate_n_typed(interp, str_len, char);
1596 const int wordsize = pf->header->wordsize;
1597
1598 strcpy(p, (const char*) (*cursor));
1599 *((const unsigned char **) (cursor)) += ROUND_UP_B(str_len, wordsize);
1600 return p;
1601 }
1602
1603 /*
1604
1605 =item C<opcode_t* PF_store_cstring(opcode_t *cursor, const char *s)>
1606
1607 Writes a C<NULL>-terminated string to the stream.
1608
1609 =cut
1610
1611 */
1612
1613 PARROT_WARN_UNUSED_RESULT
1614 PARROT_CANNOT_RETURN_NULL
1615 opcode_t*
PF_store_cstring(ARGOUT (opcode_t * cursor),ARGIN (const char * s))1616 PF_store_cstring(ARGOUT(opcode_t *cursor), ARGIN(const char *s))
1617 {
1618 ASSERT_ARGS(PF_store_cstring)
1619 /*
1620 * This is not very efficient for filling padding with zeros.
1621 * But it's more efficient than calculate strlen twice.
1622 */
1623 size_t store_size = PF_size_cstring(s);
1624 memset((char *) cursor, 0, store_size * sizeof (opcode_t));
1625 strcpy((char *) cursor, s);
1626 return cursor + store_size;
1627 }
1628
1629 /*
1630
1631 =item C<size_t PF_size_cstring(const char *s)>
1632
1633 Returns store size of a C-string in C<opcode_t> units.
1634
1635 =cut
1636
1637 */
1638
1639 PARROT_PURE_FUNCTION
1640 size_t
PF_size_cstring(ARGIN (const char * s))1641 PF_size_cstring(ARGIN(const char *s))
1642 {
1643 ASSERT_ARGS(PF_size_cstring)
1644 size_t str_len;
1645
1646 PARROT_ASSERT(s);
1647 str_len = strlen(s);
1648 return ROUND_UP(str_len + 1, sizeof (opcode_t));
1649 }
1650
1651 /*
1652
1653 =item C<void PackFile_assign_transforms(PackFile *pf)>
1654
1655 Assigns transform functions to the vtable.
1656
1657 =cut
1658
1659 */
1660
1661 void
PackFile_assign_transforms(ARGMOD (PackFile * pf))1662 PackFile_assign_transforms(ARGMOD(PackFile *pf))
1663 {
1664 ASSERT_ARGS(PackFile_assign_transforms)
1665 const int need_endianize = pf->header->byteorder != PARROT_BIGENDIAN;
1666 const int need_wordsize = pf->header->wordsize != sizeof (opcode_t);
1667
1668 pf->need_endianize = need_endianize;
1669 pf->need_wordsize = need_wordsize;
1670
1671 #if PARROT_BIGENDIAN
1672 /* this Parrot is on a BIG ENDIAN machine */
1673 if (need_endianize) {
1674 if (pf->header->wordsize == 4)
1675 pf->fetch_op = fetch_op_le_4;
1676 else
1677 pf->fetch_op = fetch_op_le_8;
1678 pf->fetch_iv = pf->fetch_op;
1679
1680 switch (pf->header->floattype) {
1681 # if NUMVAL_SIZE == 8
1682 case FLOATTYPE_8:
1683 pf->fetch_nv = fetch_buf_le_8;
1684 break;
1685 case FLOATTYPE_12:
1686 pf->fetch_nv = cvt_num12_num8_le;
1687 break;
1688 case FLOATTYPE_16:
1689 pf->fetch_nv = cvt_num16_num8_le;
1690 break;
1691 # endif
1692 # if NUMVAL_SIZE == 16
1693 case FLOATTYPE_8:
1694 pf->fetch_nv = cvt_num8_num16_le;
1695 break;
1696 case FLOATTYPE_12:
1697 pf->fetch_nv = cvt_num12_num16_le;
1698 break;
1699 case FLOATTYPE_16:
1700 pf->fetch_nv = fetch_buf_le_16;
1701 break;
1702 # endif
1703 default:
1704 Parrot_x_force_error_exit(NULL, 1,
1705 "PackFile_unpack: unsupported float conversion %d to %d, "
1706 "PARROT_BIGENDIAN=%d\n",
1707 NUMVAL_SIZE, pf->header->floattype, PARROT_BIGENDIAN);
1708 break;
1709 }
1710 return;
1711 }
1712 else { /* no need_endianize */
1713 if (pf->header->wordsize == 4)
1714 pf->fetch_op = fetch_op_be_4;
1715 else
1716 pf->fetch_op = fetch_op_be_8;
1717 pf->fetch_iv = pf->fetch_op;
1718
1719 switch (pf->header->floattype) {
1720 # if NUMVAL_SIZE == 8
1721 case FLOATTYPE_8: /* native */
1722 break;
1723 case FLOATTYPE_12:
1724 pf->fetch_nv = cvt_num12_num8;
1725 break;
1726 case FLOATTYPE_16:
1727 pf->fetch_nv = cvt_num16_num8;
1728 break;
1729 # endif
1730 # if NUMVAL_SIZE == 16
1731 case FLOATTYPE_8:
1732 pf->fetch_nv = cvt_num8_num16;
1733 break;
1734 case FLOATTYPE_12:
1735 pf->fetch_nv = cvt_num12_num16;
1736 break;
1737 case FLOATTYPE_16: /* native */
1738 break;
1739 # endif
1740 default:
1741 Parrot_x_force_error_exit(NULL, 1,
1742 "PackFile_unpack: unsupported float conversion %d to %d, "
1743 "PARROT_BIGENDIAN=%d\n",
1744 NUMVAL_SIZE, pf->header->floattype, PARROT_BIGENDIAN);
1745 break;
1746 }
1747 return;
1748 }
1749
1750 #else /* ENDIAN */
1751
1752 /* this Parrot is on a LITTLE ENDIAN machine */
1753 if (need_endianize) {
1754 if (pf->header->wordsize == 4)
1755 pf->fetch_op = fetch_op_be_4;
1756 else
1757 pf->fetch_op = fetch_op_be_8;
1758 pf->fetch_iv = pf->fetch_op;
1759
1760 switch (pf->header->floattype) {
1761 # if NUMVAL_SIZE == 8
1762 case FLOATTYPE_8:
1763 pf->fetch_nv = fetch_buf_be_8;
1764 break;
1765 case FLOATTYPE_12:
1766 Parrot_x_force_error_exit(NULL, 1, "PackFile_unpack: invalid floattype 1 big-endian");
1767 break;
1768 case FLOATTYPE_16:
1769 pf->fetch_nv = cvt_num16_num8_be;
1770 break;
1771 # endif
1772 # if NUMVAL_SIZE == 12
1773 case FLOATTYPE_8:
1774 pf->fetch_nv = cvt_num8_num12_be;
1775 break;
1776 case FLOATTYPE_12:
1777 Parrot_x_force_error_exit(NULL, 1, "PackFile_unpack: invalid floattype 1 big-endian");
1778 break;
1779 case FLOATTYPE_16:
1780 pf->fetch_nv = cvt_num16_num12_be;
1781 break;
1782 # endif
1783 # if NUMVAL_SIZE == 16
1784 case FLOATTYPE_8:
1785 pf->fetch_nv = cvt_num8_num16_be;
1786 break;
1787 case FLOATTYPE_12:
1788 Parrot_x_force_error_exit(NULL, 1, "PackFile_unpack: invalid floattype 1 big-endian");
1789 break;
1790 case FLOATTYPE_16:
1791 pf->fetch_nv = fetch_buf_be_16;
1792 break;
1793 # endif
1794 default:
1795 Parrot_x_force_error_exit(NULL, 1,
1796 "PackFile_unpack: unsupported float conversion %d to %d, "
1797 "PARROT_BIGENDIAN=%d\n",
1798 NUMVAL_SIZE, pf->header->floattype, PARROT_BIGENDIAN);
1799 break;
1800 }
1801 return;
1802 }
1803 else {
1804 if (pf->header->wordsize == 4)
1805 pf->fetch_op = fetch_op_le_4;
1806 else
1807 pf->fetch_op = fetch_op_le_8;
1808 pf->fetch_iv = pf->fetch_op;
1809
1810 switch (pf->header->floattype) {
1811 # if NUMVAL_SIZE == 8
1812 case FLOATTYPE_8: /* native */
1813 break;
1814 case FLOATTYPE_12:
1815 pf->fetch_nv = cvt_num12_num8;
1816 break;
1817 case FLOATTYPE_16:
1818 pf->fetch_nv = cvt_num16_num8;
1819 break;
1820 # endif
1821 # if NUMVAL_SIZE == 12
1822 case FLOATTYPE_8:
1823 pf->fetch_nv = cvt_num8_num12;
1824 break;
1825 case FLOATTYPE_12: /* native */
1826 break;
1827 case FLOATTYPE_16:
1828 pf->fetch_nv = cvt_num16_num12;
1829 break;
1830 # endif
1831 # if NUMVAL_SIZE == 16
1832 case FLOATTYPE_8:
1833 pf->fetch_nv = cvt_num8_num16;
1834 break;
1835 case FLOATTYPE_12:
1836 pf->fetch_nv = cvt_num12_num16;
1837 break;
1838 case FLOATTYPE_16: /* native */
1839 break;
1840 # endif
1841 default:
1842 Parrot_x_force_error_exit(NULL, 1,
1843 "PackFile_unpack: unsupported float conversion %d to %d, "
1844 "PARROT_BIGENDIAN=%d\n",
1845 NUMVAL_SIZE, pf->header->floattype, PARROT_BIGENDIAN);
1846 break;
1847 }
1848 return;
1849 }
1850 #endif
1851 }
1852
1853
1854 /*
1855
1856 =item C<static INTVAL fetch_iv_le(INTVAL w)>
1857
1858 This function converts a 4 or 8 byte C<INTVAL> into little endian
1859 format. If the native format is already little endian, then no
1860 conversion is done.
1861
1862 =cut
1863
1864 */
1865
1866 PARROT_INLINE
1867 PARROT_WARN_UNUSED_RESULT
1868 PARROT_CONST_FUNCTION
1869 static INTVAL
fetch_iv_le(INTVAL w)1870 fetch_iv_le(INTVAL w)
1871 {
1872 ASSERT_ARGS(fetch_iv_le)
1873 #if !PARROT_BIGENDIAN
1874 return w;
1875 #else
1876 # if INTVAL_SIZE == 4
1877 return (w << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | (w >> 24);
1878 # else
1879 # if INTVAL_SIZE == 8
1880 INTVAL r;
1881
1882 r = w << 56;
1883 r |= (w & 0xff00) << 40;
1884 r |= (w & 0xff0000) << 24;
1885 r |= (w & 0xff000000) << 8;
1886 r |= (w & 0xff00000000) >> 8;
1887 r |= (w & 0xff0000000000) >> 24;
1888 r |= (w & 0xff000000000000) >> 40;
1889 r |= (w & 0xff00000000000000) >> 56;
1890 return r;
1891 # else
1892 Parrot_x_force_error_exit(NULL, 1, "Unsupported INTVAL_SIZE=%d\n",
1893 INTVAL_SIZE);
1894 # endif
1895 # endif
1896 #endif
1897 }
1898
1899 /*
1900
1901 =item C<static INTVAL fetch_iv_be(INTVAL w)>
1902
1903 This function converts a 4 or 8 byte C<INTVAL> into big endian format.
1904 If the native format is already big endian, then no conversion is done.
1905
1906 =cut
1907
1908 */
1909
1910 PARROT_INLINE
1911 PARROT_WARN_UNUSED_RESULT
1912 PARROT_CONST_FUNCTION
1913 static INTVAL
fetch_iv_be(INTVAL w)1914 fetch_iv_be(INTVAL w)
1915 {
1916 ASSERT_ARGS(fetch_iv_be)
1917 #if PARROT_BIGENDIAN
1918 return w;
1919 #else
1920 # if INTVAL_SIZE == 4
1921 return (w << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | (w >> 24);
1922 # else
1923 # if INTVAL_SIZE == 8
1924 INTVAL r;
1925 r = w << 56;
1926 r |= (w & 0xff00) << 40;
1927 r |= (w & 0xff0000) << 24;
1928 r |= (w & 0xff000000) << 8;
1929 r |= (w & 0xff00000000) >> 8;
1930 r |= (w & 0xff0000000000) >> 24;
1931 r |= (w & 0xff000000000000) >> 40;
1932 r |= (w & 0xff00000000000000) >> 56;
1933 return r;
1934 # else
1935 Parrot_x_force_error_exit(NULL, 1, "Unsupported INTVAL_SIZE=%d\n", INTVAL_SIZE);
1936 # endif
1937 # endif
1938 #endif
1939 }
1940
1941 /*
1942
1943 =item C<static opcode_t fetch_op_be(opcode_t w)>
1944
1945 Same as C<fetch_iv_be> for opcode_t
1946
1947 =cut
1948
1949 */
1950
1951 PARROT_INLINE
1952 PARROT_WARN_UNUSED_RESULT
1953 PARROT_CONST_FUNCTION
1954 static opcode_t
fetch_op_be(opcode_t w)1955 fetch_op_be(opcode_t w)
1956 {
1957 ASSERT_ARGS(fetch_op_be)
1958 #if PARROT_BIGENDIAN
1959 return w;
1960 #else
1961 # if OPCODE_T_SIZE == 4
1962 return (w << 24) | ((w & 0x0000ff00) << 8) | ((w & 0x00ff0000) >> 8) |
1963 ((w & 0xff000000) >> 24);
1964 # else
1965 opcode_t r;
1966
1967 r = w << 56;
1968 r |= (w & 0xff00) << 40;
1969 r |= (w & 0xff0000) << 24;
1970 r |= (w & 0xff000000) << 8;
1971 r |= (w & 0xff00000000) >> 8;
1972 r |= (w & 0xff0000000000) >> 24;
1973 r |= (w & 0xff000000000000) >> 40;
1974 r |= (w & 0xff00000000000000) >> 56;
1975 return r;
1976 # endif
1977 #endif
1978 }
1979
1980 /*
1981
1982 =item C<static opcode_t fetch_op_le(opcode_t w)>
1983
1984 Same as C<fetch_iv_le> for opcode_t
1985
1986 =cut
1987
1988 */
1989
1990 PARROT_INLINE
1991 PARROT_WARN_UNUSED_RESULT
1992 PARROT_CONST_FUNCTION
1993 static opcode_t
fetch_op_le(opcode_t w)1994 fetch_op_le(opcode_t w)
1995 {
1996 ASSERT_ARGS(fetch_op_le)
1997 #if !PARROT_BIGENDIAN
1998 return w;
1999 #else
2000 # if OPCODE_T_SIZE == 4
2001 return (w << 24) | ((w & 0x0000ff00) << 8) | ((w & 0x00ff0000) >> 8) |
2002 ((w & 0xff000000) >> 24);
2003 # else
2004 opcode_t r;
2005
2006 r = w << 56;
2007 r |= (w & 0xff00) << 40;
2008 r |= (w & 0xff0000) << 24;
2009 r |= (w & 0xff000000) << 8;
2010 r |= (w & 0xff00000000) >> 8;
2011 r |= (w & 0xff0000000000) >> 24;
2012 r |= (w & 0xff000000000000) >> 40;
2013 r |= (w & 0xff00000000000000) >> 56;
2014 return r;
2015 # endif
2016 #endif
2017 }
2018
2019 /*
2020
2021 =pod
2022
2023 Unrolled routines for swapping various sizes from 32-128 bits. These
2024 should only be used if alignment is unknown or we are pulling something
2025 out of a padded buffer.
2026
2027 =cut
2028
2029 */
2030
2031 /*
2032
2033 =item C<static void fetch_buf_be_4(unsigned char *rb, const unsigned char *b)>
2034
2035 Converts a 4-byte big-endian buffer C<b> into a little-endian C<rb>.
2036
2037 =cut
2038
2039 */
2040
2041 PARROT_INLINE
2042 static void
fetch_buf_be_4(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2043 fetch_buf_be_4(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2044 {
2045 ASSERT_ARGS(fetch_buf_be_4)
2046 #if PARROT_BIGENDIAN
2047 memcpy(rb, b, 4);
2048 #else
2049 rb[0] = b[3];
2050 rb[1] = b[2];
2051 rb[2] = b[1];
2052 rb[3] = b[0];
2053 #endif
2054 }
2055
2056 /*
2057
2058 =item C<static void fetch_buf_le_4(unsigned char *rb, const unsigned char *b)>
2059
2060 Converts a 4-byte little-endian buffer C<b> into a big-endian buffer C<rb>.
2061
2062 =cut
2063
2064 */
2065
2066 PARROT_INLINE
2067 static void
fetch_buf_le_4(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2068 fetch_buf_le_4(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2069 {
2070 ASSERT_ARGS(fetch_buf_le_4)
2071 #if !PARROT_BIGENDIAN
2072 memcpy(rb, b, 4);
2073 #else
2074 rb[0] = b[3];
2075 rb[1] = b[2];
2076 rb[2] = b[1];
2077 rb[3] = b[0];
2078 #endif
2079 }
2080
2081 /*
2082
2083 =item C<static void fetch_buf_be_8(unsigned char *rb, const unsigned char *b)>
2084
2085 Converts an 8-byte big-endian buffer C<b> into a little-endian buffer C<rb>
2086
2087 =cut
2088
2089 */
2090
2091 PARROT_INLINE
2092 static void
fetch_buf_be_8(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2093 fetch_buf_be_8(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2094 {
2095 ASSERT_ARGS(fetch_buf_be_8)
2096 #if PARROT_BIGENDIAN
2097 memcpy(rb, b, 8);
2098 #else
2099 rb[0] = b[7];
2100 rb[1] = b[6];
2101 rb[2] = b[5];
2102 rb[3] = b[4];
2103 rb[4] = b[3];
2104 rb[5] = b[2];
2105 rb[6] = b[1];
2106 rb[7] = b[0];
2107 #endif
2108 }
2109
2110 /*
2111
2112 =item C<static void fetch_buf_le_8(unsigned char *rb, const unsigned char *b)>
2113
2114 Converts an 8-byte little-endian buffer C<b> into a big-endian buffer C<rb>.
2115
2116 =cut
2117
2118 */
2119
2120 PARROT_INLINE
2121 static void
fetch_buf_le_8(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2122 fetch_buf_le_8(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2123 {
2124 ASSERT_ARGS(fetch_buf_le_8)
2125 #if !PARROT_BIGENDIAN
2126 memcpy(rb, b, 8);
2127 #else
2128 rb[0] = b[7];
2129 rb[1] = b[6];
2130 rb[2] = b[5];
2131 rb[3] = b[4];
2132 rb[4] = b[3];
2133 rb[5] = b[2];
2134 rb[6] = b[1];
2135 rb[7] = b[0];
2136 #endif
2137 }
2138
2139 /*
2140
2141 =item C<static void fetch_buf_le_12(unsigned char *rb, const unsigned char *b)>
2142
2143 Converts a 12-byte little-endian buffer C<b> into a big-endian buffer C<b>.
2144
2145 =cut
2146
2147 */
2148
2149 PARROT_INLINE
2150 static void
fetch_buf_le_12(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2151 fetch_buf_le_12(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2152 {
2153 ASSERT_ARGS(fetch_buf_le_12)
2154 #if !PARROT_BIGENDIAN
2155 memcpy(rb, b, 12);
2156 #else
2157 rb[0] = b[11];
2158 rb[1] = b[10];
2159 rb[2] = b[9];
2160 rb[3] = b[8];
2161 rb[4] = b[7];
2162 rb[5] = b[6];
2163 rb[6] = b[5];
2164 rb[7] = b[4];
2165 rb[8] = b[3];
2166 rb[9] = b[2];
2167 rb[10] = b[1];
2168 rb[11] = b[0];
2169 #endif
2170 }
2171
2172 /*
2173
2174 =item C<static void fetch_buf_be_12(unsigned char *rb, const unsigned char *b)>
2175
2176 Converts a 12-byte big-endian buffer C<b> into a little-endian buffer C<b>.
2177
2178 =cut
2179
2180 */
2181
2182 PARROT_INLINE
2183 static void
fetch_buf_be_12(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2184 fetch_buf_be_12(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2185 {
2186 ASSERT_ARGS(fetch_buf_be_12)
2187 #if PARROT_BIGENDIAN
2188 memcpy(rb, b, 12);
2189 #else
2190 rb[0] = b[11];
2191 rb[1] = b[10];
2192 rb[2] = b[9];
2193 rb[3] = b[8];
2194 rb[4] = b[7];
2195 rb[5] = b[6];
2196 rb[6] = b[5];
2197 rb[7] = b[4];
2198 rb[8] = b[3];
2199 rb[9] = b[2];
2200 rb[10] = b[1];
2201 rb[11] = b[0];
2202 #endif
2203 }
2204
2205 /*
2206
2207 =item C<static void fetch_buf_le_16(unsigned char *rb, const unsigned char *b)>
2208
2209 Converts a 16-byte little-endian buffer C<b> into a big-endian buffer C<b>.
2210
2211 =cut
2212
2213 */
2214
2215 PARROT_INLINE
2216 static void
fetch_buf_le_16(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2217 fetch_buf_le_16(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2218 {
2219 ASSERT_ARGS(fetch_buf_le_16)
2220 #if !PARROT_BIGENDIAN
2221 memcpy(rb, b, 16);
2222 #else
2223 rb[0] = b[15];
2224 rb[1] = b[14];
2225 rb[2] = b[13];
2226 rb[3] = b[12];
2227 rb[4] = b[11];
2228 rb[5] = b[10];
2229 rb[6] = b[9];
2230 rb[7] = b[8];
2231 rb[8] = b[7];
2232 rb[9] = b[6];
2233 rb[10] = b[5];
2234 rb[11] = b[4];
2235 rb[12] = b[3];
2236 rb[13] = b[2];
2237 rb[14] = b[1];
2238 rb[15] = b[0];
2239 #endif
2240 }
2241
2242 /*
2243
2244 =item C<static void fetch_buf_be_16(unsigned char *rb, const unsigned char *b)>
2245
2246 Converts a 16-byte big-endian buffer C<b> into a little-endian buffer C<b>.
2247
2248 =cut
2249
2250 */
2251
2252 PARROT_INLINE
2253 static void
fetch_buf_be_16(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2254 fetch_buf_be_16(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2255 {
2256 ASSERT_ARGS(fetch_buf_be_16)
2257 #if PARROT_BIGENDIAN
2258 memcpy(rb, b, 16);
2259 #else
2260 rb[0] = b[15];
2261 rb[1] = b[14];
2262 rb[2] = b[13];
2263 rb[3] = b[12];
2264 rb[4] = b[11];
2265 rb[5] = b[10];
2266 rb[6] = b[9];
2267 rb[7] = b[8];
2268 rb[8] = b[7];
2269 rb[9] = b[6];
2270 rb[10] = b[5];
2271 rb[11] = b[4];
2272 rb[12] = b[3];
2273 rb[13] = b[2];
2274 rb[14] = b[1];
2275 rb[15] = b[0];
2276 #endif
2277 }
2278
2279 /*
2280
2281 =item C<static void fetch_buf_le_32(unsigned char *rb, const unsigned char *b)>
2282
2283 Converts a 32-byte little-endian buffer C<b> into a big-endian buffer C<b>.
2284
2285 =cut
2286
2287 */
2288
2289 PARROT_INLINE
2290 static void
fetch_buf_le_32(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2291 fetch_buf_le_32(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2292 {
2293 ASSERT_ARGS(fetch_buf_le_32)
2294 #if !PARROT_BIGENDIAN
2295 memcpy(rb, b, 32);
2296 #else
2297 rb[0] = b[31];
2298 rb[1] = b[30];
2299 rb[2] = b[29];
2300 rb[3] = b[28];
2301 rb[4] = b[27];
2302 rb[5] = b[26];
2303 rb[6] = b[25];
2304 rb[7] = b[24];
2305 rb[8] = b[23];
2306 rb[9] = b[22];
2307 rb[10] = b[21];
2308 rb[11] = b[20];
2309 rb[12] = b[19];
2310 rb[13] = b[18];
2311 rb[14] = b[17];
2312 rb[15] = b[16];
2313 rb[16] = b[15];
2314 rb[17] = b[14];
2315 rb[18] = b[13];
2316 rb[19] = b[12];
2317 rb[20] = b[11];
2318 rb[21] = b[10];
2319 rb[22] = b[9];
2320 rb[23] = b[8];
2321 rb[24] = b[7];
2322 rb[25] = b[6];
2323 rb[26] = b[5];
2324 rb[27] = b[4];
2325 rb[28] = b[3];
2326 rb[29] = b[2];
2327 rb[30] = b[1];
2328 rb[31] = b[0];
2329 #endif
2330 }
2331
2332 /*
2333
2334 =item C<static void fetch_buf_be_32(unsigned char *rb, const unsigned char *b)>
2335
2336 Converts a 32-byte big-endian buffer C<b> into a little-endian buffer C<b>.
2337
2338 =cut
2339
2340 */
2341
2342 PARROT_INLINE
2343 static void
fetch_buf_be_32(ARGOUT (unsigned char * rb),ARGIN (const unsigned char * b))2344 fetch_buf_be_32(ARGOUT(unsigned char *rb), ARGIN(const unsigned char *b))
2345 {
2346 ASSERT_ARGS(fetch_buf_be_32)
2347 #if PARROT_BIGENDIAN
2348 memcpy(rb, b, 32);
2349 #else
2350 rb[0] = b[31];
2351 rb[1] = b[30];
2352 rb[2] = b[29];
2353 rb[3] = b[28];
2354 rb[4] = b[27];
2355 rb[5] = b[26];
2356 rb[6] = b[25];
2357 rb[7] = b[24];
2358 rb[8] = b[23];
2359 rb[9] = b[22];
2360 rb[10] = b[21];
2361 rb[11] = b[20];
2362 rb[12] = b[19];
2363 rb[13] = b[18];
2364 rb[14] = b[17];
2365 rb[15] = b[16];
2366 rb[16] = b[15];
2367 rb[17] = b[14];
2368 rb[18] = b[13];
2369 rb[19] = b[12];
2370 rb[20] = b[11];
2371 rb[21] = b[10];
2372 rb[22] = b[9];
2373 rb[23] = b[8];
2374 rb[24] = b[7];
2375 rb[25] = b[6];
2376 rb[26] = b[5];
2377 rb[27] = b[4];
2378 rb[28] = b[3];
2379 rb[29] = b[2];
2380 rb[30] = b[1];
2381 rb[31] = b[0];
2382 #endif
2383 }
2384
2385
2386 /*
2387
2388 =back
2389
2390 =head1 TODO
2391
2392 C<<PF_store_<type>()>> - write an opcode_t stream to cursor in natural
2393 byte-ordering.
2394
2395 C<<PF_fetch_<type>()>> - read items and possibly convert the foreign
2396 format.
2397
2398 C<<PF_size_<type>()>> - return the needed size in C<opcode_t> units.
2399
2400 =cut
2401
2402 */
2403
2404 /*
2405 * Local variables:
2406 * c-file-style: "parrot"
2407 * End:
2408 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
2409 */
2410