do_misc.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /*
  2. * Sources of the "MISCELLANEOUS" group instructions
  3. */
  4. /* $Id$ */
  5. #include <em_abs.h>
  6. #include "logging.h"
  7. #include "global.h"
  8. #include "log.h"
  9. #include "trap.h"
  10. #include "warn.h"
  11. #include "mem.h"
  12. #include "memdirect.h"
  13. #include "shadow.h"
  14. #include "text.h"
  15. #include "read.h"
  16. #include "fra.h"
  17. #include "rsb.h"
  18. #include "linfil.h"
  19. extern int running; /* from main.c */
  20. /* Two useful but unofficial registers */
  21. long LIN;
  22. ptr FIL;
  23. PRIVATE index_jump(), range_check(), search_jump();
  24. PRIVATE gto();
  25. #define asp(l) newSP(SP + arg_f(l))
  26. DoASP(l)
  27. register long l;
  28. {
  29. /* ASP f: Adjust the stack pointer by f */
  30. LOG(("@M6 DoASP(%ld)", l));
  31. asp(l);
  32. }
  33. DoASS(l)
  34. register size l;
  35. {
  36. /* ASS w: Adjust the stack pointer by w-byte integer */
  37. LOG(("@M6 DoASS(%ld)", l));
  38. spoilFRA();
  39. l = spop(arg_wi(l));
  40. asp(l);
  41. }
  42. #define block_move(a1,a2,n) \
  43. if (in_stack(a1)) { \
  44. if (in_stack(a2)) st_mvs(a1, a2, n); \
  45. else st_mvd(a1, a2, n); } \
  46. else { if (in_stack(a2)) dt_mvs(a1, a2, n); \
  47. else dt_mvd(a1, a2, n); }
  48. DoBLM(l)
  49. register size l;
  50. {
  51. /* BLM z: Block move z bytes; first pop destination addr, then source addr */
  52. register ptr dp1, dp2; /* Destination Pointers */
  53. LOG(("@M6 DoBLM(%ld)", l));
  54. spoilFRA();
  55. dp1 = dppop();
  56. dp2 = dppop();
  57. block_move(dp1, dp2, arg_z(l));
  58. }
  59. DoBLS(l)
  60. register size l;
  61. {
  62. /* BLS w: Block move, size is in w-byte integer on top of stack */
  63. register ptr dp1, dp2;
  64. LOG(("@M6 DoBLS(%ld)", l));
  65. spoilFRA();
  66. l = upop(arg_wi(l));
  67. dp1 = dppop();
  68. dp2 = dppop();
  69. block_move(dp1, dp2, arg_z(l));
  70. }
  71. DoCSA(l)
  72. register size l;
  73. {
  74. /* CSA w: Case jump; address of jump table at top of stack */
  75. LOG(("@M6 DoCSA(%ld)", l));
  76. spoilFRA();
  77. index_jump(arg_wi(l));
  78. }
  79. DoCSB(l)
  80. register size l;
  81. {
  82. /* CSB w: Table lookup jump; address of jump table at top of stack */
  83. LOG(("@M6 DoCSB(%ld)", l));
  84. spoilFRA();
  85. search_jump(arg_wi(l));
  86. }
  87. DoDCH()
  88. {
  89. /* DCH -: Follow dynamic chain, convert LB to LB of caller */
  90. register ptr lb;
  91. LOG(("@M6 DoDCH()"));
  92. spoilFRA();
  93. lb = dppop();
  94. if (!is_LB(lb)) {
  95. wtrap(WDCHBADLB, ESTACK);
  96. }
  97. dppush(st_lddp(lb + rsb_LB));
  98. }
  99. DoDUP(arg)
  100. size arg;
  101. {
  102. /* DUP s: Duplicate top s bytes */
  103. register ptr oldSP = SP;
  104. LOG(("@M6 DoDUP(%ld)", arg));
  105. spoilFRA();
  106. st_inc(arg_s(arg));
  107. st_mvs(SP, oldSP, arg);
  108. }
  109. DoDUS(l)
  110. register size l;
  111. {
  112. /* DUS w: Duplicate top w bytes */
  113. register ptr oldSP;
  114. LOG(("@M6 DoDUS(%ld)", l));
  115. spoilFRA();
  116. l = upop(arg_wi(l));
  117. oldSP = SP;
  118. st_inc(arg_s(l));
  119. st_mvs(SP, oldSP, l);
  120. }
  121. DoEXG(l)
  122. register size l;
  123. {
  124. /* EXG w: Exchange top w bytes */
  125. register ptr oldSP = SP;
  126. LOG(("@M6 DoEXG(%ld)", l));
  127. spoilFRA();
  128. st_inc(arg_w(l));
  129. st_mvs(SP, oldSP, l);
  130. st_mvs(oldSP, oldSP + l, l);
  131. st_mvs(oldSP + l, SP, l);
  132. st_dec(l);
  133. }
  134. DoFIL(arg)
  135. register unsigned long arg;
  136. {
  137. /* FIL g: File name (external 4 := g) */
  138. register ptr p = i2p(arg);
  139. LOG(("@M6 DoFIL(%lu)", p));
  140. spoilFRA();
  141. if (p > HB) {
  142. wtrap(WILLFIL, EILLINS);
  143. }
  144. putFIL(arg_g(p));
  145. }
  146. DoGTO(arg)
  147. register unsigned long arg;
  148. {
  149. /* GTO g: Non-local goto, descriptor at g */
  150. register ptr p = i2p(arg);
  151. LOG(("@M6 DoGTO(%lu)", p));
  152. gto(arg_gto(p));
  153. }
  154. DoLIM()
  155. {
  156. /* LIM -: Load 16 bit ignore mask */
  157. LOG(("@M6 DoLIM()"));
  158. spoilFRA();
  159. wpush(IgnMask);
  160. }
  161. DoLIN(l)
  162. register unsigned long l;
  163. {
  164. /* LIN n: Line number (external 0 := n) */
  165. LOG(("@M6 DoLIN(%lu)", l));
  166. spoilFRA();
  167. putLIN((long) arg_lin(l));
  168. }
  169. DoLNI()
  170. {
  171. /* LNI -: Line number increment */
  172. LOG(("@M6 DoLNI()"));
  173. spoilFRA();
  174. putLIN((long)getLIN() + 1);
  175. }
  176. DoLOR(l)
  177. register long l;
  178. {
  179. /* LOR r: Load register (0=LB, 1=SP, 2=HP) */
  180. LOG(("@M6 DoLOR(%ld)", l));
  181. spoilFRA();
  182. switch ((int) arg_r(l)) {
  183. case 0:
  184. dppush(LB);
  185. break;
  186. case 1:
  187. dppush(SP);
  188. break;
  189. case 2:
  190. dppush(HP);
  191. break;
  192. }
  193. }
  194. DoLPB()
  195. {
  196. /* LPB -: Convert local base to argument base */
  197. register ptr lb;
  198. LOG(("@M6 DoLPB()"));
  199. spoilFRA();
  200. lb = dppop();
  201. if (!is_LB(lb)) {
  202. wtrap(WLPBBADLB, ESTACK);
  203. }
  204. dppush(lb + rsbsize);
  205. }
  206. DoMON()
  207. {
  208. /* MON -: Monitor call */
  209. LOG(("@M6 DoMON()"));
  210. spoilFRA();
  211. moncall();
  212. }
  213. DoNOP()
  214. {
  215. /* NOP -: No operation */
  216. LOG(("@M6 DoNOP()"));
  217. spoilFRA();
  218. message("NOP instruction");
  219. }
  220. DoRCK(l)
  221. register size l;
  222. {
  223. /* RCK w: Range check; trap on error */
  224. LOG(("@M6 DoRCK(%ld)", l));
  225. spoilFRA();
  226. range_check(arg_wi(l));
  227. }
  228. DoRTT()
  229. {
  230. /* RTT -: Return from trap */
  231. LOG(("@M6 DoRTT()"));
  232. switch (poprsb(1)) {
  233. case RSB_STP:
  234. warning(WRTTEMPTY);
  235. running = 0; /* stop the machine */
  236. return;
  237. case RSB_CAL:
  238. warning(WRTTCALL);
  239. return;
  240. case RSB_RTT:
  241. /* OK */
  242. break;
  243. case RSB_NRT:
  244. warning(WRTTNRTT);
  245. running = 0; /* stop the machine */
  246. return;
  247. default:
  248. warning(WRTTBAD);
  249. return;
  250. }
  251. /* pop the trap number */
  252. uwpop();
  253. /* restore the Function Return Area */
  254. FRA_def = uwpop();
  255. FRASize = uwpop();
  256. popFRA(FRASize);
  257. }
  258. DoSIG()
  259. {
  260. /* SIG -: Trap errors to proc identifier on top of stack, \-2 resets default */
  261. register long tpi = spop(psize);
  262. LOG(("@M6 DoSIG()"));
  263. spoilFRA();
  264. if (OnTrap == TR_HALT) {
  265. npush(-2L, psize);
  266. }
  267. else npush(TrapPI, psize);
  268. if (tpi == -2) {
  269. OnTrap = TR_HALT;
  270. TrapPI = 0;
  271. }
  272. else {
  273. tpi = arg_p(tpi); /* do not test earlier! */
  274. OnTrap = TR_TRAP;
  275. TrapPI = tpi;
  276. }
  277. }
  278. DoSIM()
  279. {
  280. /* SIM -: Store 16 bit ignore mask */
  281. LOG(("@M6 DoSIM()"));
  282. spoilFRA();
  283. IgnMask = (uwpop() | PreIgnMask) & MASK2;
  284. }
  285. DoSTR(l)
  286. register long l;
  287. {
  288. /* STR r: Store register (0=LB, 1=SP, 2=HP) */
  289. LOG(("@M6 DoSTR(%ld)", l));
  290. spoilFRA();
  291. switch ((int) arg_r(l)) {
  292. case 0:
  293. newLB(dppop());
  294. pop_frames();
  295. break;
  296. case 1:
  297. newSP(dppop());
  298. break;
  299. case 2:
  300. newHP(dppop());
  301. break;
  302. }
  303. }
  304. DoTRP()
  305. {
  306. /* TRP -: Cause trap to occur (Error number on stack) */
  307. register unsigned int tr = (unsigned int)uwpop();
  308. LOG(("@M6 DoTRP()"));
  309. spoilFRA();
  310. if (tr > 15 || !(IgnMask&BIT(tr))) {
  311. wtrap(WTRP, (int)tr);
  312. }
  313. }
  314. /* Service routines */
  315. PRIVATE gto(p)
  316. ptr p;
  317. {
  318. register ptr old_LB = LB;
  319. register ptr new_PC = dt_ldip(p);
  320. register ptr new_SP = dt_lddp(p + psize);
  321. register ptr new_LB = dt_lddp(p + (2 * psize));
  322. while (old_LB < new_LB) {
  323. PI = st_lds(old_LB + rsb_PI, psize);
  324. old_LB = st_lddp(old_LB + rsb_LB);
  325. }
  326. if (old_LB != new_LB) {
  327. wtrap(WGTORSB, EBADGTO);
  328. }
  329. newLB(new_LB);
  330. pop_frames();
  331. newSP(new_SP);
  332. newPC(new_PC);
  333. }
  334. /*
  335. The LIN and FIL routines.
  336. The values of LIN and FIL are kept in EM machine registers
  337. (variables LIN and FIL) and in the data space.
  338. */
  339. putLIN(lin)
  340. long lin;
  341. {
  342. dt_unprot(i2p(LINO_AD), (long)LINSIZE);
  343. dt_stn(i2p(LINO_AD), lin, (long)LINSIZE);
  344. LIN = lin;
  345. dt_prot(i2p(LINO_AD), (long)LINSIZE);
  346. }
  347. putFIL(fil)
  348. ptr fil;
  349. {
  350. dt_unprot(i2p(FILN_AD), psize);
  351. dt_stdp(i2p(FILN_AD), fil);
  352. FIL = fil;
  353. dt_prot(i2p(FILN_AD), psize);
  354. }
  355. /********************************************************
  356. * Case jump by indexing *
  357. * *
  358. * 1. pop case descriptor pointer. *
  359. * 2. pop table index. *
  360. * 3. Calculate (table index) - (lower bound). *
  361. * 4. Check if in range. *
  362. * 5. If in range: load Program Counter value. *
  363. * 6. Else: load default value. *
  364. ********************************************************/
  365. PRIVATE index_jump(nbytes)
  366. size nbytes;
  367. {
  368. register ptr cdp = dppop(); /* Case Descriptor Pointer */
  369. register long t_index = /* Table INDEX */
  370. spop(nbytes) - mem_lds(cdp + psize, nbytes);
  371. register ptr nPC = 0; /* New Program Counter */
  372. if (t_index >= 0 && t_index <= mem_lds(cdp + nbytes + psize, nbytes)) {
  373. nPC = mem_ldip(cdp + (2 * nbytes) + ((t_index + 1) * psize));
  374. }
  375. if (nPC == 0 && (nPC = mem_ldip(cdp)) == 0) {
  376. trap(ECASE);
  377. }
  378. newPC(nPC);
  379. }
  380. /********************************************************
  381. * Case jump by table search *
  382. * *
  383. * 1. pop case descriptor pointer. *
  384. * 2. pop search value. *
  385. * 3. Load number of table entries. *
  386. * 4. Check if search value in table. *
  387. * 5. If found: load Program Counter value. *
  388. * 6. Else: load default value. *
  389. ********************************************************/
  390. PRIVATE search_jump(nbytes)
  391. size nbytes;
  392. {
  393. register ptr cdp = dppop(); /* Case Descriptor Pointer */
  394. register long sv = spop(nbytes);/* Search Value */
  395. register long nt = /* Number of Table-entries */
  396. mem_lds(cdp + psize, nbytes);
  397. register ptr nPC; /* New Program Counter */
  398. while (--nt >= 0) {
  399. if (sv == mem_lds(cdp + (nt+1) * (nbytes+psize), nbytes)) {
  400. nPC = mem_ldip(cdp + nbytes + (nt+1)*(nbytes+psize));
  401. if (nPC == 0)
  402. trap(ECASE);
  403. newPC(nPC);
  404. return;
  405. }
  406. }
  407. nPC = mem_ldip(cdp);
  408. if (nPC == 0)
  409. trap(ECASE);
  410. newPC(nPC);
  411. }
  412. /********************************************************
  413. * Range check *
  414. * *
  415. * 1. Load range descriptor. *
  416. * 2. Check against lower and upper bound. *
  417. * 3. Generate trap if necessary. *
  418. * 4. DON'T remove integer. *
  419. ********************************************************/
  420. PRIVATE range_check(nbytes)
  421. size nbytes;
  422. {
  423. register ptr rdp = dppop(); /* Range check Descriptor Pointer */
  424. register long cv = /* Check Value */
  425. st_lds(SP, nbytes);
  426. if (must_test && !(IgnMask&BIT(ERANGE))) {
  427. if ( cv < mem_lds(rdp, nbytes)
  428. || cv > mem_lds(rdp + nbytes, nbytes)
  429. ) {
  430. trap(ERANGE);
  431. }
  432. }
  433. }