123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- /*
- * Sources of the "MISCELLANEOUS" group instructions
- */
- /* $Id$ */
- #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"
- #include "shadow.h"
- #include "text.h"
- #include "read.h"
- #include "fra.h"
- #include "rsb.h"
- #include "linfil.h"
- extern int running; /* from main.c */
- /* Two useful but unofficial registers */
- long LIN;
- ptr FIL;
- PRIVATE index_jump(), range_check(), search_jump();
- PRIVATE gto();
- #define asp(l) newSP(SP + arg_f(l))
- DoASP(l)
- register long l;
- {
- /* ASP f: Adjust the stack pointer by f */
- LOG(("@M6 DoASP(%ld)", l));
- asp(l);
- }
- DoASS(l)
- register size l;
- {
- /* ASS w: Adjust the stack pointer by w-byte integer */
- LOG(("@M6 DoASS(%ld)", l));
- 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); }
- DoBLM(l)
- register size l;
- {
- /* BLM z: Block move z bytes; first pop destination addr, then source addr */
- register ptr dp1, dp2; /* Destination Pointers */
- LOG(("@M6 DoBLM(%ld)", l));
- spoilFRA();
- dp1 = dppop();
- dp2 = dppop();
- block_move(dp1, dp2, arg_z(l));
- }
- DoBLS(l)
- register size l;
- {
- /* BLS w: Block move, size is in w-byte integer on top of stack */
- register ptr dp1, dp2;
- LOG(("@M6 DoBLS(%ld)", l));
- spoilFRA();
- l = upop(arg_wi(l));
- dp1 = dppop();
- dp2 = dppop();
- block_move(dp1, dp2, arg_z(l));
- }
- DoCSA(l)
- register size l;
- {
- /* CSA w: Case jump; address of jump table at top of stack */
- LOG(("@M6 DoCSA(%ld)", l));
- spoilFRA();
- index_jump(arg_wi(l));
- }
- DoCSB(l)
- register size l;
- {
- /* CSB w: Table lookup jump; address of jump table at top of stack */
- LOG(("@M6 DoCSB(%ld)", l));
- spoilFRA();
- search_jump(arg_wi(l));
- }
- DoDCH()
- {
- /* DCH -: Follow dynamic chain, convert LB to LB of caller */
- register ptr lb;
- LOG(("@M6 DoDCH()"));
- spoilFRA();
- lb = dppop();
- if (!is_LB(lb)) {
- wtrap(WDCHBADLB, ESTACK);
- }
- dppush(st_lddp(lb + rsb_LB));
- }
- DoDUP(arg)
- size arg;
- {
- /* DUP s: Duplicate top s bytes */
- register ptr oldSP = SP;
- LOG(("@M6 DoDUP(%ld)", arg));
- spoilFRA();
- st_inc(arg_s(arg));
- st_mvs(SP, oldSP, arg);
- }
- DoDUS(l)
- register size l;
- {
- /* DUS w: Duplicate top w bytes */
- register ptr oldSP;
- LOG(("@M6 DoDUS(%ld)", l));
- spoilFRA();
- l = upop(arg_wi(l));
- oldSP = SP;
- st_inc(arg_s(l));
- st_mvs(SP, oldSP, l);
- }
- DoEXG(l)
- register size l;
- {
- /* EXG w: Exchange top w bytes */
- register ptr oldSP = SP;
- LOG(("@M6 DoEXG(%ld)", l));
- 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);
- }
- DoFIL(arg)
- register unsigned long arg;
- {
- /* FIL g: File name (external 4 := g) */
- register ptr p = i2p(arg);
- LOG(("@M6 DoFIL(%lu)", p));
- spoilFRA();
- if (p > HB) {
- wtrap(WILLFIL, EILLINS);
- }
- putFIL(arg_g(p));
- }
- DoGTO(arg)
- register unsigned long arg;
- {
- /* GTO g: Non-local goto, descriptor at g */
- register ptr p = i2p(arg);
- LOG(("@M6 DoGTO(%lu)", p));
- gto(arg_gto(p));
- }
- DoLIM()
- {
- /* LIM -: Load 16 bit ignore mask */
- LOG(("@M6 DoLIM()"));
- spoilFRA();
- wpush(IgnMask);
- }
- DoLIN(l)
- register unsigned long l;
- {
- /* LIN n: Line number (external 0 := n) */
- LOG(("@M6 DoLIN(%lu)", l));
- spoilFRA();
- putLIN((long) arg_lin(l));
- }
- DoLNI()
- {
- /* LNI -: Line number increment */
- LOG(("@M6 DoLNI()"));
- spoilFRA();
- putLIN((long)getLIN() + 1);
- }
- DoLOR(l)
- register long l;
- {
- /* LOR r: Load register (0=LB, 1=SP, 2=HP) */
- LOG(("@M6 DoLOR(%ld)", l));
- spoilFRA();
- switch ((int) arg_r(l)) {
- case 0:
- dppush(LB);
- break;
- case 1:
- dppush(SP);
- break;
- case 2:
- dppush(HP);
- break;
- }
- }
- DoLPB()
- {
- /* LPB -: Convert local base to argument base */
- register ptr lb;
- LOG(("@M6 DoLPB()"));
- spoilFRA();
- lb = dppop();
- if (!is_LB(lb)) {
- wtrap(WLPBBADLB, ESTACK);
- }
- dppush(lb + rsbsize);
- }
- DoMON()
- {
- /* MON -: Monitor call */
- LOG(("@M6 DoMON()"));
- spoilFRA();
- moncall();
- }
- DoNOP()
- {
- /* NOP -: No operation */
- LOG(("@M6 DoNOP()"));
- spoilFRA();
- message("NOP instruction");
- }
- DoRCK(l)
- register size l;
- {
- /* RCK w: Range check; trap on error */
- LOG(("@M6 DoRCK(%ld)", l));
- spoilFRA();
- range_check(arg_wi(l));
- }
- DoRTT()
- {
- /* RTT -: Return from trap */
- LOG(("@M6 DoRTT()"));
- 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 */
- uwpop();
-
- /* restore the Function Return Area */
- FRA_def = uwpop();
- FRASize = uwpop();
- popFRA(FRASize);
- }
- DoSIG()
- {
- /* SIG -: Trap errors to proc identifier on top of stack, \-2 resets default */
- register long tpi = spop(psize);
- LOG(("@M6 DoSIG()"));
- spoilFRA();
- if (OnTrap == TR_HALT) {
- npush(-2L, psize);
- }
- else npush(TrapPI, psize);
- if (tpi == -2) {
- OnTrap = TR_HALT;
- TrapPI = 0;
- }
- else {
- tpi = arg_p(tpi); /* do not test earlier! */
- OnTrap = TR_TRAP;
- TrapPI = tpi;
- }
- }
- DoSIM()
- {
- /* SIM -: Store 16 bit ignore mask */
- LOG(("@M6 DoSIM()"));
- spoilFRA();
- IgnMask = (uwpop() | PreIgnMask) & MASK2;
- }
- DoSTR(l)
- register long l;
- {
- /* STR r: Store register (0=LB, 1=SP, 2=HP) */
- LOG(("@M6 DoSTR(%ld)", l));
- spoilFRA();
- switch ((int) arg_r(l)) {
- case 0:
- newLB(dppop());
- pop_frames();
- break;
- case 1:
- newSP(dppop());
- break;
- case 2:
- newHP(dppop());
- break;
- }
- }
- DoTRP()
- {
- /* TRP -: Cause trap to occur (Error number on stack) */
- register unsigned int tr = (unsigned int)uwpop();
- LOG(("@M6 DoTRP()"));
- spoilFRA();
- if (tr > 15 || !(IgnMask&BIT(tr))) {
- wtrap(WTRP, (int)tr);
- }
- }
- /* Service routines */
- PRIVATE gto(p)
- ptr p;
- {
- 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.
- */
- putLIN(lin)
- long lin;
- {
- dt_unprot(i2p(LINO_AD), (long)LINSIZE);
- dt_stn(i2p(LINO_AD), lin, (long)LINSIZE);
- LIN = lin;
- dt_prot(i2p(LINO_AD), (long)LINSIZE);
- }
- putFIL(fil)
- ptr fil;
- {
- 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. *
- ********************************************************/
- PRIVATE index_jump(nbytes)
- size nbytes;
- {
- register ptr cdp = dppop(); /* Case Descriptor Pointer */
- register long t_index = /* Table INDEX */
- spop(nbytes) - mem_lds(cdp + psize, nbytes);
- register ptr nPC = 0; /* New Program Counter */
- if (t_index >= 0 && t_index <= mem_lds(cdp + nbytes + psize, nbytes)) {
- nPC = mem_ldip(cdp + (2 * nbytes) + ((t_index + 1) * psize));
- }
- if (nPC == 0 && (nPC = mem_ldip(cdp)) == 0) {
- 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. *
- ********************************************************/
- PRIVATE search_jump(nbytes)
- size nbytes;
- {
- register ptr cdp = dppop(); /* Case Descriptor Pointer */
- register long sv = spop(nbytes);/* Search Value */
- register long nt = /* Number of Table-entries */
- mem_lds(cdp + psize, nbytes);
- register ptr nPC; /* New Program Counter */
- while (--nt >= 0) {
- if (sv == mem_lds(cdp + (nt+1) * (nbytes+psize), nbytes)) {
- nPC = mem_ldip(cdp + nbytes + (nt+1)*(nbytes+psize));
- 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. *
- ********************************************************/
- PRIVATE range_check(nbytes)
- size nbytes;
- {
- register ptr rdp = dppop(); /* Range check Descriptor Pointer */
- register long cv = /* Check Value */
- st_lds(SP, nbytes);
- if (must_test && !(IgnMask&BIT(ERANGE))) {
- if ( cv < mem_lds(rdp, nbytes)
- || cv > mem_lds(rdp + nbytes, nbytes)
- ) {
- trap(ERANGE);
- }
- }
- }
|