2019-03-17 14:42:00 +00:00
|
|
|
/** @file
|
|
|
|
* Sources of the "MISCELLANEOUS" 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
|
|
|
|
|
|
|
#include <em_abs.h>
|
|
|
|
#include "logging.h"
|
|
|
|
#include "global.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "trap.h"
|
|
|
|
#include "warn.h"
|
|
|
|
#include "mem.h"
|
|
|
|
#include "memdirect.h"
|
2019-03-17 14:42:00 +00:00
|
|
|
#include "segment.h"
|
1988-06-22 16:57:09 +00:00
|
|
|
#include "shadow.h"
|
2019-03-17 14:42:00 +00:00
|
|
|
#include "data.h"
|
1988-06-22 16:57:09 +00:00
|
|
|
#include "text.h"
|
2019-03-17 14:42:00 +00:00
|
|
|
#include "stack.h"
|
1988-06-22 16:57:09 +00:00
|
|
|
#include "read.h"
|
|
|
|
#include "fra.h"
|
|
|
|
#include "rsb.h"
|
2019-03-17 14:42:00 +00:00
|
|
|
#include "io.h"
|
1988-06-22 16:57:09 +00:00
|
|
|
#include "linfil.h"
|
Cut down some clang warnings
Edit C code to reduce warnings from clang. Most warnings are for
implicit declarations of functions, but some warnings want me to add
parentheses or curly braces, or to cast arguments for printf().
Make a few other changes, like declaring float_cst() in h/con_float to
be static, and using C99 bool in ego/ra/makeitems.c and
ego/share/makecldef.c. Such changes don't silence warnings; I make
such changes while I silence warnings in the same file. In
float_cst(), rename parameter `str` to `float_str`, so it doesn't
share a name with the global variable `str`.
Remove `const` from `newmodule(const char *)` in mach/proto/as to
silence a warning. I wrongly added the `const` in d347207.
For warnings about implicit declarations of functions, the fix is to
declare the function before calling it. For example, my OpenBSD
system needs <sys/wait.h> to declare wait().
In util/int, add "whatever.h" to declare more functions. Remove old
declarations from "mem.h", to prefer the newer declarations of the
same functions in "data.h" and "stack.h".
2019-10-23 20:06:36 +00:00
|
|
|
#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
|
|
|
/** Current line number */
|
1988-06-22 16:57:09 +00:00
|
|
|
long LIN;
|
2019-03-17 14:42:00 +00:00
|
|
|
/** Pointer to the filename. */
|
1988-06-22 16:57:09 +00:00
|
|
|
ptr FIL;
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
PRIVATE void index_jump(size), range_check(size), search_jump(size);
|
|
|
|
PRIVATE void gto(ptr);
|
1988-06-22 16:57:09 +00:00
|
|
|
|
|
|
|
#define asp(l) newSP(SP + arg_f(l))
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** ASP f: Adjust the stack pointer by f */
|
|
|
|
void DoASP(register long l)
|
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoASP(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
asp(l);
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** ASS w: Adjust the stack pointer by w-byte integer */
|
|
|
|
void DoASS(register size l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoASS(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
l = spop(arg_wi(l));
|
|
|
|
asp(l);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define block_move(a1,a2,n) \
|
|
|
|
if (in_stack(a1)) { \
|
|
|
|
if (in_stack(a2)) st_mvs(a1, a2, n); \
|
|
|
|
else st_mvd(a1, a2, n); } \
|
|
|
|
else { if (in_stack(a2)) dt_mvs(a1, a2, n); \
|
|
|
|
else dt_mvd(a1, a2, n); }
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** BLM z: Block move z bytes; first pop destination addr, then source addr */
|
|
|
|
void DoBLM(register size l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr dp1, dp2; /* Destination Pointers */
|
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoBLM(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
dp1 = dppop();
|
|
|
|
dp2 = dppop();
|
|
|
|
block_move(dp1, dp2, arg_z(l));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** BLS w: Block move, size is in w-byte integer on top of stack */
|
|
|
|
void DoBLS(register size l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr dp1, dp2;
|
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoBLS(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
l = upop(arg_wi(l));
|
|
|
|
dp1 = dppop();
|
|
|
|
dp2 = dppop();
|
|
|
|
block_move(dp1, dp2, arg_z(l));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** CSA w: Case jump; address of jump table at top of stack */
|
|
|
|
void DoCSA(register size l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoCSA(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
index_jump(arg_wi(l));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** CSB w: Table lookup jump; address of jump table at top of stack */
|
|
|
|
void DoCSB(register size l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoCSB(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
search_jump(arg_wi(l));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** DCH -: Follow dynamic chain, convert LB to LB of caller */
|
|
|
|
void DoDCH(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr lb;
|
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoDCH()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
lb = dppop();
|
|
|
|
if (!is_LB(lb)) {
|
|
|
|
wtrap(WDCHBADLB, ESTACK);
|
|
|
|
}
|
|
|
|
dppush(st_lddp(lb + rsb_LB));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** DUP s: Duplicate top s bytes */
|
|
|
|
void DoDUP(size arg)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr oldSP = SP;
|
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoDUP(%ld)", arg));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
st_inc(arg_s(arg));
|
|
|
|
st_mvs(SP, oldSP, arg);
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** DUS w: Duplicate top w bytes */
|
|
|
|
void DoDUS(register size l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr oldSP;
|
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoDUS(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
l = upop(arg_wi(l));
|
|
|
|
oldSP = SP;
|
|
|
|
st_inc(arg_s(l));
|
|
|
|
st_mvs(SP, oldSP, l);
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** EXG w: Exchange top w bytes */
|
|
|
|
void DoEXG(register size l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr oldSP = SP;
|
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoEXG(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
st_inc(arg_w(l));
|
|
|
|
st_mvs(SP, oldSP, l);
|
|
|
|
st_mvs(oldSP, oldSP + l, l);
|
|
|
|
st_mvs(oldSP + l, SP, l);
|
|
|
|
st_dec(l);
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** FIL g: File name (external 4 := g) */
|
|
|
|
void DoFIL(register unsigned long arg)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
register ptr p = i2p(arg);
|
1988-06-22 16:57:09 +00:00
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoFIL(%lu)", p));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
if (p > HB) {
|
|
|
|
wtrap(WILLFIL, EILLINS);
|
|
|
|
}
|
|
|
|
putFIL(arg_g(p));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** GTO g: Non-local goto, descriptor at g */
|
|
|
|
void DoGTO(register unsigned long arg)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
register ptr p = i2p(arg);
|
1988-06-22 16:57:09 +00:00
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoGTO(%lu)", p));
|
1988-06-22 16:57:09 +00:00
|
|
|
gto(arg_gto(p));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** LIM -: Load 16 bit ignore mask */
|
|
|
|
void DoLIM(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoLIM()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
1989-11-13 15:36:12 +00:00
|
|
|
wpush(IgnMask);
|
1988-06-22 16:57:09 +00:00
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** LIN n: Line number (external 0 := n) */
|
|
|
|
void DoLIN(register unsigned long l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoLIN(%lu)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
putLIN((long) arg_lin(l));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** LNI -: Line number increment */
|
|
|
|
void DoLNI(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoLNI()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
putLIN((long)getLIN() + 1);
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** LOR r: Load register (0=LB, 1=SP, 2=HP) */
|
|
|
|
void DoLOR(register long l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoLOR(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
switch ((int) arg_r(l)) {
|
|
|
|
case 0:
|
|
|
|
dppush(LB);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
dppush(SP);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
dppush(HP);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** LPB -: Convert local base to argument base */
|
|
|
|
void DoLPB(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr lb;
|
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoLPB()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
lb = dppop();
|
|
|
|
if (!is_LB(lb)) {
|
|
|
|
wtrap(WLPBBADLB, ESTACK);
|
|
|
|
}
|
|
|
|
dppush(lb + rsbsize);
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** MON -: Monitor call */
|
|
|
|
void DoMON(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoMON()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
moncall();
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** NOP -: No operation */
|
|
|
|
void DoNOP(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoNOP()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
message("NOP instruction");
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** RCK w: Range check; trap on error */
|
|
|
|
void DoRCK(register size l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoRCK(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
range_check(arg_wi(l));
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** RTT -: Return from trap */
|
|
|
|
void DoRTT(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoRTT()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
|
|
|
|
switch (poprsb(1)) {
|
|
|
|
case RSB_STP:
|
|
|
|
warning(WRTTEMPTY);
|
|
|
|
running = 0; /* stop the machine */
|
|
|
|
return;
|
|
|
|
case RSB_CAL:
|
|
|
|
warning(WRTTCALL);
|
|
|
|
return;
|
|
|
|
case RSB_RTT:
|
|
|
|
/* OK */
|
|
|
|
break;
|
|
|
|
case RSB_NRT:
|
|
|
|
warning(WRTTNRTT);
|
|
|
|
running = 0; /* stop the machine */
|
|
|
|
return;
|
|
|
|
default:
|
|
|
|
warning(WRTTBAD);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pop the trap number */
|
1989-11-22 13:38:37 +00:00
|
|
|
uwpop();
|
1988-06-22 16:57:09 +00:00
|
|
|
|
|
|
|
/* restore the Function Return Area */
|
1989-11-22 13:38:37 +00:00
|
|
|
FRA_def = uwpop();
|
|
|
|
FRASize = uwpop();
|
1988-06-22 16:57:09 +00:00
|
|
|
popFRA(FRASize);
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** SIG -: Trap errors to proc identifier on top of stack, \-2 resets default */
|
|
|
|
void DoSIG(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register long tpi = spop(psize);
|
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoSIG()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
1990-01-26 16:43:29 +00:00
|
|
|
if (OnTrap == TR_HALT) {
|
|
|
|
npush(-2L, psize);
|
|
|
|
}
|
|
|
|
else npush(TrapPI, psize);
|
1988-06-22 16:57:09 +00:00
|
|
|
if (tpi == -2) {
|
|
|
|
OnTrap = TR_HALT;
|
|
|
|
TrapPI = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tpi = arg_p(tpi); /* do not test earlier! */
|
|
|
|
OnTrap = TR_TRAP;
|
|
|
|
TrapPI = tpi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** SIM -: Store 16 bit ignore mask */
|
|
|
|
void DoSIM(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoSIM()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
1989-11-22 13:38:37 +00:00
|
|
|
IgnMask = (uwpop() | PreIgnMask) & MASK2;
|
1988-06-22 16:57:09 +00:00
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** STR r: Store register (0=LB, 1=SP, 2=HP) */
|
|
|
|
void DoSTR(register long l)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoSTR(%ld)", l));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
switch ((int) arg_r(l)) {
|
|
|
|
case 0:
|
|
|
|
newLB(dppop());
|
|
|
|
pop_frames();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
newSP(dppop());
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
newHP(dppop());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
/** TRP -: Cause trap to occur (Error number on stack) */
|
|
|
|
void DoTRP(void)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
1989-11-22 13:38:37 +00:00
|
|
|
register unsigned int tr = (unsigned int)uwpop();
|
1988-06-22 16:57:09 +00:00
|
|
|
|
1990-06-21 12:16:31 +00:00
|
|
|
LOG(("@M6 DoTRP()"));
|
1988-06-22 16:57:09 +00:00
|
|
|
spoilFRA();
|
|
|
|
if (tr > 15 || !(IgnMask&BIT(tr))) {
|
|
|
|
wtrap(WTRP, (int)tr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Service routines */
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
PRIVATE void gto(ptr p)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr old_LB = LB;
|
|
|
|
register ptr new_PC = dt_ldip(p);
|
|
|
|
register ptr new_SP = dt_lddp(p + psize);
|
|
|
|
register ptr new_LB = dt_lddp(p + (2 * psize));
|
|
|
|
|
|
|
|
while (old_LB < new_LB) {
|
|
|
|
PI = st_lds(old_LB + rsb_PI, psize);
|
|
|
|
old_LB = st_lddp(old_LB + rsb_LB);
|
|
|
|
}
|
|
|
|
if (old_LB != new_LB) {
|
|
|
|
wtrap(WGTORSB, EBADGTO);
|
|
|
|
}
|
|
|
|
|
|
|
|
newLB(new_LB);
|
|
|
|
pop_frames();
|
|
|
|
newSP(new_SP);
|
|
|
|
newPC(new_PC);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
The LIN and FIL routines.
|
|
|
|
The values of LIN and FIL are kept in EM machine registers
|
|
|
|
(variables LIN and FIL) and in the data space.
|
|
|
|
*/
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
void putLIN(long lin)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
dt_unprot(i2p(LINO_AD), (long)LINSIZE);
|
|
|
|
dt_stn(i2p(LINO_AD), lin, (long)LINSIZE);
|
|
|
|
LIN = lin;
|
|
|
|
dt_prot(i2p(LINO_AD), (long)LINSIZE);
|
|
|
|
}
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
void putFIL(ptr fil)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
dt_unprot(i2p(FILN_AD), psize);
|
|
|
|
dt_stdp(i2p(FILN_AD), fil);
|
|
|
|
FIL = fil;
|
|
|
|
dt_prot(i2p(FILN_AD), psize);
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************
|
|
|
|
* Case jump by indexing *
|
|
|
|
* *
|
|
|
|
* 1. pop case descriptor pointer. *
|
|
|
|
* 2. pop table index. *
|
|
|
|
* 3. Calculate (table index) - (lower bound). *
|
|
|
|
* 4. Check if in range. *
|
|
|
|
* 5. If in range: load Program Counter value. *
|
|
|
|
* 6. Else: load default value. *
|
|
|
|
********************************************************/
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
PRIVATE void index_jump(size nbytes)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr cdp = dppop(); /* Case Descriptor Pointer */
|
|
|
|
register long t_index = /* Table INDEX */
|
1989-11-22 13:38:37 +00:00
|
|
|
spop(nbytes) - mem_lds(cdp + psize, nbytes);
|
1993-11-24 12:39:19 +00:00
|
|
|
register ptr nPC = 0; /* New Program Counter */
|
1988-06-22 16:57:09 +00:00
|
|
|
|
1989-11-22 13:38:37 +00:00
|
|
|
if (t_index >= 0 && t_index <= mem_lds(cdp + nbytes + psize, nbytes)) {
|
|
|
|
nPC = mem_ldip(cdp + (2 * nbytes) + ((t_index + 1) * psize));
|
1988-06-22 16:57:09 +00:00
|
|
|
}
|
1993-11-24 12:39:19 +00:00
|
|
|
if (nPC == 0 && (nPC = mem_ldip(cdp)) == 0) {
|
1988-06-22 16:57:09 +00:00
|
|
|
trap(ECASE);
|
|
|
|
}
|
|
|
|
newPC(nPC);
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************
|
|
|
|
* Case jump by table search *
|
|
|
|
* *
|
|
|
|
* 1. pop case descriptor pointer. *
|
|
|
|
* 2. pop search value. *
|
|
|
|
* 3. Load number of table entries. *
|
|
|
|
* 4. Check if search value in table. *
|
|
|
|
* 5. If found: load Program Counter value. *
|
|
|
|
* 6. Else: load default value. *
|
|
|
|
********************************************************/
|
|
|
|
|
2019-03-17 14:42:00 +00:00
|
|
|
PRIVATE void search_jump(size nbytes)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr cdp = dppop(); /* Case Descriptor Pointer */
|
|
|
|
register long sv = spop(nbytes);/* Search Value */
|
|
|
|
register long nt = /* Number of Table-entries */
|
1989-11-22 13:38:37 +00:00
|
|
|
mem_lds(cdp + psize, nbytes);
|
1988-06-22 16:57:09 +00:00
|
|
|
register ptr nPC; /* New Program Counter */
|
|
|
|
|
|
|
|
while (--nt >= 0) {
|
1989-11-22 13:38:37 +00:00
|
|
|
if (sv == mem_lds(cdp + (nt+1) * (nbytes+psize), nbytes)) {
|
|
|
|
nPC = mem_ldip(cdp + nbytes + (nt+1)*(nbytes+psize));
|
1988-06-22 16:57:09 +00:00
|
|
|
if (nPC == 0)
|
|
|
|
trap(ECASE);
|
|
|
|
newPC(nPC);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nPC = mem_ldip(cdp);
|
|
|
|
if (nPC == 0)
|
|
|
|
trap(ECASE);
|
|
|
|
newPC(nPC);
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************
|
|
|
|
* Range check *
|
|
|
|
* *
|
|
|
|
* 1. Load range descriptor. *
|
|
|
|
* 2. Check against lower and upper bound. *
|
|
|
|
* 3. Generate trap if necessary. *
|
|
|
|
* 4. DON'T remove integer. *
|
|
|
|
********************************************************/
|
2019-03-17 14:42:00 +00:00
|
|
|
PRIVATE void range_check(size nbytes)
|
1988-06-22 16:57:09 +00:00
|
|
|
{
|
|
|
|
register ptr rdp = dppop(); /* Range check Descriptor Pointer */
|
|
|
|
register long cv = /* Check Value */
|
|
|
|
st_lds(SP, nbytes);
|
|
|
|
|
|
|
|
if (must_test && !(IgnMask&BIT(ERANGE))) {
|
1989-11-22 13:38:37 +00:00
|
|
|
if ( cv < mem_lds(rdp, nbytes)
|
|
|
|
|| cv > mem_lds(rdp + nbytes, nbytes)
|
1988-06-22 16:57:09 +00:00
|
|
|
) {
|
|
|
|
trap(ERANGE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|