/* copro struct */

#define i_orgeip    _info
#define i_retsys    _info+4
#define i_ebx	    _info+8
#define i_ecx	    _info+12
#define i_edx	    _info+16
#define i_esi	    _info+20
#define i_edi	    _info+24
#define i_ebp	    _info+28
#define i_eax	    _info+32
#define i_ds	    _info+36
#define i_es	    _info+40
#define i_fs	    _info+44
#define i_gs	    _info+48
#define i_orgeax    _info+52
#define i_eip	    _info+56
#define i_cs	    _info+60
#define i_eflags    _info+64
#define i_esp	    _info+68
#define i_ss	    _info+72

#define i_vm86_es   _info+76
#define i_vm86_ds   _info+80
#define i_vm86_fs   _info+84
#define i_vm86_gs   _info+88


	.globl _fpu_entry
	.globl _back_to_prg
	.globl _debugged
	.globl _used_math
	.globl _raise

	.text

/* called from extender: 1. init exception ; 2. change mathe state */
/* gs = emu data seg */

_fpu_entry:
	cmpl	$0x12345678,%eax	/* init call ? */
	jz	L10
	movl	%edx, %gs:_debugged	/* debugged>0 : don't lookahead */
	movl	%ecx, %gs:_used_math	/* used_math>0: don't init */
	lret


/* ! can't use movl %eax,gs:xx (bug ??) */


_emu_selector:
	.long 0

	.align 2,144
/* init exception vector 7 */
L10:
	movw	%gs, %cx
	movw	%cx, %gs:_emu_selector	/* save dataseg in code */
	movw	%edx, %gs:emu_esp	/* save dataseg in code */

	movw	%cs,%cx 		/* cx:edx exception-handler */
	movl	$_exception7,%edx
	movw	$0x203,%ax
	movw	$0x7,%bx		/* 387 exception */
	int	$0x31
	jnc	1f
	movl	$0,%eax 		/* 0 = error */
	jmp	2f
1:
	movl	$_copro , %eax		/* return coprostruct */
2:
	lret



/* stack after exception :
*
*		0  = DPMIeip,
*		4  = DPMIcs,
*		8  = error code,
*		12 = eip,
*		16 = cs,
*		20 = eflags,
*		24 = esp,
*		28 = ss
*/

#define EIP	12
#define CS	16
#define EFLAGS	20
#define ESP	24
#define SS	28

/* entry for emulation :
**	ds,es,fs,gs = user_prg_ds
**	stack = dpmi-server ss,esp
*/

	.align 2,144
_exception7:
	pushl	%cs:_emu_selector	/* load datasegment */
	popl	%ds

	movw	%es, i_ds
	movw	%es, i_es
	movw	%fs, i_fs
	movl	%eax, i_eax
	movl	%eax, i_orgeax
	movl	%ebx, i_ebx
	movl	%ecx, i_ecx
	movl	%edx, i_edx
	movl	%esi, i_esi
	movl	%edi, i_edi
	movl	%ebp, i_ebp


	/* save regs on dpmi stack */
	movl	EIP(%esp), %eax
	movl	%eax, i_orgeip
	movl	%eax, i_eip
	movl	CS(%esp), %eax
	movl	%eax, i_cs
	movl	EFLAGS(%esp), %eax
	andl	$0xFFFEFFFF,%eax	/* clear resume flag */
	movl	%eax, i_eflags
	andl	$0xFFFFFEFF,%eax	/* clear step flag */
	orl	$0x200,%eax		/* set iflag */
	movl	%eax, EFLAGS(%esp)	/* save back */
	movl	ESP(%esp), %eax
	movl	%eax, i_esp
	movl	SS(%esp), %eax
	movl	%eax, i_ss

	/* prepare stack frame for lret */
	movw	%ds, %ax
	movw	%ax, SS(%esp)
	movl	emu_esp, %eax
	movl	%eax, ESP(%esp)
	movw	%cs, %ax
	movw	%ax, CS(%esp)
	movl	$emulate, %eax
	movl	%eax, EIP(%esp)

	/* resore eax (not necessary?) */
	movl	i_eax, %eax
	pushl	%es
	popl	%ds

	lret
	/* back to dpmi-handler */
	/* jmp to our handler cs:emulate */


/* called from DPMI-server after return from exception7 */
/* cs:eip and ss:esp are ok */

	.align 2,144
emulate:
	movw	%ss, %ax	/* set ds,es */
	movw	%ax, %ds
	movw	%ax, %es
	pushl	$_info
	call	_math_emulate
_back_to_prg:
	movl	i_eax,%eax
	movl	i_ebx,%ebx
	movl	i_ecx,%ecx
	movl	i_edx,%edx
	movl	i_esi,%esi
	movl	i_edi,%edi
	movl	i_ebp,%ebp
	movw	i_es,%es
	movw	i_fs,%fs

	movw	i_ss,%ss	/* change stack to user */
	movl	i_esp,%esp

	pushl	i_eflags
	pushl	i_cs
	pushl	i_eip
	movw	i_ds,%ds
	iret

_abort_emu:
_raise:
	movw $0x7f0e,%ax
	movw $0x8 ,%cx
	int $0x21

	movw $0x4cff,%ax
	int $0x21
	ret



	.data

	rsxfpu_ver:
		.long 109

	dpmi_esp:
		.long 0
	dpmi_ss:
		.long 0
	emu_esp:
		.long 0xfff0
	_debugged:
		.long 0
	_used_math:
		.long 0

		.globl _process_npx
	_process_npx:
		.long _copro

	.lcomm _copro,172
	.comm _info,92

