📄 bterp.c
字号:
/*
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));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -