Coop.Machine.Mod 17 KB

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