I386.Builtins.Mod 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  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+l+4] ; multiplicand_hi
  118. MOV ECX, [EBP+r+4] ; multiplier_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+l+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+r+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. MOV EBX,EAX
  305. SHRD EAX,EDX,CL ; First apply shift count.
  306. SHRD EDX,EBX,CL ; mod 32 to EDX:EAX
  307. TEST ECX,32 ; Need to shift by another 32?
  308. JZ rshiftdone ; No, done.
  309. MOV EBX,EAX
  310. SHRD EAX,EDX,CL
  311. SHRD EDX,EBX,CL
  312. rshiftdone:
  313. POP ECX
  314. END RorH;
  315. PROCEDURE RolH*(l: HUGEINT; r: LONGINT): HUGEINT;
  316. CODE{SYSTEM.i386}
  317. PUSH ECX
  318. ; taken from "Software Optimization Guide for AMD64 Processors"
  319. MOV ECX,[EBP+r+0]
  320. MOV EAX,[EBP+l+0]
  321. MOV EDX,[EBP+l+4]
  322. ; EDX <- EAX <- EBX (intially=EDX)
  323. ; Shift EDX:EAX left, shift count in ECX (count
  324. ; applied modulo 64).
  325. MOV EBX,EDX
  326. SHLD EDX,EAX,CL ; First apply shift count.
  327. SHLD EAX, EBX, CL
  328. TEST ECX,32 ; Need to shift by another 32?
  329. JZ lshiftdone ; No, done.
  330. MOV EBX,EDX
  331. SHLD EDX,EAX,CL
  332. SHLD EAX, EBX, CL
  333. lshiftdone:
  334. POP ECX
  335. END RolH;
  336. PROCEDURE CasH*(VAR value: HUGEINT; old, new: HUGEINT): HUGEINT;
  337. CODE{SYSTEM.Pentium}
  338. PUSH ECX
  339. MOV EAX, [EBP + old + 0]
  340. MOV EDX, [EBP + old + 4]
  341. MOV EBX, [EBP + new + 0]
  342. MOV ECX, [EBP + new + 4]
  343. MOV EDI, [EBP + value]
  344. LOCK CMPXCHG8B [EDI]
  345. POP ECX
  346. END CasH;
  347. PROCEDURE EntierXH*(x: LONGREAL): HUGEINT;
  348. CODE
  349. FLD QWORD [EBP+x]
  350. SUB ESP, 12
  351. FNSTCW [ESP]
  352. FWAIT
  353. MOV ESI, [ESP]
  354. AND ESI, 0000F3FFH
  355. OR ESI, 00000400H
  356. MOV [ESP+4], ESI
  357. FLDCW [ESP+4]
  358. FISTP QWORD [ESP+4]
  359. FWAIT
  360. FLDCW [ESP]
  361. POP EDI
  362. POP EAX
  363. POP EDX
  364. END EntierXH;
  365. PROCEDURE EntierRH*(x: REAL): HUGEINT;
  366. CODE
  367. FLD DWORD [EBP+x]
  368. SUB ESP, 12
  369. FNSTCW [ESP]
  370. FWAIT
  371. MOV ESI, [ESP]
  372. AND ESI, 0000F3FFH
  373. OR ESI, 00000400H
  374. MOV [ESP+4], ESI
  375. FLDCW [ESP+4]
  376. FISTP QWORD [ESP+4]
  377. FWAIT
  378. FLDCW [ESP]
  379. POP EDI
  380. POP EAX
  381. POP EDX
  382. END EntierRH;
  383. (* compare strings,
  384. returns 0 if strings are equal,
  385. returns +1 if left is lexicographic greater than right,
  386. returns -1 if left is lexicographics smaller than right
  387. traps if src or destination is not 0X terminated and comparison is not finished
  388. *)
  389. PROCEDURE CompareString*(CONST left,right: ARRAY OF CHAR): SHORTINT;
  390. VAR i: LONGINT; res: SHORTINT; l,r: CHAR;
  391. BEGIN {UNCOOPERATIVE}
  392. i := 0; res := 0;
  393. LOOP
  394. l := left[i]; (* index check included *)
  395. r := right[i]; (* index check included *)
  396. IF (res = 0) THEN
  397. IF (l > r) THEN
  398. res := 1; EXIT
  399. ELSIF (l<r) THEN
  400. res := -1; EXIT
  401. ELSIF l=0X THEN
  402. EXIT
  403. END;
  404. END;
  405. INC(i);
  406. END;
  407. RETURN res
  408. END CompareString;
  409. (* copy string from src to dest, emits trap if not 0X terminated or destination too short *)
  410. PROCEDURE CopyString*(VAR dest: ARRAY OF CHAR; CONST src: ARRAY OF CHAR);
  411. VAR i: LONGINT; ch :CHAR; l1,l2: LONGINT;
  412. BEGIN {UNCOOPERATIVE}
  413. (*
  414. i := 0;
  415. REPEAT
  416. ch := src[i]; (* index check included *)
  417. dest[i] := ch; (* index check included *)
  418. INC(i);
  419. UNTIL ch=0X;
  420. *)
  421. (*! currently implemented: old PACO semantics *)
  422. l1 := LEN(dest);
  423. l2 := LEN(src);
  424. IF l2 < l1 THEN l1 := l2 END;
  425. SYSTEM.MOVE(ADDRESSOF(src[0]),ADDRESSOF(dest[0]),l1);
  426. dest[l1-1] := 0X; (* this implies that COPY assumes a string *)
  427. END CopyString;
  428. PROCEDURE EnsureAllocatedStack*(size: SIZE);
  429. VAR i: ADDRESS; temp: ADDRESS;
  430. BEGIN {UNCOOPERATIVE}
  431. FOR i := 0 TO size BY 4096 DO
  432. SYSTEM.GET(ADDRESSOF(i)-i,temp);
  433. (*
  434. SYSTEM.PUT(ADDRESSOF(val)-i,0);
  435. *)
  436. END;
  437. (*
  438. CODE{SYSTEM.i386}
  439. MOV EAX, [EBP+size]
  440. SHR EAX,12 ; divide by 4096
  441. MOV ECX,-4
  442. start:
  443. MOV EDX,[EBP+ECX]
  444. SUB ECX,4096
  445. TST EAX
  446. DEC EAX
  447. JNZ start
  448. *)
  449. END EnsureAllocatedStack;
  450. BEGIN
  451. (*! assumed that modules = 0, implicit call of InsertModule *)
  452. END Builtins.
  453. Builtins.Obw