ack/util/int/do_proc.c

147 lines
2.9 KiB
C
Raw Normal View History

2019-03-17 14:42:00 +00:00
/** @file
* Sources of the "PROCEDURE CALL" group instructions
1988-06-22 16:57:09 +00:00
*/
1994-06-24 11:31:16 +00:00
/* $Id$ */
1988-06-22 16:57:09 +00:00
2019-03-17 14:42:00 +00:00
#include "em_abs.h"
1988-06-22 16:57:09 +00:00
#include "logging.h"
#include "global.h"
#include "log.h"
#include "mem.h"
#include "shadow.h"
#include "memdirect.h"
2019-03-17 14:42:00 +00:00
#include "segment.h"
1988-06-22 16:57:09 +00:00
#include "trap.h"
#include "warn.h"
#include "text.h"
#include "proctab.h"
#include "fra.h"
#include "rsb.h"
#include "linfil.h"
#include "switch.h"
#include "whatever.h"
1988-06-22 16:57:09 +00:00
extern int running; /* from main.c */
2019-03-17 14:42:00 +00:00
/* Forward declarations */
PRIVATE void lfr(size), ret(size);
1988-06-22 16:57:09 +00:00
2019-03-17 14:42:00 +00:00
/** CAI -: Call procedure (procedure identifier on stack) */
void DoCAI(void) /* proc identifier on top of stack */
1988-06-22 16:57:09 +00:00
{
register long pi = spop(psize);
LOG(("@P6 DoCAI(%lu)", pi));
1988-06-22 16:57:09 +00:00
call(arg_p(pi), RSB_CAL);
}
2019-03-17 14:42:00 +00:00
/** CAL p: Call procedure (with identifier p) */
void DoCAL(register long pi)
1988-06-22 16:57:09 +00:00
{
LOG(("@P6 DoCAL(%lu)", pi));
1988-06-22 16:57:09 +00:00
call(arg_p(pi), RSB_CAL);
}
2019-03-17 14:42:00 +00:00
/** LFR s: Load function result */
void DoLFR(register size l)
1988-06-22 16:57:09 +00:00
{
LOG(("@P6 DoLFR(%ld)", l));
1988-06-22 16:57:09 +00:00
lfr(arg_s(l));
}
2019-03-17 14:42:00 +00:00
/** RET z: Return (function result consists of top z bytes) */
void DoRET(register size l)
1988-06-22 16:57:09 +00:00
{
LOG(("@P6 DoRET(%ld)", l));
1988-06-22 16:57:09 +00:00
ret(arg_z(l));
}
/************************************************************************
2019-03-17 14:42:00 +00:00
* Calling a new procedure. *
1988-06-22 16:57:09 +00:00
************************************************************************/
2019-03-17 14:42:00 +00:00
void call(long new_PI, int rsbcode)
1988-06-22 16:57:09 +00:00
{
/* 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));
}
/************************************************************************
2019-03-17 14:42:00 +00:00
* Loading a function result. *
1988-06-22 16:57:09 +00:00
************************************************************************/
2019-03-17 14:42:00 +00:00
PRIVATE void lfr(size sz)
1988-06-22 16:57:09 +00:00
{
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 */
1988-06-22 16:57:09 +00:00
pushFRA(sz);
spoilFRA();
}
/************************************************************************
* Returning from a procedure. *
************************************************************************/
2019-03-17 14:42:00 +00:00
PRIVATE void ret(size sz)
1988-06-22 16:57:09 +00:00
{
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;
}
}