/* X0.c This is the startup module for external functions. Recompiling requires Borland C++ or Turbo C and Assembler. There is an alternate startup module in this file for external functions which do not require DS=SS. The math library, ld.lib, which has been provided, does not require DS=SS. Programs built with this save some disk space. Options. You must set Opt=1 or Opt=2. 1. External function sets up its own stack segment. This allows you to guarantee enough stack space, but more importantly, it allows DS=SS which is what the compiler expects in tiny model. Unfortunately, however, the floating point emulator doesn't work in a foreign stack segment. Do not use this option unless you are using a math coprocessor. 2. External function uses Mercury's stack segment. This is more efficient, but requires you to write your function in tiny model without using DS=SS, which Borland C tiny model normally assumes. Most simple functions in tiny model don't actually make use of DS=SS, but this option is dangerous unless you are familiar with the way Turbo C generates code. bcc -c -mt! -w -ox01 -DOpt=1 -Z -O x0 bcc -c -mt! -w -ox02 -DOpt=2 -Z -O x0 x01.obj uses stack swap x02.obj uses Mercury stack See the examples, GCD.C and ASINH.C, for instructions on how to link. Using Option 1 requires linking with F87.OBJ. If using Turbo, compile with "tcc -c -mt -w ...". */ #pragma inline /* TC is not too happy about this, but it does the right thing. */ #pragma warn -asm asm DGROUP group _TEXT,_DATA,_BSS #pragma warn .asm pascal xmain(double far *); /* To handle tiny model properly, must have CS=DS=SS. Simple programs, eg not passing addresses of local variables, don't need SS. */ #ifndef Opt #error Must define Opt=1 or Opt=2. #endif #if Opt == 1 #define SwapSS 1 #endif #if Opt == 2 #define SwapSS 0 #endif #if !SwapSS /* Opt = 2 */ static void far pascal start(double *a) { _ES = _SI = _DS; _DS = _CS; xmain((double _es *) a); _DS = _SI; return; } #else /* Opt = 1 */ /* make external, so user can set it? */ #define StackWords 1000 int stack[StackWords] = { 0 }; /* Must preserve bp, si, di, ds, ss. Called with ds = ss. */ static void far pascal start(double *a) { _BX = (unsigned int) a; asm mov cx, sp asm mov dx, ss _AX = (unsigned int) (&stack[StackWords]); /* switch to local stack */ asm push cs asm pop ss asm mov sp, ax /* save prior ss, sp */ asm push dx asm push cx /* set ds=cs */ asm push cs asm pop ds /* call xmain */ asm mov es, dx xmain((double _es *) _BX); /* restore ss, sp, ds=ss */ asm pop cx asm pop dx asm mov ss, dx asm mov sp, cx asm mov ds, dx return; } #endif