AMD64.CPU.Mod 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. (* Runtime support for CPU internals *)
  2. (* Copyright (C) Florian Negele *)
  3. MODULE CPU;
  4. IMPORT SYSTEM;
  5. CONST StackSize* = 1024 * SIZEOF(ADDRESS);
  6. CONST Quantum* = 1000000;
  7. CONST CacheLineSize* = 64;
  8. CONST StackDisplacement* = 0;
  9. PROCEDURE Backoff-;
  10. CODE
  11. MOV EBX, 80000H
  12. loop:
  13. DEC EBX
  14. JNZ loop
  15. END Backoff;
  16. (* cpu control *)
  17. PROCEDURE {NORETURN} Reset-;
  18. CODE
  19. CLI
  20. PUSH 0
  21. PUSH 0
  22. LIDT [RSP]
  23. INT3
  24. END Reset;
  25. PROCEDURE {NORETURN} Halt-;
  26. CODE
  27. CLI
  28. end:
  29. HLT
  30. JMP end
  31. END Halt;
  32. (* input / output ports *)
  33. PROCEDURE OutChar- (port: SIZE; value: CHAR);
  34. CODE
  35. MOV AL, [RBP + value]
  36. MOV DX, [RBP + port]
  37. OUT DX, AL
  38. END OutChar;
  39. PROCEDURE OutByte- (port: SIZE; value: SIZE);
  40. CODE
  41. MOV AL, [RBP + value]
  42. MOV DX, [RBP + port]
  43. OUT DX, AL
  44. END OutByte;
  45. PROCEDURE OutSet- (port: SIZE; value: SET);
  46. CODE
  47. MOV AL, [RBP + value]
  48. MOV DX, [RBP + port]
  49. OUT DX, AL
  50. END OutSet;
  51. PROCEDURE InChar- (port: SIZE): CHAR;
  52. CODE
  53. MOV DX, [RBP + port]
  54. IN AL, DX
  55. END InChar;
  56. PROCEDURE InByte- (port: SIZE): SIZE;
  57. CODE
  58. MOV DX, [RBP + port]
  59. IN AL, DX
  60. MOVZX EAX, AL
  61. END InByte;
  62. PROCEDURE InSet- (port: SIZE): SET;
  63. CODE
  64. MOV DX, [RBP + port]
  65. IN AL, DX
  66. MOVZX EAX, AL
  67. END InSet;
  68. PROCEDURE -SaveResult-;
  69. CODE
  70. PUSH RAX
  71. END SaveResult;
  72. PROCEDURE -RestoreResultAndReturn-;
  73. CODE
  74. POP RAX
  75. LEA RSP, [RBP+8]
  76. POP RBP
  77. RET
  78. END RestoreResultAndReturn;
  79. PROCEDURE Mask- (port: SIZE; value: SET);
  80. BEGIN {UNCOOPERATIVE, UNCHECKED}
  81. OutSet (port, InSet (port) + value);
  82. END Mask;
  83. PROCEDURE Unmask- (port: SIZE; value: SET);
  84. BEGIN {UNCOOPERATIVE, UNCHECKED}
  85. OutSet (port, InSet (port) - value);
  86. END Unmask;
  87. (* interrupt handling *)
  88. CONST Interrupts* = 48;
  89. CONST IRQ0* = 32; IRQ1* = 33; IRQ2* = 34; IRQ3* = 35; IRQ4* = 36; IRQ5* = 37; IRQ6* = 38; IRQ7* = 39;
  90. CONST IRQ8* = 40; IRQ9* = 41; IRQ10* = 42; IRQ11* = 43; IRQ12* = 44; IRQ13* = 45; IRQ14* = 46; IRQ15* = 47;
  91. CONST PIC1CommandPort = 020H; PIC1DataPort = 021H; PIC2CommandPort = 0A0H; PIC2DataPort = 0A1H;
  92. CONST ICW1_ICW4 = 001H; ICW1_INIT = 010H; ICW4_8086 = 001H; PIC_EOI = 020H; PIC_READ_ISR = 00AH;
  93. TYPE InterruptHandler* = PROCEDURE (index: SIZE);
  94. VAR handlers: ARRAY Interrupts OF InterruptHandler;
  95. PROCEDURE InstallInterrupt- (handler: InterruptHandler; index: SIZE): InterruptHandler;
  96. VAR previous: InterruptHandler;
  97. BEGIN {UNCOOPERATIVE, UNCHECKED}
  98. ASSERT (handler # NIL); ASSERT (index < Interrupts);
  99. REPEAT previous := CAS (handlers[index], NIL, NIL) UNTIL CAS (handlers[index], previous, handler) = previous;
  100. IF previous = NIL THEN EnableIRQ (index) END;
  101. RETURN previous;
  102. END InstallInterrupt;
  103. PROCEDURE HandleInterrupt (index: SIZE);
  104. BEGIN {UNCOOPERATIVE, UNCHECKED}
  105. CODE
  106. PUSH RAX
  107. PUSH RCX
  108. PUSH RDX
  109. PUSH RBX
  110. PUSH RSI
  111. PUSH RDI
  112. PUSH R8
  113. PUSH R9
  114. PUSH R10
  115. PUSH R11
  116. PUSH R12
  117. PUSH R13
  118. PUSH R14
  119. PUSH R15
  120. END;
  121. SYSTEM.SetActivity (NIL);
  122. IF handlers[index] # NIL THEN handlers[index] (index) ELSE HALT (1234) END;
  123. IF index >= IRQ8 THEN
  124. OutByte (PIC2CommandPort, PIC_EOI); OutByte (PIC1CommandPort, PIC_EOI);
  125. ELSIF index >= IRQ0 THEN
  126. OutByte (PIC1CommandPort, PIC_EOI);
  127. END;
  128. CODE
  129. POP R15
  130. POP R14
  131. POP R13
  132. POP R12
  133. POP R11
  134. POP R10
  135. POP R9
  136. POP R8
  137. POP RDI
  138. POP RSI
  139. POP RBX
  140. POP RDX
  141. POP RCX
  142. POP RAX
  143. END;
  144. END HandleInterrupt;
  145. PROCEDURE DisableInterrupt- (index: SIZE);
  146. VAR previous: InterruptHandler;
  147. BEGIN {UNCOOPERATIVE, UNCHECKED}
  148. ASSERT (index < Interrupts);
  149. DisableIRQ (index);
  150. REPEAT previous := CAS (handlers[index], NIL, NIL) UNTIL CAS (handlers[index], previous, NIL) = previous;
  151. END DisableInterrupt;
  152. PROCEDURE EnableIRQ- (index: SIZE);
  153. BEGIN {UNCOOPERATIVE, UNCHECKED}
  154. ASSERT (index < Interrupts);
  155. IF (index >= IRQ0) & (index <= IRQ7) THEN Unmask (PIC1DataPort, {index - IRQ0}) END;
  156. IF (index >= IRQ8) & (index <= IRQ15) THEN Unmask (PIC2DataPort, {index - IRQ8}) END;
  157. END EnableIRQ;
  158. PROCEDURE DisableIRQ- (index: SIZE);
  159. BEGIN {UNCOOPERATIVE, UNCHECKED}
  160. ASSERT (index < Interrupts);
  161. IF (index >= IRQ0) & (index <= IRQ7) THEN Mask (PIC1DataPort, {index - IRQ0}) END;
  162. IF (index >= IRQ8) & (index <= IRQ15) THEN Mask (PIC2DataPort, {index - IRQ8}) END;
  163. END DisableIRQ;
  164. VAR idt-: ARRAY Interrupts OF ARRAY 8 OF INTEGER;
  165. VAR wrapper: ARRAY Interrupts OF ARRAY 20 OF CHAR;
  166. PROCEDURE Initialize-;
  167. CONST IRETQ = 0CFX; PUSH = 06AX; CALL = 0E8X; REX = 048X; ADD = 083X; RSP = 0C4X;
  168. VAR i, c: SIZE; address: ADDRESS;
  169. BEGIN {UNCOOPERATIVE, UNCHECKED}
  170. (* ICW1: initialization *)
  171. OutByte (PIC1CommandPort, ICW1_INIT + ICW1_ICW4);
  172. OutByte (PIC2CommandPort, ICW1_INIT + ICW1_ICW4);
  173. (* ICW2: vector offsets *)
  174. OutByte (PIC1DataPort, IRQ0);
  175. OutByte (PIC2DataPort, IRQ8);
  176. (* ICW3: cascading *)
  177. OutByte (PIC1DataPort, 4);
  178. OutByte (PIC2DataPort, 2);
  179. (* ICW4: mode *)
  180. OutByte (PIC1DataPort, ICW4_8086);
  181. OutByte (PIC2DataPort, ICW4_8086);
  182. (* mask all maskable interrupts *)
  183. OutChar (PIC1DataPort, 0FBX);
  184. OutChar (PIC2DataPort, 0FFX);
  185. FOR i := 0 TO Interrupts - 1 DO
  186. IF (i # 9) & (i # 15) & ((i < 20) OR (i > 29)) & (i # 31) THEN
  187. idt[i][0] := INTEGER (ADDRESS OF wrapper[i] MOD 10000H);
  188. idt[i][1] := INTEGER(8H);
  189. idt[i][2] := INTEGER(8E00H);
  190. idt[i][3] := INTEGER(ADDRESS OF wrapper[i] DIV 10000H);
  191. c := 0;
  192. IF i # 2 THEN
  193. IF (i = 8) OR (i >= 10) & (i <= 14) OR (i = 17) THEN
  194. wrapper[i][c] := REX; INC (c);
  195. wrapper[i][c] := ADD; INC (c);
  196. wrapper[i][c] := RSP; INC (c);
  197. wrapper[i][c] := CHR (8); INC (c);
  198. END;
  199. wrapper[i][c] := PUSH; INC (c);
  200. wrapper[i][c] := CHR (i); INC (c);
  201. wrapper[i][c] := CALL; INC (c);
  202. address := ADDRESS OF HandleInterrupt - ADDRESS OF wrapper[i][c + 4];
  203. wrapper[i][c] := CHR (address DIV 1H); INC (c);
  204. wrapper[i][c] := CHR (address DIV 100H); INC (c);
  205. wrapper[i][c] := CHR (address DIV 10000H); INC (c);
  206. wrapper[i][c] := CHR (address DIV 1000000H); INC (c);
  207. wrapper[i][c] := REX; INC (c);
  208. wrapper[i][c] := ADD; INC (c);
  209. wrapper[i][c] := RSP; INC (c);
  210. wrapper[i][c] := CHR (8); INC (c);
  211. END;
  212. wrapper[i][c] := IRETQ;
  213. ELSE
  214. idt[i][0] := 0;
  215. idt[i][1] := 0;
  216. idt[i][2] := 0;
  217. idt[i][3] := 0;
  218. END;
  219. idt[i][4] := 0;
  220. idt[i][5] := 0;
  221. idt[i][6] := 0;
  222. idt[i][7] := 0;
  223. END;
  224. CODE
  225. LEA RAX, idt
  226. PUSH RAX
  227. MOV AX, Interrupts * 8
  228. PUSH AX
  229. LIDT [RSP]
  230. STI
  231. END;
  232. END Initialize;
  233. END CPU.