home *** CD-ROM | disk | FTP | other *** search
- /*
- 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
- (954) 463-4754
- ndc@icanect.net
- 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_LONG 1
- #define SUPPORT_LONG_DOUBLE 1
-
- #define NEED_BYTECODES 1
- #define NEED_AOUT_FORMAT 1
- #include "oxbytes.h"
-
- #define NEED_FUNCTHUNK 1
- #include "oxanf.h"
- #include <stdlib.h>
- #include <setjmp.h>
- #include <stdio.h>
-
- #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<b)?a:b)
-
- #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));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))));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))));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
- asm ("fstpt %0" :: "g"(lastval.Udouble));
- #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:ERROR: bad opcode for `mover' at pc=%lx\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:ERROR: 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 = 0;
-
- dd = iv->dd;
- fs = base_stack + sizeof(SB);
- pc = iv->text_base + pc_offset;
- bes = es;
-
- if(iv->debug) {
- printf("FUNCTION ofs=%lx 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:%lx op=%x es=%p val=%lx oval=%lx nval=%lx\n",
- ((char*)pc) - iv->text_base, *pc, es,
- *((long*)es), *((long*)oes), *((long*)nes));
- fflush(stdout);
- }
- if(es < bes) {
- printf("bterp:ERROR: STACK UNDERFLOW ofs:%lx op=%x es=%p val=%lx oval=%lx nval=%lx\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("bterp:ERROR: STACK OVERFLOW ofs:%lx op=%x es=%p val=%lx oval=%lx nval=%lx\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: user 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=%lx es=%p val=0x%lx\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:
- FDEREF1_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 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 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
- asm ("fstpt %0" : "=g"(lastval.Ulongdouble) :);
- #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=%lx es=%p val=0x%lx\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 = strlen(path)-1;
-
- for( ; i >= 0; --i)
- if(path[i] == '/' || path[i] == '\\' || 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] == '\\' || 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:ERROR: 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:ERROR: file `%s' %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:ERROR: 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
-