page	, 132
	subttl	Copyright (c) 2011-2012,2018-2020, the ACME Software Deli

; ============================================================================
;   This program is distributed in the hope that it will be useful, but
;   WITHOUT ANY WARRANTY; without even the implied warranty of
;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
;
;   Permission to use for any purpose, modify, copy, and make enhancements
;   and derivative works of the software is granted if attribution is given to
;   R.M. Gillmore, dba the ACME Software Deli, as the author
;
;   While the ACME Software Deli does not work for money, there is nonetheless a
;   a significant amount of work involved.  The ACME Software Deli maintains the
;   rights to all code written, though it may be used and distributed as long as
;   the following conditions are maintained.
;
;   1.  The copyright statement at the top of each code block is maintained in
;       your distribution.
;   2.  You do not identify yourself as the ACME Software Deli
;   3.  Any changes made to the software are sent to the ACME Software Deli
; ============================================================================
	page

	name	sysCallsAsm
	.186

include regDefs.e86

plmLibrary_Code	segment	public	'Code'
ifndef SMALL
	db	'@(#)sysCaAsm.a86  $Author: rmgillmore $ $Date:: 2025-05-04 19:35:39#$:', 0
endif

	plmLibrary_CGroup	Group	plmLibrary_Code

	assume	cs:plmLibrary_CGroup

	public	int86Asm

sysCallThruVectorsFrame	struc
	SysCall_OldFrame	Dw	?
	SysCall_RtnAddr		Dd	?
	SysCall_IntVector	Dd	?	; call through this pointer
	SysCall_RegPtr		Dd	?	; the address of a bank of registers (registerType)
sysCallThruVectorsFrame	ends

int86Asm	proc	far
	Push	Bp
	Mov	Bp, Sp
	Push	Ds			; DS must be preserved

	Lds	Si, [Bp].SysCall_RegPtr	; the address of the caller's registers
	Mov	Ax, Ds:[Si].Es_r
	Mov	Es, Ax
	Mov	Di, Ds:[Si].Di_r
	Mov	Bx, Ds:[Si].Bx_r
	Mov	Cx, Ds:[Si].Cx_r
	Mov	Dx, Ds:[Si].Dx_r

	Mov	Ax, Ds:[Si].Ds_r	; retrieve the DS and SI registers, but
	Push	Ax			; don't put them in the registers until
	Mov	Ax, Ds:[Si].Si_r	; after the caller's register structure has
	Push	Ax			; been completely loaded
	Mov	Ax, Ds:[Si].Ax_r	; WE MUST DO AX LAST since we used it otherwise

	Pop	Si			; we were using these registers, but the
	Pop	Ds			; caller could have specified something there

;	Stc				; set the carry flag (so that it can remain set
;					; in the interrupt handler for error conditions)

	Cli				; Clear the interrupt enable flag to
	PushF				; make this look like an INT instruction
	Call	[Bp].SysCall_IntVector	; call through the interrupt vector

	Push	Ds			; save the flags first since they will be
	Push	Si			; changed by copy
	PushF

	Lds	Si, [Bp].SysCall_RegPtr

	Mov	Ds:[Si].Ax_r, Ax	; store the registers for the caller
	Mov	Ds:[Si].Bx_r, Bx
	Mov	Ds:[Si].Cx_r, Cx
	Mov	Ds:[Si].Dx_r, Dx
	Mov	Ax, Es
	Mov	Ds:[Si].Es_r, Ax
	Mov	Ds:[Si].Di_r, Di
	Pop	Ax			; restore the flags from the stack
	Mov	Ds:[Si].Flags, Ax
	Pop	Ax			; restore Si
	Mov	Ds:[Si].Si_r, Ax
	Pop	Ax			; restore Ds
	Mov	Ds:[Si].Ds_r, Ax

	Pop	Ds			; restore data segment
	Pop	Bp			; restore stack frame
	ret
int86Asm	endp

plmLibrary_Code	ends
	end