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"
23 extern int running; /* from main.c */
25 /* Two useful but unofficial registers */
29 PRIVATE index_jump(), range_check(), search_jump();
32 #define asp(l) newSP(SP + arg_f(l))
37 /* ASP f: Adjust the stack pointer by f */
39 LOG(("@M6 DoASP(%ld)", l));
46 /* ASS w: Adjust the stack pointer by w-byte integer */
48 LOG(("@M6 DoASS(%ld)", l));
54 #define block_move(a1,a2,n) \
56 if (in_stack(a2)) st_mvs(a1, a2, n); \
57 else st_mvd(a1, a2, n); } \
58 else { if (in_stack(a2)) dt_mvs(a1, a2, n); \
59 else dt_mvd(a1, a2, n); }
64 /* BLM z: Block move z bytes; first pop destination addr, then source addr */
65 register ptr dp1, dp2; /* Destination Pointers */
67 LOG(("@M6 DoBLM(%ld)", l));
71 block_move(dp1, dp2, arg_z(l));
77 /* BLS w: Block move, size is in w-byte integer on top of stack */
78 register ptr dp1, dp2;
80 LOG(("@M6 DoBLS(%ld)", l));
85 block_move(dp1, dp2, arg_z(l));
91 /* CSA w: Case jump; address of jump table at top of stack */
93 LOG(("@M6 DoCSA(%ld)", l));
95 index_jump(arg_wi(l));
101 /* CSB w: Table lookup jump; address of jump table at top of stack */
103 LOG(("@M6 DoCSB(%ld)", l));
105 search_jump(arg_wi(l));
110 /* DCH -: Follow dynamic chain, convert LB to LB of caller */
113 LOG(("@M6 DoDCH()"));
117 wtrap(WDCHBADLB, ESTACK);
119 dppush(st_lddp(lb + rsb_LB));
125 /* DUP s: Duplicate top s bytes */
126 register ptr oldSP = SP;
128 LOG(("@M6 DoDUP(%ld)", arg));
131 st_mvs(SP, oldSP, arg);
137 /* DUS w: Duplicate top w bytes */
140 LOG(("@M6 DoDUS(%ld)", l));
145 st_mvs(SP, oldSP, l);
151 /* EXG w: Exchange top w bytes */
152 register ptr oldSP = SP;
154 LOG(("@M6 DoEXG(%ld)", l));
157 st_mvs(SP, oldSP, l);
158 st_mvs(oldSP, oldSP + l, l);
159 st_mvs(oldSP + l, SP, l);
164 register unsigned long arg;
166 /* FIL g: File name (external 4 := g) */
167 register ptr p = i2p(arg);
169 LOG(("@M6 DoFIL(%lu)", p));
172 wtrap(WILLFIL, EILLINS);
178 register unsigned long arg;
180 /* GTO g: Non-local goto, descriptor at g */
181 register ptr p = i2p(arg);
183 LOG(("@M6 DoGTO(%lu)", p));
189 /* LIM -: Load 16 bit ignore mask */
190 LOG(("@M6 DoLIM()"));
196 register unsigned long l;
198 /* LIN n: Line number (external 0 := n) */
200 LOG(("@M6 DoLIN(%lu)", l));
202 putLIN((long) arg_lin(l));
207 /* LNI -: Line number increment */
208 LOG(("@M6 DoLNI()"));
210 putLIN((long)getLIN() + 1);
216 /* LOR r: Load register (0=LB, 1=SP, 2=HP) */
218 LOG(("@M6 DoLOR(%ld)", l));
220 switch ((int) arg_r(l)) {
235 /* LPB -: Convert local base to argument base */
238 LOG(("@M6 DoLPB()"));
242 wtrap(WLPBBADLB, ESTACK);
244 dppush(lb + rsbsize);
249 /* MON -: Monitor call */
250 LOG(("@M6 DoMON()"));
257 /* NOP -: No operation */
258 LOG(("@M6 DoNOP()"));
260 message("NOP instruction");
266 /* RCK w: Range check; trap on error */
268 LOG(("@M6 DoRCK(%ld)", l));
270 range_check(arg_wi(l));
275 /* RTT -: Return from trap */
276 LOG(("@M6 DoRTT()"));
281 running = 0; /* stop the machine */
291 running = 0; /* stop the machine */
298 /* pop the trap number */
301 /* restore the Function Return Area */
309 /* SIG -: Trap errors to proc identifier on top of stack, \-2 resets default */
310 register long tpi = spop(psize);
312 LOG(("@M6 DoSIG()"));
314 if (OnTrap == TR_HALT) {
317 else npush(TrapPI, psize);
323 tpi = arg_p(tpi); /* do not test earlier! */
331 /* SIM -: Store 16 bit ignore mask */
332 LOG(("@M6 DoSIM()"));
334 IgnMask = (uwpop() | PreIgnMask) & MASK2;
340 /* STR r: Store register (0=LB, 1=SP, 2=HP) */
342 LOG(("@M6 DoSTR(%ld)", l));
344 switch ((int) arg_r(l)) {
360 /* TRP -: Cause trap to occur (Error number on stack) */
361 register unsigned int tr = (unsigned int)uwpop();
363 LOG(("@M6 DoTRP()"));
365 if (tr > 15 || !(IgnMask&BIT(tr))) {
366 wtrap(WTRP, (int)tr);
371 /* Service routines */
376 register ptr old_LB = LB;
377 register ptr new_PC = dt_ldip(p);
378 register ptr new_SP = dt_lddp(p + psize);
379 register ptr new_LB = dt_lddp(p + (2 * psize));
381 while (old_LB < new_LB) {
382 PI = st_lds(old_LB + rsb_PI, psize);
383 old_LB = st_lddp(old_LB + rsb_LB);
385 if (old_LB != new_LB) {
386 wtrap(WGTORSB, EBADGTO);
388 read_proctab(PI, &proctab);
397 The LIN and FIL routines.
398 The values of LIN and FIL are kept in EM machine registers
399 (variables LIN and FIL) and in the data space.
405 dt_unprot(i2p(LINO_AD), (long)LINSIZE);
406 dt_stn(i2p(LINO_AD), lin, (long)LINSIZE);
408 dt_prot(i2p(LINO_AD), (long)LINSIZE);
414 dt_unprot(i2p(FILN_AD), psize);
415 dt_stdp(i2p(FILN_AD), fil);
417 dt_prot(i2p(FILN_AD), psize);
420 /********************************************************
421 * Case jump by indexing *
423 * 1. pop case descriptor pointer. *
424 * 2. pop table index. *
425 * 3. Calculate (table index) - (lower bound). *
426 * 4. Check if in range. *
427 * 5. If in range: load Program Counter value. *
428 * 6. Else: load default value. *
429 ********************************************************/
431 PRIVATE index_jump(nbytes)
434 register ptr cdp = dppop(); /* Case Descriptor Pointer */
435 register long t_index = /* Table INDEX */
436 spop(nbytes) - mem_lds(cdp + psize, nbytes);
437 register ptr nPC = 0; /* New Program Counter */
439 if (t_index >= 0 && t_index <= mem_lds(cdp + nbytes + psize, nbytes)) {
440 nPC = mem_ldip(cdp + (2 * nbytes) + ((t_index + 1) * psize));
442 if (nPC == 0 && (nPC = mem_ldip(cdp)) == 0) {
448 /********************************************************
449 * Case jump by table search *
451 * 1. pop case descriptor pointer. *
452 * 2. pop search value. *
453 * 3. Load number of table entries. *
454 * 4. Check if search value in table. *
455 * 5. If found: load Program Counter value. *
456 * 6. Else: load default value. *
457 ********************************************************/
459 PRIVATE search_jump(nbytes)
462 register ptr cdp = dppop(); /* Case Descriptor Pointer */
463 register long sv = spop(nbytes);/* Search Value */
464 register long nt = /* Number of Table-entries */
465 mem_lds(cdp + psize, nbytes);
466 register ptr nPC; /* New Program Counter */
469 if (sv == mem_lds(cdp + (nt+1) * (nbytes+psize), nbytes)) {
470 nPC = mem_ldip(cdp + nbytes + (nt+1)*(nbytes+psize));
483 /********************************************************
486 * 1. Load range descriptor. *
487 * 2. Check against lower and upper bound. *
488 * 3. Generate trap if necessary. *
489 * 4. DON'T remove integer. *
490 ********************************************************/
492 PRIVATE range_check(nbytes)
495 register ptr rdp = dppop(); /* Range check Descriptor Pointer */
496 register long cv = /* Check Value */
499 if (must_test && !(IgnMask&BIT(ERANGE))) {
500 if ( cv < mem_lds(rdp, nbytes)
501 || cv > mem_lds(rdp + nbytes, nbytes)