20-interrupt.red 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. %
  2. % 20-INTERRUPT.RED -- Crude Interrupt Handler for DEC-20
  3. % Author: M. L. Griss and D. Morrison
  4. % Utah Symbolic Computation Group
  5. % Computer Science Dept.
  6. % University of Utah
  7. % Date: 20 May 1981
  8. % Copyright (c) University of Utah
  9. % It is assumed that the system dependent portion of an implementation will
  10. %supply the following 3 functions:
  11. %
  12. % InitializeInterrupts
  13. % EnableInterrupts
  14. % DisableInterrupts
  15. % DismissInterrupt
  16. %
  17. % While these are machine dependent, the interrupt handlers themselves are
  18. % are expected to generally be machine independent, simply calling
  19. % DismissInterrupt when done. The assignment of terminal-initiated interrupts
  20. % to keys is machine dependent.
  21. imports '(Addr2ID); % for code-address-to-symbol
  22. on Syslisp;
  23. %internal WARRAY InterruptLevelTable[2],
  24. % InterruptPCStorage[2],
  25. % InterruptChannelTable[35];
  26. FLUID '(InterruptLevelTable
  27. LoadAverageStore
  28. InterruptPCStorage
  29. InterruptChannelTable
  30. );
  31. compiletime << WCONST !.FHSLF=8#400000;>>;
  32. if FUnBoundP 'XJsysError then <<
  33. syslsp procedure XJsysError(); % autoloading stub
  34. << Load JSYS;
  35. Apply(function XJsysError, '()) >>;
  36. >>;
  37. syslsp procedure InitializeInterrupts();
  38. % Initializes interrupt handlers for both machine- and terminal-initiated
  39. % interrupts. Most cases should dispatch to machine-independent handlers.
  40. % Leaves the interrupt system enabled.
  41. % In this Tops-20 (machine-code) version we currently handle:
  42. % just playing, for now
  43. begin
  44. (LispVar InterruptLevelTable):=GtWarray 3;
  45. (LispVar InterruptPCStorage):=GtWarray 3;
  46. (LispVar InterruptChannelTable):=GtWarray 36;
  47. (LispVar LoadAverageStore) := MkString(4, char BLANK);
  48. ClearInterrupts();
  49. % set up interrupt tables -- see Monitor Calls Manual for details
  50. For i := 0:35 do %/ Some bug, wiped out next one when after
  51. (LispVar InterruptChannelTable)[i]:=0;
  52. for i := 0:2 do
  53. (LispVar InterruptLevelTable)[i]:=(LispVar InterruptPCStorage) + i;
  54. % Terminal Interupts (Procedure on channel/level)
  55. % Note LEVEL is 1,2,3
  56. PutInterrupt(0,1,'DoControlG);
  57. PutInterrupt(1,1,'SaveAndCallControlT); % control T not working yet
  58. PutInterrupt(2,1,'SaveAndBreak);
  59. % special channels
  60. PutInterrupt(6,1,'ArithOverflow);
  61. PutInterrupt(7,1,'FloatArithOverflow);
  62. PutInterrupt(9,1,'PushDownOverflow);
  63. % Now Install tables
  64. Xjsys0(!.FHSLF,
  65. XWD((LispVar InterruptLevelTable),
  66. (LispVar InterruptChannelTable)),0,0,const jsSIR);
  67. EnableInterrupts();
  68. ActivateChannel(0);
  69. ActivateChannel(1);
  70. ActivateChannel(2);
  71. ActivateChannel(6);
  72. ActivateChannel(7);
  73. ActivateChannel(9);
  74. PutTerminalInterrupt(7,0); % Char CNTRL-G on 0
  75. PutTerminalInterrupt(4,0); % Char CNTRL-D on 2
  76. PutTerminalInterrupt(20,1); % Char cntrl-t on 1, not working yet
  77. PutTerminalInterrupt(0,2); % Char BREAK on 2
  78. PutTerminalInterrupt(2,2); % Char cntrl-B on 2
  79. ClearInterrupts();
  80. end;
  81. syslsp procedure SetContinueAddress(Level,Address);
  82. begin scalar x;
  83. x:=(LispVar InterruptLevelTable)[Level-1];
  84. x[0]:=address;
  85. end;
  86. % FunctionCellLocation is used by LAP
  87. off Syslisp;
  88. fluid '(!*WritingFaslFile);
  89. lisp procedure SetContinueFunction(Level,FunctionName);
  90. begin scalar !*WritingFaslFile;
  91. SetContinueAddress(Level, FunctionCellLocation FunctionName);
  92. end;
  93. lisp procedure PutInterrupt(Channel,Level,ActionId);
  94. begin scalar !*WritingFaslFile;
  95. WPutV(InterruptChannelTable,
  96. Channel,
  97. XWD(Level, FunctionCellLocation ActionId));
  98. end;
  99. on Syslisp;
  100. syslsp procedure XWD(a,b);
  101. Lor(Lsh(a,18),b);
  102. syslsp procedure PutTerminalInterrupt(CntrlChar,Channel);
  103. Xjsys0(XWD(CntrlChar,Channel),0,0,0,const jsATI);
  104. syslsp procedure RemoveTerminalInterrupt(CntrlChar,Channel);
  105. Xjsys0(XWD(CntrlChar,Channel),0,0,0,const jsDTI);
  106. syslsp procedure ReadTerminalWord;
  107. Xjsys1(0,0,0,0,Const jsRTIW);
  108. syslsp procedure SetTerminalWordBit(n);
  109. <<XJsys0(Lor(ReadTerminalLWord(),Dec20Bit n),0,0,const jsSTIW);
  110. ReadTerminalWord()>>;
  111. syslsp procedure SetTerminalWord(MSK);
  112. <<Xjsys0(Lor(ReadTerminalWord(),MSK),0,0,0,const jsSTIW);
  113. ReadTerminalWord()>>;
  114. syslsp procedure ClearInterrupts;
  115. Xjsys0(0,0,0,0,const jsCIS); % clear any pending interrupts
  116. syslsp procedure SignalChannel n; %. Test on channel n
  117. Xjsys0(!.FHSLF,Dec20Bit n,0,0,const jsIIC);
  118. syslsp procedure EnableInterrupts;
  119. Xjsys0(!.FHSLF,0,0,0,const jsEIR);
  120. syslsp procedure DisableInterrupts;
  121. Xjsys0(!.FHSLF,0,0,0,const jsDIR);
  122. syslsp procedure ActivateChannel(n); %. Inform OS of channel
  123. Xjsys0(!.FHSLF,Dec20Bit n,0,0,const jsAIC);
  124. syslsp procedure DeActivateChannel(n); %. Inform OS of channel
  125. Xjsys0(!.FHSLF,Dec20Bit n,0,0,const jsDIC);
  126. syslsp procedure Dec20Bit n; %. Bits [0 to 35]
  127. Dec20Fld(1,35-n);
  128. syslsp procedure Dec20Fld(x,y);
  129. LSH(x,y);
  130. syslsp procedure DismissInterrupt;
  131. % Warning: an interrupt handler should not attempt to resume if may have
  132. % caused a garbage collection.
  133. Xjsys0(0,0,0,0,const jsDEBRK);
  134. % ----- Some default handlers ----------
  135. syslsp procedure DoControlG;
  136. << ClearTerminalInputBuffer(); % CFIBF
  137. ChannelWriteChar(LispVAR StdOUT!*, Char BELL);
  138. ErrorPrintF "*** Restarting";
  139. SetContinueFunction(1,'Reset);
  140. DismissInterrupt()>>;
  141. syslsp procedure ClearTerminalInputBuffer();
  142. Xjsys0(8#100,0,0,0,const jsCFIBF);
  143. syslsp procedure ArithOverflow;
  144. <<SetContinueFunction(1,'ArithOverFlowError);
  145. DismissInterrupt()>>;
  146. syslsp procedure ArithOverFlowError;
  147. StdError('"Integer overflow");
  148. syslsp procedure FloatArithOverflow;
  149. <<SetContinueFunction(1,'FloatArithOverFlowError);
  150. DismissInterrupt()>>;
  151. syslsp procedure FloatArithOverFlowError;
  152. StdError('"Floating point overflow");
  153. lap '((!*entry PushDownOverflow expr 0)
  154. (sub (reg st) (lit (halfword 1000 1000))) % move the stack back
  155. (!*MOVE (WConst 1) (REG 1))
  156. (movei 2 ErrorAddress)
  157. (!*CALL SetContinueAddress)
  158. (!*JCALL DismissInterrupt)
  159. ErrorAddress
  160. (!*MOVE '"Stack overflow" (reg 1))
  161. (!*JCALL StdError) % normal error
  162. );
  163. lap '((!*entry FindLoadAverage expr 0)
  164. (move 1 (lit (fullword 8#000014000014))) % 1 min avg, .systa
  165. (getab)
  166. (!*EXIT 0)
  167. (hrrz 2 (fluid LoadAverageStore))
  168. (hrli 2 8#10700) % make a byte pointer
  169. (exch 1 2)
  170. (move 3 (lit (fullword 8#024037020200)))
  171. (flout)
  172. (!*EXIT 0)
  173. (!*EXIT 0)
  174. );
  175. syslsp procedure DoControlT();
  176. begin scalar RunningFunctionID, CameFrom;
  177. % ClearTerminalInputBuffer();
  178. FindLoadAverage();
  179. CameFrom := INF ((LispVar InterruptPCStorage)[0]);
  180. RunningFunctionID := code!-address!-to!-symbol CameFrom or 'UNKNOWN;
  181. ErrorPrintF("^T: in %p at %o, load %w",
  182. RunningFunctionID, CameFrom, LispVar LoadAverageStore);
  183. end;
  184. >>;
  185. syslsp procedure DoBreak();
  186. begin scalar RunningFunctionID, CameFrom, CurrentChannel;
  187. ClearTerminalInputBuffer();
  188. CameFrom := INF( (LispVar InterruptPCStorage)[0]);
  189. RunningFunctionID := code!-address!-to!-symbol CameFrom or 'UNKNOWN;
  190. CurrentChannel := WRS NIL;
  191. ErrorPrintF("*** Break in %p at %o", RunningFunctionID, CameFrom);
  192. ErrorSet(quote Break(), NIL, NIL);
  193. WRS CurrentChannel;
  194. end;
  195. lap '((!*Entry SaveAndCallControlT expr 0)
  196. %
  197. % Save all regs, call DoControlT and dismiss
  198. %
  199. (adjsp (reg st) 14) % allocate 14 slots on the stack
  200. (hrri (reg nil) (indexed (reg st) -13)) % set up BLT pointer
  201. (hrli (reg nil) 1) % move regs 1..14 onto the stack
  202. (blt (reg nil) (indexed (reg st) 0))
  203. (move (reg nil) (fluid nil)) % fix reg nil
  204. (!*CALL DoControlT) % call the function
  205. (hrli (reg nil) (indexed (reg st) -13))
  206. (hrri (reg nil) 1)
  207. (blt (reg nil) 14) % move the registers back off the stack
  208. (move (reg nil) (fluid nil)) % restore reg nil again
  209. (adjsp (reg st) -14)
  210. (debrk)
  211. );
  212. >>;
  213. lap '((!*Entry SaveAndBreak expr 0)
  214. %
  215. % Save all regs, call DoBreak and dismiss
  216. %
  217. (adjsp (reg st) 14) % allocate 14 slots on the stack
  218. (hrri (reg nil) (indexed (reg st) -13)) % set up BLT pointer
  219. (hrli (reg nil) 1) % move regs 1..14 onto the stack
  220. (blt (reg nil) (indexed (reg st) 0))
  221. (move (reg nil) (fluid nil)) % fix reg nil
  222. (!*CALL DoBreak) % call the function
  223. (hrli (reg nil) (indexed (reg st) -13))
  224. (hrri (reg nil) 1)
  225. (blt (reg nil) 14) % move the registers back off the stack
  226. (move (reg nil) (fluid nil)) % restore reg nil again
  227. (adjsp (reg st) -14)
  228. (debrk)
  229. );
  230. InitializeInterrupts();
  231. off syslisp;
  232. END;