At 06:18 PM 5/11/2002 -0400, Bryan C. Warnock wrote: >On Sat, 2002-05-04 at 01:52, Melvin Smith wrote: > > Reposted to the list so people can comment. > > > > As per the IRC discussion with Dan..... > > > > I've made some progress, not all there, but getting there. > > I have the loader handling arbitrary byteordering, now I'm > > working on wordsize transforms. > >Since I missed the discussion, I count three size situations. > >- n bit reading n bit bytecode. A straight read. >- 32 bit reading 64 bit bytecode. But 64 bit bytecode is simply 32 bits >padded out, so simply read every n+1 words. >- 64 bit reading 32 bit bytecode. Read and extend. > >Is that along the lines of what you were thinking of?
Yes, exactly. > > So what I do is read in the byteorder matrix, transform it with > > the native matrix, and use that to transform bytecodes > > in the rest of the file. The routine works 80% as fast a hardcoded > > routines with #ifdefs, however the advantage is we can support > > any byteorder/wordsize that an assembler can write. > >Is native optimized away, or do you suffer a penatly doing a null >transform? Optimized away. Actually I redid it Thursday and checked in conditional compilation versions for big and little endian, abandoning the little matrix trick for the added 20% in speed. I'll wait and see if we ever have need for anything other than lil/big endian before putting the fancy matrix back in. Packfile has a vtable now, if the function pointer is null it does a straight memcpy for the time being. This it not final though, I still want to just map the bytecode segments directly over if no transform is required. >I'd suggest adding: > > char prefix[4] = { 0xCC, 0x0D, 0x0A, 0x1A }; >The PBC metadata should indicate the source language and compiler, for >sure. I like that too. After the 2nd rework here is where we are... #define PACKFILE_HEADER_BYTES 16 struct PackFile_Header { unsigned char wordsize; unsigned char byteorder; unsigned char major; unsigned char minor; unsigned char flags; unsigned char floattype; unsigned char pad[10]; /* Start words/opcodes on 8-byte boundary */ opcode_t magic; opcode_t opcodetype; opcode_t fixup_ss; opcode_t const_ss; opcode_t bytecode_ss; }; And the vtable is in the PackFile below. struct PackFile { struct PackFile_Header * header; struct PackFile_FixupTable * fixup_table; struct PackFile_ConstTable * const_table; size_t byte_code_size; /* size in bytes */ opcode_t * byte_code; INTVAL need_wordsize; INTVAL need_endianize; opcode_t (*fetch_op)(opcode_t); INTVAL (*fetch_iv)(INTVAL); void (*fetch_nv)(unsigned char *, unsigned char *); }; The fetch ops are defined as below. Nothing forces you actually to call the fetchop vfun though, if you check pf->need_endianize | need_wordize then a simple memcpy or pointer assignment should be used for the raw bytecode segments. INLINE opcode_t PackFile_fetch_op(struct PackFile *pf, opcode_t *stream) { if(pf->fetch_op == NULL) return *stream; return (pf->fetch_op)(*stream); } Fixup tables, symbol tables, etc. still probably can be scanned with the fetch routines. More comments are welcome. -Melvin