I386.Builtins.Mod 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. MODULE Builtins; (** AUTHOR "fof"; PURPOSE "Built-in functions for the Active Oberon Compiler"; *)
  2. IMPORT SYSTEM;
  3. VAR
  4. kernelModule-: ARRAY 32 OF ADDRESS;
  5. modules-: LONGINT;
  6. PROCEDURE InsertModule*(a: ADDRESS): BOOLEAN;
  7. BEGIN {UNCOOPERATIVE}
  8. kernelModule[modules] := a;
  9. INC(modules);
  10. RETURN TRUE
  11. END InsertModule;
  12. PROCEDURE DivHA(l,r: HUGEINT): HUGEINT;
  13. CODE{SYSTEM.i386}
  14. PUSH ECX
  15. ; taken from "Software Optimization Guide for AMD64 Processors"
  16. ; divides two signed 64-bit numbers and delivers the quotient
  17. ;
  18. ; In: [EBP+l+4]:[EBP+l+0] = dividend (l)
  19. ; [EBP+r+4]:[EBP+r+0] = divisor (r)
  20. ; Out: EDX:EAX = quotient of division
  21. MOV EDX, [EBP+l+4] ; dividend_hi
  22. MOV EAX, [EBP+l+0] ; dividend_lo
  23. MOV ECX, [EBP+r+4] ; divisor_hi
  24. MOV EBX, [EBP+r+0] ; divisor_lo
  25. MOV ESI, ECX ; divisor_hi
  26. XOR ESI, EDX ; divisor_hi ^ dividend_hi
  27. SAR ESI, 31 ; (quotient < 0) ? -1 : 0
  28. MOV EDI, EDX ; dividend_hi
  29. SAR EDI, 31 ; (dividend < 0) ? -1 : 0
  30. XOR EAX, EDI ; If (dividend < 0),
  31. XOR EDX, EDI ; compute 1's complement of dividend.
  32. SUB EAX, EDI ; If (dividend < 0),
  33. SBB EDX, EDI ; compute 2's complement of dividend.
  34. MOV EDI, ECX ; divisor_hi
  35. SAR EDI, 31 ; (divisor < 0) ? -1 : 0
  36. XOR EBX, EDI ; If (divisor < 0),
  37. XOR ECX, EDI ; compute 1's complement of divisor.
  38. SUB EBX, EDI ; If (divisor < 0),
  39. SBB ECX, EDI ; compute 2's complement of divisor.
  40. JNZ BIGDIVISOR ; divisor > 2^32 - 1
  41. CMP EDX, EBX ; Only one division needed (ECX = 0)?
  42. JAE TWODIVS ; Need two divisions.
  43. DIV EBX ; EAX = quotient_lo
  44. MOV EDX, ECX ; EDX = quotient_hi = 0 (quotient in EDX:EAX)
  45. XOR EAX, ESI ; If (quotient < 0),
  46. XOR EDX, ESI ; compute 1's complement of result.
  47. SUB EAX, ESI ; If (quotient < 0),
  48. SBB EDX, ESI ; compute 2's complement of result.
  49. JMP DONE
  50. TWODIVS:
  51. MOV ECX, EAX ; Save dividend_lo in ECX.
  52. MOV EAX, EDX ; Get dividend_hi.
  53. XOR EDX, EDX ; Zero-extend it into EDX:EAX.
  54. DIV EBX ; QUOtient_hi in EAX
  55. XCHG EAX, ECX ; ECX = quotient_hi, EAX = dividend_lo
  56. DIV EBX ; EAX = quotient_lo
  57. MOV EDX, ECX ; EDX = quotient_hi (quotient in EDX:EAX)
  58. JMP MAKESIGN ; Make quotient signed.
  59. BIGDIVISOR:
  60. SUB ESP, 12 ; Create three local variables.
  61. MOV [ESP], EAX ; dividend_lo
  62. MOV [ESP+4], EBX ; divisor_lo
  63. MOV [ESP+8], EDX ; dividend_hi
  64. MOV EDI, ECX ; Save divisor_hi.
  65. SHR EDX, 1 ; Shift both
  66. RCR EAX, 1 ; divisor and
  67. ROR EDI, 1 ; and dividend
  68. RCR EBX, 1 ; right by 1 bit.
  69. BSR ECX, ECX ; ECX = number of remaining shifts
  70. SHRD EBX, EDI, CL ; Scale down divisor and
  71. SHRD EAX, EDX, CL ; dividend such that divisor is
  72. SHR EDX, CL ; less than 2^32 (that is, fits in EBX).
  73. ROL EDI, 1 ; Restore original divisor_hi.
  74. DIV EBX ; COMpute quotient.
  75. MOV EBX, [ESP] ; dividend_lo
  76. MOV ECX, EAX ; Save quotient.
  77. IMUL EDI, EAX ; quotient * divisor high word (low only)
  78. MUL DWORD [ESP+4] ; quotient * divisor low word
  79. ADD EDX, EDI ; EDX:EAX = quotient * divisor
  80. SUB EBX, EAX ; dividend_lo - (quot.*divisor)_lo
  81. MOV EAX, ECX ; Get quotient.
  82. MOV ECX, [ESP+8] ; dividend_hi
  83. SBB ECX, EDX ; Subtract (divisor * quot.) from dividend
  84. SBB EAX, 0 ; Adjust quotient if remainder is negative.
  85. XOR EDX, EDX ; Clear high word of quotient.
  86. ADD ESP, 12 ; Remove local variables.
  87. MAKESIGN:
  88. XOR EAX, ESI ; If (quotient < 0),
  89. XOR EDX, ESI ; compute 1's complement of result.
  90. SUB EAX, ESI ; If (quotient < 0),
  91. SBB EDX, ESI ; compute 2's complement of result.
  92. DONE:
  93. POP ECX
  94. END DivHA;
  95. PROCEDURE DivH*(l,r: HUGEINT): HUGEINT;
  96. VAR result: HUGEINT;
  97. BEGIN {UNCOOPERATIVE, UNCHECKED}
  98. IF l > 0 THEN RETURN DivHA(l,r)
  99. ELSIF l< 0 THEN
  100. result := -DivHA(-l,r);
  101. IF result * r # l THEN DEC(result) END; (* mathematical definition of DIV and MOD, to be optimized in DivHA *)
  102. RETURN result
  103. ELSE RETURN 0
  104. END;
  105. END DivH;
  106. PROCEDURE MulH*(l,r: HUGEINT): HUGEINT;
  107. CODE{SYSTEM.i386}
  108. PUSH ECX
  109. ; taken from "Software Optimization Guide for AMD64 Processors"
  110. ; computes the low-order half of the product of its
  111. ; arguments, two 64-bit integers.
  112. ;
  113. ; In: [EBP+l+4]:[EBP+l+0] = multiplicand (l)
  114. ; [EBP+r+4]:[EBP+r+0] = multiplier (r)
  115. ; Out: EDX:EAX = (multiplicand * multiplier) % 2^64
  116. ; Destroys: EAX, ECX, EDX, EFlags
  117. MOV EDX, [EBP+r+4] ; multiplier_hi
  118. MOV ECX, [EBP+l+4] ; multiplicand_hi
  119. OR EDX,ECX ; One operand >= 2^32?
  120. MOV EDX, [EBP+l+0] ; multiplier_lo
  121. MOV EAX, [EBP+r+0] ; multiplicand_lo
  122. JNZ twomul ; Yes, need two multiplies.
  123. MUL EDX ; multiplicand_lo * multiplier_lo
  124. JMP done ; Done, return to caller.
  125. twomul:
  126. IMUL EDX, [EBP+r+4] ; p3_lo = multiplicand_hi * multiplier_lo
  127. IMUL ECX,EAX ; p2_lo = multiplier_hi * multiplicand_lo
  128. ADD ECX, EDX ; p2_lo + p3_lo
  129. MUL DWORD [EBP+l+0] ; p1 = multiplicand_lo * multiplier_lo
  130. ADD EDX,ECX ; p1 + p2_lo + p3_lo = result in EDX:EAX
  131. done:
  132. POP ECX
  133. END MulH;
  134. PROCEDURE ModHA(l,r: HUGEINT): HUGEINT;
  135. CODE{SYSTEM.i386}
  136. PUSH ECX
  137. ; taken from "Software Optimization Guide for AMD64 Processors"
  138. ; DIVIDES TWO SIGNED 64-BIT NUMBERS AND RETURNS THE REMAINDER.
  139. ;
  140. ; IN: [EBP+l+4]:[EBP+l+0] = DIVIDEND (l)
  141. ; [EBP+r+4]:[EBP+r+0] = DIVISOR (r)
  142. ;
  143. ; OUT: EDX:EAX = REMAINDER OF DIVISION
  144. ;
  145. ; DESTROYS: EAX, ECX, EDX, EFLAGS
  146. MOV EDX, [EBP+l+4] ; DIVIDEND-HI
  147. MOV EAX, [EBP+l+0] ; DIVIDEND-LO
  148. MOV ECX, [EBP+r+4] ; DIVISOR-HI
  149. MOV EBX, [EBP+r+0] ; DIVISOR-LO
  150. MOV ESI, EDX ; SIGN(REMAINDER) == SIGN(DIVIDEND)
  151. SAR ESI, 31 ; (REMAINDER < 0) ? -1 : 0
  152. MOV EDI, EDX ; DIVIDEND-HI
  153. SAR EDI, 31 ; (DIVIDEND < 0) ? -1 : 0
  154. XOR EAX, EDI ; IF (DIVIDEND < 0),
  155. XOR EDX, EDI ; COMPUTE 1'S COMPLEMENT OF DIVIDEND.
  156. SUB EAX, EDI ; IF (DIVIDEND < 0),
  157. SBB EDX, EDI ; COMPUTE 2'S COMPLEMENT OF DIVIDEND.
  158. MOV EDI, ECX ; DIVISOR-HI
  159. SAR EDI, 31 ; (DIVISOR < 0) ? -1 : 0
  160. XOR EBX, EDI ; IF (DIVISOR < 0),
  161. XOR ECX, EDI ; COMPUTE 1'S COMPLEMENT OF DIVISOR.
  162. SUB EBX, EDI ; IF (DIVISOR < 0),
  163. SBB ECX, EDI ; COMPUTE 2'S COMPLEMENT OF DIVISOR.
  164. JNZ SRBIGDIVISOR ; DIVISOR > 2^32 - 1
  165. CMP EDX, EBX ; ONLY ONE DIVISION NEEDED (ECX = 0)?
  166. JAE SRTWODIVS ; NO, NEED TWO DIVISIONS.
  167. DIV EBX ; EAX = QUOTIENT_LO
  168. MOV EAX, EDX ; EAX = REMAINDER_LO
  169. MOV EDX, ECX ; EDX = REMAINDER_LO = 0
  170. XOR EAX, ESI ; IF (REMAINDER < 0),
  171. XOR EDX, ESI ; COMPUTE 1'S COMPLEMENT OF RESULT.
  172. SUB EAX, ESI ; IF (REMAINDER < 0),
  173. SBB EDX, ESI ; COMPUTE 2'S COMPLEMENT OF RESULT.
  174. JMP done ; DONE, RETURN TO CALLER.
  175. SRTWODIVS:
  176. MOV ECX, EAX ; SAVE DIVIDEND_LO IN ECX.
  177. MOV EAX, EDX ; GET DIVIDEND_HI.
  178. XOR EDX, EDX ; ZERO-EXTEND IT INTO EDX:EAX.
  179. DIV EBX ; EAX = QUOTIENT_HI, EDX = INTERMEDIATE REMAINDER
  180. MOV EAX, ECX ; EAX = DIVIDEND_LO
  181. DIV EBX ; EAX = QUOTIENT_LO
  182. MOV EAX, EDX ; REMAINDER_LO
  183. XOR EDX, EDX ; REMAINDER_HI = 0
  184. JMP SRMAKESIGN ;MAKE REMAINDER SIGNED.
  185. SRBIGDIVISOR:
  186. SUB ESP, 16 ;CREATE THREE LOCAL VARIABLES.
  187. MOV [ESP], EAX ; DIVIDEND_LO
  188. MOV [ESP+4], EBX ; DIVISOR_LO
  189. MOV [ESP+8], EDX ; DIVIDEND_HI
  190. MOV [ESP+12], ECX ; DIVISOR_HI
  191. MOV EDI, ECX ; SAVE DIVISOR_HI.
  192. SHR EDX, 1 ; SHIFT BOTH
  193. RCR EAX, 1 ; DIVISOR AND
  194. ROR EDI, 1 ; AND DIVIDEND
  195. RCR EBX, 1 ; RIGHT BY 1 BIT.
  196. BSR ECX, ECX ; ECX = NUMBER OF REMAINING SHIFTS
  197. SHRD EBX, EDI, CL ; SCALE DOWN DIVISOR AND
  198. SHRD EAX, EDX, CL ; DIVIDEND SUCH THAT DIVISOR IS
  199. SHR EDX, CL ; LESS THAN 2^32 (THAT IS, FITS IN EBX).
  200. ROL EDI, 1 ; RESTORE ORIGINAL DIVISOR_HI.
  201. DIV EBX ; COMPUTE QUOTIENT.
  202. MOV EBX, [ESP] ; DIVIDEND_LO
  203. MOV ECX, EAX ; SAVE QUOTIENT.
  204. IMUL EDI, EAX ; QUOTIENT * DIVISOR HIGH WORD (LOW ONLY)
  205. MUL DWORD [ESP+4] ; QUOTIENT * DIVISOR LOW WORD
  206. ADD EDX, EDI ; EDX:EAX = QUOTIENT * DIVISOR
  207. SUB EBX, EAX ; DIVIDEND_LO - (QUOT.*DIVISOR)_LO
  208. MOV ECX, [ESP+8] ; DIVIDEND_HI
  209. SBB ECX, EDX ; SUBTRACT DIVISOR * QUOT. FROM DIVIDEND.
  210. SBB EAX, EAX ; REMAINDER < 0 ? 0XFFFFFFFF : 0
  211. MOV EDX, [ESP+12] ; DIVISOR_HI
  212. AND EDX, EAX ; REMAINDER < 0 ? DIVISOR_HI : 0
  213. AND EAX, [ESP+4] ; REMAINDER < 0 ? DIVISOR_LO : 0
  214. ADD EAX, EBX ; REMAINDER_LO
  215. ADD EDX, ECX ; REMAINDER_HI
  216. ADD ESP, 16 ; REMOVE LOCAL VARIABLES.
  217. SRMAKESIGN:
  218. XOR EAX, ESI ; IF (REMAINDER < 0),
  219. XOR EDX, ESI ; COMPUTE 1'S COMPLEMENT OF RESULT.
  220. SUB EAX, ESI ; IF (REMAINDER < 0),
  221. SBB EDX, ESI ; COMPUTE 2'S COMPLEMENT OF RESULT.
  222. done:
  223. POP ECX
  224. END ModHA;
  225. PROCEDURE ModH*(l,r: HUGEINT): HUGEINT;
  226. VAR res: HUGEINT;
  227. BEGIN {UNCOOPERATIVE, UNCHECKED}
  228. res := ModHA(l,r);
  229. IF res < 0 THEN INC(res,r) END;
  230. RETURN res
  231. END ModH;
  232. PROCEDURE AbsH*(l: HUGEINT): HUGEINT;
  233. BEGIN {UNCOOPERATIVE, UNCHECKED}
  234. IF l< 0 THEN RETURN -l ELSE RETURN l END;
  235. END AbsH;
  236. PROCEDURE AslH*(l: HUGEINT; r: LONGINT): HUGEINT; (*! coincides with Logic Shift, remove ? *)
  237. BEGIN {UNCOOPERATIVE, UNCHECKED}
  238. RETURN LslH(l,r)
  239. END AslH;
  240. PROCEDURE LslH*(l: HUGEINT; r: LONGINT): HUGEINT;
  241. CODE{SYSTEM.i386}
  242. PUSH ECX
  243. ; taken from "Software Optimization Guide for AMD64 Processors"
  244. MOV ECX,[EBP+r+0]
  245. MOV EAX,[EBP+l+0]
  246. MOV EDX,[EBP+l+4]
  247. ; Shift EDX:EAX left, shift count in ECX (count
  248. ; applied modulo 64).
  249. SHLD EDX,EAX,CL ; First apply shift count.
  250. SHL EAX,CL ; mod 32 to EDX:EAX
  251. TEST ECX,32 ; Need to shift by another 32?
  252. JZ lshiftdone ; No, done.
  253. MOV EDX,EAX ; Left shift EDX:EAX
  254. XOR EAX,EAX ; by 32 bits
  255. lshiftdone:
  256. POP ECX
  257. END LslH;
  258. PROCEDURE AsrH*(l: HUGEINT; r: LONGINT): HUGEINT;
  259. CODE{SYSTEM.i386}
  260. PUSH ECX
  261. ; taken from "Software Optimization Guide for AMD64 Processors"
  262. MOV ECX,[EBP+r+0]
  263. MOV EAX,[EBP+l+0]
  264. MOV EDX,[EBP+l+4]
  265. ; Shift EDX:EAX right, shift count in ECX (count
  266. ; applied modulo 64).
  267. SHRD EAX,EDX,CL ; First apply shift count.
  268. SAR EDX,CL ; mod 32 to EDX:EAX
  269. TEST ECX,32 ; Need to shift by another 32?
  270. JZ rshiftdone ; No, done.
  271. MOV EAX,EDX ; Left shift EDX:EAX
  272. SAR EDX,31 ; by 32 bits (fill EDX with sign bits)
  273. rshiftdone:
  274. POP ECX
  275. END AsrH;
  276. PROCEDURE LsrH*(l: HUGEINT; r: LONGINT): HUGEINT;
  277. CODE{SYSTEM.i386}
  278. PUSH ECX
  279. ; taken from "Software Optimization Guide for AMD64 Processors"
  280. MOV ECX,[EBP+r+0]
  281. MOV EAX,[EBP+l+0]
  282. MOV EDX,[EBP+l+4]
  283. ; Shift EDX:EAX right, shift count in ECX (count
  284. ; applied modulo 64).
  285. SHRD EAX,EDX,CL ; First apply shift count.
  286. SHR EDX,CL ; mod 32 to EDX:EAX
  287. TEST ECX,32 ; Need to shift by another 32?
  288. JZ rshiftdone ; No, done.
  289. MOV EAX,EDX ; Left shift EDX:EAX
  290. XOR EDX,EDX ; by 32 bits (clear EDX)
  291. rshiftdone:
  292. POP ECX
  293. END LsrH;
  294. PROCEDURE RorH*(l: HUGEINT; r: LONGINT): HUGEINT;
  295. CODE{SYSTEM.i386}
  296. PUSH ECX
  297. ; taken from "Software Optimization Guide for AMD64 Processors"
  298. MOV ECX,[EBP+r+0]
  299. MOV EAX,[EBP+l+0]
  300. MOV EDX,[EBP+l+4]
  301. ; EBX (initially=EAX) -> EDX -> EAX
  302. ; Shift EDX:EAX right, shift count in ECX (count
  303. ; applied modulo 64).
  304. TEST ECX,32 ; Need to shift by 32?
  305. JZ rest ; No.
  306. XCHG EDX,EAX
  307. rest:
  308. MOV EBX,EAX
  309. SHRD EAX,EDX,CL
  310. SHRD EDX,EBX,CL
  311. POP ECX
  312. END RorH;
  313. PROCEDURE RolH*(l: HUGEINT; r: LONGINT): HUGEINT;
  314. CODE{SYSTEM.i386}
  315. PUSH ECX
  316. ; taken from "Software Optimization Guide for AMD64 Processors"
  317. MOV ECX,[EBP+r+0]
  318. MOV EAX,[EBP+l+0]
  319. MOV EDX,[EBP+l+4]
  320. ; EDX <- EAX <- EBX (intially=EDX)
  321. ; Shift EDX:EAX left, shift count in ECX (count
  322. ; applied modulo 64).
  323. TEST ECX,32 ; Need to shift by 32?
  324. JZ rest ; No.
  325. XCHG EDX,EAX
  326. rest:
  327. MOV EBX,EDX
  328. SHLD EDX,EAX,CL
  329. SHLD EAX,EBX,CL
  330. POP ECX
  331. END RolH;
  332. PROCEDURE CasH*(VAR value: HUGEINT; old, new: HUGEINT): HUGEINT;
  333. CODE{SYSTEM.Pentium}
  334. PUSH ECX
  335. MOV EAX, [EBP + old + 0]
  336. MOV EDX, [EBP + old + 4]
  337. MOV EBX, [EBP + new + 0]
  338. MOV ECX, [EBP + new + 4]
  339. MOV EDI, [EBP + value]
  340. LOCK CMPXCHG8B [EDI]
  341. POP ECX
  342. END CasH;
  343. PROCEDURE EntierXH*(x: LONGREAL): HUGEINT;
  344. CODE
  345. FLD QWORD [EBP+x]
  346. SUB ESP, 12
  347. FNSTCW [ESP]
  348. FWAIT
  349. MOV ESI, [ESP]
  350. AND ESI, 0000F3FFH
  351. OR ESI, 00000400H
  352. MOV [ESP+4], ESI
  353. FLDCW [ESP+4]
  354. FISTP QWORD [ESP+4]
  355. FWAIT
  356. FLDCW [ESP]
  357. POP EDI
  358. POP EAX
  359. POP EDX
  360. END EntierXH;
  361. PROCEDURE EntierRH*(x: REAL): HUGEINT;
  362. CODE
  363. FLD DWORD [EBP+x]
  364. SUB ESP, 12
  365. FNSTCW [ESP]
  366. FWAIT
  367. MOV ESI, [ESP]
  368. AND ESI, 0000F3FFH
  369. OR ESI, 00000400H
  370. MOV [ESP+4], ESI
  371. FLDCW [ESP+4]
  372. FISTP QWORD [ESP+4]
  373. FWAIT
  374. FLDCW [ESP]
  375. POP EDI
  376. POP EAX
  377. POP EDX
  378. END EntierRH;
  379. (* compare strings,
  380. returns 0 if strings are equal,
  381. returns +1 if left is lexicographic greater than right,
  382. returns -1 if left is lexicographics smaller than right
  383. traps if src or destination is not 0X terminated and comparison is not finished
  384. *)
  385. PROCEDURE CompareString*(CONST left,right: ARRAY OF CHAR): SHORTINT;
  386. VAR i: SIZE; res: SHORTINT; l, r: CHAR;
  387. BEGIN {UNCOOPERATIVE, UNCHECKED}
  388. i := 0; res := 0;
  389. LOOP
  390. ASSERT (i < LEN (left));
  391. ASSERT (i < LEN (right));
  392. l := left[i];
  393. r := right[i];
  394. IF (res = 0) THEN
  395. IF (l > r) THEN
  396. res := 1; EXIT
  397. ELSIF (l<r) THEN
  398. res := -1; EXIT
  399. ELSIF l=0X THEN
  400. EXIT
  401. END;
  402. END;
  403. INC(i);
  404. END;
  405. RETURN res
  406. END CompareString;
  407. (* copy string from src to dest, emits trap if not 0X terminated or destination too short *)
  408. PROCEDURE CopyString*(VAR dest: ARRAY OF CHAR; CONST src: ARRAY OF CHAR);
  409. VAR i: SIZE; ch :CHAR; l1, l2: SIZE;
  410. BEGIN {UNCOOPERATIVE, UNCHECKED}
  411. (*
  412. i := 0;
  413. REPEAT
  414. ch := src[i]; (* index check included *)
  415. dest[i] := ch; (* index check included *)
  416. INC(i);
  417. UNTIL ch=0X;
  418. *)
  419. (*! currently implemented: old PACO semantics *)
  420. l1 := LEN(dest);
  421. l2 := LEN(src);
  422. IF l2 < l1 THEN l1 := l2 END;
  423. SYSTEM.MOVE(ADDRESSOF(src[0]),ADDRESSOF(dest[0]),l1);
  424. dest[l1-1] := 0X; (* this implies that COPY assumes a string *)
  425. END CopyString;
  426. PROCEDURE EnsureAllocatedStack*(size: SIZE);
  427. VAR i: ADDRESS; temp: ADDRESS;
  428. BEGIN {UNCOOPERATIVE, UNCHECKED}
  429. FOR i := 0 TO size BY 4096 DO
  430. SYSTEM.GET(ADDRESSOF(i)-i,temp);
  431. END;
  432. END EnsureAllocatedStack;
  433. BEGIN
  434. (*! assumed that modules = 0, implicit call of InsertModule *)
  435. END Builtins.
  436. Builtins.Obw