Category : Recently Uploaded Files
Archive   : OXCC1430.ZIP
Filename : BTERP.C

 
Output of file : BTERP.C contained in archive : OXCC1430.ZIP
/*
bterp.c -- v1.430 interpreter prototype for oxcc byte codes

Copyright (c) 1995
Norman D. Culver dba
Oxbow Software
1323 S.E. 17th Street #662
Ft. Lauderdale, FL 33316
(305) 527-1663 Voice
(305) 760-7584 Fax
(305) 760-4679 Data
[email protected]
All rights reserved.

* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by Norman D. Culver dba Oxbow Software''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

*/

#define SUPPORT_LONG_DOUBLE 0
#define SUPPORT_LONG_LONG 0

#define NEED_BYTECODES 1
#define NEED_AOUT_FORMAT 1
#include "oxbytes.h"

#define NEED_FUNCTHUNK 1
#include "oxanf.h"
#include
#include
#include

#define PROG bterp
#define USING_FRAMEWORK 1

#define SWITCHMOD 1009
typedef struct _key
{
unsigned long k[2];
unsigned long hv;
} KEY, *KEYP;

typedef struct _nodeS
{
unsigned long value;
unsigned long key[2];
struct _nodeS *fptr;
} NodeS, *NodePS;

typedef struct _callblk {
void *loc;
char *es;
unsigned short argofs;
unsigned short flags;
long argsiz;
char *base_stack; /* must be last element */
} *PCB;

typedef struct _stakblk {
void *backlink;
long first_loc;
long last_loc;
char *cbes;
void *thunkaddr;
int stksize;
} SB, *PSB;

typedef struct _fe {
char *filename;
long string_size;
char *strings;
char *text_start_address;
char *data_start_address;
char *bss_start_address;
} *FE;

typedef struct _iv {
struct _iv *piv;
char *text_base;
char *dd;
void **struclist;
long slcnt;
long strretcnt;
void *allocalist;
NodePS *swtable;
char *chunkbase;
void *chunklist;
long chunksize;
FE entry;
char *filename;
char *funcptr;
Pft ft;
long funcaddr;
long stksiz;
long argsiz;
long maxes;
char *base_stack;
char *e_stack;
jmp_buf jb;
#define MAX_RUNARGS 15
long run_argcnt;
char *run_args[MAX_RUNARGS];
int debug;
} *Piv;

typedef struct _retval {
void *ptr;
long p1;
long p2;
} RV;

int cfeprintf(const char *fmt, ...);

void _ExternCall();
void _ExternCallS();
void *oxlink_load_bare_symb(const char *symb, int dynlink);
void *oxlink_find_bare_func(const char *);
void *oxlink_find_func(const char *);
int oxlink_load_file(const char *);
int oxlink_load_object(const char *);
int oxlink_unload_file(const char *, int);
void oxlink_demand_load(void);
void oxlink_demand_noload(void);
void *oxlink_get_entry_struct(const char *filename);
char *oxlink_errstr(void);

static void* bterp_eval();

#define SZ (20) /* size of evaluation stack frame */

#define MIN(a,b) ((a
#define SRC(a) (a<<4)
#define G1(a) ((unsigned long)*((unsigned char*)(a)))
#define G2(a) ((unsigned long)*((unsigned short*)(a)))
#define G3(a) (*((unsigned long*)(a))&0x00ffffff)
#define G4(a) (*((unsigned long*)(a)))
#define G8(a) (*((double*)(a)))
#define GX(a) (*((long double*)(a)))
#define GP1(a) ((long)*((char*)(a)))
#define GP2(a) ((long)*((short*)(a)))
#define GP3(a) ((*((long*)(a))<<8)>>8)
#define GP4(a) (*((long*)(a)))

#define NEG_ES(t) {*((t*)es)=-(*((t*)es));break;}
#define NOT_ES(t) {*((t*)es)=!(*((t*)es));break;}
#define NOT_ES1 {*es=(((long*)es)[0]==0&&((long*)es)[1]==0)?1:0;}
#define COMP_ES(t) {*((t*)es)=~(*((t*)es));break;}
#define TRUTH_ES(t) {*((long*)es)=(*((t*)es))?1:0;break;}
#define TRUTH_ES1 {*((long*)es)=(((long*)es)[0]==0&&((long*)es)[1]==0)?0:1;}
#define GT_ES(t) {*((long*)oes)=(*((t*)oes)>*((t*)es))?1:0;es=oes;break;}
#define LT_ES(t) {*((long*)oes)=(*((t*)oes)<*((t*)es))?1:0;es=oes;break;}
#define GE_ES(t) {*((long*)oes)=(*((t*)oes)>=*((t*)es))?1:0;es=oes;break;}
#define LE_ES(t) {*((long*)oes)=(*((t*)oes)<=*((t*)es))?1:0;es=oes;break;}
#define NE_ES(t) {*((long*)oes)=(*((t*)oes)!=*((t*)es))?1:0;es=oes;break;}
#define EQ_ES(t) {*((long*)oes)=(*((t*)oes)==*((t*)es))?1:0;es=oes;break;}
#define ADD_ES(t) {*((t*)oes)+=*((t*)es);es=oes;break;}
#define SUB_ES(t) {*((t*)oes)-=*((t*)es);es=oes;break;}
#define MUL_ES(t) {*((t*)oes)*=*((t*)es);es=oes;break;}
#define DIV_ES(t) {*((t*)oes)/=*((t*)es);es=oes;break;}
#define OR_ES(t) {*((t*)oes)|=*((t*)es);es=oes;break;}
#define AND_ES(t) {*((t*)oes)&=*((t*)es);es=oes;break;}
#define XOR_ES(t) {*((t*)oes)^=*((t*)es);es=oes;break;}
#define MOD_ES(t) {*((t*)oes)%=*((unsigned long*)es);es=oes;break;}
#define MODL_ES(t) {*((t*)oes)%=*((unsigned long long*)es);es=oes;break;}
#define MODI_ES(t) {*((t*)es)%=*((unsigned short*)np);pc+=2;break;}
#define RSH_ES(t) {*((t*)oes)>>=*((unsigned char*)es);es=oes;break;}
#define LSH_ES(t) {*((t*)oes)<<=*((unsigned char*)es);es=oes;break;}
#define RSHI_ES(t) {*((t*)es)>>=*np;pc+=1;break;}
#define LSHI_ES(t) {*((t*)es)<<=*np;pc+=1;break;}
#define DEREF_ES(t) {*((long*)es)=**((t**)es);break;}
#define UDEREF_ES(t) {*((unsigned long*)es)=**((t**)es);break;}
#define FDEREF_ES(t) {*((t*)es)=**((t**)es);break;}
#define DEREF1_ES(t) {*((long*)nes)=**((t**)es);es=nes;break;}
#define UDEREF1_ES(t) {*((unsigned long*)nes)=**((t**)es);es=nes;break;}
#define FDEREF1_ES(t) {*((t*)nes)=**((t**)es);es=nes;break;}
#define SIGNE if(*(es+3)&0x80)*((long*)(es+4))=-1;else *((long*)(es+4))=0
#define USIGNE *((long*)(es+4))=0
#define LOADI1() {*((long*)nes)=GP1(np);es=nes;SIGNE;pc+=1;break;}
#define LOADI2() {*((long*)nes)=GP2(np);es=nes;SIGNE;pc+=2;break;}
#define LOADI4() {*((long*)nes)=GP4(np);es=nes;SIGNE;pc+=4;break;}
#define LOADUI1() {*((unsigned long*)nes)=G1(np);es=nes;USIGNE;pc+=1;break;}
#define LOADUI2() {*((unsigned long*)nes)=G2(np);es=nes;USIGNE;pc+=2;break;}
#define LOADUI4() {*((unsigned long*)nes)=G4(np);es=nes;USIGNE;pc+=4;break;}
#define LOADI8() {*((double*)nes)=G8(np);es=nes;pc+=8;break;}
#define LOADIX() {*((long double*)nes)=GX(np);es=nes;pc+=XSZ;break;}

#define LOADADDRI1() {*((unsigned long*)nes)=(G1(np)<<2);es=nes;pc+=1;break;}
#define LOADADDRI2() {*((unsigned long*)nes)=(G2(np)<<2);es=nes;pc+=2;break;}
#define LOADADDRI3() {*((unsigned long*)nes)=(G3(np)<<0);es=nes;pc+=3;break;}
#define LOADADDRI4() {*((unsigned long*)nes)=G4(np);es=nes;pc+=4;break;}

#define LOADSTK1(t) {*((t*)nes)=*((t*)(fs+(G1(np)<<2)));es=nes;pc+=1;break;}
#define LOADSTK2(t) {*((t*)nes)=*((t*)(fs+(G2(np)<<2)));es=nes;pc+=2;break;}
#define LOADSTK3(t) {*((t*)nes)=*((t*)(fs+(G3(np)<<0)));es=nes;pc+=3;break;}

#define STORSTK1(t) {*((t*)(fs+(G1(np)<<2)))=*((t*)es);es=oes;pc+=1;break;}
#define STORSTK2(t) {*((t*)(fs+(G2(np)<<2)))=*((t*)es);es=oes;pc+=2;break;}
#define STORSTK3(t) {*((t*)(fs+(G3(np)<<0)))=*((t*)es);es=oes;pc+=3;break;}

#define STORSTKI1(t) {*((t*)(fs+(G1(np)<<2)))=*((t*)(np+1));pc+=sizeof(t)+1;break;}
#define STORSTKI2(t) {*((t*)(fs+(G2(np)<<2)))=*((t*)(np+2));pc+=sizeof(t)+2;break;}
#define STORSTKI3(t) {*((t*)(fs+(G3(np)<<0)))=*((t*)(np+3));pc+=sizeof(t)+3;break;}

#define LOADMEM1(t) {*((t*)nes)=*((t*)(dd+(G1(np)<<2)));es=nes;pc+=1;break;}
#define LOADMEM2(t) {*((t*)nes)=*((t*)(dd+(G2(np)<<2)));es=nes;pc+=2;break;}
#define LOADMEM3(t) {*((t*)nes)=*((t*)(dd+(G3(np)<<0)));es=nes;pc+=3;break;}
#define LOADMEM4(t) {*((t*)nes)=*((t*)((void*)G4(np)));es=nes;pc+=4;break;}

#define STORMEM1(t) {*((t*)(dd+(G1(np)<<2)))=*((t*)es);es=oes;pc+=1;break;}
#define STORMEM2(t) {*((t*)(dd+(G2(np)<<2)))=*((t*)es);es=oes;pc+=2;break;}
#define STORMEM3(t) {*((t*)(dd+(G3(np)<<2)))=*((t*)es);es=oes;pc+=3;break;}
#define STORMEM4(t) {*((t*)((void*)G4(np)))=*((t*)es);es=oes;pc+=4;break;}

#define STORMEMI1(t) {*((t*)(dd+(G1(np)<<2)))=*((t*)(np+1));pc+=sizeof(t)+1;break;}
#define STORMEMI2(t) {*((t*)(dd+(G2(np)<<2)))=*((t*)(np+2));pc+=sizeof(t)+2;break;}
#define STORMEMI3(t) {*((t*)(dd+(G3(np)<<0)))=*((t*)(np+3));pc+=sizeof(t)+3;break;}
#define STORMEMI4(t) {*((t*)((void*)G4(np)))=*((t*)(np+4));pc+=sizeof(t)+4;break;}

static unsigned long bfields[33] = {
0x00000000,0x00000001,0x00000003,0x00000007,
0x0000000f,0x0000001f,0x0000003f,0x0000007f,
0x000000ff,0x000001ff,0x000003ff,0x000007ff,
0x00000fff,0x00001fff,0x00003fff,0x00007fff,
0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
0x000fffff,0x001fffff,0x003fffff,0x007fffff,
0x00ffffff,0x01ffffff,0x03ffffff,0x07ffffff,
0x0fffffff,0x1fffffff,0x3fffffff,0x7fffffff,
0xfffffff
};
static unsigned long tsfields[33] = {
0x00000000,0x00000001,0x00000002,0x00000004,
0x00000008,0x00000010,0x00000020,0x00000040,
0x00000080,0x00000100,0x00000200,0x00000400,
0x00000800,0x00001000,0x00002000,0x00004000,
0x00008000,0x00010000,0x00020000,0x00040000,
0x00080000,0x00100000,0x00200000,0x00400000,
0x00800000,0x01000000,0x02000000,0x04000000,
0x08000000,0x10000000,0x20000000,0x40000000,
0x80000000
};
static unsigned long sfields[33] = {
0x00000000,0xfffffffe,0xfffffffc,0xfffffff8,
0xfffffff0,0xffffffe0,0xffffffc0,0xffffff80,
0xffffff00,0xfffffe00,0xfffffc00,0xfffff800,
0xfffff000,0xffffe000,0xffffc000,0xffff8000,
0xffff0000,0xfffe0000,0xfffc0000,0xfff80000,
0xfff00000,0xffe00000,0xffc00000,0xff800000,
0xff000000,0xfe000000,0xfc000000,0xf8000000,
0xf0000000,0xe0000000,0xc0000000,0x80000000,
0x80000000
};
#if SUPPORT_LONG_LONG
static unsigned long long lbfields[65] = {
0x0000000000000000LL,0x0000000000000001LL,0x0000000000000003LL,0x0000000000000007LL,
0x000000000000000fLL,0x000000000000001fLL,0x000000000000003fLL,0x000000000000007fLL,
0x00000000000000ffLL,0x00000000000001ffLL,0x00000000000003ffLL,0x00000000000007ffLL,
0x0000000000000fffLL,0x0000000000001fffLL,0x0000000000003fffLL,0x0000000000007fffLL,
0x000000000000ffffLL,0x000000000001ffffLL,0x000000000003ffffLL,0x000000000007ffffLL,
0x00000000000fffffLL,0x00000000001fffffLL,0x00000000003fffffLL,0x00000000007fffffLL,
0x0000000000ffffffLL,0x0000000001ffffffLL,0x0000000003ffffffLL,0x0000000007ffffffLL,
0x000000000fffffffLL,0x000000001fffffffLL,0x000000003fffffffLL,0x000000007fffffffLL,
0x00000000ffffffffLL,0x00000001ffffffffLL,0x00000003ffffffffLL,0x00000007ffffffffLL,
0x0000000fffffffffLL,0x0000001fffffffffLL,0x0000003fffffffffLL,0x0000007fffffffffLL,
0x000000ffffffffffLL,0x000001ffffffffffLL,0x000003ffffffffffLL,0x000007ffffffffffLL,
0x00000fffffffffffLL,0x00001fffffffffffLL,0x00003fffffffffffLL,0x00007fffffffffffLL,
0x0000ffffffffffffLL,0x0001ffffffffffffLL,0x0003ffffffffffffLL,0x0007ffffffffffffLL,
0x000fffffffffffffLL,0x001fffffffffffffLL,0x003fffffffffffffLL,0x007fffffffffffffLL,
0x00ffffffffffffffLL,0x01ffffffffffffffLL,0x03ffffffffffffffLL,0x07ffffffffffffffLL,
0x0fffffffffffffffLL,0x1fffffffffffffffLL,0x3fffffffffffffffLL,0x7fffffffffffffffLL,
0xfffffffffffffffLL
};
static unsigned long long ltsfields[65] = {
0x0000000000000000LL,0x0000000000000001LL,0x0000000000000002LL,0x0000000000000004LL,
0x0000000000000008LL,0x0000000000000010LL,0x0000000000000020LL,0x0000000000000040LL,
0x0000000000000080LL,0x0000000000000100LL,0x0000000000000200LL,0x0000000000000400LL,
0x0000000000000800LL,0x0000000000001000LL,0x0000000000002000LL,0x0000000000004000LL,
0x0000000000008000LL,0x0000000000010000LL,0x0000000000020000LL,0x0000000000040000LL,
0x0000000000080000LL,0x0000000000100000LL,0x0000000000200000LL,0x0000000000400000LL,
0x0000000000800000LL,0x0000000001000000LL,0x0000000002000000LL,0x0000000004000000LL,
0x0000000008000000LL,0x0000000010000000LL,0x0000000020000000LL,0x0000000040000000LL,
0x0000000080000000LL,0x0000000100000000LL,0x0000000200000000LL,0x0000000400000000LL,
0x0000000800000000LL,0x0000001000000000LL,0x0000002000000000LL,0x0000004000000000LL,
0x0000008000000000LL,0x0000010000000000LL,0x0000020000000000LL,0x0000040000000000LL,
0x0000080000000000LL,0x0000100000000000LL,0x0000200000000000LL,0x0000400000000000LL,
0x0000800000000000LL,0x0001000000000000LL,0x0002000000000000LL,0x0004000000000000LL,
0x0008000000000000LL,0x0010000000000000LL,0x0020000000000000LL,0x0040000000000000LL,
0x0080000000000000LL,0x0100000000000000LL,0x0200000000000000LL,0x0400000000000000LL,
0x0800000000000000LL,0x1000000000000000LL,0x2000000000000000LL,0x4000000000000000LL,
0x8000000000000000LL
};
static unsigned long long lsfields[65] = {
0x0000000000000000LL,0xfffffffffffffffeLL,0xfffffffffffffffcLL,0xfffffffffffffff8LL,
0xfffffffffffffff0LL,0xffffffffffffffe0LL,0xffffffffffffffc0LL,0xffffffffffffff80LL,
0xffffffffffffff00LL,0xfffffffffffffe00LL,0xfffffffffffffc00LL,0xfffffffffffff800LL,
0xfffffffffffff000LL,0xffffffffffffe000LL,0xffffffffffffc000LL,0xffffffffffff8000LL,
0xffffffffffff0000LL,0xfffffffffffe0000LL,0xfffffffffffc0000LL,0xfffffffffff80000LL,
0xfffffffffff00000LL,0xffffffffffe00000LL,0xffffffffffc00000LL,0xffffffffff800000LL,
0xffffffffff000000LL,0xfffffffffe000000LL,0xfffffffffc000000LL,0xfffffffff8000000LL,
0xfffffffff0000000LL,0xffffffffe0000000LL,0xffffffffc0000000LL,0xffffffff80000000LL,
0xffffffff00000000LL,0xfffffffe00000000LL,0xfffffffc00000000LL,0xfffffff800000000LL,
0xfffffff000000000LL,0xffffffe000000000LL,0xffffffc000000000LL,0xffffff8000000000LL,
0xffffff0000000000LL,0xfffffe0000000000LL,0xfffffc0000000000LL,0xfffff80000000000LL,
0xfffff00000000000LL,0xffffe00000000000LL,0xffffc00000000000LL,0xffff800000000000LL,
0xffff000000000000LL,0xfffe000000000000LL,0xfffc000000000000LL,0xfff8000000000000LL,
0xfff0000000000000LL,0xffe0000000000000LL,0xffc0000000000000LL,0xff80000000000000LL,
0xff00000000000000LL,0xfe00000000000000LL,0xfc00000000000000LL,0xf800000000000000LL,
0xf000000000000000LL,0xe000000000000000LL,0xc000000000000000LL,0x8000000000000000LL,
0x8000000000000000LL
};
#endif /* SUPPORT_LONG_LONG */

static char thunk386[41] =
{/* THE EXTERNAL CALLBACK THUNK (Intel 386) */
0x55, /* pushl %ebp */
0x89,0xE5, /* movl %esp,%ebp */
0x68,0,0,0,0, /* pushl ft */
0x68,0,0,0,0, /* pushl iv */
0x68,0,0,0,0, /* pushl base_stack */
0x83,0xEC,0x0C, /* subl $12,%esp (RETVAL) */
0xB8,0,0,0,0, /* movl _bterp_handle_callbacks,%eax */
0xFF,0xD0, /* call *%eax */
0x8B,0x04,0x24, /* movl (%esp),%eax */
0x8B,0x54,0x24,0x04,/* movl 4(%esp),%edx */
0x8B,0x4C,0x24,0x08,/* movl 8(%esp),%ecx */
0xC9, /* leave */
0xC3 /* ret */
};
static char thunk386S[42] =
{/* THE EXTERNAL CALLBACK THUNK (Intel 386) */
0x55, /* pushl %ebp */
0x89,0xE5, /* movl %esp,%ebp */
0x68,0,0,0,0, /* pushl ft */
0x68,0,0,0,0, /* pushl iv */
0x68,0,0,0,0, /* pushl base_stack */
0x83,0xEC,0x0C, /* subl $12,%esp (RETVAL) */
0xB8,0,0,0,0, /* movl _bterp_handle_callbacks,%eax */
0xFF,0xD0, /* call *%eax */
0x8B,0x04,0x24, /* movl (%esp),%eax */
0x8B,0x54,0x24,0x04,/* movl 4(%esp),%edx */
0x8B,0x4C,0x24,0x08,/* movl 8(%esp),%ecx */
0xC9, /* leave */
0xC2,0x04 /* ret $4 (prune structret arg, GCC convention) */
};



/* ========================== INTERPRETER CODE =========================== */

static int
findswitch(Piv iv, unsigned long *key, void *result)
{
int bin;
NodePS node;
bin = (((~key[0] ^ key[1]) * 1103515245UL) + 12345) % SWITCHMOD;
if((node = iv->swtable[bin]))
{
do {
if(node->key[0] == key[0] && node->key[1] == key[1])
{
*((NodePS*)result) = node;
return 1;
}
} while((node = node->fptr));
}
return 0;
}
static void *
new_Snode(Piv iv)
{
void *p;

if(iv->chunksize < sizeof(NodeS))
{
iv->chunkbase = calloc(1, 4088);
*((void**)iv->chunkbase) = iv->chunklist;
iv->chunklist = iv->chunkbase;
iv->chunkbase += sizeof(void*);
iv->chunksize = 4088 - sizeof(void*);
}
p = iv->chunkbase;
iv->chunkbase += sizeof(NodeS);
iv->chunksize -= sizeof(NodeS);
return p;
}
static void
saveswitch(Piv iv, unsigned long *key, long value)
{
int bin;
NodePS node;

bin = (((~key[0] ^ key[1]) * 1103515245UL) + 12345) % SWITCHMOD;
node = new_Snode(iv);
node->key[0] = key[0];
node->key[1] = key[1];
node->value = value;
node->fptr = iv->swtable[bin];
iv->swtable[bin] = node;
}
static void
purge_allocas(Piv iv, void *last)
{
while(iv->allocalist && (iv->allocalist != last))
{
void *this = iv->allocalist;
iv->allocalist = *((void**)this);
free(this);
}
}

static void
_bterp_handle_callbacks(RV retval, char *base_stack, Piv iv, Pft ft,
int ebp, int pret, ...)
{/* Call to interpreted function from external function */
unsigned short fmods;
long stksiz, maxes, strucsiz, fs_size, argofs, es_beg, argsiz;
int hidden;
void *strret = 0;
void *argaddr, *e_stack, *lastalloca;
void *pes;
DATUM lastval;

fmods = ft->fmods;
argaddr = ((long*)&pret)+1;
if((hidden = (fmods & Fretstr)))
{/* return a struct or union */
strucsiz = ft->retsiz<<2;
strret = (void*) *(((long*)&pret)+1);
}
stksiz = ft->stksiz<<2;
maxes = ft->maxes;
argsiz = ft->argsiz<<2;

if(fmods & Fnested)
{/* callback to nested function */
argofs = ft->stkbeg+(stksiz-argsiz-hidden);
e_stack = ((PSB)base_stack)->cbes;
}
else
{/* callback to non-nested function */
if(fmods & Fellipsis)
argsiz += 128;
es_beg = stksiz+hidden+argsiz;
argofs = stksiz;
fs_size = es_beg + ((maxes+6)*SZ);

/* Create a stack for the called function */
base_stack = calloc(1, fs_size + sizeof(SB));
e_stack = base_stack + sizeof(SB) + es_beg;
((PSB)base_stack)->stksize = fs_size + sizeof(SB);
}

/* Copy the callers arguments */
memcpy(base_stack+argofs+sizeof(SB),argaddr,argsiz+hidden);

/* EVALUATE THE FUNCTION */
lastalloca = iv->allocalist;
pes = bterp_eval(iv, ft->funcaddr, base_stack, e_stack,
base_stack+((PSB)base_stack)->stksize);

/* Transfer the return value */
#if SUPPORT_LONG_DOUBLE
lastval.Ulongdouble = *((long double*)pes);
#else
lastval.Udouble = *((double*)pes);
#endif

/* Return to callers' stack */
if(fmods & Fretdbl)
{
asm ("fldl %0" :: "g"(lastval.Udouble));
}
else if(fmods & Fretflt)
{
asm ("flds %0" :: "g"(lastval.Ufloat));

}
else if(fmods & Fretldbl)
{
#if SUPPORT_LONG_DOUBLE
#else
asm ("fldl %0" :: "g"(lastval.Udouble));
#endif
}
else if(strret)
{/* return pointer to struct */
retval.ptr = strret;
/* GCC needs this */
memcpy(&retval.p1, strret, MIN(8,strucsiz)); /* 8 bytes of struct */
}
else
{
retval.ptr = lastval.Upointer;
retval.p1 = lastval.lng.d[1];
retval.p2 = lastval.lng.d[2];
}
purge_allocas(iv, lastalloca);
if(fmods & Fnested)
{
#if 0
*((char**)pes) -= SZ;
#endif
ft->fmods &= ~Fthunked;
free(((PSB)base_stack)->thunkaddr);
}
else
{
free(base_stack);
}
}

static void *
make_callback_thunk(Piv iv, void *base_stack, Pft ft)
{
char *pth;

if(ft->fmods & Fretstr)
{
pth = malloc(sizeof(thunk386S));
memcpy(pth, thunk386S, sizeof(thunk386S));
}
else
{
pth = malloc(sizeof(thunk386));
memcpy(pth, thunk386, sizeof(thunk386));
}
*((long*)&pth[4]) = (long)ft;
*((long*)&pth[9]) = (long)iv;
*((long*)&pth[14]) = (long)base_stack;
*((long*)&pth[22]) = (long)_bterp_handle_callbacks;

return pth;
}
static void
ensure_strrets(Piv iv)
{
if(iv->strretcnt+1 >= iv->slcnt) {
iv->slcnt += 128;
iv->struclist = realloc(iv->struclist, iv->slcnt * sizeof(void *));
}
}
static void
prune_structs(Piv iv)
{
while(iv->strretcnt > 0)
{
free(iv->struclist[--iv->strretcnt]);
}
}
static int
mover(Piv iv, unsigned char *dp, int opcode, int size, char *src, char *dst)
{
char *s, *d;
int bump;

switch(opcode)
{
case S1|D1:
s = src+(G1(dp)<<2);
d = dst+(G1(dp+1)<<2);
bump = 3;
break;
case S1|D2:
s = src+(G1(dp)<<2);
d = dst+(G2(dp+1)<<2);
bump = 4;
break;
case S1|D3:
s = src+(G1(dp)<<2);
d = dst+(G3(dp+1)<<0);
bump = 5;
break;
case S1|D4:
s = src+(G1(dp)<<2);
d = (void*)G4(dp+1);
bump = 6;
break;
case S2|D1:
s = src+(G2(dp)<<2);
d = dst+G1(dp+2);
bump = 4;
break;
case S2|D2:
s = src+(G2(dp)<<2);
d = dst+(G2(dp+2)<<2);
bump = 5;
break;
case S2|D3:
s = src+(G2(dp)<<2);
d = dst+(G3(dp+2)<<0);
bump = 6;
break;
case S2|D4:
s = src+(G2(dp)<<2);
d = (void*)G4(dp+2);
bump = 7;
break;
case S3|D1:
s = src+(G3(dp)<<0);
d = dst+(G1(dp+3)<<2);
bump = 5;
break;
case S3|D2:
s = src+(G3(dp)<<0);
d = dst+(G2(dp+3)<<2);
bump = 6;
break;
case S3|D3:
s = src+(G3(dp)<<0);
d = dst+(G3(dp+3)<<0);
bump = 7;
break;
case S3|D4:
s = src+(G3(dp)<<0);
d = (void*)G4(dp+3);
bump = 8;
break;
case S4|D1:
s = (void*)G4(dp);
d = dst+(G1(dp+4)<<2);
bump = 6;
break;
case S4|D2:
s = (void*)G4(dp);
d = dst+(G2(dp+4)<<2);
bump = 7;
break;
case S4|D3:
s = (void*)G4(dp);
d = dst+(G3(dp+4)<<0);
bump = 8;
break;
case S4|D4:
s = (void*)G4(dp);
d = (void*)G4(dp+4);
bump = 9;
break;
default:
printf("bterp: BAD OPCODE for `mover' at pc=%x\n",
((char*)dp - iv->text_base) - 1);
longjmp(iv->jb, 1);
}
if(size == B1)
*((char*)d) = *((char*)s);
else if(size == B2)
*((short*)d) = *((short*)s);
else if(size == B4)
*((long*)d) = *((long*)s);
else if(size == B8)
*((double*)d) = *((double*)s);
else
memcpy(d,s,XSZ);
return bump;
}
static void
load_efunc(Piv iv, Pft ft)
{
void *e_faddr;
if(!(e_faddr = oxlink_find_bare_func((void*)ft->funcaddr)))
{/* not in core, load the file */
if(!(e_faddr = oxlink_load_bare_symb((void*)ft->funcaddr, 1)))
{
printf("bterp: Can't load function `%s'\n", (char*)ft->funcaddr);
exit(1);
}
}
ft->funcaddr = (long)e_faddr;
ft->fmods |= Fthunked;
}
/* MOST OF THESE BUILTINS ARE UNNECESSARY DEMOS */
/* PUT ANYTHING THAT COULD BE CALLED THROUGH A FUNCPTR HERE */
static int
do_builtin(Piv iv, unsigned char code, char **pes)
{/* NOTE: builtins with no args and void return must leave a pseudo ret on stack */
char *es, *oes;
es = *pes;
oes = es-SZ;

switch(code)
{
case ALLOCA:
{
char *abuf = malloc(*((unsigned*)es)+sizeof(void*));
*((void**)es) = abuf+sizeof(void*);
*((void**)abuf) = iv->allocalist;
iv->allocalist = abuf;
return 1;
}
case STRLEN:
{
*((unsigned*)es) = strlen(*((const char**)es));
return 1;
}
case STRCPY:
{
*((void**)oes) = strcpy(*((char**)oes),*((const char**)es));
*pes = oes;
return 1;
}
case STRCAT:
{
*((void**)oes) = strcat(*((char**)oes),*((const char**)es));
*pes = oes;
return 1;
}
case MEMCPY:
{
*((void**)(oes-SZ)) = memcpy(*((void**)(oes-SZ)),*((const void**)oes),*((unsigned*)es));
*pes -= 2*SZ;
return 1;
}
case MEMMOVE:
{
*((void**)(oes-SZ)) = memmove(*((void**)(oes-SZ)),*((const void**)oes),*((unsigned*)es));
*pes -= 2*SZ;
return 1;
}
case MEMSET:
{
*((void**)(oes-SZ)) =
memset(*((void**)(oes-SZ)),*((int*)oes),*((long*)es));
*pes -= 2*SZ;
return 1;
}
case BZERO:
{
memset(*((void**)oes),0,*((unsigned*)es));
*pes = oes;
return 0;
}
case DEBUG:
{
iv->debug=1;
printf("DEBUG ON\n");
fflush(stdout);
*pes = es+SZ; /* pseudo ret */
return 0;
}
case NODEBUG:
{
iv->debug=0;
printf("DEBUG OFF\n");
fflush(stdout);
*pes = es+SZ; /* pseudo ret */
return 0;
}
case MALLOC:
{
*((void**)es) = malloc(*((unsigned*)es));
return 1;
}
case CALLOC:
{
*((void**)oes) = calloc(*((unsigned*)oes),*((unsigned*)es));
*pes = oes;
return 1;
}
case REALLOC:
{
*((void**)oes) = realloc(*((void**)oes),*((unsigned*)es));
*pes = oes;
return 1;
}
}
return 0;
}
static void *
bterp_eval(Piv iv, long pc_offset, void *base_stack, char *es, char *eb)
{
char *dd, *fs;
unsigned char *pc, *np;
char *oes, *nes, *bes;
long first_loc = -100;
long last_loc;

dd = iv->dd;
fs = base_stack + sizeof(SB);
pc = iv->text_base + pc_offset;
bes = es;

if(iv->debug) {
printf("FUNCTION ofs=%x pc=%p bs=%p fs=%p es=%p dd=%p eb=%p\n",
pc_offset, pc, base_stack, fs, es, dd, eb);
fflush(stdout);
}
for(;;++pc)
{
np = pc+1;
oes = es-SZ;
nes = es+SZ;

if(iv->debug) {
printf("ofs:%x op=%x es=%p val=%x oval=%x nval=%x\n",
((char*)pc) - iv->text_base, *pc, es,
*((long*)es), *((long*)oes), *((long*)nes));
fflush(stdout);
}
if(es < bes) {
printf("STACK UNDERFLOW ofs:%x op=%x es=%p val=%x oval=%x nval=%x\n",
((char*)pc) - iv->text_base, *pc, es, *((long*)es), *((long*)oes), *((long*)nes));
fflush(stdout);
longjmp(iv->jb, (int)es);
}
if(es >= eb) {
printf("STACK OVERFLOW ofs:%x op=%x es=%p val=%x oval=%x nval=%x\n",
((char*)pc) - iv->text_base, *pc, es, *((long*)es), *((long*)oes), *((long*)nes));
fflush(stdout);
longjmp(iv->jb, (int)es);
}
switch(*pc)
{
case LOCATE|J1:
{
last_loc = ((char*)(pc + GP1(np))) - iv->text_base;
if(first_loc == -100) first_loc = last_loc;
++pc;
break;
}
case LOCATE|J2:
{
last_loc = ((char*)(pc + GP2(np))) - iv->text_base;
if(first_loc == -100) first_loc = last_loc;
pc += 2;
break;
}
case LOCATE|J3:
{
last_loc = ((char*)(pc + GP3(np))) - iv->text_base;
if(first_loc == -100) first_loc = last_loc;
pc += 3;
break;
}
case LOCATE|J4:
{
last_loc = ((char*)(pc + GP4(np))) - iv->text_base;
if(first_loc == -100) first_loc = last_loc;
pc += 4;
break;
}
case LS|A1|B1:
LOADSTK1(char);
case LS|A1|B2:
LOADSTK1(short);
case LS|A1|B4:
LOADSTK1(long);
case LS|A1|B8:
LOADSTK1(double);
case LS|A2|B1:
LOADSTK2(char);
case LS|A2|B2:
LOADSTK2(short);
case LS|A2|B4:
LOADSTK2(long);
case LS|A2|B8:
LOADSTK2(double);
case LS|A3|B1:
LOADSTK3(char);
case LS|A3|B2:
LOADSTK3(short);
case LS|A3|B4:
LOADSTK3(long);
case LS|A3|B8:
LOADSTK3(double);

case NEG|BYTE:
NEG_ES(char);
case NEG|SHORT:
NEG_ES(short);
case NEG|LONG:
NEG_ES(long);
case NEG|UBYTE:
NEG_ES(unsigned char);
case NEG|USHORT:
NEG_ES(unsigned short);
case NEG|ULONG:
NEG_ES(unsigned long);
case NEG|FLOAT:
NEG_ES(float);
case NEG|DOUBLE:
NEG_ES(double);

case LM|A1|B1:
LOADMEM1(char);
case LM|A1|B2:
LOADMEM1(short);
case LM|A1|B4:
LOADMEM1(long);
case LM|A1|B8:
LOADMEM1(double);
case LM|A2|B1:
LOADMEM2(char);
case LM|A2|B2:
LOADMEM2(short);
case LM|A2|B4:
LOADMEM2(long);
case LM|A2|B8:
LOADMEM2(double);
case LM|A3|B1:
LOADMEM3(char);
case LM|A3|B2:
LOADMEM3(short);
case LM|A3|B4:
LOADMEM3(long);
case LM|A3|B8:
LOADMEM3(double);
case LM|A4|B1:
LOADMEM4(char);
case LM|A4|B2:
LOADMEM4(short);
case LM|A4|B4:
LOADMEM4(long);
case LM|A4|B8:
LOADMEM4(double);

case COMP|B1:
COMP_ES(char);
case COMP|B2:
COMP_ES(short);
case COMP|B4:
COMP_ES(long);
#if SUPPORT_LONG_LONG
case COMP|B8:
COMP_ES(long long);
#else
#endif
case JMP|J1:
pc += GP1(np)-1;
break;
case JMP|J2:
pc += GP2(np)-1;
break;
case JMP|J3:
pc += GP3(np)-1;
break;
case JMP|J4:
pc += GP4(np)-1;
break;

case LJMPT|J1:
if(*(es)) pc += GP1(np)-1;
else {pc += 1; es=oes;}
break;
case LJMPT|J2:
if(*(es)) pc += GP2(np)-1;
else {pc += 2; es=oes;}
break;
case LJMPT|J3:
if(*(es)) pc += GP3(np)-1;
else {pc += 3; es=oes;}
break;
case LJMPT|J4:
if(*(es)) pc += GP4(np)-1;
else {pc += 4; es=oes;}
break;

case JMPT|J1:
if(*(es)) pc += GP1(np)-1;
else pc += 1;
es = oes;
break;
case JMPT|J2:
if(*(es)) pc += GP2(np)-1;
else pc += 2;
es = oes;
break;
case JMPT|J3:
if(*(es)) pc += GP3(np)-1;
else pc += 3;
es = oes;
break;
case JMPT|J4:
if(*(es)) pc += GP4(np)-1;
else pc += 4;
es = oes;
break;

case LJMPF|J1:
if(!*(es)) pc += GP1(np)-1;
else {pc += 1; es=oes;}
break;
case LJMPF|J2:
if(!*(es)) pc += GP2(np)-1;
else {pc += 2; es=oes;};
break;
case LJMPF|J3:
if(!*(es)) pc += GP3(np)-1;
else {pc += 3; es=oes;}
break;
case LJMPF|J4:
if(!*(es)) pc += GP4(np)-1;
else {pc +=4; es=oes;}
break;

case JMPF|J1:
if(!*(es)) pc += GP1(np)-1;
else pc += 1;
es = oes;
break;
case JMPF|J2:
if(!*(es)) pc += GP2(np)-1;
else pc += 2;
es = oes;
break;
case JMPF|J3:
if(!*(es)) pc += GP3(np)-1;
else pc += 3;
es = oes;
break;
case JMPF|J4:
if(!*(es)) pc += GP4(np)-1;
else pc +=4;
es = oes;
break;

case NOT|B1:
NOT_ES(char);
case NOT|B2:
NOT_ES(short);
case NOT|B4: /* also FLOAT */
NOT_ES(long);
case NOT|B8: /* also DOUBLE */
#if SUPPORT_LONG_LONG
NOT_ES(long long);
#else
NOT_ES1;
#endif
case SS|A1|B1:
STORSTK1(char);
case SS|A1|B2:
STORSTK1(short);
case SS|A1|B4:
STORSTK1(long);
case SS|A1|B8:
STORSTK1(double);
case SS|A2|B1:
STORSTK2(char);
case SS|A2|B2:
STORSTK2(short);
case SS|A2|B4:
STORSTK2(long);
case SS|A2|B8:
STORSTK2(double);
case SS|A3|B1:
STORSTK3(char);
case SS|A3|B2:
STORSTK3(short);
case SS|A3|B4:
STORSTK3(long);
case SS|A3|B8:
STORSTK3(double);

case TRUTHOF|B2:
TRUTH_ES(short);
case TRUTHOF|B4: /* also FLOAT */
TRUTH_ES(long);
case TRUTHOF|B8: /* also DOUBLE */
#if SUPPORT_LONG_LONG
TRUTH_ES(long long);
#else
TRUTH_ES1;
#endif
case CVT:
{
++pc;
++np;
switch(*pc)
{
case SRC(BYTE)|SHORT:
*((short*)es) = *((char*)es);
break;
case SRC(BYTE)|LONG:
*((long*)es) = *((char*)es);
break;
case SRC(BYTE)|USHORT:
*((unsigned short*)es) = *((char*)es);
break;
case SRC(BYTE)|ULONG:
*((unsigned long*)es) = *((char*)es);
break;
case SRC(BYTE)|FLOAT:
*((float*)es) = *((char*)es);
break;
case SRC(BYTE)|DOUBLE:
*((double*)es) = *((char*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(BYTE)|CLONGLONG:
*((long long*)es) = *((char*)es);
break;
case SRC(BYTE)|CULONGLONG:
*((unsigned long long*)es) = *((char*)es);
break;
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(BYTE)|CLONGDOUBLE:
*((long double*)es) = *((char*)es);
break;
#endif
case SRC(SHORT)|LONG:
*((long*)es) = *((short*)es);
break;
case SRC(SHORT)|ULONG:
*((unsigned long*)es) = *((short*)es);
break;
case SRC(SHORT)|FLOAT:
*((float*)es) = *((short*)es);
break;
case SRC(SHORT)|DOUBLE:
*((double*)es) = *((short*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(SHORT)|CLONGLONG:
*((long long*)es) = *((short*)es);
break;
case SRC(SHORT)|CULONGLONG:
*((unsigned long long*)es) = *((short*)es);
break;
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(SHORT)|CLONGDOUBLE:
*((long double*)es) = *((short*)es);
break;
#endif
case SRC(LONG)|FLOAT:
*((float*)es) = *((long*)es);
break;
case SRC(LONG)|DOUBLE:
*((double*)es) = *((long*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(LONG)|CLONGLONG:
*((long long*)es) = *((long*)es);
break;
case SRC(LONG)|CULONGLONG:
*((unsigned long long*)es) = *((long*)es);
break;
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(LONG)|CLONGDOUBLE:
*((long double*)es) = *((long*)es);
break;
#endif
case SRC(UBYTE)|SHORT:
*((short*)es) = *((unsigned char*)es);
break;
case SRC(UBYTE)|LONG:
*((long*)es) = *((unsigned char*)es);
break;
case SRC(UBYTE)|USHORT:
*((unsigned short*)es) = *((unsigned char*)es);
break;
case SRC(UBYTE)|ULONG:
*((unsigned long*)es) = *((unsigned char*)es);
break;
case SRC(UBYTE)|FLOAT:
*((float*)es) = *((unsigned char*)es);
break;
case SRC(UBYTE)|DOUBLE:
*((double*)es) = *((unsigned char*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(UBYTE)|CLONGLONG:
*((long long*)es) = *((unsigned char*)es);
break;
case SRC(UBYTE)|CULONGLONG:
*((unsigned long long*)es) = *((unsigned char*)es);
break;
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(UBYTE)|CLONGDOUBLE:
*((long double*)es) = *((unsigned char*)es);
break;
#endif
case SRC(USHORT)|LONG:
*((long*)es) = *((unsigned short*)es);
break;
case SRC(USHORT)|ULONG:
*((unsigned long*)es) = *((unsigned short*)es);
break;
case SRC(USHORT)|FLOAT:
*((float*)es) = *((unsigned short*)es);
break;
case SRC(USHORT)|DOUBLE:
*((double*)es) = *((unsigned short*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(USHORT)|CLONGLONG:
*((long long*)es) = *((unsigned short*)es);
break;
case SRC(USHORT)|CULONGLONG:
*((unsigned long long*)es) = *((unsigned short*)es);
break;
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(USHORT)|CLONGDOUBLE:
*((long double*)es) = *((unsigned short*)es);
break;
#endif
case SRC(ULONG)|FLOAT:
*((float*)es) = *((unsigned long*)es);
break;
case SRC(ULONG)|DOUBLE:
*((double*)es) = *((unsigned long*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(ULONG)|CLONGLONG:
*((long long*)es) = *((unsigned long*)es);
break;
case SRC(ULONG)|CULONGLONG:
*((unsigned long long*)es) = *((unsigned long*)es);
break;
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(ULONG)|CLONGDOUBLE:
*((long double*)es) = *((unsigned long*)es);
break;
#endif
case SRC(FLOAT)|BYTE:
*((char*)es) = *((float*)es);
break;
case SRC(FLOAT)|SHORT:
*((short*)es) = *((float*)es);
break;
case SRC(FLOAT)|LONG:
*((long*)es) = *((float*)es);
break;
case SRC(FLOAT)|UBYTE:
*((unsigned char*)es) = *((float*)es);
break;
case SRC(FLOAT)|USHORT:
*((unsigned short*)es) = *((float*)es);
break;
case SRC(FLOAT)|ULONG:
*((unsigned long*)es) = *((float*)es);
break;
case SRC(FLOAT)|DOUBLE:
*((double*)es) = *((float*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(FLOAT)|CLONGLONG:
*((long long*)es) = *((float*)es);
break;
case SRC(FLOAT)|CULONGLONG:
*((unsigned long long*)es) = *((float*)es);
break;
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(FLOAT)|CLONGDOUBLE:
*((long double*)es) = *((float*)es);
break;
#endif
case SRC(DOUBLE)|BYTE:
*((char*)es) = *((double*)es);
break;
case SRC(DOUBLE)|SHORT:
*((short*)es) = *((double*)es);
break;
case SRC(DOUBLE)|LONG:
*((long*)es) = *((double*)es);
break;
case SRC(DOUBLE)|UBYTE:
*((unsigned char*)es) = *((double*)es);
break;
case SRC(DOUBLE)|USHORT:
*((unsigned short*)es) = *((double*)es);
break;
case SRC(DOUBLE)|ULONG:
*((unsigned long*)es) = *((double*)es);
break;
case SRC(DOUBLE)|FLOAT:
*((float*)es) = *((double*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(DOUBLE)|CLONGLONG:
*((long long*)es) = *((double*)es);
break;
case SRC(DOUBLE)|CULONGLONG:
*((unsigned long long*)es) = *((double*)es);
break;
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(DOUBLE)|CLONGDOUBLE:
*((long double*)es) = *((double*)es);
break;
#endif
#if SUPPORT_LONG_LONG
case SRC(CLONGLONG)|FLOAT:
*((float*)es) = *((long long*)es);
break;
case SRC(CLONGLONG)|DOUBLE:
*((double*)es) = *((long long*)es);
break;
#if SUPPORT_LONG_DOUBLE
case SRC(CLONGLONG)|CLONGDOUBLE:
*((long double*)es) = *((long long*)es);
break;
#endif
case SRC(CULONGLONG)|FLOAT:
*((float*)es) = *((unsigned long long*)es);
break;
case SRC(CULONGLONG)|DOUBLE:
*((double*)es) = *((unsigned long long*)es);
break;
#if SUPPORT_LONG_DOUBLE
case SRC(CULONGLONG)|CLONGDOUBLE:
*((long double*)es) = *((unsigned long long*)es);
break;
#endif
#endif
#if SUPPORT_LONG_DOUBLE
case SRC(CLONGDOUBLE)|BYTE:
*((char*)es) = *((long double*)es);
break;
case SRC(CLONGDOUBLE)|SHORT:
*((short*)es) = *((long double*)es);
break;
case SRC(CLONGDOUBLE)|LONG:
*((long*)es) = *((long double*)es);
break;
case SRC(CLONGDOUBLE)|UBYTE:
*((unsigned char*)es) = *((long double*)es);
break;
case SRC(CLONGDOUBLE)|USHORT:
*((unsigned short*)es) = *((long double*)es);
break;
case SRC(CLONGDOUBLE)|ULONG:
*((unsigned long*)es) = *((long double*)es);
break;
case SRC(CLONGDOUBLE)|FLOAT:
*((float*)es) = *((long double*)es);
break;
case SRC(CLONGDOUBLE)|DOUBLE:
*((double*)es) = *((long double*)es);
break;
#if SUPPORT_LONG_LONG
case SRC(CLONGDOUBLE)|CLONGLONG:
*((long long*)es) = *((long double*)es);
break;
case SRC(CLONGDOUBLE)|CULONGLONG:
*((unsigned long long*)es) = *((long double*)es);
break;
#endif
#endif
}
break;
}
case IMMED:
{

++pc;
++np;
switch(*pc)
{

case SMI|A1|B1:
STORMEMI1(char);
case SMI|A1|B2:
STORMEMI1(short);
case SMI|A1|B4:
STORMEMI1(long);
case SMI|A1|B8:
STORMEMI1(double);
case SMI|A2|B1:
STORMEMI2(char);
case SMI|A2|B2:
STORMEMI2(short);
case SMI|A2|B4:
STORMEMI2(long);
case SMI|A2|B8:
STORMEMI2(double);
case SMI|A3|B1:
STORMEMI3(char);
case SMI|A3|B2:
STORMEMI3(short);
case SMI|A3|B4:
STORMEMI3(long);
case SMI|A3|B8:
STORMEMI3(double);
case SMI|A4|B1:
STORMEMI4(char);
case SMI|A4|B2:
STORMEMI4(short);
case SMI|A4|B4:
STORMEMI4(long);
case SMI|A4|B8:
STORMEMI4(double);

case SSI|A1|B1:
STORSTKI1(char);
case SSI|A1|B2:
STORSTKI1(short);
case SSI|A1|B4:
STORSTKI1(long);
case SSI|A1|B8:
STORSTKI1(double);
case SSI|A2|B1:
STORSTKI2(char);
case SSI|A2|B2:
STORSTKI2(short);
case SSI|A2|B4:
STORSTKI2(long);
case SSI|A2|B8:
STORSTKI2(double);
case SSI|A3|B1:
STORSTKI3(char);
case SSI|A3|B2:
STORSTKI3(short);
case SSI|A3|B4:
STORSTKI3(long);
case SSI|A3|B8:
STORSTKI3(double);

case MODI|BYTE:
MODI_ES(char);
case MODI|SHORT:
MODI_ES(short);
case MODI|LONG:
MODI_ES(long);
case MODI|UBYTE:
MODI_ES(unsigned char);
case MODI|USHORT:
MODI_ES(unsigned short);
case MODI|ULONG:
MODI_ES(unsigned long);

case DEREF|BYTE:
DEREF_ES(char);
case DEREF|SHORT:
DEREF_ES(short);
case DEREF|LONG:
DEREF_ES(long);
case DEREF|UBYTE:
UDEREF_ES(unsigned char);
case DEREF|USHORT:
UDEREF_ES(unsigned short);
case DEREF|ULONG:
UDEREF_ES(unsigned long);
case DEREF|FLOAT:
FDEREF_ES(float);
case DEREF|DOUBLE:
FDEREF_ES(double);

case DEREF1|BYTE:
DEREF1_ES(char);
case DEREF1|SHORT:
DEREF1_ES(short);
case DEREF1|LONG:
DEREF1_ES(long);
case DEREF1|UBYTE:
UDEREF1_ES(unsigned char);
case DEREF1|USHORT:
UDEREF1_ES(unsigned short);
case DEREF1|ULONG:
UDEREF1_ES(unsigned long);
case DEREF1|FLOAT:
FDEREF1_ES(float);
case DEREF1|DOUBLE:
FDEREF1_ES(double);
}
break;
}
case LI|B1:
LOADI1();
case LI|B2:
LOADI2();
case LI|B4:
LOADI4();
case LI|B8:
LOADI8();
case LAI|D1:
LOADADDRI1();
case LAI|D2:
LOADADDRI2();
case LAI|D3:
LOADADDRI3();
case LAI|D4:
LOADADDRI4();

case LUI|B1:
LOADUI1();
case LUI|B2:
LOADUI2();
case LUI|B4:
LOADUI4();
case LUI|B8:
LOADI8();

case SM|A1|B1:
STORMEM1(char);
case SM|A1|B2:
STORMEM1(short);
case SM|A1|B4:
STORMEM1(long);
case SM|A1|B8:
STORMEM1(double);
case SM|A2|B1:
STORMEM2(char);
case SM|A2|B2:
STORMEM2(short);
case SM|A2|B4:
STORMEM2(long);

case SM|A2|B8:
STORMEM2(double);
case SM|A3|B1:
STORMEM3(char);
case SM|A3|B2:
STORMEM3(short);
case SM|A3|B4:
STORMEM3(long);
case SM|A3|B8:
STORMEM3(double);
case SM|A4|B1:
STORMEM4(char);
case SM|A4|B2:
STORMEM4(short);
case SM|A4|B4:
STORMEM4(long);
case SM|A4|B8:
STORMEM4(double);


case ADD|BYTE:
ADD_ES(char);
case ADD|SHORT:
ADD_ES(short);
case ADD|LONG:
ADD_ES(long);
case ADD|UBYTE:
ADD_ES(unsigned char);
case ADD|USHORT:
ADD_ES(unsigned short);
case ADD|ULONG:
ADD_ES(unsigned long);
case ADD|FLOAT:
ADD_ES(float);
case ADD|DOUBLE:
ADD_ES(double);

case SUB|BYTE:
SUB_ES(char);
case SUB|SHORT:
SUB_ES(short);
case SUB|LONG:
SUB_ES(long);
case SUB|UBYTE:
SUB_ES(unsigned char);
case SUB|USHORT:
SUB_ES(unsigned short);
case SUB|ULONG:
SUB_ES(unsigned long);
case SUB|FLOAT:
SUB_ES(float);
case SUB|DOUBLE:
SUB_ES(double);

case MUL|BYTE:
MUL_ES(char);
case MUL|SHORT:
MUL_ES(short);
case MUL|LONG:
MUL_ES(long);
case MUL|UBYTE:
MUL_ES(unsigned char);
case MUL|USHORT:
MUL_ES(unsigned short);
case MUL|ULONG:
MUL_ES(unsigned long);
case MUL|FLOAT:
MUL_ES(float);
case MUL|DOUBLE:
MUL_ES(double);

case DIV|BYTE:
DIV_ES(char);
case DIV|SHORT:
DIV_ES(short);
case DIV|LONG:
DIV_ES(long);
case DIV|UBYTE:
DIV_ES(unsigned char);
case DIV|USHORT:
DIV_ES(unsigned short);
case DIV|ULONG:
DIV_ES(unsigned long);
case DIV|FLOAT:
DIV_ES(float);
case DIV|DOUBLE:
DIV_ES(double);

case OR|B1:
OR_ES(unsigned char);
case OR|B2:
OR_ES(unsigned short);
case OR|B4:
OR_ES(unsigned long);

case XOR|B1:
XOR_ES(unsigned char);
case XOR|B2:
XOR_ES(unsigned short);
case XOR|B4:
XOR_ES(unsigned long);

case AND|B1:
AND_ES(unsigned char);
case AND|B2:
AND_ES(unsigned short);
case AND|B4:
AND_ES(unsigned long);

#if SUPPORT_LONG_LONG
case OR|B8:
OR_ES(unsigned long long);
case AND|B8:
AND_ES(unsigned long long);
case XOR|B8
XOR_ES(unsigned long long);
#else
#endif

case MOD|BYTE:
MOD_ES(char);
case MOD|SHORT:
MOD_ES(short);
case MOD|LONG:
MOD_ES(long);
case MOD|UBYTE:
MOD_ES(unsigned char);
case MOD|USHORT:
MOD_ES(unsigned short);
case MOD|ULONG:
MOD_ES(unsigned long);

case XTD:
{
++pc;
++np;
switch(*pc)
{
case LSH|B1:
LSH_ES(char);
case LSH|B2:
LSH_ES(short);
case LSH|B4:
LSH_ES(long);
case LSH|B8:
LSH_ES(long long);

case LSHI|B1:
LSHI_ES(char);
case LSHI|B2:
LSHI_ES(short);
case LSHI|B4:
LSHI_ES(long);
case LSHI|B8:
LSHI_ES(long long);

case RSH|BYTE:
RSH_ES(char);
case RSH|SHORT:
RSH_ES(short);
case RSH|LONG:
RSH_ES(long);
case RSH|UBYTE:
RSH_ES(unsigned char);
case RSH|USHORT:
RSH_ES(unsigned short);
case RSH|ULONG:
RSH_ES(unsigned long);

case RSHI|BYTE:
RSHI_ES(char);
case RSHI|SHORT:
RSHI_ES(short);
case RSHI|LONG:
RSHI_ES(long);
case RSHI|UBYTE:
RSHI_ES(unsigned char);
case RSHI|USHORT:
RSHI_ES(unsigned short);
case RSHI|ULONG:
RSHI_ES(unsigned long);

case BUILTIN:
{
++pc;
++np;
switch(*pc)
{/* THESE BUILTINS CANNOT BE CALLED THROUGH A FUNCPTR */
case SETJMP:
{
long *jb;

jb = *((void**)es);
*((long*)es) = 0;

jb[0] = (long)iv->allocalist;
jb[1] = (long)pc;
if((jb = (long*)setjmp(((void*)&jb[4]))))
{
void *bs,*qs;
pc = (void*)jb[1];
*((long*)es) = jb[2];
bs = (void*)jb[3];
while(bs != base_stack)
{
qs = ((PSB)bs)->backlink;
free(bs);
bs = qs;
}
purge_allocas(iv, (void*)jb[0]);

prune_structs(iv);
}
break;
}
case LONGJMP:
{
long *jb;

jb = *((void**)oes);
jb[2] = *((long*)es);
jb[3] = (long)base_stack;
longjmp(((void*)&jb[4]), (long)jb);
break;
}
case ABORT:
printf("bterp: program called abort.\n");
case EXIT:
{
void *bs, *qs;
bs = base_stack;
while(bs != iv->base_stack)
{
qs = ((PSB)bs)->backlink;
free(bs);
bs = qs;
}
purge_allocas(iv, 0);
longjmp(iv->jb, (int)es);
break;
}
default:
do_builtin(iv, *pc, &es);
break;
}
break;
} /* END: XTD BUILTIN */
case CLRDAT:
{
memset(*((void**)oes), 0, *((long*)es));
es -= 2*SZ;
break;
}
case SWITCH:
{
unsigned long key[2];
unsigned char **result;

key[0] = *((unsigned short*)np)<<11;
key[1] = *((long*)es);
if(findswitch(iv, key, &result))
{
pc = *result - 1;
}
else
{
pc += 2;
}
es = oes;
break;
}
case CALLSETUP:
{
PCB cb = (PCB)es;
Pft ft = cb->loc;
int hidden;
long stksiz, maxes;
long argsiz, strucsiz;
int flags = 0;
if(ft->fmods & Fbuiltin)
{/* This only happens if the programmer uses a function
pointer which points to a builtin function. */
flags = 0x80;
}
cb->argsiz = argsiz = G4(np);

if((hidden = ft->fmods & Fretstr))
{/* function returning a structure */
strucsiz = ft->retsiz<<2;
}
stksiz = ft->stksiz<<2;
maxes = ft->maxes;

if(ft->fmods & Fnested)
{/* Calling nested function */
cb->argofs = (ft->stkbeg+(stksiz-(ft->argsiz<<2)-hidden)) >> 2;
if(ft->funcaddr >= first_loc && ft->funcaddr <= last_loc)
{/* call from enclosing function */
cb->base_stack = base_stack;
cb->es = es;
cb->flags = 0x10 + hidden;
}
else
{/* callback from another function */
PSB prev = (PSB)(fs - sizeof(SB));
long floc = prev->first_loc;
long lloc = prev->last_loc;

while((prev = prev->backlink))
{
if( ft->funcaddr >= floc
&& ft->funcaddr <= lloc)
{/* This is the container of the nested func */
cb->base_stack = (char*)prev;
cb->es = prev->cbes;
break;
}
floc = prev->first_loc;
lloc = prev->last_loc;
}
cb->flags = 0x20 + hidden;
}
}
else if(ft->fmods & Fextern)
{/* Calling external function */
/* Dynamic link it */
if(!(ft->fmods & Fthunked))
load_efunc(iv, ft);

cb->base_stack = calloc(1, sizeof(SB)+argsiz+hidden);
cb->argsiz = argsiz+hidden;
cb->argofs = 0;
cb->flags = 0x40 + hidden;
}
else
{/* Calling interpreted function */
if(flags & 0x80)
{
cb->flags = flags;
cb->es = cb->base_stack = calloc(1, 128);
}
else
{
long es_beg;
long fs_size;
PSB sp;
es_beg = stksiz+hidden+argsiz;
fs_size = es_beg + ((maxes+6)*SZ);
cb->base_stack = calloc(1, fs_size+sizeof(SB));
sp = (PSB)cb->base_stack;
cb->es = cb->base_stack + sizeof(SB) + es_beg;
cb->argofs = stksiz >> 2;
cb->flags = flags + hidden;
sp->first_loc = first_loc;
sp->last_loc = last_loc;
sp->backlink = base_stack;
sp->stksize = fs_size+sizeof(SB);
}
}
if(hidden)
{/* function returning a structure */
void *strucptr = malloc(strucsiz);
*((void**)(cb->base_stack+sizeof(SB)+(cb->argofs<<2))) = strucptr;
ensure_strrets(iv);
iv->struclist[iv->strretcnt++] = strucptr;
}
pc += 4;
break;
}
case RETSTRUCT:
{
long size = G2(np)<<2;
long offset = G2(np+2)<<2;
void *dst;

dst = fs + offset;
dst = *((void**)dst);
memcpy(dst, *((void**)es), size);
if(iv->debug) {
printf("RETSTRUCT ofs=%x es=%p val=0x%x\n", pc_offset, es, *((long*)es));
fflush(stdout);
}
return es;
}
case PRUNESTRUCT:
{
prune_structs(iv);
break;
}
case GETBITFIELD:
{
if(pc[1] + pc[2] <= 32)
{
*((long*)es) >>= pc[1];
*((long*)es) &= bfields[pc[2]];
if(pc[3])
{/* sign extend */
if(*((long*)es) & tsfields[pc[2]])
{
*((long*)es) |= sfields[pc[2]];
((long*)es)[1] = 0xffffffff;
}
else ((long*)es)[1] = 0;
}
}
else
{
#if SUPPORT_LONG_LONG
*((long long*)es) >>= pc[1];
*((long long*)es) &= lbfields[pc[2]];
if(pc[3])
{
if(*((long long)es) & ltsfields[pc[2]])
*((long long)es) |= lsfields[pc[2]]);
}
#else
#endif
}
pc += 3;
break;
}
case PUTBITFIELD:
{

if(pc[1] + pc[2] <= 32)
{
unsigned long mask = bfields[pc[2]];
void *dst = *((void **)oes);
unsigned long dat = *((long*)es);
dat &= mask;
dat <<= pc[1];
mask <<= pc[1];
switch(pc[3])
{
case 1:
*((char*)dst) &= ~mask;
*((char*)dst) |= dat;
break;
case 2:
*((short*)dst) &= ~mask;
*((short*)dst) |= dat;
break;
case 4:
*((long*)dst) &= ~mask;
*((long*)dst) |= dat;
break;
default:
break;
}
}
else
{
#if SUPPORT_LONG_LONG
unsigned long long mask = lbfields[pc[2]];
void *dst = *((void **)oes);
unsigned long long dat = *(unsigned long long *)es);
dat &= mask;
dat <<= pc[1];
mask <<= pc[1];
switch(pc[3])
{
case 1:
*((char*)dst) &= ~mask;
*((char*)dst) |= dat;
break;
case 2:
*((short*)dst) &= ~mask;
*((short*)dst) |= dat;
break;
case 4:
*((long*)dst) &= ~mask;
*((long*)dst) |= dat;
break;
case 8:
*((long long*)dst) &= ~mask;
*((long long*)dst) |= dat;
break;
default:
break;
}
#else
#endif
}
pc += 3;
es -= 2*SZ;
break;
}
#if SUPPORT_LONG_DOUBLE
case LI:
LOADIX();
#endif
case IMMED:
{
++pc;
++np;
switch(*pc)
{
#if SUPPORT_LONG_DOUBLE

case SMI|A1:
STORMEMI1(long double);
case SMI|A2:
STORMEMI2(long double);
case SMI|A3:
STORMEMI3(long double);
case SMI|A4:
STORMEMI4(long double);

case SSI|A1:
STORSTKI1(long double);
case SSI|A2:
STORSTKI2(long double);
case SSI|A3:
STORSTKI3(long double);

case DEREF|LONGDOUBLE:
FDEREF_ES(long double);
case DEREF1|LONGDOUBLE:
FDEREF1_ES(long double);
#endif
#if SUPPORT_LONG_LONG
case DEREF|LONGLONG:
case DEREF|ULONGLONG:
FDEREF_ES(long long);

case DEREF1|LONGLONG:
case DEREF1|ULONGLONG:
FDREF1_ES(long long);

case MODI|LONGLONG:
MODI_ES(long long);
case MODI|ULONGLONG:
MODI_ES(unsigned long long);
#endif
}
break;
}/* END: XTD IMMED */
#if SUPPORT_LONG_LONG

case ADD|LONGLONG:
ADD_ES(long long);
case ADD|ULONGLONG:
ADD_ES(unsigned long long);
case SUB|LONGLONG:
SUB_ES(long long);
case SUB|ULONGLONG:
SUB_ES(unsigned long long);
case MUL|LONGLONG:
MUL_ES(long long);
case MUL|ULONGLONG:
MUL_ES(unsigned long long);
case DIV|LONGLONG:
DIV_ES(long long);
case DIV|ULONGLONG:
DIV_ES(unsigned long long);
case NEG|LONGLONG:
NEG_ES(long long);
case NEG|ULONGLONG:
NEG_ES(unsigned long long);
case LT|LONGLONG:
LT_ES(long long);
case LT|ULONGLONG:
LT_ES(unsigned long long);
case GT|LONGLONG:
GT_ES(long long);
case GT|ULONGLONG:
GT_ES(unsigned long long);
case LE|LONGLONG:
LE_ES(long long);
case LE|ULONGLONG:
LE_ES(unsigned long long);
case GE|LONGLONG:
GE_ES(long long);
case GE|ULONGLONG:
GE_ES(unsigned long long);
case NE|LONGLONG:
NE_ES(long long);
case NE|ULONGLONG:
NE_ES(unsigned long long);
case EQ|LONGLONG:
EQ_ES(long long);
case EQ|ULONGLONG:
EQ_ES(unsigned long long);
case RSH|SLONGLONG:
RSH_ES(long long);
case RSH|SULONGLONG:
RSH_ES(unsigned long long);

case MOD|LONGLONG:
MODL_ES(long long);
case MOD|ULONGLONG:
MODL_ES(unsigned long long);


case RSHI|SLONGLONG:
RSHI_ES(long long);
case RSHI|SULONGLONG:
RSHI_ES(unsigned long long);
#endif

#if SUPPORT_LONG_DOUBLE

case ADD|LONGDOUBLE:
ADD_ES(long double);
case SUB|LONGDOUBLE:
SUB_ES(long double);
case MUL|LONGDOUBLE:
MUL_ES(long double);
case DIV|LONGDOUBLE:
DIV_ES(long double);
case TRUTHOF|BX:
TRUTH_ES(long double);
case NOT|BX:
NOT_ES(long double);
case NEG|LONGDOUBLE:
NEG_ES(long double);
case LT|LONGDOUBLE:
LT_ES(long double);
case GT|LONGDOUBLE:
GT_ES(long double);
case LE|LONGDOUBLE:
LE_ES(long double);
case GE|LONGDOUBLE:
GE_ES(long double);
case NE|LONGDOUBLE:
NE_ES(long double);
case EQ|LONGDOUBLE:
EQ_ES(long double);

case LS|A1:
LOADSTK1(long double);
case LS|A2:
LOADSTK2(long double);
case LS|A3:
LOADSTK3(long double);
case LS|A4:
LOADSTK4(long double);

case LM|A1:
LOADMEM1(long double);
case LM|A2:
LOADMEM2(long double);
case LM|A3:
LOADMEM3(long double);
case LM|A4:
LOADMEM4(long double);

case SS|A1:
STORSTK1(long double);
case SS|A2:
STORSTK2(long double);
case SS|A3:
STORSTK3(long double);
case SS|A4:
STORSTK4(long double);

case SM|A1:
STORMEM1(long double);
case SM|A2:
STORMEM2(long double);
case SM|A3:
STORMEM3(long double);
case SM|A4:
STORMEM4(long double);

case MOVSS:
{
pc += mover(iv, np+1, *np, BX, fs, fs);
break;
}
case MOVSM:
{
pc += mover(iv, np+1, *np, BX, fs, dd);
break;
}
case MOVMS:
{
pc += mover(iv, np+1, *np, BX, dd, fs);
break;
}
case MOVMM:
{
pc += mover(iv, np+1, *np, BX, dd, dd);
break;
}
#endif /* SUPPORT_LONG_DOUBLE */
}
break;
}/* END: XTD */

case GT|BYTE:
GT_ES(char);
case GT|SHORT:
GT_ES(short);
case GT|LONG:
GT_ES(long);
case GT|UBYTE:
GT_ES(unsigned char);
case GT|USHORT:
GT_ES(unsigned short);
case GT|ULONG:
GT_ES(unsigned long);
case GT|FLOAT:
GT_ES(float);
case GT|DOUBLE:
GT_ES(double);

case LT|BYTE:
LT_ES(char);
case LT|SHORT:
LT_ES(short);
case LT|LONG:
LT_ES(long);
case LT|UBYTE:
LT_ES(unsigned char);
case LT|USHORT:
LT_ES(unsigned short);
case LT|ULONG:
LT_ES(unsigned long);
case LT|FLOAT:
LT_ES(float);
case LT|DOUBLE:
LT_ES(double);

case GE|BYTE:
GE_ES(char);
case GE|SHORT:
GE_ES(short);
case GE|LONG:
GE_ES(long);
case GE|UBYTE:
GE_ES(unsigned char);
case GE|USHORT:
GE_ES(unsigned short);
case GE|ULONG:
GE_ES(unsigned long);
case GE|FLOAT:
GE_ES(float);
case GE|DOUBLE:
GE_ES(double);

case LE|BYTE:
LE_ES(char);
case LE|SHORT:
LE_ES(short);
case LE|LONG:
LE_ES(long);
case LE|UBYTE:
LE_ES(unsigned char);
case LE|USHORT:
LE_ES(unsigned short);
case LE|ULONG:
LE_ES(unsigned long);
case LE|FLOAT:
LE_ES(float);
case LE|DOUBLE:
LE_ES(double);

case NE|BYTE:
NE_ES(char);
case NE|SHORT:
NE_ES(short);
case NE|LONG:
NE_ES(long);
case NE|UBYTE:
NE_ES(unsigned char);
case NE|USHORT:
NE_ES(unsigned short);
case NE|ULONG:
NE_ES(unsigned long);
case NE|FLOAT:
NE_ES(float);
case NE|DOUBLE:
NE_ES(double);

case EQ|BYTE:
EQ_ES(char);
case EQ|SHORT:
EQ_ES(short);
case EQ|LONG:
EQ_ES(long);
case EQ|UBYTE:
EQ_ES(unsigned char);
case EQ|USHORT:
EQ_ES(unsigned short);
case EQ|ULONG:
EQ_ES(unsigned long);
case EQ|FLOAT:
EQ_ES(float);
case EQ|DOUBLE:
EQ_ES(double);

case ARG:
case ARGA:
case ARGF:
{
PCB cb = (PCB)(es-(3*SZ));
long size = *((long*)es);
void *src = oes-SZ;
void *dst;
if(cb->flags & 0x80)
{/* arg to builtin func */
cb->es += SZ;
dst = cb->es;
}
else
{
dst = cb->base_stack+sizeof(SB)+(cb->argofs<<2)+*((long*)oes);
}
if(*pc == ARGA)
{/* dereference */
src = *((void**)src);
}
else if(*pc == ARGF)
{/* Passing address of function */
Pft ft = *((Pft*)src);

if(ft->fmods & Fnested)
{/* Record the current evaluation stack
the nested func will be called back */
((PSB)base_stack)->cbes = (void*)cb;
}
if(cb->flags & 0x40)
{/* To an external function */
if(!(ft->fmods & Fextern))
{/* Passing address of local function */
if(!(ft->fmods & Fthunked))
{
*((void**)src) = make_callback_thunk( iv,
base_stack,
ft);
ft->fmods |= Fthunked;
if(ft->fmods & Fnested)
{/* The thunk will be freed later */
((PSB)base_stack)->thunkaddr = *((void**)src);
}
}
}
}
}/* END: *pc == ARGF */
switch(size)
{
case 1:
*((char*)dst) = *((char*)src);
break;
case 2:
*((short*)dst) = *((short*)src);
break;
case 4:
*((long*)dst) = *((long*)src);
break;
case 8:
*((double*)dst) = *((double*)src);
break;
default:
memcpy(dst, src, size);
break;
}
es -= 3*SZ;
break;
}

case MOVSS|B1:
case MOVSS|B2:
case MOVSS|B4:
case MOVSS|B8:
{
pc += mover(iv, np+1, *np, *pc & 3, fs, fs);
break;
}
case MOVSM|B1:
case MOVSM|B2:
case MOVSM|B4:
case MOVSM|B8:
{
pc += mover(iv, np+1, *np, *pc & 3, fs, dd);
break;
}
case MOVMS|B1:
case MOVMS|B2:
case MOVMS|B4:
case MOVMS|B8:
{
pc += mover(iv, np+1, *np, *pc & 3, dd, fs);
break;
}
case MOVMM|B1:
case MOVMM|B2:
case MOVMM|B4:
case MOVMM|B8:
{
pc += mover(iv, np+1, *np, *pc & 3, dd, dd);
break;
}
case DUMP:
{
es = oes;
break;
}
case REGAIN:
{
es = nes;
break;
}
case CALL:
{
PCB cb = (PCB)es;
Pft ft = cb->loc;
if(cb->flags & 0x80)
{/* call builtin function through a function pointer */
char *pes = cb->es;

if(do_builtin(iv, (unsigned char)ft->funcaddr, &pes))
{/* builtin returned something */
#if SUPPORT_LONG_DOUBLE
*((long double*)es) = *((long double*)(pes));
#else
*((double*)es) = *((double*)pes);
#endif
}
free(cb->base_stack);
}
else if(cb->flags & 0x40)
{/* call external function */
unsigned short fmods = ft->fmods;
DATUM lastval;
if(fmods & Fretstr)
{
_ExternCallS( ft->funcaddr,
cb->base_stack+sizeof(SB),
cb->argsiz,
&lastval);
}
else
{
_ExternCall( ft->funcaddr,
cb->base_stack+sizeof(SB),
cb->argsiz,
&lastval);
}
if(fmods & Fretdbl)
{
asm ("fstpl %0" : "=g"(lastval.Udouble) :);
}
else if(fmods & Fretflt)
{
asm ("fstps %0" : "=g"(lastval.Ufloat) :);
}
else if(fmods & Fretldbl)
{
#if SUPPORT_LONG_DOUBLE
#else
asm ("fstpl %0" : "=g"(lastval.Udouble) :);
#endif
}
#if SUPPORT_LONG_DOUBLE
*((long double*)es) = lastval.Ulongdouble;
#else
*((double*)es) = lastval.Udouble;
#endif
free(cb->base_stack);
}/* END: call external func */
else
{ /* call internal function */
void *pes;
void *lastalloca = iv->allocalist;
pes = bterp_eval(iv, ft->funcaddr, cb->base_stack, cb->es,
cb->base_stack+((PSB)cb->base_stack)->stksize);
#if SUPPORT_LONG_DOUBLE
*((long double*)es) = *((long double*)pes);
#else
*((double*)es) = *((double*)pes);
#endif
if(cb->flags & 0x20)
{/* calledback a nested function */

}
else if(!(cb->flags & 0x10))
{/* called interpreted function */
free(cb->base_stack);
}
purge_allocas(iv, lastalloca);
}/* END: call internal function */
break;
}
case RET:
{
if(iv->debug) {
printf("RET ofs=%x es=%p val=0x%x\n", pc_offset, es, *((long*)es));
fflush(stdout);
}
return es;
}
case SWAP:
{
char t[SZ];
memcpy(t,es,SZ);
memcpy(es,oes,SZ);
memcpy(oes,t,SZ);
break;
}
case SWAP4:
{
long x;
x = *((long *)es);
*((long*)es) = *((long*)oes);
*((long*)oes) = x;
break;
}
case SWAP4DEEP:
{
long x;
x = *((long*)oes);
*((long*)oes) = *((long*)(oes-SZ));
*((long*)(oes-SZ)) = x;
break;
}
case DUP:
{
memcpy(nes,es,SZ);
es = nes;
break;
}
case DUP4:
{
*((long*)nes) = *((long*)es);
es = nes;
break;
}
case ABSMEM:
{
*((unsigned long*)es) += (unsigned long)dd;
break;
}
case ABSSTK:
{
*((unsigned long*)es) += (unsigned long)fs;
break;
}
case MOVDA1:
{
**((char**)(oes)) = *((char*)es);
es -= 2*SZ;
break;
}
case MOVDA2:
{
**((short**)(oes)) = *((short*)es);
es -= 2*SZ;
break;
}
case MOVDA4:
{
**((long**)(oes)) = *((long*)es);
es -= 2*SZ;
break;
}
case MOVDA8:
{
**((double**)(oes)) = *((double*)es);
es -= 2*SZ;
break;
}
case MOVDAX:
{
#if SUPPORT_LONG_DOUBLE
**((long double**)(oes)) = *((long double*)es);
#else
memcpy(*((void**)(oes)), es, XSZ);
#endif
es -= 2*SZ;
break;
}
case MOVAA1:
{
**((char**)(oes)) = **((char**)es);
es -= 2*SZ;
break;
}
case MOVAA2:
{
**((short**)(oes)) = **((short**)es);
es -= 2*SZ;
break;
}
case MOVAA4:
{
**((long**)(oes)) = **((long**)es);
es -= 2*SZ;
break;
}
case MOVAA8:
{
**((double**)(oes)) = **((double**)es);
es -= 2*SZ;
break;
}
case MOVAAX:
{
#if SUPPORT_LONG_DOUBLE
**((long double**)(oes)) = **((long double**)es);
#else
memcpy(*((void**)(oes)), *((void**)es), XSZ);
#endif
es -= 2*SZ;
break;
}
case MOVAAC:
{
memcpy(*((void**)(es-(2*SZ))), *((void**)(oes)), *((long*)(es)));
es -= 3*SZ;
break;
}
}
}/* END: for(;;++pc) */
/* NOT REACHED */
return 0;
}/* END: bterp_eval() */
/* ====================== END INTERPRETER CODE ===================== */

/* ================== INITIALIZATION CODE BELOW THIS POINT ================ */
static Piv tiv; /* temporary storage of iv whilst calling oxlink */

int
bterp_setup_functhunk(FE entry, struct nlist *nl)
{/* Called from the dynamic linker */
Pft ft;

ft = (void*)(entry->data_start_address + nl->n_value);

if(ft->fmods & Fextern)
{/* store a pointer to the function name string */
if(!(ft->fmods & Fthunked))
{
ft->funcaddr = (long)(entry->strings + nl->n_un.n_strx);
}
return 0;
}
else if(!(ft->fmods & Fthunked))
{/* export a useful address */
nl->n_value = (long)make_callback_thunk(tiv, 0, ft);
ft->fmods |= Fthunked;
}
return 1;
}
void
bterp_setup_switch(FE entry, struct nlist *nl)
{/* Called from the dynamic linker */
unsigned long key[2];
long value;

if(tiv->swtable == 0)
tiv->swtable = calloc(1, SWITCHMOD*sizeof(void*));

key[0] = nl->n_desc<<11;
key[1] = nl->n_un.n_strx;
value = (long)(entry->text_start_address + nl->n_value);
saveswitch(tiv, key, value);
}

/* ====================== THE MAIN PROGRAM =============================== */

static char *
filenameof(char *path)
{
char *ret = path;
int i;
for(i = 0; path[i]; ++i)
if(path[i] == '/')
ret = &path[i+1];
return ret;
}

static char *
propernameof(char *path)
{
int pathlen = strlen(path);
char *name = malloc(pathlen+8);
int i;

strcpy(name, path);
for(i = pathlen-1; i >= 0; --i)
{
if(name[i] == '/' || name[i] == '\\')
break;
else if(name[i] == '.')
return name;
}
strcat(name, ".byt");
return name;
}
static char *
basenameof(char *filename)
{
char *name = malloc(strlen(filename)+8);
int i;
strcpy(name, filename);
for(i = 0; name[i]; ++i)
if(name[i] == '.')
name[i] = 0;
return name;
}
static void
setup_run_args(Piv iv, int argc, char **argv, char *startname)
{
int i;

if(!startname)
{
startname = basenameof(filenameof(argv[1]));
}
iv->run_argcnt = argc - 1;
if(iv->run_argcnt > MAX_RUNARGS)
iv->run_argcnt = MAX_RUNARGS;
iv->run_args[0] = startname;
for(i = 1; i < iv->run_argcnt; ++i)
{
iv->run_args[i] = argv[i+1];
}
}
static void
Usage()
{
puts(
"Usage: bterp [+Sd] file [args]...\n"
" +S name == start execution at function `name'\n"
" +d == print debug stmts\n"
" Default execution starts at function `file'\n"
);
}
#if USING_FRAMEWORK
int
PROG (int argc, char **argv)
#else
int
main(int argc, char **argv)
#endif
{
int i, j;
char *startname;
long *argptr;
long es_beg, fs_size;
int *pes, ret;
Piv iv;

iv = tiv = calloc(1, sizeof(struct _iv));
iv->piv = iv;

startname = 0;
for(i = 1; i < argc; ++i)
{
int trimsize = 1;
if(argv[i][0] == '+')
{
for (j=1; argv[i][j]; j++)
{
switch(argv[i][j])
{
case 'd':
iv->debug = 1;
break;
case 'S':
if(argv[i][j+1]) {
startname = &argv[i][j+1];
}
else if(i < argc-1) {
startname = argv[i+1];
trimsize = 2;
} else {
printf("bterp: No starting fuction name\n");
Usage();
return 1;
}
goto trim;
break;
}
}
trim:
/* Trim switch */
for(j = i; j < argc-trimsize; ++j)
argv[j] = argv[j+trimsize];
argc -= trimsize;
--i; /* i will be bumped by for */
}
}
if(argc > 1)
{
PSB sp;
iv->filename = propernameof(argv[1]);
if(oxlink_load_object(iv->filename)) /* try library list */
{
oxlink_demand_noload();
if(oxlink_load_file(iv->filename)) /* try search path */
{
printf("bterp: file `%s' err:%s\n", iv->filename, oxlink_errstr());
exit(1);
}
oxlink_demand_load();
}
iv->entry = oxlink_get_entry_struct(iv->filename);
iv->text_base = iv->entry->text_start_address;
iv->dd = iv->entry->data_start_address;

setup_run_args(iv, argc, argv, startname);
if(!(iv->funcptr = oxlink_find_func("main")))
{
if(!(iv->funcptr = oxlink_find_func(iv->run_args[0])))
{
printf("bterp: function `%s' not found in file\n", iv->run_args[0]);
oxlink_unload_file(iv->filename, 0);
free(iv->filename);
free(iv->run_args[0]);
free(iv);
return 1;
}
}
iv->ft = *((Pft*)(&iv->funcptr[4]));
iv->funcaddr = iv->ft->funcaddr;
iv->stksiz = iv->ft->stksiz<<2;
iv->argsiz = iv->ft->argsiz<<2;
iv->maxes = iv->ft->maxes;

es_beg = iv->stksiz+iv->argsiz;
fs_size = es_beg + ((iv->maxes+6)*SZ);
iv->base_stack = calloc(1, fs_size + sizeof(SB));
iv->e_stack = iv->base_stack + sizeof(SB) + es_beg;

/* Fill in _stakblk */
sp = (PSB)iv->base_stack;
sp->first_loc = iv->funcaddr;
sp->last_loc = iv->dd - iv->text_base;
sp->stksize = fs_size + sizeof(SB);

/* Fill in the arguments */
argptr = (long*)(iv->base_stack + iv->stksiz + sizeof(SB));
if(iv->argsiz >= 4)
argptr[0] = iv->run_argcnt;
if(iv->argsiz >= 8)
argptr[1] = (long)iv->run_args;

if((pes = (void*)setjmp(iv->jb)))
goto done;

/* Call the starting function */
pes = bterp_eval(iv, iv->funcaddr, iv->base_stack, iv->e_stack,
iv->base_stack + (fs_size+sizeof(SB)));
done:
ret = *pes;
prune_structs(iv);
oxlink_unload_file(iv->filename, 0);
free(iv->filename);
free(iv->run_args[0]);
free(iv->base_stack);
if(iv->swtable)
{
void *p = iv->chunklist;
free(iv->swtable);
while(p)
{
void *q = p;
p = *((void**)p);
free(q);
}
}
free(iv);
return ret;
}
else
{
Usage();
return 1;
}
}
#if 0 /* used for testing */
int bterpcallback(int (*pfunc)())
{
return pfunc();
}
#endif


  3 Responses to “Category : Recently Uploaded Files
Archive   : OXCC1430.ZIP
Filename : BTERP.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/