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