2 * Sources of the "MISCELLANEOUS" group instructions
5 /* $Id: do_misc.c,v 2.8 1994/06/24 10:46:42 ceriel Exp $ */
14 #include "memdirect.h"
22 extern int running; /* from main.c */
24 /* Two useful but unofficial registers */
28 PRIVATE index_jump(), range_check(), search_jump();
31 #define asp(l) newSP(SP + arg_f(l))
36 /* ASP f: Adjust the stack pointer by f */
38 LOG(("@M6 DoASP(%ld)", l));
45 /* ASS w: Adjust the stack pointer by w-byte integer */
47 LOG(("@M6 DoASS(%ld)", l));
53 #define block_move(a1,a2,n) \
55 if (in_stack(a2)) st_mvs(a1, a2, n); \
56 else st_mvd(a1, a2, n); } \
57 else { if (in_stack(a2)) dt_mvs(a1, a2, n); \
58 else dt_mvd(a1, a2, n); }
63 /* BLM z: Block move z bytes; first pop destination addr, then source addr */
64 register ptr dp1, dp2; /* Destination Pointers */
66 LOG(("@M6 DoBLM(%ld)", l));
70 block_move(dp1, dp2, arg_z(l));
76 /* BLS w: Block move, size is in w-byte integer on top of stack */
77 register ptr dp1, dp2;
79 LOG(("@M6 DoBLS(%ld)", l));
84 block_move(dp1, dp2, arg_z(l));
90 /* CSA w: Case jump; address of jump table at top of stack */
92 LOG(("@M6 DoCSA(%ld)", l));
94 index_jump(arg_wi(l));
100 /* CSB w: Table lookup jump; address of jump table at top of stack */
102 LOG(("@M6 DoCSB(%ld)", l));
104 search_jump(arg_wi(l));
109 /* DCH -: Follow dynamic chain, convert LB to LB of caller */
112 LOG(("@M6 DoDCH()"));
116 wtrap(WDCHBADLB, ESTACK);
118 dppush(st_lddp(lb + rsb_LB));
124 /* DUP s: Duplicate top s bytes */
125 register ptr oldSP = SP;
127 LOG(("@M6 DoDUP(%ld)", arg));
130 st_mvs(SP, oldSP, arg);
136 /* DUS w: Duplicate top w bytes */
139 LOG(("@M6 DoDUS(%ld)", l));
144 st_mvs(SP, oldSP, l);
150 /* EXG w: Exchange top w bytes */
151 register ptr oldSP = SP;
153 LOG(("@M6 DoEXG(%ld)", l));
156 st_mvs(SP, oldSP, l);
157 st_mvs(oldSP, oldSP + l, l);
158 st_mvs(oldSP + l, SP, l);
163 register unsigned long arg;
165 /* FIL g: File name (external 4 := g) */
166 register ptr p = i2p(arg);
168 LOG(("@M6 DoFIL(%lu)", p));
171 wtrap(WILLFIL, EILLINS);
177 register unsigned long arg;
179 /* GTO g: Non-local goto, descriptor at g */
180 register ptr p = i2p(arg);
182 LOG(("@M6 DoGTO(%lu)", p));
188 /* LIM -: Load 16 bit ignore mask */
189 LOG(("@M6 DoLIM()"));
195 register unsigned long l;
197 /* LIN n: Line number (external 0 := n) */
199 LOG(("@M6 DoLIN(%lu)", l));
201 putLIN((long) arg_lin(l));
206 /* LNI -: Line number increment */
207 LOG(("@M6 DoLNI()"));
209 putLIN((long)getLIN() + 1);
215 /* LOR r: Load register (0=LB, 1=SP, 2=HP) */
217 LOG(("@M6 DoLOR(%ld)", l));
219 switch ((int) arg_r(l)) {
234 /* LPB -: Convert local base to argument base */
237 LOG(("@M6 DoLPB()"));
241 wtrap(WLPBBADLB, ESTACK);
243 dppush(lb + rsbsize);
248 /* MON -: Monitor call */
249 LOG(("@M6 DoMON()"));
256 /* NOP -: No operation */
257 LOG(("@M6 DoNOP()"));
259 message("NOP instruction");
265 /* RCK w: Range check; trap on error */
267 LOG(("@M6 DoRCK(%ld)", l));
269 range_check(arg_wi(l));
274 /* RTT -: Return from trap */
275 LOG(("@M6 DoRTT()"));
280 running = 0; /* stop the machine */
290 running = 0; /* stop the machine */
297 /* pop the trap number */
300 /* restore the Function Return Area */
308 /* SIG -: Trap errors to proc identifier on top of stack, \-2 resets default */
309 register long tpi = spop(psize);
311 LOG(("@M6 DoSIG()"));
313 if (OnTrap == TR_HALT) {
316 else npush(TrapPI, psize);
322 tpi = arg_p(tpi); /* do not test earlier! */
330 /* SIM -: Store 16 bit ignore mask */
331 LOG(("@M6 DoSIM()"));
333 IgnMask = (uwpop() | PreIgnMask) & MASK2;
339 /* STR r: Store register (0=LB, 1=SP, 2=HP) */
341 LOG(("@M6 DoSTR(%ld)", l));
343 switch ((int) arg_r(l)) {
359 /* TRP -: Cause trap to occur (Error number on stack) */
360 register unsigned int tr = (unsigned int)uwpop();
362 LOG(("@M6 DoTRP()"));
364 if (tr > 15 || !(IgnMask&BIT(tr))) {
365 wtrap(WTRP, (int)tr);
370 /* Service routines */
375 register ptr old_LB = LB;
376 register ptr new_PC = dt_ldip(p);
377 register ptr new_SP = dt_lddp(p + psize);
378 register ptr new_LB = dt_lddp(p + (2 * psize));
380 while (old_LB < new_LB) {
381 PI = st_lds(old_LB + rsb_PI, psize);
382 old_LB = st_lddp(old_LB + rsb_LB);
384 if (old_LB != new_LB) {
385 wtrap(WGTORSB, EBADGTO);
395 The LIN and FIL routines.
396 The values of LIN and FIL are kept in EM machine registers
397 (variables LIN and FIL) and in the data space.
403 dt_unprot(i2p(LINO_AD), (long)LINSIZE);
404 dt_stn(i2p(LINO_AD), lin, (long)LINSIZE);
406 dt_prot(i2p(LINO_AD), (long)LINSIZE);
412 dt_unprot(i2p(FILN_AD), psize);
413 dt_stdp(i2p(FILN_AD), fil);
415 dt_prot(i2p(FILN_AD), psize);
418 /********************************************************
419 * Case jump by indexing *
421 * 1. pop case descriptor pointer. *
422 * 2. pop table index. *
423 * 3. Calculate (table index) - (lower bound). *
424 * 4. Check if in range. *
425 * 5. If in range: load Program Counter value. *
426 * 6. Else: load default value. *
427 ********************************************************/
429 PRIVATE index_jump(nbytes)
432 register ptr cdp = dppop(); /* Case Descriptor Pointer */
433 register long t_index = /* Table INDEX */
434 spop(nbytes) - mem_lds(cdp + psize, nbytes);
435 register ptr nPC = 0; /* New Program Counter */
437 if (t_index >= 0 && t_index <= mem_lds(cdp + nbytes + psize, nbytes)) {
438 nPC = mem_ldip(cdp + (2 * nbytes) + ((t_index + 1) * psize));
440 if (nPC == 0 && (nPC = mem_ldip(cdp)) == 0) {
446 /********************************************************
447 * Case jump by table search *
449 * 1. pop case descriptor pointer. *
450 * 2. pop search value. *
451 * 3. Load number of table entries. *
452 * 4. Check if search value in table. *
453 * 5. If found: load Program Counter value. *
454 * 6. Else: load default value. *
455 ********************************************************/
457 PRIVATE search_jump(nbytes)
460 register ptr cdp = dppop(); /* Case Descriptor Pointer */
461 register long sv = spop(nbytes);/* Search Value */
462 register long nt = /* Number of Table-entries */
463 mem_lds(cdp + psize, nbytes);
464 register ptr nPC; /* New Program Counter */
467 if (sv == mem_lds(cdp + (nt+1) * (nbytes+psize), nbytes)) {
468 nPC = mem_ldip(cdp + nbytes + (nt+1)*(nbytes+psize));
481 /********************************************************
484 * 1. Load range descriptor. *
485 * 2. Check against lower and upper bound. *
486 * 3. Generate trap if necessary. *
487 * 4. DON'T remove integer. *
488 ********************************************************/
490 PRIVATE range_check(nbytes)
493 register ptr rdp = dppop(); /* Range check Descriptor Pointer */
494 register long cv = /* Check Value */
497 if (must_test && !(IgnMask&BIT(ERANGE))) {
498 if ( cv < mem_lds(rdp, nbytes)
499 || cv > mem_lds(rdp + nbytes, nbytes)