152 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Sources of the "PROCEDURE CALL" group instructions
 | |
|  */
 | |
| 
 | |
| /* $Header$ */
 | |
| 
 | |
| #include	<em_abs.h>
 | |
| #include	"logging.h"
 | |
| #include	"global.h"
 | |
| #include	"log.h"
 | |
| #include	"mem.h"
 | |
| #include	"shadow.h"
 | |
| #include	"memdirect.h"
 | |
| #include	"trap.h"
 | |
| #include	"warn.h"
 | |
| #include	"text.h"
 | |
| #include	"proctab.h"
 | |
| #include	"fra.h"
 | |
| #include	"rsb.h"
 | |
| #include	"linfil.h"
 | |
| 
 | |
| extern int running;			/* from main.c */
 | |
| 
 | |
| PRIVATE lfr(), ret();
 | |
| 
 | |
| DoCAI()				/* proc identifier on top of stack */
 | |
| {
 | |
| 	/* CAI -: Call procedure (procedure identifier on stack) */
 | |
| 	register long pi = spop(psize);
 | |
| 
 | |
| 	LOG(("@P6 DoCAI(%lu)", pi));
 | |
| 	call(arg_p(pi), RSB_CAL);
 | |
| }
 | |
| 
 | |
| DoCAL(pi)
 | |
| 	register long pi;
 | |
| {
 | |
| 	/* CAL p: Call procedure (with identifier p) */
 | |
| 
 | |
| 	LOG(("@P6 DoCAL(%lu)", pi));
 | |
| 	call(arg_p(pi), RSB_CAL);
 | |
| }
 | |
| 
 | |
| DoLFR(l)
 | |
| 	register size l;
 | |
| {
 | |
| 	/* LFR s: Load function result */
 | |
| 
 | |
| 	LOG(("@P6 DoLFR(%ld)", l));
 | |
| 	lfr(arg_s(l));
 | |
| }
 | |
| 
 | |
| DoRET(l)
 | |
| 	register size l;
 | |
| {
 | |
| 	/* RET z: Return (function result consists of top z bytes) */
 | |
| 
 | |
| 	LOG(("@P6 DoRET(%ld)", l));
 | |
| 	ret(arg_z(l));
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *		Calling a new procedure.				*
 | |
|  ************************************************************************/
 | |
| 
 | |
| call(new_PI, rsbcode)
 | |
| 	long new_PI;
 | |
| 	int rsbcode;
 | |
| {
 | |
| 	/* legality of new_PI has already been checked */
 | |
| 	register size nloc = proctab[new_PI].pr_nloc;
 | |
| 	register ptr ep = proctab[new_PI].pr_ep;
 | |
| 
 | |
| 	push_frame(SP);			/* remember AB */
 | |
| 	pushrsb(rsbcode);
 | |
| 
 | |
| 	/* do the call */
 | |
| 	PI = new_PI;
 | |
| 	st_inc(nloc);
 | |
| 	newPC(ep);
 | |
| 	spoilFRA();
 | |
| 	LOG(("@p5 call: new_PI = %lu, nloc = %lu, ep = %lu",
 | |
| 				new_PI, nloc, ep));
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *		Loading a function result.				*
 | |
|  ************************************************************************/
 | |
| 
 | |
| PRIVATE lfr(sz)
 | |
| 	size sz;
 | |
| {
 | |
| 	if (sz > FRALimit) {
 | |
| 		wtrap(WILLLFR, EILLINS);
 | |
| 	}
 | |
| 
 | |
| 	LOG(("@p5 lfr: size = %ld", sz));
 | |
| 
 | |
| #ifdef	LOGGING
 | |
| 	if (!FRA_def) {
 | |
| 		warning(WRFUNGAR);
 | |
| 	}
 | |
| 	if (sz != FRASize) {
 | |
| 		warning(FRASize < sz ? WRFUNSML : WRFUNLAR);
 | |
| 	}
 | |
| #endif	/* LOGGING */
 | |
| 
 | |
| 	pushFRA(sz);
 | |
| 	spoilFRA();
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *		Returning from a procedure.				*
 | |
|  ************************************************************************/
 | |
| 
 | |
| PRIVATE ret(sz)
 | |
| 	size sz;
 | |
| {
 | |
| 	if (sz > FRALimit) {
 | |
| 		wtrap(WILLRET, EILLINS);
 | |
| 	}
 | |
| 
 | |
| 	LOG(("@p5 ret: size = %ld", sz));
 | |
| 
 | |
| 	/* retrieve return value from stack */
 | |
| 	FRA_def = DEFINED;
 | |
| 	FRASize = sz;
 | |
| 	popFRA(FRASize);
 | |
| 
 | |
| 	switch (poprsb(0)) {
 | |
| 	case RSB_STP:
 | |
| 		if (sz == wsize) {
 | |
| 			ES_def = DEFINED;
 | |
| 			ES = btol(FRA[sz-1]);
 | |
| 					/* one byte only */
 | |
| 		}
 | |
| 		running = 0;		/* stop the machine */
 | |
| 		return;
 | |
| 	case RSB_CAL:
 | |
| 		/* OK */
 | |
| 		break;
 | |
| 	case RSB_RTT:
 | |
| 	case RSB_NRT:
 | |
| 		warning(WRETTRAP);
 | |
| 		running = 0;		/* stop the machine */
 | |
| 		return;
 | |
| 	default:
 | |
| 		warning(WRETBAD);
 | |
| 		return;
 | |
| 	}
 | |
| }
 | |
| 
 |