# New Ticket Created by Leopold Toetsch # Please include the string: [perl #20597] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=20597 >
Next try. This patch obsoletes #20584. - more wordsize fixes - routine for converting i386 12 byte long double to IEEE (modulo NaN's and such) - the latter needs still work, if machine is big endian, but swapping buffer bytes before or after ;-) could do it. Thanks for testing. leo -- attachment 1 ------------------------------------------------------ url: http://rt.perl.org/rt2/attach/49861/38438/6d8a85/packfile6.patch
--- parrot/include/parrot/packfile.h Tue Jan 28 10:21:49 2003 +++ parrot-leo/include/parrot/packfile.h Tue Jan 28 12:56:08 2003 @@ -319,11 +319,13 @@ opcode_t * PackFile_Constant_unpack_key(struct Parrot_Interp *interpreter, struct PackFile * pf, struct PackFile_Constant *, opcode_t * packed); -opcode_t PackFile_fetch_op(struct PackFile *pf, opcode_t *stream); +opcode_t PackFile_fetch_op(struct PackFile *pf, opcode_t **stream); -INTVAL PackFile_fetch_iv(struct PackFile *pf, opcode_t *stream); +INTVAL PackFile_fetch_iv(struct PackFile *pf, opcode_t **stream); FLOATVAL PackFile_fetch_nv(struct PackFile *pf, opcode_t **stream); + +char * PackFile_fetch_cstring(struct PackFile *pf, opcode_t **stream); void PackFile_assign_transforms(struct PackFile *pf); --- parrot/packfile.c Tue Jan 28 10:21:48 2003 +++ parrot-leo/packfile.c Wed Jan 29 08:57:06 2003 @@ -95,13 +95,16 @@ ***************************************/ opcode_t -PackFile_fetch_op(struct PackFile *pf, opcode_t *stream) { - if(pf->fetch_op == NULL) - return *stream; +PackFile_fetch_op(struct PackFile *pf, opcode_t **stream) { + opcode_t o; + if (!pf->fetch_op) + return *(*stream)++; #if TRACE_PACKFILE == 2 PIO_eprintf(NULL, "PackFile_fetch_op: Reordering.\n"); #endif - return (pf->fetch_op)(*stream); + o = (pf->fetch_op)(**stream); + ((unsigned char *) (*stream)) += pf->header->wordsize; + return o; } /*************************************** @@ -116,12 +119,53 @@ ***************************************/ INTVAL -PackFile_fetch_iv(struct PackFile *pf, opcode_t *stream) { +PackFile_fetch_iv(struct PackFile *pf, opcode_t **stream) { if(pf->fetch_iv == NULL) - return *stream; - return (pf->fetch_iv)(*stream); + return *(*stream++); + PIO_eprintf(NULL, "PackFile_fetch_iv: Unsupported.\n"); + exit(1); + return (pf->fetch_iv)(**stream); } +/* convert i386 LE 12 byte long double to IEEE 8 byte doubles + * TODO: nan's and such + */ +static void cvt_num12_num8(unsigned char *dest, unsigned char *src) +{ + int expo, i, s; + + memset (dest, 0, 8); + /* exponents 15 -> 11 bits */ + s = src[9] & 0x80; /* sign */ + expo = ((src[9] & 0x7f)<< 8 | src[8]) - 16383; /* - bias */ + expo += 1023; /* + bias 8byte */ + expo <<= 4; + dest[6] = (expo & 0xff); + dest[7] = (expo & 0x7f00) >> 8; + if (s) + dest[7] |= 0x80; + /* long double frac 63 bits => 52 bits + src[7] &= 0x7f; reset integer bit */ + for (i = 0; i < 6; i++) { + dest[i+1] |= (i==5 ? src[7]&0x7f : src[i+2]) >> 3; + dest[i] |= (src[i+2] & 0x1f) << 5; + } + dest[0] |= src[1] >> 3; +} + +static void cvt_num12_num8_be(unsigned char *dest, unsigned char *src) +{ + cvt_num12_num8(dest, src); + /* TODO endianize */ + internal_exception(1, "TODO cvt_num12_num8_be\n"); +} + +static void cvt_num12_num8_le(unsigned char *dest, unsigned char *src) +{ + cvt_num12_num8(dest, src); + /* TODO endianize */ + internal_exception(1, "TODO cvt_num12_num8_le\n"); +} /*************************************** =item fetch_nv @@ -140,9 +184,8 @@ * to use memcpy() for native byteorder. */ FLOATVAL f; - HUGEFLOATVAL g; double d; - if(pf->fetch_nv == NULL) { + if (!pf->fetch_nv) { #if TRACE_PACKFILE PIO_eprintf(NULL, "PackFile_fetch_nv: Native [%d bytes]..\n", sizeof(FLOATVAL)); @@ -153,15 +196,13 @@ return f; } f = (FLOATVAL) 0; - g = (HUGEFLOATVAL) 0; #if TRACE_PACKFILE PIO_eprintf(NULL, "PackFile_fetch_nv: Byteordering..\n"); #endif /* Here is where the size transforms get messy */ if (NUMVAL_SIZE == 8 && pf->header->floattype == 1) { - (pf->fetch_nv)((unsigned char *)&g, (unsigned char *) *stream); + (pf->fetch_nv)((unsigned char *)&f, (unsigned char *) *stream); ((unsigned char *) (*stream)) += 12; - f = g; } else { (pf->fetch_nv)((unsigned char *)&d, (unsigned char *) *stream); @@ -171,42 +212,90 @@ return f; } +static opcode_t +fetch_op_mixed(opcode_t b) +{ + union { + unsigned char buf[8]; + opcode_t o1; + opcode_t o2; + } u; + opcode_t o; + +#if PARROT_BIGENDIAN +# if OPCODE_T_SIZE == 4 + /* wordsize = 8 then */ + fetch_buf_le_8(u.buf, (unsigned char *) b); + return u.o2; /* or u.o1 */ +# else + o = fetch_op_le(b); /* or fetch_be_le_4 and convert? */ + return o >> 32; /* or o & 0xffffffff */ +# endif +#else +# if OPCODE_T_SIZE == 4 + /* wordsize = 8 then */ + fetch_buf_be_8(u.buf, (unsigned char *) b); + return u.o1; /* or u.o2 */ +# else + o = fetch_op_be(b); + return o & 0xffffffff; +# endif + +#endif +} /* * Assign transform functions to vtable */ -void PackFile_assign_transforms(struct PackFile *pf) { +void +PackFile_assign_transforms(struct PackFile *pf) { #if PARROT_BIGENDIAN if(pf->header->byteorder != PARROT_BIGENDIAN) { pf->need_endianize = 1; + if (pf->header->wordsize == sizeof(opcode_t)) pf->fetch_op = fetch_op_le; + else { + pf->need_wordsize = 1; + pf->fetch_op = fetch_op_mixed; + } + pf->fetch_iv = fetch_iv_le; if (pf->header->floattype == 0) pf->fetch_nv = fetch_buf_le_8; else if (pf->header->floattype == 1) - pf->fetch_nv = fetch_buf_le_12; + pf->fetch_nv = cvt_num12_num8_le; } #else if(pf->header->byteorder != PARROT_BIGENDIAN) { pf->need_endianize = 1; + if (pf->header->wordsize == sizeof(opcode_t)) { pf->fetch_op = fetch_op_be; + } + else { + pf->need_wordsize = 1; + pf->fetch_op = fetch_op_mixed; + } pf->fetch_iv = fetch_iv_be; if (pf->header->floattype == 0) pf->fetch_nv = fetch_buf_be_8; else if (pf->header->floattype == 1) - pf->fetch_nv = fetch_buf_be_12; + pf->fetch_nv = cvt_num12_num8_be; } else { if (NUMVAL_SIZE == 8 && pf->header->floattype == 1) - pf->fetch_nv = fetch_buf_le_12; + pf->fetch_nv = cvt_num12_num8; else if (NUMVAL_SIZE != 8 && pf->header->floattype == 0) pf->fetch_nv = fetch_buf_le_8; /* XXX else */ + } # if TRACE_PACKFILE PIO_eprintf(NULL, "header->byteorder [%d] native byteorder [%d]\n", pf->header->byteorder, PARROT_BIGENDIAN); # endif - } #endif + if (pf->header->wordsize != sizeof(opcode_t)) { + pf->need_wordsize = 1; + pf->fetch_op = fetch_op_mixed; + } } /*************************************** @@ -343,16 +432,6 @@ PIO_eprintf(NULL, "byteorder: %d\n", header->byteorder); #endif - /* - * FIXME - */ - if(self->need_wordsize) { - PIO_eprintf(NULL, - "PackFile_unpack: Unimplemented wordsize transform.\n"); - PIO_eprintf(NULL, "File has wordsize: %d (native is %d)\n", - header->wordsize, sizeof(opcode_t)); - return 0; - } if (header->major != PARROT_MAJOR_VERSION || header->minor != (PARROT_MINOR_VERSION|PARROT_PATCH_VERSION)) { PIO_eprintf(NULL, "PackFile_unpack: Bytecode not valid for this " @@ -370,7 +449,7 @@ /* * Unpack and verify the magic which is stored byteorder of the file: */ - header->magic = PackFile_fetch_op(self, cursor++); + header->magic = PackFile_fetch_op(self, &cursor); /* * The magic and opcodetype fields are in native byteorder. @@ -384,7 +463,7 @@ return 0; } - header->opcodetype = PackFile_fetch_op(self, cursor++); + header->opcodetype = PackFile_fetch_op(self, &cursor); #if TRACE_PACKFILE PIO_eprintf(NULL, "PackFile_unpack(): Magic verified.\n"); @@ -394,7 +473,7 @@ * Unpack the Fixup Table Segment: */ - header->dir_format = PackFile_fetch_op(self, cursor++); + header->dir_format = PackFile_fetch_op(self, &cursor); /* old compat mode for assemble.pl */ if (header->dir_format == 0) { @@ -402,7 +481,7 @@ /* * Unpack the Constant Table Segment: */ - header->const_ss = PackFile_fetch_op(self, cursor++); + header->const_ss = PackFile_fetch_op(self, &cursor); self->const_table->base.op_count = header->const_ss / sizeof(opcode_t); if (!PackFile_check_segment_size(header->const_ss, @@ -419,14 +498,14 @@ } /* Segment size is in bytes */ - cursor += header->const_ss / sizeof(opcode_t); + (char *)cursor += header->const_ss; /* * Unpack the Byte Code Segment: * PackFile new did generate already a default code segment */ - header->bytecode_ss = PackFile_fetch_op(self, cursor++); + header->bytecode_ss = PackFile_fetch_op(self, &cursor); if (!PackFile_check_segment_size(header->bytecode_ss, "bytecode")) { @@ -445,10 +524,10 @@ (int)header->dir_format); return 0; } - cursor++; /* pad */ + (void)PackFile_fetch_op(self, &cursor); /* pad */ self->directory->base.file_offset = (size_t)(cursor - self->src); - cursor = PackFile_Segment_unpack(interpreter, (struct PackFile_Segment *) - self->directory, cursor); + cursor = PackFile_Segment_unpack(interpreter, + (struct PackFile_Segment *) self->directory, cursor); } self->byte_code = self->cur_cs->base.data; self->byte_code_size = self->cur_cs->base.size * sizeof(opcode_t); @@ -662,10 +741,10 @@ struct PackFile_Segment *self, opcode_t *cursor) { if (self->pf->header->dir_format) { - self->op_count = PackFile_fetch_op(self->pf, cursor++); - self->itype = PackFile_fetch_op(self->pf, cursor++); - self->id = PackFile_fetch_op(self->pf, cursor++); - self->size = PackFile_fetch_op(self->pf, cursor++); + self->op_count = PackFile_fetch_op(self->pf, &cursor); + self->itype = PackFile_fetch_op(self->pf, &cursor); + self->id = PackFile_fetch_op(self->pf, &cursor); + self->size = PackFile_fetch_op(self->pf, &cursor); } if (self->size == 0) return cursor; @@ -696,7 +775,7 @@ else { int i; for(i = 0; i < (int)self->size ; i++) { - self->data[i] = PackFile_fetch_op(self->pf, cursor++); + self->data[i] = PackFile_fetch_op(self->pf, &cursor); #if TRACE_PACKFILE PIO_eprintf(NULL, "op[%u]->[%u]\n", *(cursor-1), self->data[i]); @@ -928,8 +1007,10 @@ size_t i; struct PackFile_Directory *dir = (struct PackFile_Directory *) segp; struct PackFile * self = dir->base.pf; + opcode_t *pos; + int wordsize = self->header->wordsize; - dir->num_segments = PackFile_fetch_op (self, cursor++); + dir->num_segments = PackFile_fetch_op (self, &cursor); dir->segments = mem_sys_realloc (dir->segments, sizeof(struct PackFile_Segment *) * dir->num_segments); @@ -939,12 +1020,12 @@ size_t tmp; UINTVAL type; const char *name; - type = PackFile_fetch_op (self, cursor++); + type = PackFile_fetch_op (self, &cursor); /* get name */ str_len = strlen ((char *)cursor) + 1; name = (char *)cursor; + cursor += ROUND_UP(str_len, wordsize) / sizeof(opcode_t); - cursor += ROUND_UP(str_len, sizeof(opcode_t)) / sizeof(opcode_t); switch (type) { case PF_CONST_SEG: seg = (struct PackFile_Segment *)self->const_table; @@ -969,10 +1050,11 @@ break; } - seg->file_offset = PackFile_fetch_iv(self, cursor++); - seg->op_count = PackFile_fetch_op(self, cursor++); + seg->file_offset = PackFile_fetch_op(self, &cursor); + seg->op_count = PackFile_fetch_op(self, &cursor); - tmp = PackFile_fetch_op (self, self->src + seg->file_offset); + pos = self->src + seg->file_offset; + tmp = PackFile_fetch_op (self, &pos); if (seg->op_count != tmp) { fprintf (stderr, "%s: Size in directory (%d) doesn't match size " @@ -994,7 +1076,6 @@ cursor += 4 - (cursor - self->src) % 4; /* and now unpack contents of dir */ for (i = 0; cursor && i < dir->num_segments; i++) { - opcode_t *pos; size_t tmp = *cursor; /* check len again */ pos = PackFile_Segment_unpack (interpreter, dir->segments[i], cursor); @@ -1246,8 +1327,9 @@ char *name = (char *)cursor; char *code_name; struct PackFile_ByteCode *code; + int wordsize = self->pf->header->wordsize; - cursor += ROUND_UP(str_len, sizeof(opcode_t)) / sizeof(opcode_t); + cursor += ROUND_UP(str_len, wordsize) / sizeof(opcode_t); str_len = strlen(self->name); code_name = mem_sys_allocate(str_len); strcpy(code_name, self->name); @@ -1500,7 +1582,7 @@ PackFile_FixupTable_clear(self); pf = self->base.pf; - self->fixup_count = PackFile_fetch_op(pf, cursor++); + self->fixup_count = PackFile_fetch_op(pf, &cursor); if (self->fixup_count) { self->fixups = mem_sys_allocate_zeroed(self->fixup_count * @@ -1517,12 +1599,12 @@ for (i = 0; i < self->fixup_count; i++) { self->fixups[i] = mem_sys_allocate(sizeof(struct PackFile_FixupEntry)); - self->fixups[i]->type = PackFile_fetch_op(pf, cursor++); + self->fixups[i]->type = PackFile_fetch_op(pf, &cursor); switch (self->fixups[i]->type) { case 0: self->fixups[i]->u.t0.code_seg = - PackFile_fetch_op(pf, cursor++); - self->fixups[i]->u.t0.offset = PackFile_fetch_op(pf, cursor++); + PackFile_fetch_op(pf, &cursor); + self->fixups[i]->u.t0.offset = PackFile_fetch_op(pf, &cursor); break; default: PIO_eprintf(interpreter, @@ -1618,7 +1700,7 @@ PackFile_ConstTable_clear(self); - self->const_count = PackFile_fetch_op(pf, cursor++); + self->const_count = PackFile_fetch_op(pf, &cursor); #if TRACE_PACKFILE PIO_eprintf(interpreter, @@ -1799,8 +1881,8 @@ opcode_t type; opcode_t size; - type = PackFile_fetch_op(pf, cursor++); - size = PackFile_fetch_op(pf, cursor++); + type = PackFile_fetch_op(pf, &cursor); + size = PackFile_fetch_op(pf, &cursor); #if TRACE_PACKFILE PIO_eprintf(NULL, "PackFile_Constant_unpack(): Type is %ld ('%c')...\n", @@ -1906,14 +1988,15 @@ opcode_t encoding; opcode_t type; size_t size; + int wordsize = pf->header->wordsize; /* don't let PBC mess our internals */ - flags = 0 ; cursor++; - encoding = PackFile_fetch_op(pf, cursor++); - type = PackFile_fetch_op(pf, cursor++); + flags = 0; (void)PackFile_fetch_op(pf, &cursor); + encoding = PackFile_fetch_op(pf, &cursor); + type = PackFile_fetch_op(pf, &cursor); /* These may need to be separate */ - size = (size_t)PackFile_fetch_op(pf, cursor++); + size = (size_t)PackFile_fetch_op(pf, &cursor); #if TRACE_PACKFILE PIO_eprintf(NULL, "Constant_unpack_string(): flags are 0x%04x...\n", flags); @@ -1930,7 +2013,7 @@ flags | PObj_constant_FLAG, chartype_lookup_index(type)); - size = ROUND_UP(size, sizeof(opcode_t)) / sizeof(opcode_t); + size = ROUND_UP(size, wordsize) / sizeof(opcode_t); return cursor + size; } @@ -1959,8 +2042,9 @@ INTVAL components; PMC *head; PMC *tail; + opcode_t type, op; - components = *cursor++; + components = (INTVAL)PackFile_fetch_op(pf, &cursor); head = tail = NULL; while (components-- > 0) { @@ -1974,29 +2058,31 @@ tail->vtable->init(interpreter, tail); - switch (*cursor++) { + type = PackFile_fetch_op(pf, &cursor); + op = PackFile_fetch_op(pf, &cursor); + switch (type) { case PARROT_ARG_IC: - key_set_integer(interpreter, tail, *cursor++); + key_set_integer(interpreter, tail, op); break; case PARROT_ARG_NC: key_set_number(interpreter, tail, - pf->const_table->constants[*cursor++]->u.number); + pf->const_table->constants[op]->u.number); break; case PARROT_ARG_SC: key_set_string(interpreter, tail, - pf->const_table->constants[*cursor++]->u.string); + pf->const_table->constants[op]->u.string); break; case PARROT_ARG_I: - key_set_register(interpreter, tail, *cursor++, KEY_integer_FLAG); + key_set_register(interpreter, tail, op, KEY_integer_FLAG); break; case PARROT_ARG_N: - key_set_register(interpreter, tail, *cursor++, KEY_number_FLAG); + key_set_register(interpreter, tail, op, KEY_number_FLAG); break; case PARROT_ARG_S: - key_set_register(interpreter, tail, *cursor++, KEY_string_FLAG); + key_set_register(interpreter, tail, op, KEY_string_FLAG); break; case PARROT_ARG_P: - key_set_register(interpreter, tail, *cursor++, KEY_pmc_FLAG); + key_set_register(interpreter, tail, op, KEY_pmc_FLAG); break; default: return 0;