Coop.Machine.Mod 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  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. MaxLocks = 9; (* { <= 32 } *)
  22. (* error codes *)
  23. Ok* = 0;
  24. NilAdr* = -1; (* nil value for addresses (not same as pointer NIL value) *)
  25. IRQ0* = CPU.IRQ0;
  26. MaxIRQ* = CPU.IRQ15;
  27. TYPE
  28. Vendor* = ARRAY 13 OF CHAR;
  29. IDMap* = ARRAY 16 OF SHORTINT;
  30. Range* = RECORD
  31. adr*, size*: LONGINT
  32. END;
  33. MemoryBlock* = POINTER TO MemoryBlockDesc;
  34. MemoryBlockDesc* = RECORD
  35. next- {UNTRACED}: MemoryBlock;
  36. startAdr-: ADDRESS; (* sort key in linked list of memory blocks *)
  37. size-: SIZE;
  38. beginBlockAdr-, endBlockAdr-: ADDRESS
  39. END;
  40. (* dummy definition to make GC work for both I386 and Win32 - copied from I386.Machine.Mod, but not really used *)
  41. Stack* = RECORD (** values are read-only *)
  42. low: ADDRESS; (* lowest virtual address that may be allocated for stack *)
  43. adr*: ADDRESS; (* lowest address on allocated stack *) (* exported for Objects only *)
  44. high*: ADDRESS; (* next virtual address after stack *) (* exported for Objects only *)
  45. END;
  46. Address32* = LONGINT;
  47. VAR
  48. MMXSupport*: BOOLEAN;
  49. SSESupport*: BOOLEAN;
  50. SSE2Support*: BOOLEAN;
  51. SSE3Support-: BOOLEAN; (* PH 04/11*)
  52. SSSE3Support-: BOOLEAN;
  53. SSE41Support-: BOOLEAN;
  54. SSE42Support-: BOOLEAN;
  55. SSE5Support-: BOOLEAN;
  56. AVXSupport-: BOOLEAN;
  57. version*: ARRAY 64 OF CHAR; (** Aos version *)
  58. features*,features2*: SET; (** processor features *)
  59. fcr*: SET; (** default floating-point control register value (default rounding mode is towards -infinity, for ENTIER) *)
  60. mhz*: HUGEINT; (** clock rate of GetTimer() in MHz, or 0 if not known *)
  61. boottime-: HUGEINT; (** in timer units *)
  62. VAR
  63. lock-: ARRAY MaxLocks OF CHAR; (* not implemented as SET because of shared access *)
  64. mutex: ARRAY MaxLocks OF Mutexes.Mutex;
  65. memBlockHead-{UNTRACED}, memBlockTail-{UNTRACED}: MemoryBlock; (* head and tail of sorted list of memory blocks *)
  66. (** 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. *)
  67. PROCEDURE StrToInt*( VAR i: LONGINT; CONST s: ARRAY OF CHAR ): LONGINT;
  68. VAR vd, vh, sgn, d: LONGINT; hex: BOOLEAN;
  69. BEGIN
  70. vd := 0; vh := 0; hex := FALSE;
  71. IF s[i] = "-" THEN sgn := -1; INC( i ) ELSE sgn := 1 END;
  72. LOOP
  73. IF (s[i] >= "0") & (s[i] <= "9") THEN d := ORD( s[i] ) - ORD( "0" )
  74. ELSIF (CAP( s[i] ) >= "A") & (CAP( s[i] ) <= "F") THEN d := ORD( CAP( s[i] ) ) - ORD( "A" ) + 10; hex := TRUE
  75. ELSE EXIT
  76. END;
  77. vd := 10 * vd + d; vh := 16 * vh + d; INC( i )
  78. END;
  79. IF CAP( s[i] ) = "H" THEN hex := TRUE; INC( i ) END; (* optional H *)
  80. IF hex THEN vd := vh END;
  81. RETURN sgn * vd
  82. END StrToInt;
  83. (** -- Atomic operations -- *)
  84. (** Atomic INC with one parameter. *)
  85. PROCEDURE -Inc*( VAR x: LONGINT );
  86. CODE {SYSTEM.i386}
  87. POP EAX
  88. LOCK
  89. INC DWORD[EAX]
  90. END Inc;
  91. (** Atomic EXCL. *)
  92. PROCEDURE Excl*( VAR s: SET; bit: LONGINT );
  93. CODE {SYSTEM.i386}
  94. MOV EAX, [EBP+bit]
  95. MOV EBX, [EBP+s]
  96. LOCK
  97. BTR [EBX], EAX
  98. END Excl;
  99. (** -- Miscellaneous -- *)
  100. (** This procedure should be called in all spin loops as a hint to the processor (e.g. Pentium 4). *)
  101. PROCEDURE -SpinHint*;
  102. CODE {SYSTEM.i386}
  103. REP NOP ; PAUSE instruction (* NOP on pre-P4 processors, Spin Loop Hint on P4 and after *)
  104. END SpinHint;
  105. (* Return current instruction pointer *)
  106. PROCEDURE CurrentPC* (): ADDRESS;
  107. CODE {SYSTEM.i386}
  108. MOV EAX, [EBP+4]
  109. END CurrentPC;
  110. (* Return current frame pointer *)
  111. PROCEDURE -CurrentBP* (): ADDRESS;
  112. CODE {SYSTEM.i386}
  113. MOV EAX, EBP
  114. END CurrentBP;
  115. (* Set current frame pointer *)
  116. PROCEDURE -SetBP* (bp: ADDRESS);
  117. CODE {SYSTEM.i386}
  118. POP EBP
  119. END SetBP;
  120. (* Return current stack pointer *)
  121. PROCEDURE -CurrentSP* (): ADDRESS;
  122. CODE {SYSTEM.i386}
  123. MOV EAX, ESP
  124. END CurrentSP;
  125. (* Set current stack pointer *)
  126. PROCEDURE -SetSP* (sp: ADDRESS);
  127. CODE {SYSTEM.i386}
  128. POP ESP
  129. END SetSP;
  130. PROCEDURE MapPhysical*(physAdr: ADDRESS; size: SIZE; VAR virtAdr: ADDRESS);
  131. BEGIN
  132. virtAdr := physAdr;
  133. END MapPhysical;
  134. (** Unmap an area previously mapped with MapPhysical. *)
  135. PROCEDURE UnmapPhysical*(virtAdr: ADDRESS; size: SIZE);
  136. END UnmapPhysical;
  137. (** Translate a virtual address range to num ranges of physical address. num returns 0 on error. *)
  138. PROCEDURE TranslateVirtual*(virtAdr: ADDRESS; size: SIZE; VAR num: LONGINT; VAR physAdr: ARRAY OF Range);
  139. CONST PS = 4096;
  140. VAR ofs, phys1: ADDRESS; size1: SIZE;
  141. BEGIN
  142. num := 0;
  143. LOOP
  144. IF size = 0 THEN EXIT END;
  145. IF num = LEN(physAdr) THEN num := 0; EXIT END; (* index check *)
  146. ofs := virtAdr MOD PS; (* offset in page *)
  147. size1 := PS - ofs; (* distance to next page boundary *)
  148. IF size1 > size THEN size1 := size END;
  149. phys1 := virtAdr - ofs;
  150. physAdr[num].adr := phys1 - phys1 MOD PS + ofs;
  151. physAdr[num].size := size1; INC(num);
  152. INC(virtAdr, size1); DEC(size, size1)
  153. END;
  154. IF num = 0 THEN physAdr[0].adr := NilAdr; physAdr[0].size := 0 END;
  155. END TranslateVirtual;
  156. PROCEDURE Ensure32BitAddress*(adr: ADDRESS): Address32;
  157. BEGIN
  158. ASSERT (Address32 (adr) = adr);
  159. RETURN Address32 (adr);
  160. END Ensure32BitAddress;
  161. PROCEDURE Is32BitAddress*(adr: ADDRESS): BOOLEAN;
  162. BEGIN RETURN Address32 (adr) = adr;
  163. END Is32BitAddress;
  164. (** 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. *)
  165. PROCEDURE GetInit* (n: LONGINT; VAR val: LONGINT);
  166. BEGIN Environment.GetInit (n, val);
  167. END GetInit;
  168. (** Fill "size" bytes at "destAdr" with "filler". "size" must be multiple of 4. *)
  169. PROCEDURE Fill32*( destAdr, size, filler: LONGINT );
  170. CODE {SYSTEM.i386}
  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:
  180. SHR ECX, 2
  181. CLD
  182. REP STOSD
  183. POP ECX
  184. END Fill32;
  185. (** -- HUGEINT operations -- *)
  186. (** Return h*g. *)
  187. (** Return h*g. based on code from "AMD Athlon Processor x86 code optimization guide" *)
  188. PROCEDURE MulH* (h, g: HUGEINT): HUGEINT;
  189. CODE {SYSTEM.i386}
  190. PUSH ECX
  191. MOV EDX, [EBP+12] ; y_hi
  192. MOV ECX, [EBP+20] ; x_hi
  193. OR EDX, ECX ; are x_hi and y_hi both zeros?
  194. MOV EDX, [EBP+16] ; x_lo
  195. MOV EAX, [EBP+8] ; y_lo
  196. JNZ fullMul ; yes, requires full multiplication
  197. MUL EDX ; EDX:EAX := y_lo * x_lo
  198. JMP exit ; done, return to caller
  199. fullMul: ; full multiplication is required
  200. MUL ECX ; EAX := LO(y_lo*x_hi)
  201. MOV EBX, EAX ; keep the result
  202. MOV EAX, [EBP+12] ; y_hi
  203. MUL DWORD [EBP+16] ; EAX := LO(y_hi*x_lo)
  204. ADD EBX, EAX ; EBX := LO(y_lo*x_hi) + LO(y_hi*x_lo)
  205. MOV EAX, [EBP+8] ; y_lo
  206. MUL DWORD [EBP+16] ; EDX := HI(y_lo*x_lo), EAX := LO(y_lo*x_lo)
  207. ADD EDX, EBX ; EDX := y_lo*x_hi + y_hi*x_lo + HI(y_lo*x_lo)
  208. exit:
  209. POP ECX
  210. END MulH;
  211. (** Return h DIV g. Rounding and division by zero behaviour is currently undefined. *)
  212. PROCEDURE DivH* (x, y: HUGEINT): HUGEINT;
  213. CODE {SYSTEM.i386}
  214. PUSH ECX
  215. MOV ECX, [EBP+12] ; y-hi
  216. MOV EBX, [EBP+8] ; y-lo
  217. MOV EDX, [EBP+20] ; x-hi
  218. MOV EAX, [EBP+16] ; x-lo
  219. MOV ESI, ECX ; y-hi
  220. XOR ESI, EDX ; y-hi ^ x-hi
  221. SAR ESI, 31 ; (quotient < 0) ? -1 : 0
  222. MOV EDI, EDX ; x-hi
  223. SAR EDI, 31 ; (x < 0) ? -1 : 0
  224. XOR EAX, EDI ; if (x < 0)
  225. XOR EDX, EDI ; compute 1s complement of x
  226. SUB EAX, EDI ; if (x < 0)
  227. SBB EDX, EDI ; compute 2s complement of x
  228. MOV EDI, ECX ; y-hi
  229. SAR EDI, 31 ; (y < 0) ? -1 : 0
  230. XOR EBX, EDI ; if (y < 0)
  231. XOR ECX, EDI ; compute 1s complement of y
  232. SUB EBX, EDI ; if (y < 0)
  233. SBB ECX, EDI ; compute 2s complement of y
  234. JNZ bigDivisor ; y > 2^32-1
  235. CMP EDX, EBX ; only one division needed ? (ECX = 0)
  236. JAE twoDivs ; need two divisions
  237. DIV EBX ; EAX = quotient-lo
  238. MOV EDX, ECX ; EDX = quotient-hi = 0
  239. ; quotient in EDX:EAX
  240. XOR EAX, ESI ; if (quotient < 0)
  241. XOR EDX, ESI ; compute 1s complement of result
  242. SUB EAX, ESI ; if (quotient < 0)
  243. SBB EDX, ESI ; compute 2s complement of result
  244. JMP exit ; done, return to caller
  245. twoDivs:
  246. MOV ECX, EAX ; save x-lo in ECX
  247. MOV EAX, EDX ; get x-hi
  248. XOR EDX, EDX ; zero extend it into EDX:EAX
  249. DIV EBX ; quotient-hi in EAX
  250. XCHG EAX, ECX ; ECX = quotient-hi, EAX = x-lo
  251. DIV EBX ; EAX = quotient-lo
  252. MOV EDX, ECX ; EDX = quotient-hi
  253. ; quotient in EDX:EAX
  254. JMP makeSign ; make quotient signed
  255. bigDivisor:
  256. SUB ESP, 12 ; create three local variables
  257. MOV [ESP], EAX ; x-lo
  258. MOV [ESP+4], EBX ; y-lo
  259. MOV [ESP+8], EDX ; x-hi
  260. MOV EDI, ECX ; save y-hi
  261. SHR EDX, 1 ; shift both
  262. RCR EAX, 1 ; y and
  263. ROR EDI, 1 ; and x
  264. RCR EBX, 1 ; right by 1 bit
  265. BSR ECX, ECX ; ECX = number of remaining shifts
  266. SHRD EBX, EDI, CL ; scale down y and
  267. SHRD EAX, EDX, CL ; x such that y
  268. SHR EDX, CL ; less than 2^32 (i.e. fits in EBX)
  269. ROL EDI, 1 ; restore original y-hi
  270. DIV EBX ; compute quotient
  271. MOV EBX, [ESP] ; x-lo
  272. MOV ECX, EAX ; save quotient
  273. IMUL EDI, EAX ; quotient * y hi-word (low only)
  274. MUL DWORD [ESP+4] ; quotient * y lo-word
  275. ADD EDX, EDI ; EDX:EAX = quotient * y
  276. SUB EBX, EAX ; x-lo - (quot.*y)-lo
  277. MOV EAX, ECX ; get quotient
  278. MOV ECX, [ESP+8] ; x-hi
  279. SBB ECX, EDX ; subtract y * quot. from x
  280. SBB EAX, 0 ; adjust quotient if remainder negative
  281. XOR EDX, EDX ; clear hi-word of quotient
  282. ADD ESP, 12 ; remove local variables
  283. makeSign:
  284. XOR EAX, ESI ; if (quotient < 0)
  285. XOR EDX, ESI ; compute 1s complement of result
  286. SUB EAX, ESI ; if (quotient < 0)
  287. SBB EDX, ESI ; compute 2s complement of result
  288. exit:
  289. POP ECX
  290. END DivH;
  291. (** Return ASH(h, n). *)
  292. PROCEDURE -ASHH*( h: HUGEINT; n: LONGINT ): HUGEINT;
  293. CODE {SYSTEM.i386}
  294. POP EBX
  295. POP EAX
  296. POP EDX
  297. CMP EBX, 0
  298. JL right
  299. AND EBX, 63 ; limit count, like ASH
  300. JZ exit
  301. ll:
  302. SHL EAX, 1
  303. RCL EDX, 1
  304. DEC EBX
  305. JNZ ll
  306. JMP exit
  307. right:
  308. NEG EBX
  309. AND EBX, 63 ; limit count, like ASH
  310. JZ exit
  311. lr:
  312. SAR EDX, 1
  313. RCR EAX, 1
  314. DEC EBX
  315. JNZ lr
  316. exit:
  317. END ASHH;
  318. (** Return a HUGEINT composed of high and low. *)
  319. PROCEDURE -LInt2ToHInt*( high, low: LONGINT ): HUGEINT;
  320. CODE {SYSTEM.i386}
  321. POP EAX
  322. POP EDX
  323. END LInt2ToHInt;
  324. (** Return h as a LONGREAL, with possible loss of precision. *)
  325. PROCEDURE -HIntToLReal*( h: HUGEINT ): LONGREAL;
  326. CODE {SYSTEM.i386, SYSTEM.FPU}
  327. FILD QWORD[ESP]
  328. FWAIT
  329. ADD ESP, 8
  330. END HIntToLReal;
  331. (** -- Processor initialization -- *)
  332. PROCEDURE -SetFCR( s: SET );
  333. CODE {SYSTEM.i386, SYSTEM.FPU}
  334. FLDCW [ESP] ; parameter s
  335. POP EAX
  336. END SetFCR;
  337. PROCEDURE -FCR( ): SET;
  338. CODE {SYSTEM.i386, SYSTEM.FPU}
  339. PUSH 0
  340. FNSTCW [ESP]
  341. FWAIT
  342. POP EAX
  343. END FCR;
  344. PROCEDURE -InitFPU;
  345. CODE {SYSTEM.i386, SYSTEM.FPU}
  346. FNINIT
  347. END InitFPU;
  348. (** CPU identification. *)
  349. PROCEDURE CPUID*( VAR vendor: Vendor; VAR version: LONGINT; VAR features1,features2: SET );
  350. CODE {SYSTEM.i386, SYSTEM.Pentium}
  351. PUSH ECX
  352. MOV EAX, 0
  353. CPUID
  354. CMP EAX, 0
  355. JNE ok
  356. MOV ESI, [EBP+vendor]
  357. MOV [ESI], AL ; AL = 0
  358. MOV ESI, [EBP+version]
  359. MOV [ESI], EAX ; EAX = 0
  360. MOV ESI, [EBP+features1]
  361. MOV [ESI], EAX
  362. MOV ESI, [EBP+features2]
  363. MOV [ESI], EAX
  364. JMP end
  365. ok:
  366. MOV ESI, [EBP+vendor]
  367. MOV [ESI], EBX
  368. MOV [ESI+4], EDX
  369. MOV [ESI+8], ECX
  370. MOV BYTE [ESI+12], 0
  371. MOV EAX, 1
  372. CPUID
  373. MOV ESI, [EBP+version]
  374. MOV [ESI], EAX
  375. MOV ESI, [EBP+features1]
  376. MOV [ESI], EDX
  377. MOV ESI, [EBP+features2]
  378. MOV [ESI], ECX
  379. end:
  380. POP ECX
  381. END CPUID;
  382. PROCEDURE GetConfig* ( CONST name: ARRAY OF CHAR; VAR val: ARRAY OF CHAR );
  383. PROCEDURE GetString EXTERN "Environment.GetString" ( CONST name: ARRAY OF CHAR; VAR val: ARRAY OF CHAR );
  384. BEGIN GetString (name, val);
  385. END GetConfig;
  386. PROCEDURE Shutdown*( restart: BOOLEAN );
  387. BEGIN
  388. IF restart THEN Environment.Reboot ELSE Environment.Shutdown END;
  389. END Shutdown;
  390. PROCEDURE Cli*;
  391. BEGIN HALT (1234);
  392. END Cli;
  393. PROCEDURE Sti*;
  394. BEGIN HALT (1234);
  395. END Sti;
  396. (* Dan: from new Machine *)
  397. PROCEDURE -GetTimer*(): HUGEINT;
  398. CODE {SYSTEM.Pentium}
  399. RDTSC ; set EDX:EAX
  400. END GetTimer;
  401. (** Disable interrupts and return old interrupt state. *)
  402. PROCEDURE -DisableInterrupts* (): SET;
  403. CODE {SYSTEM.i386}
  404. PUSHFD
  405. CLI
  406. POP EAX
  407. END DisableInterrupts;
  408. (** Restore interrupt state. Parameter s must be return value of earlier DisableInterrupts call on same processor. *)
  409. PROCEDURE -RestoreInterrupts* (s: SET);
  410. CODE {SYSTEM.i386}
  411. POPFD
  412. END RestoreInterrupts;
  413. PROCEDURE ID*(): LONGINT;
  414. BEGIN
  415. RETURN Processors.GetCurrentIndex ();
  416. END ID;
  417. (* setup MMX, SSE and SSE2..SSE5 and AVX extension *)
  418. PROCEDURE -InitSSE;
  419. CODE {SYSTEM.Pentium, SYSTEM.Privileged}
  420. MOV EAX, CR4
  421. OR EAX, 00000200H ; set bit 9 (OSFXSR)
  422. AND EAX, 0FFFFFBFFH ; delete bit 10 (OSXMMEXCPT)
  423. MOV CR4, EAX
  424. END InitSSE;
  425. PROCEDURE InitBootProcessor-;
  426. CONST
  427. MMXFlag=23;(*IN features from EBX*)
  428. FXSRFlag = 24;
  429. SSEFlag = 25;
  430. SSE2Flag = 26;
  431. SSE3Flag = 0; (*IN features2 from ECX*) (*PH 04/11*)
  432. SSSE3Flag =9;
  433. SSE41Flag =19;
  434. SSE42Flag =20;
  435. SSE5Flag = 11;
  436. AVXFlag = 28;
  437. VAR vendor: Vendor; ver: LONGINT;
  438. BEGIN {UNCOOPERATIVE, UNCHECKED}
  439. CPUID(vendor, ver, features,features2);
  440. MMXSupport := MMXFlag IN features;
  441. SSESupport := SSEFlag IN features;
  442. SSE2Support := SSESupport & (SSE2Flag IN features);
  443. SSE3Support := SSE2Support & (SSE3Flag IN features2);
  444. SSSE3Support := SSE3Support & (SSSE3Flag IN features2); (* PH 04/11*)
  445. SSE41Support := SSE3Support & (SSE41Flag IN features2);
  446. SSE42Support := SSE3Support & (SSE42Flag IN features2);
  447. SSE5Support := SSE3Support & (SSE5Flag IN features2);
  448. AVXSupport := SSE3Support & (AVXFlag IN features2);
  449. fcr := (FCR() - {0,2,3,10,11}) + {0..5,8,9}; (* default FCR RC=00B *)
  450. InitApplicationProcessor;
  451. END InitBootProcessor;
  452. PROCEDURE InitApplicationProcessor-;
  453. BEGIN {UNCOOPERATIVE, UNCHECKED}
  454. InitFPU; SetFCR( fcr );
  455. IF Environment.IsNative & SSESupport THEN
  456. InitSSE();
  457. END;
  458. END InitApplicationProcessor;
  459. (** Acquire a spin-lock. *)
  460. PROCEDURE Acquire*( level: LONGINT ); (* non reentrant lock (non reentrance "ensured" by ASSERT statement ), CriticalSections are reentrant *)
  461. BEGIN
  462. Mutexes.Acquire (mutex[level]);
  463. END Acquire;
  464. (** Release a spin-lock. *)
  465. PROCEDURE Release*( level: LONGINT ); (* release lock *)
  466. BEGIN
  467. Mutexes.Release (mutex[level]);
  468. END Release;
  469. (* returns if an address is a currently allocated heap address *)
  470. PROCEDURE ValidHeapAddress*(p: ADDRESS): BOOLEAN;
  471. BEGIN
  472. RETURN p # NIL;
  473. END ValidHeapAddress;
  474. PROCEDURE GetFreeK* (VAR total, lowFree, highFree: SIZE);
  475. BEGIN
  476. total := 0; lowFree := 0; highFree := 0;
  477. END GetFreeK;
  478. PROCEDURE PhysicalAdr*(adr: ADDRESS; size: SIZE): ADDRESS;
  479. BEGIN RETURN adr;
  480. END PhysicalAdr;
  481. (** -- Atomic operations -- *)
  482. (** Atomic INC(x). *)
  483. PROCEDURE -AtomicInc*( VAR x: LONGINT );
  484. CODE {SYSTEM.i386}
  485. POP EAX
  486. LOCK
  487. INC DWORD[EAX]
  488. END AtomicInc;
  489. (** Atomic DEC(x). *)
  490. PROCEDURE -AtomicDec*( VAR x: LONGINT );
  491. CODE {SYSTEM.i386}
  492. POP EAX
  493. LOCK
  494. DEC DWORD[EAX]
  495. END AtomicDec;
  496. (** Atomic INC(x, y). *)
  497. PROCEDURE -AtomicAdd*( VAR x: LONGINT; y: LONGINT );
  498. CODE {SYSTEM.i386}
  499. POP EBX
  500. POP EAX
  501. LOCK
  502. ADD DWORD[EAX], EBX
  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 {SYSTEM.i386}
  507. POP EBX
  508. MOV AL, 1
  509. XCHG [EBX], AL
  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 {SYSTEM.i386}
  514. POP EBX ; new
  515. POP EAX ; old
  516. POP EDX ; address of x
  517. DB 0F0X, 00FX, 0B1X, 01AX ; LOCK CMPXCHG [EDX], EBX; atomicly compare x with old and set it to new if equal
  518. END AtomicCAS;
  519. (* function returning the number of processors that are available to Aos *)
  520. PROCEDURE NumberOfProcessors*( ): LONGINT;
  521. BEGIN
  522. RETURN Processors.count;
  523. END NumberOfProcessors;
  524. (* function for changing byte order *)
  525. PROCEDURE ChangeByteOrder* (n: LONGINT): LONGINT;
  526. CODE { SYSTEM.Pentium }
  527. MOV EAX, [EBP+n] ; load n in eax
  528. BSWAP EAX ; swap byte order
  529. END ChangeByteOrder;
  530. PROCEDURE -GetEAX*(): LONGINT;
  531. CODE{SYSTEM.i386}
  532. END GetEAX;
  533. PROCEDURE -GetECX*(): LONGINT;
  534. CODE{SYSTEM.i386}
  535. MOV EAX,ECX
  536. END GetECX;
  537. PROCEDURE -SetEAX*(n: LONGINT);
  538. CODE{SYSTEM.i386} POP EAX
  539. END SetEAX;
  540. PROCEDURE -SetEBX*(n: LONGINT);
  541. CODE{SYSTEM.i386}
  542. POP EBX
  543. END SetEBX;
  544. PROCEDURE -SetECX*(n: LONGINT);
  545. CODE{SYSTEM.i386}
  546. POP ECX
  547. END SetECX;
  548. PROCEDURE -SetEDX*(n: LONGINT);
  549. CODE{SYSTEM.i386}
  550. POP EDX
  551. END SetEDX;
  552. PROCEDURE -SetESI*(n: LONGINT);
  553. CODE{SYSTEM.i386}
  554. POP ESI
  555. END SetESI;
  556. PROCEDURE -SetEDI*(n: LONGINT);
  557. CODE{SYSTEM.i386}
  558. POP EDI
  559. END SetEDI;
  560. PROCEDURE Portin8*(port: LONGINT; VAR val: CHAR);
  561. CODE{SYSTEM.i386}
  562. MOV EDX,[EBP+port]
  563. IN AL, DX
  564. MOV EBX, [EBP+val]
  565. MOV [EBX], AL
  566. END Portin8;
  567. PROCEDURE Portin16*(port: LONGINT; VAR val: INTEGER);
  568. CODE{SYSTEM.i386}
  569. MOV EDX,[EBP+port]
  570. IN AX, DX
  571. MOV EBX, [EBP+val]
  572. MOV [EBX], AX
  573. END Portin16;
  574. PROCEDURE Portin32*(port: LONGINT; VAR val: LONGINT);
  575. CODE{SYSTEM.i386}
  576. MOV EDX,[EBP+port]
  577. IN EAX, DX
  578. MOV EBX, [EBP+val]
  579. MOV [EBX], EAX
  580. END Portin32;
  581. PROCEDURE Portout8*(port: LONGINT; val: CHAR);
  582. CODE{SYSTEM.i386}
  583. MOV AL,[EBP+val]
  584. MOV EDX,[EBP+port]
  585. OUT DX,AL
  586. END Portout8;
  587. PROCEDURE Portout16*(port: LONGINT; val: INTEGER);
  588. CODE{SYSTEM.i386}
  589. MOV AX,[EBP+val]
  590. MOV EDX,[EBP+port]
  591. OUT DX,AX
  592. END Portout16;
  593. PROCEDURE Portout32*(port: LONGINT; val: LONGINT);
  594. CODE{SYSTEM.i386}
  595. MOV EAX,[EBP+val]
  596. MOV EDX,[EBP+port]
  597. OUT DX,EAX
  598. END Portout32;
  599. (* Delay for IO *)
  600. PROCEDURE -Wait*;
  601. CODE {SYSTEM.i386}
  602. JMP 0
  603. JMP 0
  604. JMP 0
  605. END Wait;
  606. (** Read a byte from the non-volatile setup memory. *)
  607. PROCEDURE GetNVByte* (ofs: LONGINT): CHAR;
  608. VAR c: CHAR;
  609. BEGIN
  610. Portout8 (70H, CHR(ofs)); Wait; Portin8(71H, c);
  611. RETURN c
  612. END GetNVByte;
  613. (** Write a byte to the non-volatile setup memory. *)
  614. PROCEDURE PutNVByte* (ofs: LONGINT; val: CHAR);
  615. BEGIN
  616. Portout8 (70H, CHR(ofs)); Wait; Portout8 (71H, val)
  617. END PutNVByte;
  618. PROCEDURE InvalidateDCacheRange*(a: ADDRESS; s: SIZE);
  619. BEGIN
  620. END InvalidateDCacheRange;
  621. PROCEDURE FlushDCacheRange*(a: ADDRESS; s: SIZE);
  622. BEGIN
  623. END FlushDCacheRange;
  624. BEGIN
  625. Trace.String("Machine: "); Trace.Blue; Trace.StringLn (Version); Trace.Default;
  626. boottime:=GetTimer();
  627. COPY( Version, version );
  628. END Machine.