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


Reply via email to