Coop.Machine.Mod 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  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. PUSH ECX
  172. MOV EDI, [EBP+destAdr]
  173. MOV ECX, [EBP+size]
  174. MOV EAX, [EBP+filler]
  175. TEST ECX, 3
  176. JZ ok
  177. PUSH 8 ; ASSERT failure
  178. INT 3
  179. ok: SHR ECX, 2
  180. CLD
  181. REP STOSD
  182. POP ECX
  183. #ELSIF AMD64 THEN
  184. PUSH RCX
  185. MOV RDI, [RBP + destAdr]
  186. MOV RCX, [RBP + size]
  187. MOV EAX, [RBP + filler]
  188. TEST RCX, 3
  189. JZ ok
  190. PUSH 8 ; ASSERT failure
  191. INT 3
  192. ok: SHR RCX, 2
  193. CLD
  194. REP STOSD
  195. POP RCX
  196. #ELSE
  197. unimplemented
  198. #END
  199. END Fill32;
  200. (** -- Processor initialization -- *)
  201. PROCEDURE -SetFCR( s: SET );
  202. CODE
  203. #IF I386 THEN
  204. FLDCW [ESP] ; parameter s
  205. POP EAX
  206. #ELSIF AMD64 THEN
  207. FLDCW WORD [RSP] ; parameter s
  208. POP RAX
  209. #ELSE
  210. unimplemented
  211. #END
  212. END SetFCR;
  213. PROCEDURE -FCR( ): SET;
  214. CODE
  215. #IF I386 THEN
  216. PUSH 0
  217. FNSTCW [ESP]
  218. FWAIT
  219. POP EAX
  220. #ELSIF AMD64 THEN
  221. PUSH 0
  222. FNSTCW WORD [RSP]
  223. FWAIT
  224. POP RAX
  225. #ELSE
  226. unimplemented
  227. #END
  228. END FCR;
  229. PROCEDURE -InitFPU;
  230. CODE
  231. #IF I386 THEN
  232. FNINIT
  233. #ELSIF AMD64 THEN
  234. FNINIT
  235. #ELSE
  236. unimplemented
  237. #END
  238. END InitFPU;
  239. (** CPU identification. *)
  240. PROCEDURE CPUID*( VAR vendor: Vendor; VAR version: LONGINT; VAR features1,features2: SET );
  241. CODE
  242. #IF I386 THEN
  243. PUSH ECX
  244. MOV EAX, 0
  245. CPUID
  246. CMP EAX, 0
  247. JNE ok
  248. MOV ESI, [EBP+vendor]
  249. MOV [ESI], AL ; AL = 0
  250. MOV ESI, [EBP+version]
  251. MOV [ESI], EAX ; EAX = 0
  252. MOV ESI, [EBP+features1]
  253. MOV [ESI], EAX
  254. MOV ESI, [EBP+features2]
  255. MOV [ESI], EAX
  256. JMP end
  257. ok:
  258. MOV ESI, [EBP+vendor]
  259. MOV [ESI], EBX
  260. MOV [ESI+4], EDX
  261. MOV [ESI+8], ECX
  262. MOV BYTE [ESI+12], 0
  263. MOV EAX, 1
  264. CPUID
  265. MOV ESI, [EBP+version]
  266. MOV [ESI], EAX
  267. MOV ESI, [EBP+features1]
  268. MOV [ESI], EDX
  269. MOV ESI, [EBP+features2]
  270. MOV [ESI], ECX
  271. end:
  272. POP ECX
  273. #ELSIF AMD64 THEN
  274. PUSH RCX
  275. MOV EAX, 0
  276. CPUID
  277. CMP EAX, 0
  278. JNE ok
  279. MOV RSI, [RBP+vendor]
  280. MOV [RSI], AL ; AL = 0
  281. MOV RSI, [RBP+version]
  282. MOV [RSI], EAX ; EAX = 0
  283. MOV RSI, [RBP+features1]
  284. MOV [RSI], EAX
  285. MOV RSI, [RBP+features2]
  286. MOV [RSI], EAX
  287. JMP end
  288. ok:
  289. MOV RSI, [RBP+vendor]
  290. MOV [RSI], EBX
  291. MOV [RSI+4], EDX
  292. MOV [RSI+8], ECX
  293. MOV BYTE [RSI+12], 0
  294. MOV EAX, 1
  295. CPUID
  296. MOV RSI, [RBP+version]
  297. MOV [RSI], EAX
  298. MOV RSI, [RBP+features1]
  299. MOV [RSI], EDX
  300. MOV RSI, [RBP+features2]
  301. MOV [RSI], RCX
  302. end:
  303. POP RCX
  304. #ELSE
  305. unimplemented
  306. #END
  307. END CPUID;
  308. PROCEDURE GetConfig* ( CONST name: ARRAY OF CHAR; VAR val: ARRAY OF CHAR );
  309. PROCEDURE GetString EXTERN "Environment.GetString" ( CONST name: ARRAY OF CHAR; VAR val: ARRAY OF CHAR );
  310. BEGIN GetString (name, val);
  311. END GetConfig;
  312. PROCEDURE Shutdown*( restart: BOOLEAN );
  313. BEGIN
  314. IF restart THEN Environment.Reboot ELSE Environment.Shutdown END;
  315. END Shutdown;
  316. PROCEDURE Cli*;
  317. BEGIN HALT (1234);
  318. END Cli;
  319. PROCEDURE Sti*;
  320. BEGIN HALT (1234);
  321. END Sti;
  322. (* Dan: from new Machine *)
  323. PROCEDURE -GetTimer*(): HUGEINT;
  324. CODE
  325. #IF I386 THEN
  326. RDTSC ; set EDX:EAX
  327. #ELSIF AMD64 THEN
  328. XOR RAX, RAX
  329. RDTSC ; set EDX:EAX
  330. SHL RDX, 32
  331. OR RAX, RDX
  332. #ELSE
  333. unimplemented
  334. #END
  335. END GetTimer;
  336. (** Disable interrupts and return old interrupt state. *)
  337. PROCEDURE -DisableInterrupts* (): SET;
  338. CODE
  339. #IF I386 THEN
  340. PUSHFD
  341. CLI
  342. POP EAX
  343. #ELSIF AMD64 THEN
  344. PUSHFQ
  345. CLI
  346. POP RAX
  347. #ELSE
  348. unimplemented
  349. #END
  350. END DisableInterrupts;
  351. (** Restore interrupt state. Parameter s must be return value of earlier DisableInterrupts call on same processor. *)
  352. PROCEDURE -RestoreInterrupts* (s: SET);
  353. CODE
  354. #IF I386 THEN
  355. POPFD
  356. #ELSIF AMD64 THEN
  357. POPFQ
  358. #ELSE
  359. unimplemented
  360. #END
  361. END RestoreInterrupts;
  362. PROCEDURE ID*(): SIZE;
  363. BEGIN
  364. RETURN Processors.GetCurrentIndex ();
  365. END ID;
  366. (* setup MMX, SSE and SSE2..SSE5 and AVX extension *)
  367. PROCEDURE -InitSSE;
  368. CODE
  369. #IF I386 THEN
  370. MOV EAX, CR4
  371. OR EAX, 00000200H ; set bit 9 (OSFXSR)
  372. AND EAX, 0FFFFFBFFH ; delete bit 10 (OSXMMEXCPT)
  373. MOV CR4, EAX
  374. #ELSIF AMD64 THEN
  375. MOV EAX, CR4
  376. OR EAX, 00000200H ; set bit 9 (OSFXSR)
  377. AND EAX, 0FFFFFBFFH ; delete bit 10 (OSXMMEXCPT)
  378. MOV CR4, EAX
  379. #ELSE
  380. unimplemented
  381. #END
  382. END InitSSE;
  383. PROCEDURE InitBootProcessor-;
  384. CONST
  385. MMXFlag=23;(*IN features from EBX*)
  386. FXSRFlag = 24;
  387. SSEFlag = 25;
  388. SSE2Flag = 26;
  389. SSE3Flag = 0; (*IN features2 from ECX*) (*PH 04/11*)
  390. SSSE3Flag =9;
  391. SSE41Flag =19;
  392. SSE42Flag =20;
  393. SSE5Flag = 11;
  394. AVXFlag = 28;
  395. VAR vendor: Vendor; ver: LONGINT;
  396. BEGIN {UNCOOPERATIVE, UNCHECKED}
  397. CPUID(vendor, ver, features,features2);
  398. MMXSupport := MMXFlag IN features;
  399. SSESupport := SSEFlag IN features;
  400. SSE2Support := SSESupport & (SSE2Flag IN features);
  401. SSE3Support := SSE2Support & (SSE3Flag IN features2);
  402. SSSE3Support := SSE3Support & (SSSE3Flag IN features2); (* PH 04/11*)
  403. SSE41Support := SSE3Support & (SSE41Flag IN features2);
  404. SSE42Support := SSE3Support & (SSE42Flag IN features2);
  405. SSE5Support := SSE3Support & (SSE5Flag IN features2);
  406. AVXSupport := SSE3Support & (AVXFlag IN features2);
  407. fcr := (FCR() - {0,2,3,10,11}) + {0..5,8,9}; (* default FCR RC=00B *)
  408. InitApplicationProcessor;
  409. END InitBootProcessor;
  410. PROCEDURE InitApplicationProcessor-;
  411. BEGIN {UNCOOPERATIVE, UNCHECKED}
  412. InitFPU; SetFCR( fcr );
  413. IF Environment.IsNative & SSESupport THEN
  414. InitSSE();
  415. END;
  416. END InitApplicationProcessor;
  417. (** Acquire a spin-lock. *)
  418. PROCEDURE Acquire*( level: LONGINT ); (* non reentrant lock (non reentrance "ensured" by ASSERT statement ), CriticalSections are reentrant *)
  419. BEGIN
  420. Mutexes.Acquire (mutex[level]);
  421. END Acquire;
  422. (** Release a spin-lock. *)
  423. PROCEDURE Release*( level: LONGINT ); (* release lock *)
  424. BEGIN
  425. Mutexes.Release (mutex[level]);
  426. END Release;
  427. (* returns if an address is a currently allocated heap address *)
  428. PROCEDURE ValidHeapAddress*(p: ADDRESS): BOOLEAN;
  429. BEGIN
  430. RETURN p # NIL;
  431. END ValidHeapAddress;
  432. PROCEDURE GetFreeK* (VAR total, lowFree, highFree: SIZE);
  433. BEGIN
  434. total := 0; lowFree := 0; highFree := 0;
  435. END GetFreeK;
  436. PROCEDURE PhysicalAdr*(adr: ADDRESS; size: SIZE): ADDRESS;
  437. BEGIN RETURN adr;
  438. END PhysicalAdr;
  439. (** -- Atomic operations -- *)
  440. (** Atomic INC(x). *)
  441. PROCEDURE -AtomicInc*( VAR x: LONGINT );
  442. CODE
  443. #IF I386 THEN
  444. POP EAX
  445. LOCK
  446. INC DWORD [EAX]
  447. #ELSIF AMD64 THEN
  448. POP RAX
  449. LOCK
  450. INC DWORD [RAX]
  451. #ELSE
  452. unimplemented
  453. #END
  454. END AtomicInc;
  455. (** Atomic DEC(x). *)
  456. PROCEDURE -AtomicDec*( VAR x: LONGINT );
  457. CODE
  458. #IF I386 THEN
  459. POP EAX
  460. LOCK
  461. DEC DWORD [EAX]
  462. #ELSIF AMD64 THEN
  463. POP RAX
  464. LOCK
  465. DEC DWORD [RAX]
  466. #ELSE
  467. unimplemented
  468. #END
  469. END AtomicDec;
  470. (** Atomic INC(x, y). *)
  471. PROCEDURE -AtomicAdd*( VAR x: LONGINT; y: LONGINT );
  472. CODE
  473. #IF I386 THEN
  474. POP EBX
  475. POP EAX
  476. LOCK
  477. ADD DWORD [EAX], EBX
  478. #ELSIF AMD64 THEN
  479. POP EBX
  480. POP RAX
  481. LOCK
  482. ADD DWORD [RAX], EBX
  483. #ELSE
  484. unimplemented
  485. #END
  486. END AtomicAdd;
  487. (** Atomic test-and-set. Set x = TRUE and return old value of x. *)
  488. PROCEDURE -AtomicTestSet*( VAR x: BOOLEAN ): BOOLEAN;
  489. CODE
  490. #IF I386 THEN
  491. POP EBX
  492. MOV AL, 1
  493. XCHG [EBX], AL
  494. #ELSIF AMD64 THEN
  495. POP RBX
  496. MOV AL, 1
  497. XCHG [RBX], AL
  498. #ELSE
  499. unimplemented
  500. #END
  501. END AtomicTestSet;
  502. (* Atomic compare-and-swap. Set x = new if x = old and return old value of x *)
  503. PROCEDURE -AtomicCAS* (VAR x: LONGINT; old, new: LONGINT): LONGINT;
  504. CODE
  505. #IF I386 THEN
  506. POP EBX ; new
  507. POP EAX ; old
  508. POP EDX ; address of x
  509. LOCK CMPXCHG [EDX], EBX ; atomicly compare x with old and set it to new if equal
  510. #ELSIF AMD64 THEN
  511. POP EBX ; new
  512. POP EAX ; old
  513. POP RDX ; address of x
  514. LOCK CMPXCHG [RDX], EBX ; atomicly compare x with old and set it to new if equal
  515. #ELSE
  516. unimplemented
  517. #END
  518. END AtomicCAS;
  519. (* function returning the number of processors that are available to Aos *)
  520. PROCEDURE NumberOfProcessors*( ): SIZE;
  521. BEGIN
  522. RETURN Processors.count;
  523. END NumberOfProcessors;
  524. (* function for changing byte order *)
  525. PROCEDURE ChangeByteOrder* (n: LONGINT): LONGINT;
  526. CODE
  527. #IF I386 THEN
  528. MOV EAX, [EBP+n] ; load n in eax
  529. BSWAP EAX ; swap byte order
  530. #ELSIF AMD64 THEN
  531. MOV EAX, [RBP+n] ; load n in eax
  532. BSWAP EAX ; swap byte order
  533. #ELSE
  534. unimplemented
  535. #END
  536. END ChangeByteOrder;
  537. #IF I386 THEN
  538. PROCEDURE -GetEAX*(): LONGINT;
  539. CODE
  540. END GetEAX;
  541. PROCEDURE -GetECX*(): LONGINT;
  542. CODE MOV EAX,ECX
  543. END GetECX;
  544. PROCEDURE -SetEAX*(n: LONGINT);
  545. CODE POP EAX
  546. END SetEAX;
  547. PROCEDURE -SetEBX*(n: LONGINT);
  548. CODE POP EBX
  549. END SetEBX;
  550. PROCEDURE -SetECX*(n: LONGINT);
  551. CODE POP ECX
  552. END SetECX;
  553. PROCEDURE -SetEDX*(n: LONGINT);
  554. CODE POP EDX
  555. END SetEDX;
  556. PROCEDURE -SetESI*(n: LONGINT);
  557. CODE POP ESI
  558. END SetESI;
  559. PROCEDURE -SetEDI*(n: LONGINT);
  560. CODE POP EDI
  561. END SetEDI;
  562. PROCEDURE Portin8*(port: LONGINT; VAR val: CHAR);
  563. CODE
  564. MOV EDX, [EBP+port]
  565. IN AL, DX
  566. MOV EBX, [EBP+val]
  567. MOV [EBX], AL
  568. END Portin8;
  569. PROCEDURE Portin16*(port: LONGINT; VAR val: INTEGER);
  570. CODE
  571. MOV EDX, [EBP+port]
  572. IN AX, DX
  573. MOV EBX, [EBP+val]
  574. MOV [EBX], AX
  575. END Portin16;
  576. PROCEDURE Portin32*(port: LONGINT; VAR val: LONGINT);
  577. CODE
  578. MOV EDX, [EBP+port]
  579. IN EAX, DX
  580. MOV EBX, [EBP+val]
  581. MOV [EBX], EAX
  582. END Portin32;
  583. PROCEDURE Portout8*(port: LONGINT; val: CHAR);
  584. CODE
  585. MOV AL, [EBP+val]
  586. MOV EDX, [EBP+port]
  587. OUT DX, AL
  588. END Portout8;
  589. PROCEDURE Portout16*(port: LONGINT; val: INTEGER);
  590. CODE
  591. MOV AX, [EBP+val]
  592. MOV EDX, [EBP+port]
  593. OUT DX, AX
  594. END Portout16;
  595. PROCEDURE Portout32*(port: LONGINT; val: LONGINT);
  596. CODE
  597. MOV EAX, [EBP+val]
  598. MOV EDX, [EBP+port]
  599. OUT DX, EAX
  600. END Portout32;
  601. #ELSIF AMD64 THEN
  602. PROCEDURE -GetRAX*(): HUGEINT;
  603. CODE
  604. END GetRAX;
  605. PROCEDURE -GetRCX*(): HUGEINT;
  606. CODE MOV RAX, RCX
  607. END GetRCX;
  608. PROCEDURE -SetRAX*(n: HUGEINT);
  609. CODE POP RAX
  610. END SetRAX;
  611. PROCEDURE -SetRBX*(n: HUGEINT);
  612. CODE POP RBX
  613. END SetRBX;
  614. PROCEDURE -SetRCX*(n: HUGEINT);
  615. CODE POP RCX
  616. END SetRCX;
  617. PROCEDURE -SetRDX*(n: HUGEINT);
  618. CODE POP RDX
  619. END SetRDX;
  620. PROCEDURE -SetRSI*(n: HUGEINT);
  621. CODE POP RSI
  622. END SetRSI;
  623. PROCEDURE -SetRDI*(n: HUGEINT);
  624. CODE POP EDI
  625. END SetRDI;
  626. PROCEDURE Portin8*(port: LONGINT; VAR val: CHAR);
  627. CODE
  628. MOV EDX, [RBP+port]
  629. IN AL, DX
  630. MOV RBX, [RBP+val]
  631. MOV [RBX], AL
  632. END Portin8;
  633. PROCEDURE Portin16*(port: LONGINT; VAR val: INTEGER);
  634. CODE
  635. MOV EDX, [RBP+port]
  636. IN AX, DX
  637. MOV RBX, [RBP+val]
  638. MOV [RBX], AX
  639. END Portin16;
  640. PROCEDURE Portin32*(port: LONGINT; VAR val: LONGINT);
  641. CODE
  642. MOV EDX, [RBP+port]
  643. IN EAX, DX
  644. MOV RBX, [RBP+val]
  645. MOV [RBX], EAX
  646. END Portin32;
  647. PROCEDURE Portout8*(port: LONGINT; val: CHAR);
  648. CODE
  649. MOV AL, [RBP+val]
  650. MOV EDX, [RBP+port]
  651. OUT DX, AL
  652. END Portout8;
  653. PROCEDURE Portout16*(port: LONGINT; val: INTEGER);
  654. CODE
  655. MOV AX, [RBP+val]
  656. MOV EDX, [RBP+port]
  657. OUT DX, AX
  658. END Portout16;
  659. PROCEDURE Portout32*(port: LONGINT; val: LONGINT);
  660. CODE
  661. MOV EAX, [RBP+val]
  662. MOV EDX, [RBP+port]
  663. OUT DX, EAX
  664. END Portout32;
  665. #END
  666. (* Delay for IO *)
  667. PROCEDURE -Wait*;
  668. CODE
  669. #IF I386 THEN
  670. JMP 0
  671. JMP 0
  672. JMP 0
  673. #ELSIF AMD64 THEN
  674. JMP 0
  675. JMP 0
  676. JMP 0
  677. #ELSE
  678. unimplemented
  679. #END
  680. END Wait;
  681. (** Read a byte from the non-volatile setup memory. *)
  682. PROCEDURE GetNVByte* (ofs: LONGINT): CHAR;
  683. VAR c: CHAR;
  684. BEGIN
  685. Portout8 (70H, CHR(ofs)); Wait; Portin8(71H, c);
  686. RETURN c
  687. END GetNVByte;
  688. (** Write a byte to the non-volatile setup memory. *)
  689. PROCEDURE PutNVByte* (ofs: LONGINT; val: CHAR);
  690. BEGIN
  691. Portout8 (70H, CHR(ofs)); Wait; Portout8 (71H, val)
  692. END PutNVByte;
  693. PROCEDURE InvalidateDCacheRange*(a: ADDRESS; s: SIZE);
  694. BEGIN
  695. END InvalidateDCacheRange;
  696. PROCEDURE FlushDCacheRange*(a: ADDRESS; s: SIZE);
  697. BEGIN
  698. END FlushDCacheRange;
  699. BEGIN
  700. Trace.String("Machine: "); Trace.Blue; Trace.StringLn (Version); Trace.Default;
  701. boottime:=GetTimer();
  702. COPY( Version, version );
  703. END Machine.