Coop.Machine.Mod 18 KB

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