;******************************
;*			      *
;* call a PL/I routine from C *
;*			      *
;******************************

	.title	callpli
	.psect
	.globl	plifp

;
; For documentation on how to use it, refer to CPLI.DOC.
;
; Calling sequence is callpli(&routine, n, a1, a2, ...),
; where n is the number of arguments passed to the routine,
; and a1, a2, etc are pointers to the arguments.
;
; Refer to plient source for description of PL/I and C calling sequences.
;

;
; Algorithm:
;
; C compiles code following a call to pop the argument list:
;	for no args:	nothing		(0 words)
;	for 1 arg:	TST (sp)+	(1 word)
;	for 2 args:	CMP (sp)+,(sp)+	(1 word)
;	for >2 args:	ADD <n*2>,sp	(2 words)
; Since our call always includes the routine address and number of logical
; arguments, our actual number of arguments is 2 more than the number of
; logical arguments going to the PL/I callee, and we only need worry about
; the cases of 2 or >2 args. We check to see which it is, and skip over the
; appropriate number of words of code.
;

.iif ndf c$r4  .error CDEFS.MAC must be included in command line


callpli::
	mov (sp)+,r0	;return addr
	tst 2(sp)	;# logical args
	beq 1$
	tst (r0)+	;skip 2 words if #logical args>0 (actual>2)
1$:	tst (r0)+	;skip 1 word if =0 (2)
	mov r4,r1	;save r4 (must preserve all but r0,r1)
	jsr pc,plifp	;get PL/I frame pointer (from plient)
	jsr r5,@(sp)+	;call the routine
	mov r1,r4	;restore caller's r4
	jmp (r0)	;return, skipping arg list pop code

	.end
