/* --- Copyright University of Sussex 1994. All rights reserved. ----------
 * File:		S.pcwnt/src/alisp.s
 * Purpose:		Common Lisp support for 80x86 (Microsoft assembler)
 * Author:		Robert John Duncan, Apr 15 1994
 * Related Files:	S.pcunix/src/alisp.s
 */

/*************************************************************************
		THIS FILE WAS GENERATED AUTOMATICALLY FROM
		  /rsuna/pop/master/S.pcunix/src/alisp.s
		     ON Fri Apr 15 10:37:33 BST 1994
	  AND SUBSEQUENTLY EDITED ON Fri Apr 15 11:53:56 BST 1994
*************************************************************************/

#_<

#_INCLUDE 'declare.ph'

constant	_setstklen_diff
	;

lconstant macro	(

	;;; User stack pointer

	USP 	= "ebx",

);

>_#

	.erre	@Version ge 611
	option	casemap:none
	.386
	.model	flat


/************************* wrapping structures ************************/

	.code
	dword	L$text_size, C_LAB(Sys$-objmod_pad_key)
L$text_start:
	.data
	assume	cs:nothing
	dword	L$data_size, C_LAB(Sys$-objmod_pad_key)
L$data_start:

/**********************************************************************/


	.code

;;; _SETSTKLEN:
;;;	adjusts the number of results returned by a Lisp function.
;;;	The subroutine takes the length of the userstack before the function
;;;	call and the number of results expected (both as popints).
;;;	The actual stacklength is adjusted to fit either by erasing items
;;;	or by pushing -nil-.

;;; Call:
;;;	_setstklen(SAVED_STACKLENGTH, NRESULTS);

;;; Registers used:
;;;	EAX	desired stacklength
;;;	ECX	desired stack pointer

;;; Usage:
;;;	implements the I_SETSTACKLENGTH instruction. Where NRESULTS is
;;;	available to the run-time assembler, the code for SETSTKLEN is
;;;	expanded inline and a jump made direct to SETSTKLEN_DIFF
;;;	if necessary.

DEF_C_LAB(_setstklen)

	;;; Compute desired stacklength (SAVED_STACKLENGTH + NRESULTS)
	;;; in EAX. The two arguments are in popint words; subtracting
	;;; 6 from the total converts to sysint bytes.

	mov	eax, dword ptr [USP]
	add	eax, dword ptr [USP+4]
	sub	eax, 6
	add	USP, 8

	;;; Compute the desired stack pointer (_userhi - desired_length)
	;;; in ECX

	mov	ecx, dword ptr I_LAB(_userhi)
	sub	ecx, eax

	;;; Compare desired and actual stack pointers: if different,
	;;; jump to fix

	cmp	USP, ecx
	jne	C_LAB(_setstklen_diff)
	ret

	align	4

DEF_C_LAB(_setstklen_diff)

	;;; Desired and actual stack pointers are different:
	;;; push or pop results according to direction of difference

	jb	L$2$1

L$1$1:	;;; Actual stack is too short: push nils until the desired size
	;;; is reached

	sub	USP, 4
	mov	dword ptr [USP], C_LAB(nil)
	cmp	USP, ecx
	jne	L$1$1
	ret

L$2$1:	;;; Actual stack is too long: erase the extra results simply by
	;;; setting USP to the desired value

	mov	USP, ecx
	ret

	align	4


/***************** end labels for wrapping structures *****************/

	.code
L$text_end:
	L$text_size	equ	L$text_end-L$text_start
	.data
	assume	cs:nothing
L$data_end:
	L$data_size	equ	L$data_end-L$data_start

/**********************************************************************/

@CurSeg	ends
	extern	C_LAB(Sys$-objmod_pad_key):near
	extern	C_LAB(nil):near
	extern	I_LAB(_userhi):near
	end
