Coop.Machine.Mod 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. MODULE Machine;
  2. IMPORT CPU, Environment, Trace, Mutexes, Processors;
  3. CONST
  4. Version = "A2 Cooperative Revision 5791";
  5. MaxCPU* = Processors.Maximum; (* dummy definition to make GC for both Win32 and I386 work *)
  6. DefaultObjectFileExtension* = ".Obw";
  7. (** bits in features variable *)
  8. MTTR* = 12; MMX* = 23;
  9. debug* = FALSE; (** display more debug output during booting *)
  10. IsCooperative*= TRUE;
  11. CONST
  12. (** standard lock levels (in order) *) (* also refer to Traps.Show *)
  13. TraceOutput* = 0; (* Trace output *)
  14. Memory* = 1; (* Virtual memory management, stack and page allocation *)
  15. Heaps* = 2; (* Storage allocation and Garbage collection *)
  16. Interrupts* = 3; (* Interrupt handling. *)
  17. Modules* = 4; (* Module list *)
  18. Objects* = 5; (* Ready queue *)
  19. KernelLog* = 7; (* Atomic output *)
  20. GC* = 8;
  21. X11* = 9; (* XWindows I/O *)
  22. MaxLocks = 10; (* { <= 32 } *)
  23. (* error codes *)
  24. Ok* = 0;
  25. NilAdr* = -1; (* nil value for addresses (not same as pointer NIL value) *)
  26. IRQ0* = CPU.IRQ0;
  27. MaxIRQ* = CPU.IRQ15;
  28. TYPE
  29. Vendor* = ARRAY 13 OF CHAR;
  30. IDMap* = ARRAY 16 OF SHORTINT;
  31. Range* = RECORD
  32. adr*: ADDRESS; size*: SIZE;
  33. END;
  34. MemoryBlock* = POINTER TO MemoryBlockDesc;
  35. MemoryBlockDesc* = RECORD
  36. next- {UNTRACED}: MemoryBlock;
  37. startAdr-: ADDRESS; (* sort key in linked list of memory blocks *)
  38. size-: SIZE;
  39. beginBlockAdr-, endBlockAdr-: ADDRESS
  40. END;
  41. (* dummy definition to make GC work for both I386 and Win32 - copied from BIOS.I386.Machine.Mod, but not really used *)
  42. Stack* = RECORD (** values are read-only *)
  43. low: ADDRESS; (* lowest virtual address that may be allocated for stack *)
  44. adr*: ADDRESS; (* lowest address on allocated stack *) (* exported for Objects only *)
  45. high*: ADDRESS; (* next virtual address after stack *) (* exported for Objects only *)
  46. END;
  47. Address32* = LONGINT;
  48. VAR
  49. MMXSupport*: BOOLEAN;
  50. SSESupport*: BOOLEAN;
  51. SSE2Support*: BOOLEAN;
  52. SSE3Support-: BOOLEAN; (* PH 04/11*)
  53. SSSE3Support-: BOOLEAN;
  54. SSE41Support-: BOOLEAN;
  55. SSE42Support-: BOOLEAN;
  56. SSE5Support-: BOOLEAN;
  57. AVXSupport-: BOOLEAN;
  58. version*: ARRAY 64 OF CHAR; (** Aos version *)
  59. features*,features2*: SET; (** processor features *)
  60. fcr*: SET; (** default floating-point control register value (default rounding mode is towards -infinity, for ENTIER) *)
  61. mhz*: HUGEINT; (** clock rate of GetTimer() in MHz, or 0 if not known *)
  62. boottime-: HUGEINT; (** in timer units *)
  63. VAR
  64. lock-: ARRAY MaxLocks OF CHAR; (* not implemented as SET because of shared access *)
  65. mutex: ARRAY MaxLocks OF Mutexes.Mutex;
  66. memBlockHead-{UNTRACED}, memBlockTail-{UNTRACED}: MemoryBlock; (* head and tail of sorted list of memory blocks *)
  67. (** Convert a string to an integer. Parameter i specifies where in the string scanning should begin (usually 0 in the first call). Scanning stops at the first non-valid character, and i returns the updated position. Parameter s is the string to be scanned. The value is returned as result, or 0 if not valid. Syntax: number = ["-"] digit {digit} ["H" | "h"] . digit = "0" | ... "9" | "A" .. "F" | "a" .. "f" . If the number contains any hexdecimal letter, or if it ends in "H" or "h", it is interpreted as hexadecimal. *)
  68. PROCEDURE StrToInt*( VAR i: LONGINT; CONST s: ARRAY OF CHAR ): LONGINT;
  69. VAR vd, vh, sgn, d: LONGINT; hex: BOOLEAN;
  70. BEGIN
  71. vd := 0; vh := 0; hex := FALSE;
  72. IF s[i] = "-" THEN sgn := -1; INC( i ) ELSE sgn := 1 END;
  73. LOOP
  74. IF (s[i] >= "0") & (s[i] <= "9") THEN d := ORD( s[i] ) - ORD( "0" )
  75. ELSIF (CAP( s[i] ) >= "A") & (CAP( s[i] ) <= "F") THEN d := ORD( CAP( s[i] ) ) - ORD( "A" ) + 10; hex := TRUE
  76. ELSE EXIT
  77. END;
  78. vd := 10 * vd + d; vh := 16 * vh + d; INC( i )
  79. END;
  80. IF CAP( s[i] ) = "H" THEN hex := TRUE; INC( i ) END; (* optional H *)
  81. IF hex THEN vd := vh END;
  82. RETURN sgn * vd
  83. END StrToInt;
  84. (** -- Atomic operations -- *)
  85. (** This procedure should be called in all spin loops as a hint to the processor (e.g. Pentium 4). *)
  86. PROCEDURE -SpinHint*;
  87. CODE
  88. #IF I386 THEN
  89. PAUSE
  90. #ELSIF AMD64 THEN
  91. PAUSE
  92. #ELSE
  93. unimplemented
  94. #END
  95. END SpinHint;
  96. (* Return current instruction pointer *)
  97. PROCEDURE CurrentPC* (): ADDRESS;
  98. CODE
  99. #IF I386 THEN
  100. MOV EAX, [EBP+4]
  101. #ELSIF AMD64 THEN
  102. MOV RAX, [RBP + 8]
  103. #ELSE
  104. unimplemented
  105. #END
  106. END CurrentPC;
  107. (* Return current frame pointer *)
  108. PROCEDURE -CurrentBP* (): ADDRESS;
  109. CODE
  110. #IF I386 THEN
  111. MOV EAX, EBP
  112. #ELSIF AMD64 THEN
  113. MOV RAX, RBP
  114. #ELSE
  115. unimplemented
  116. #END
  117. END CurrentBP;
  118. (* Return current stack pointer *)
  119. PROCEDURE -CurrentSP* (): ADDRESS;
  120. CODE
  121. #IF I386 THEN
  122. MOV EAX, ESP
  123. #ELSIF AMD64 THEN
  124. MOV RAX, RSP
  125. #ELSE
  126. unimplemented
  127. #END
  128. END CurrentSP;
  129. PROCEDURE MapPhysical*(physAdr: ADDRESS; size: SIZE; VAR virtAdr: ADDRESS);
  130. BEGIN
  131. virtAdr := physAdr;
  132. END MapPhysical;
  133. (** Unmap an area previously mapped with MapPhysical. *)
  134. PROCEDURE UnmapPhysical*(virtAdr: ADDRESS; size: SIZE);
  135. END UnmapPhysical;
  136. (** Translate a virtual address range to num ranges of physical address. num returns 0 on error. *)
  137. PROCEDURE TranslateVirtual*(virtAdr: ADDRESS; size: SIZE; VAR num: LONGINT; VAR physAdr: ARRAY OF Range);
  138. CONST PS = 4096;
  139. VAR ofs, phys1: ADDRESS; size1: SIZE;
  140. BEGIN
  141. num := 0;
  142. LOOP
  143. IF size = 0 THEN EXIT END;
  144. IF num = LEN(physAdr) THEN num := 0; EXIT END; (* index check *)
  145. ofs := virtAdr MOD PS; (* offset in page *)
  146. size1 := PS - ofs; (* distance to next page boundary *)
  147. IF size1 > size THEN size1 := size END;
  148. phys1 := virtAdr - ofs;
  149. physAdr[num].adr := phys1 - phys1 MOD PS + ofs;
  150. physAdr[num].size := size1; INC(num);
  151. INC(virtAdr, size1); DEC(size, size1)
  152. END;
  153. IF num = 0 THEN physAdr[0].adr := NilAdr; physAdr[0].size := 0 END;
  154. END TranslateVirtual;
  155. PROCEDURE Ensure32BitAddress*(adr: ADDRESS): Address32;
  156. BEGIN
  157. ASSERT (Address32 (adr) = adr);
  158. RETURN Address32 (adr);
  159. END Ensure32BitAddress;
  160. PROCEDURE Is32BitAddress*(adr: ADDRESS): BOOLEAN;
  161. BEGIN RETURN Address32 (adr) = adr;
  162. END Is32BitAddress;
  163. (** Get parameter values from Init string. If n = 0, return val = ASH(bx, 16) + ax, and if n = 1, return val = ASH(dx, 16) + cx, where ax, bx, cx, dx are the register values after the OBL boot loader or noboot.exe have executed the 16-bit x86 code in the Init string. *)
  164. PROCEDURE GetInit* (n: LONGINT; VAR val: LONGINT);
  165. BEGIN Environment.GetInit (n, val);
  166. END GetInit;
  167. (** Fill "size" bytes at "destAdr" with "filler". "size" must be multiple of 4. *)
  168. PROCEDURE Fill32*(destAdr: ADDRESS; size: SIZE; filler: LONGINT);
  169. CODE
  170. #IF I386 THEN
  171. #IF COOP THEN
  172. PUSH ECX
  173. #END
  174. MOV EDI, [EBP+destAdr]
  175. MOV ECX, [EBP+size]
  176. MOV EAX, [EBP+filler]
  177. TEST ECX, 3
  178. JZ ok
  179. PUSH 8 ; ASSERT failure
  180. INT 3
  181. ok: SHR ECX, 2
  182. CLD
  183. REP STOSD
  184. #IF COOP THEN
  185. POP ECX
  186. #END
  187. #ELSIF AMD64 THEN
  188. MOV RDI, [RBP + destAdr]
  189. MOV RCX, [RBP + size]
  190. MOV EAX, [RBP + filler]
  191. TEST RCX, 3
  192. JZ ok
  193. PUSH 8 ; ASSERT failure
  194. INT 3
  195. ok: SHR RCX, 2
  196. CLD
  197. REP STOSD
  198. #ELSE
  199. unimplemented
  200. #END
  201. END Fill32;
  202. (** -- Processor initialization -- *)
  203. PROCEDURE -SetFCR( s: SET );
  204. CODE
  205. #IF I386 THEN
  206. FLDCW [ESP] ; parameter s
  207. POP EAX
  208. #ELSIF AMD64 THEN
  209. FLDCW WORD [RSP] ; parameter s
  210. POP RAX
  211. #ELSE
  212. unimplemented
  213. #END
  214. END SetFCR;
  215. PROCEDURE -FCR( ): SET;
  216. CODE
  217. #IF I386 THEN
  218. PUSH 0
  219. FNSTCW [ESP]
  220. FWAIT
  221. POP EAX
  222. #ELSIF AMD64 THEN
  223. PUSH 0
  224. FNSTCW WORD [RSP]
  225. FWAIT
  226. POP RAX
  227. #ELSE
  228. unimplemented
  229. #END
  230. END FCR;
  231. PROCEDURE -InitFPU;
  232. CODE
  233. #IF I386 THEN
  234. FNINIT
  235. #ELSIF AMD64 THEN
  236. FNINIT
  237. #ELSE
  238. unimplemented
  239. #END
  240. END InitFPU;
  241. (** CPU identification. *)
  242. PROCEDURE CPUID*( VAR vendor: Vendor; VAR version: LONGINT; VAR features1,features2: SET );
  243. CODE
  244. #IF I386 THEN
  245. #IF COOP THEN
  246. PUSH ECX
  247. #END
  248. MOV EAX, 0
  249. CPUID
  250. CMP EAX, 0
  251. JNE ok
  252. MOV ESI, [EBP+vendor]
  253. MOV [ESI], AL ; AL = 0
  254. MOV ESI, [EBP+version]
  255. MOV [ESI], EAX ; EAX = 0
  256. MOV ESI, [EBP+features1]
  257. MOV [ESI], EAX
  258. MOV ESI, [EBP+features2]
  259. MOV [ESI], EAX
  260. JMP end
  261. ok:
  262. MOV ESI, [EBP+vendor]
  263. MOV [ESI], EBX
  264. MOV [ESI+4], EDX
  265. MOV [ESI+8], ECX
  266. MOV BYTE [ESI+12], 0
  267. MOV EAX, 1
  268. CPUID
  269. MOV ESI, [EBP+version]
  270. MOV [ESI], EAX
  271. MOV ESI, [EBP+features1]
  272. MOV [ESI], EDX
  273. MOV ESI, [EBP+features2]
  274. MOV [ESI], ECX
  275. end:
  276. #IF COOP THEN
  277. POP ECX
  278. #END
  279. #ELSIF AMD64 THEN
  280. #IF COOP THEN
  281. PUSH RBX
  282. #END
  283. MOV EAX, 0
  284. CPUID
  285. CMP EAX, 0
  286. JNE ok
  287. MOV RSI, [RBP+vendor]
  288. MOV [RSI], AL ; AL = 0
  289. MOV RSI, [RBP+version]
  290. MOV [RSI], EAX ; EAX = 0
  291. MOV RSI, [RBP+features1]
  292. MOV [RSI], EAX
  293. MOV RSI, [RBP+features2]
  294. MOV [RSI], EAX
  295. JMP end
  296. ok:
  297. MOV RSI, [RBP+vendor]
  298. MOV [RSI], EBX
  299. MOV [RSI+4], EDX
  300. MOV [RSI+8], ECX
  301. MOV BYTE [RSI+12], 0
  302. MOV EAX, 1
  303. CPUID
  304. MOV RSI, [RBP+version]
  305. MOV [RSI], EAX
  306. MOV RSI, [RBP+features1]
  307. MOV [RSI], EDX
  308. MOV RSI, [RBP+features2]
  309. MOV [RSI], RCX
  310. end:
  311. #IF COOP THEN
  312. POP RBX
  313. #END
  314. #ELSE
  315. unimplemented
  316. #END
  317. END CPUID;
  318. PROCEDURE GetConfig* ( CONST name: ARRAY OF CHAR; VAR val: ARRAY OF CHAR );
  319. BEGIN Environment.GetString (name, val);
  320. END GetConfig;
  321. PROCEDURE Shutdown*( restart: BOOLEAN );
  322. BEGIN
  323. IF restart THEN Environment.Reboot ELSE Environment.Shutdown END;
  324. END Shutdown;
  325. PROCEDURE Cli*;
  326. BEGIN HALT (1234);
  327. END Cli;
  328. PROCEDURE Sti*;
  329. BEGIN HALT (1234);
  330. END Sti;
  331. (* Dan: from new Machine *)
  332. PROCEDURE -GetTimer*(): HUGEINT;
  333. CODE
  334. #IF I386 THEN
  335. RDTSC ; set EDX:EAX
  336. #ELSIF AMD64 THEN
  337. XOR RAX, RAX
  338. RDTSC ; set EDX:EAX
  339. SHL RDX, 32
  340. OR RAX, RDX
  341. #ELSE
  342. unimplemented
  343. #END
  344. END GetTimer;
  345. (** Disable interrupts and return old interrupt state. *)
  346. PROCEDURE -DisableInterrupts* (): SET;
  347. CODE
  348. #IF I386 THEN
  349. PUSHFD
  350. CLI
  351. POP EAX
  352. #ELSIF AMD64 THEN
  353. PUSHFQ
  354. CLI
  355. POP RAX
  356. #ELSE
  357. unimplemented
  358. #END
  359. END DisableInterrupts;
  360. (** Restore interrupt state. Parameter s must be return value of earlier DisableInterrupts call on same processor. *)
  361. PROCEDURE -RestoreInterrupts* (s: SET);
  362. CODE
  363. #IF I386 THEN
  364. POPFD
  365. #ELSIF AMD64 THEN
  366. POPFQ
  367. #ELSE
  368. unimplemented
  369. #END
  370. END RestoreInterrupts;
  371. PROCEDURE ID*(): SIZE;
  372. BEGIN
  373. RETURN Processors.GetCurrentIndex ();
  374. END ID;
  375. (* setup MMX, SSE and SSE2..SSE5 and AVX extension *)
  376. PROCEDURE -InitSSE;
  377. CODE
  378. #IF I386 THEN
  379. MOV EAX, CR4
  380. OR EAX, 00000200H ; set bit 9 (OSFXSR)
  381. AND EAX, 0FFFFFBFFH ; delete bit 10 (OSXMMEXCPT)
  382. MOV CR4, EAX
  383. #ELSIF AMD64 THEN
  384. MOV EAX, CR4
  385. OR EAX, 00000200H ; set bit 9 (OSFXSR)
  386. AND EAX, 0FFFFFBFFH ; delete bit 10 (OSXMMEXCPT)
  387. MOV CR4, EAX
  388. #ELSE
  389. unimplemented
  390. #END
  391. END InitSSE;
  392. PROCEDURE InitBootProcessor-;
  393. CONST
  394. MMXFlag=23;(*IN features from EBX*)
  395. FXSRFlag = 24;
  396. SSEFlag = 25;
  397. SSE2Flag = 26;
  398. SSE3Flag = 0; (*IN features2 from ECX*) (*PH 04/11*)
  399. SSSE3Flag =9;
  400. SSE41Flag =19;
  401. SSE42Flag =20;
  402. SSE5Flag = 11;
  403. AVXFlag = 28;
  404. VAR vendor: Vendor; ver: LONGINT;
  405. BEGIN {UNCOOPERATIVE, UNCHECKED}
  406. CPUID(vendor, ver, features,features2);
  407. MMXSupport := MMXFlag IN features;
  408. SSESupport := SSEFlag IN features;
  409. SSE2Support := SSESupport & (SSE2Flag IN features);
  410. SSE3Support := SSE2Support & (SSE3Flag IN features2);
  411. SSSE3Support := SSE3Support & (SSSE3Flag IN features2); (* PH 04/11*)
  412. SSE41Support := SSE3Support & (SSE41Flag IN features2);
  413. SSE42Support := SSE3Support & (SSE42Flag IN features2);
  414. SSE5Support := SSE3Support & (SSE5Flag IN features2);
  415. AVXSupport := SSE3Support & (AVXFlag IN features2);
  416. fcr := (FCR() - {0,2,3,10,11}) + {0..5,8,9}; (* default FCR RC=00B *)
  417. InitApplicationProcessor;
  418. END InitBootProcessor;
  419. PROCEDURE InitApplicationProcessor-;
  420. BEGIN {UNCOOPERATIVE, UNCHECKED}
  421. InitFPU; SetFCR( fcr );
  422. IF Environment.IsNative & SSESupport THEN
  423. InitSSE();
  424. END;
  425. END InitApplicationProcessor;
  426. (** Acquire a spin-lock. *)
  427. PROCEDURE Acquire*( level: LONGINT ); (* non reentrant lock (non reentrance "ensured" by ASSERT statement ), CriticalSections are reentrant *)
  428. BEGIN
  429. Mutexes.Acquire (mutex[level]);
  430. END Acquire;
  431. (** Release a spin-lock. *)
  432. PROCEDURE Release*( level: LONGINT ); (* release lock *)
  433. BEGIN
  434. Mutexes.Release (mutex[level]);
  435. END Release;
  436. (* returns if an address is a currently allocated heap address *)
  437. PROCEDURE ValidHeapAddress*(p: ADDRESS): BOOLEAN;
  438. BEGIN
  439. RETURN p # NIL;
  440. END ValidHeapAddress;
  441. PROCEDURE GetFreeK* (VAR total, lowFree, highFree: SIZE);
  442. BEGIN
  443. total := 0; lowFree := 0; highFree := 0;
  444. END GetFreeK;
  445. PROCEDURE PhysicalAdr*(adr: ADDRESS; size: SIZE): ADDRESS;
  446. BEGIN RETURN adr;
  447. END PhysicalAdr;
  448. (** -- Atomic operations -- *)
  449. (** Atomic INC(x). *)
  450. PROCEDURE -AtomicInc*( VAR x: LONGINT );
  451. CODE
  452. #IF I386 THEN
  453. POP EAX
  454. LOCK
  455. INC DWORD [EAX]
  456. #ELSIF AMD64 THEN
  457. POP RAX
  458. LOCK
  459. INC DWORD [RAX]
  460. #ELSE
  461. unimplemented
  462. #END
  463. END AtomicInc;
  464. (** Atomic DEC(x). *)
  465. PROCEDURE -AtomicDec*( VAR x: LONGINT );
  466. CODE
  467. #IF I386 THEN
  468. POP EAX
  469. LOCK
  470. DEC DWORD [EAX]
  471. #ELSIF AMD64 THEN
  472. POP RAX
  473. LOCK
  474. DEC DWORD [RAX]
  475. #ELSE
  476. unimplemented
  477. #END
  478. END AtomicDec;
  479. (** Atomic INC(x, y). *)
  480. PROCEDURE -AtomicAdd*( VAR x: LONGINT; y: LONGINT );
  481. CODE
  482. #IF I386 THEN
  483. POP EBX
  484. POP EAX
  485. LOCK
  486. ADD DWORD [EAX], EBX
  487. #ELSIF AMD64 THEN
  488. POP ECX
  489. POP RAX
  490. LOCK
  491. ADD DWORD [RAX], ECX
  492. #ELSE
  493. unimplemented
  494. #END
  495. END AtomicAdd;
  496. (** Atomic test-and-set. Set x = TRUE and return old value of x. *)
  497. PROCEDURE -AtomicTestSet*( VAR x: BOOLEAN ): BOOLEAN;
  498. CODE
  499. #IF I386 THEN
  500. POP EBX
  501. MOV AL, 1
  502. XCHG [EBX], AL
  503. #ELSIF AMD64 THEN
  504. POP RCX
  505. MOV AL, 1
  506. XCHG [RCX], AL
  507. #ELSE
  508. unimplemented
  509. #END
  510. END AtomicTestSet;
  511. (* Atomic compare-and-swap. Set x = new if x = old and return old value of x *)
  512. PROCEDURE -AtomicCAS* (VAR x: LONGINT; old, new: LONGINT): LONGINT;
  513. CODE
  514. #IF I386 THEN
  515. POP EBX ; new
  516. POP EAX ; old
  517. POP EDX ; address of x
  518. LOCK CMPXCHG [EDX], EBX ; atomicly compare x with old and set it to new if equal
  519. #ELSIF AMD64 THEN
  520. POP ECX ; new
  521. POP EAX ; old
  522. POP RDX ; address of x
  523. LOCK CMPXCHG [RDX], ECX ; atomicly compare x with old and set it to new if equal
  524. #ELSE
  525. unimplemented
  526. #END
  527. END AtomicCAS;
  528. (* function returning the number of processors that are available to Aos *)
  529. PROCEDURE NumberOfProcessors*( ): SIZE;
  530. BEGIN
  531. RETURN Processors.count;
  532. END NumberOfProcessors;
  533. (* function for changing byte order *)
  534. PROCEDURE ChangeByteOrder* (n: LONGINT): LONGINT;
  535. CODE
  536. #IF I386 THEN
  537. MOV EAX, [EBP+n] ; load n in eax
  538. BSWAP EAX ; swap byte order
  539. #ELSIF AMD64 THEN
  540. MOV EAX, [RBP+n] ; load n in eax
  541. BSWAP EAX ; swap byte order
  542. #ELSE
  543. unimplemented
  544. #END
  545. END ChangeByteOrder;
  546. #IF I386 THEN
  547. PROCEDURE -GetEAX*(): LONGINT;
  548. CODE
  549. END GetEAX;
  550. PROCEDURE -GetECX*(): LONGINT;
  551. CODE MOV EAX,ECX
  552. END GetECX;
  553. PROCEDURE -SetEAX*(n: LONGINT);
  554. CODE POP EAX
  555. END SetEAX;
  556. PROCEDURE -SetEBX*(n: LONGINT);
  557. CODE POP EBX
  558. END SetEBX;
  559. PROCEDURE -SetECX*(n: LONGINT);
  560. CODE POP ECX
  561. END SetECX;
  562. PROCEDURE -SetEDX*(n: LONGINT);
  563. CODE POP EDX
  564. END SetEDX;
  565. PROCEDURE -SetESI*(n: LONGINT);
  566. CODE POP ESI
  567. END SetESI;
  568. PROCEDURE -SetEDI*(n: LONGINT);
  569. CODE POP EDI
  570. END SetEDI;
  571. PROCEDURE Portin8*(port: LONGINT; VAR val: CHAR);
  572. CODE
  573. MOV EDX, [EBP+port]
  574. IN AL, DX
  575. MOV EBX, [EBP+val]
  576. MOV [EBX], AL
  577. END Portin8;
  578. PROCEDURE Portin16*(port: LONGINT; VAR val: INTEGER);
  579. CODE
  580. MOV EDX, [EBP+port]
  581. IN AX, DX
  582. MOV EBX, [EBP+val]
  583. MOV [EBX], AX
  584. END Portin16;
  585. PROCEDURE Portin32*(port: LONGINT; VAR val: LONGINT);
  586. CODE
  587. MOV EDX, [EBP+port]
  588. IN EAX, DX
  589. MOV EBX, [EBP+val]
  590. MOV [EBX], EAX
  591. END Portin32;
  592. PROCEDURE Portout8*(port: LONGINT; val: CHAR);
  593. CODE
  594. MOV AL, [EBP+val]
  595. MOV EDX, [EBP+port]
  596. OUT DX, AL
  597. END Portout8;
  598. PROCEDURE Portout16*(port: LONGINT; val: INTEGER);
  599. CODE
  600. MOV AX, [EBP+val]
  601. MOV EDX, [EBP+port]
  602. OUT DX, AX
  603. END Portout16;
  604. PROCEDURE Portout32*(port: LONGINT; val: LONGINT);
  605. CODE
  606. MOV EAX, [EBP+val]
  607. MOV EDX, [EBP+port]
  608. OUT DX, EAX
  609. END Portout32;
  610. #ELSIF AMD64 THEN
  611. PROCEDURE -GetRAX*(): HUGEINT;
  612. CODE
  613. END GetRAX;
  614. PROCEDURE -GetRCX*(): HUGEINT;
  615. CODE MOV RAX, RCX
  616. END GetRCX;
  617. PROCEDURE -SetRAX*(n: HUGEINT);
  618. CODE POP RAX
  619. END SetRAX;
  620. PROCEDURE -SetRBX*(n: HUGEINT);
  621. CODE POP RBX
  622. END SetRBX;
  623. PROCEDURE -SetRCX*(n: HUGEINT);
  624. CODE POP RCX
  625. END SetRCX;
  626. PROCEDURE -SetRDX*(n: HUGEINT);
  627. CODE POP RDX
  628. END SetRDX;
  629. PROCEDURE -SetRSI*(n: HUGEINT);
  630. CODE POP RSI
  631. END SetRSI;
  632. PROCEDURE -SetRDI*(n: HUGEINT);
  633. CODE POP EDI
  634. END SetRDI;
  635. PROCEDURE Portin8*(port: LONGINT; VAR val: CHAR);
  636. CODE
  637. MOV EDX, [RBP+port]
  638. IN AL, DX
  639. MOV RCX, [RBP+val]
  640. MOV [RCX], AL
  641. END Portin8;
  642. PROCEDURE Portin16*(port: LONGINT; VAR val: INTEGER);
  643. CODE
  644. MOV EDX, [RBP+port]
  645. IN AX, DX
  646. MOV RCX, [RBP+val]
  647. MOV [RCX], AX
  648. END Portin16;
  649. PROCEDURE Portin32*(port: LONGINT; VAR val: LONGINT);
  650. CODE
  651. MOV EDX, [RBP+port]
  652. IN EAX, DX
  653. MOV RCX, [RBP+val]
  654. MOV [RCX], EAX
  655. END Portin32;
  656. PROCEDURE Portout8*(port: LONGINT; val: CHAR);
  657. CODE
  658. MOV AL, [RBP+val]
  659. MOV EDX, [RBP+port]
  660. OUT DX, AL
  661. END Portout8;
  662. PROCEDURE Portout16*(port: LONGINT; val: INTEGER);
  663. CODE
  664. MOV AX, [RBP+val]
  665. MOV EDX, [RBP+port]
  666. OUT DX, AX
  667. END Portout16;
  668. PROCEDURE Portout32*(port: LONGINT; val: LONGINT);
  669. CODE
  670. MOV EAX, [RBP+val]
  671. MOV EDX, [RBP+port]
  672. OUT DX, EAX
  673. END Portout32;
  674. #END
  675. (* Delay for IO *)
  676. PROCEDURE -Wait*;
  677. CODE
  678. #IF I386 THEN
  679. JMP 0
  680. JMP 0
  681. JMP 0
  682. #ELSIF AMD64 THEN
  683. JMP 0
  684. JMP 0
  685. JMP 0
  686. #ELSE
  687. unimplemented
  688. #END
  689. END Wait;
  690. (** Read a byte from the non-volatile setup memory. *)
  691. PROCEDURE GetNVByte* (ofs: LONGINT): CHAR;
  692. VAR c: CHAR;
  693. BEGIN
  694. Portout8 (70H, CHR(ofs)); Wait; Portin8(71H, c);
  695. RETURN c
  696. END GetNVByte;
  697. (** Write a byte to the non-volatile setup memory. *)
  698. PROCEDURE PutNVByte* (ofs: LONGINT; val: CHAR);
  699. BEGIN
  700. Portout8 (70H, CHR(ofs)); Wait; Portout8 (71H, val)
  701. END PutNVByte;
  702. PROCEDURE InvalidateDCacheRange*(a: ADDRESS; s: SIZE);
  703. BEGIN
  704. END InvalidateDCacheRange;
  705. PROCEDURE FlushDCacheRange*(a: ADDRESS; s: SIZE);
  706. BEGIN
  707. END FlushDCacheRange;
  708. BEGIN
  709. Trace.String("Machine: "); Trace.Blue; Trace.StringLn (Version); Trace.Default;
  710. boottime:=GetTimer();
  711. COPY( Version, version );
  712. END Machine.