TRM.Builtins.Mod 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. MODULE Builtins; (** AUTHOR ""; PURPOSE ""; *)
  2. (**
  3. @concept
  4. The module [[TRMRuntime]] provides run-time services implemented as procedures. The compiler \
  5. emits procedure calls for all invocations of the runtime.
  6. **)
  7. IMPORT SYSTEM;
  8. CONST expo = 7F800000H; bias = 3F800000H;
  9. mant = 7FFFFFH; mant1 = LONGINT(0FFC00000H); mant2 = 0FFFFFFH;
  10. LimE = 0C800000H; C = 800000H; S = LONGINT(80000000H); M= LONGINT(7FFFFFFFH);
  11. VAR
  12. lastDataAddress-: ADDRESS;
  13. emptyVariable: RECORD END; (* always linked to top of used memory *)
  14. (* for testing test with intel
  15. VAR high: LONGINT;
  16. PROCEDURE SimulatedMul(l,r: LONGINT): LONGINT;
  17. VAR h: HUGEINT;
  18. BEGIN
  19. h := HUGEINT(l)*r;
  20. high := LONGINT(h DIV 100000000H);
  21. RETURN LONGINT(h MOD 100000000H);
  22. END SimulatedMul;
  23. PROCEDURE H(): LONGINT;
  24. RETURN high
  25. END H;
  26. *)
  27. PROCEDURE H(): LONGINT;
  28. CODE
  29. LDH R0
  30. END H;
  31. (* helper functions *)
  32. PROCEDURE MSK(x,bits: LONGINT): LONGINT;
  33. BEGIN
  34. RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET,x)*SYSTEM.VAL(SET,bits))
  35. END MSK;
  36. PROCEDURE NULLF(x: LONGINT): BOOLEAN;
  37. BEGIN RETURN SYSTEM.VAL(SET,x) * SYSTEM.VAL(SET,M) = {}
  38. END NULLF;
  39. PROCEDURE ConvertIR*(x: LONGINT): REAL; (* Float 32 bit *)
  40. VAR xe, s: LONGINT; odd,odd1: BOOLEAN; odds: LONGINT;
  41. BEGIN s := x;
  42. IF x # 0 THEN
  43. x := ABS(x); xe := 4B000000H;
  44. IF x >= 2*C THEN
  45. odd := FALSE; odd1 := FALSE;
  46. REPEAT
  47. odd1 := odd1 OR odd;
  48. odd := ODD(x); (* rounding bit *)
  49. x := ROT(MSK(x, -2),-1); (*ASH(x,-1);*) INC(xe,C);
  50. (*D.Hex(x,10); D.Ln;*)
  51. UNTIL x <2*C;
  52. (* round half to even, standard in IEEE 754 *)
  53. IF odd & (ODD(x) OR odd1) & (x<2*C) THEN INC(x) END; (* rounding *)
  54. ELSIF x < C THEN
  55. REPEAT x := x+x; xe := xe - C UNTIL x >= C
  56. END ;
  57. x := xe - C + x;
  58. IF s < 0 THEN x := x+S END
  59. END ;
  60. RETURN SYSTEM.VAL(REAL,x)
  61. END ConvertIR;
  62. PROCEDURE ConvertHR*(x: HUGEINT): REAL;
  63. BEGIN HALT(200);
  64. END ConvertHR;
  65. PROCEDURE ConvertRI*(l: REAL): LONGINT; (* Floor 32bit *)
  66. VAR x,xe, n, sign: LONGINT;
  67. BEGIN
  68. x := SYSTEM.VAL(LONGINT,l);
  69. IF ~NULLF(x) THEN
  70. sign := MSK(x, S);
  71. xe := MSK(x, expo) - bias; x := MSK(x, mant) + C;
  72. IF xe >= 0 THEN xe := ROT(xe, -23) ELSE xe := -1 END ;
  73. IF sign < 0 THEN x := -x END ;
  74. IF xe < 24 THEN n := 23 - xe;
  75. WHILE n > 0 DO x := ROT(MSK(x, -2), -1) + sign; DEC(n) END
  76. ELSIF xe >= 31 THEN x := MIN(LONGINT)
  77. ELSE n := xe - 23;
  78. WHILE n > 0 DO x := x+x; DEC(n) END
  79. END
  80. ELSE x := 0
  81. END ;
  82. RETURN x
  83. END ConvertRI;
  84. PROCEDURE ConvertRH*(x: REAL): HUGEINT ;
  85. BEGIN HALT(200);
  86. END ConvertRH;
  87. (* 32 bit float instructions *)
  88. PROCEDURE AddR*(l,r: REAL): REAL;
  89. VAR x,y,xe, ye, xm, ym, sign: LONGINT; odd, odd1: BOOLEAN;
  90. BEGIN
  91. x := SYSTEM.VAL(LONGINT,l);
  92. y := SYSTEM.VAL(LONGINT,r);
  93. IF NULLF(x) THEN x := y
  94. ELSIF ~NULLF(y) THEN
  95. xe := MSK(x, expo) - bias; xm := MSK(x, mant) + C;
  96. ye := MSK(y, expo) - bias; ym := MSK(y, mant) + C;
  97. IF xe < ye THEN (*denorm x*)
  98. IF ye - xe > LimE THEN xm := 0; xe := ye ELSE
  99. odd1 := FALSE; odd := FALSE;
  100. REPEAT odd1 := odd1 OR odd; odd := ODD(xm); xe := xe + C; xm := ROT(MSK(xm, -2), -1) UNTIL xe = ye;
  101. (* half even rounding *)
  102. IF odd & (odd1 OR ODD(xm)) THEN INC(xm) END;
  103. END
  104. ELSIF ye < xe THEN (*denorm y*)
  105. IF xe - ye > LimE THEN ym := 0 ELSE
  106. odd := FALSE; odd1 := FALSE;
  107. REPEAT odd1 := odd1 OR odd; odd := ODD(ym); ye := ye + C; ym := ROT(MSK(ym, -2), -1) UNTIL ye = xe;
  108. (* half even rounding *)
  109. IF odd & (odd1 OR ODD(ym)) THEN INC(xm) END;
  110. END
  111. END ;
  112. IF x < 0 THEN xm := -xm END ;
  113. IF y < 0 THEN ym := -ym END ;
  114. x := xm + ym; sign := MSK(x, S);
  115. IF x # 0 THEN
  116. IF x < 0 THEN x := -x END ;
  117. IF x >= 2*C THEN
  118. odd := ODD(x);
  119. x := ROT(MSK(x, -2), -1);
  120. (* half even rounding *)
  121. IF odd & ODD(x) THEN INC(x) END;
  122. xe := xe + C
  123. ELSE (*normalize*)
  124. WHILE x < C DO
  125. x := ROT(x, -31); xe := xe - C
  126. END
  127. END ;
  128. IF xe < -bias THEN x := 0 (*underflow*)
  129. ELSIF (xe <= bias) THEN x := (x-C) + xe + bias + sign
  130. ELSE xe := M
  131. END
  132. END
  133. END ;
  134. RETURN SYSTEM.VAL(REAL,x)
  135. END AddR;
  136. PROCEDURE SubR*(l,r: REAL): REAL;
  137. BEGIN RETURN AddR(l,-r)
  138. END SubR;
  139. PROCEDURE MulR*(l,r: REAL): REAL; (* float 32 * float 32 => float 32 *)
  140. VAR x,y,xe, ye, sign: LONGINT;
  141. BEGIN
  142. x := SYSTEM.VAL(LONGINT,l);
  143. y := SYSTEM.VAL(LONGINT,r);
  144. IF NULLF(y) THEN x := 0
  145. ELSIF ~NULLF(x) THEN
  146. sign := MSK(x, S) + MSK(y, S);
  147. xe := MSK(x, expo) - bias; x := MSK(x, mant) + C;
  148. ye := MSK(y, expo) - bias; y := MSK(y, mant) + C;
  149. xe := xe + ye; x := x * y (*testing: SimulatedMul(x,y) *);
  150. IF xe < -bias THEN x := 0 (*underflow*)
  151. ELSIF (xe <= bias) THEN
  152. x := ROT(MSK(x, mant1),-24)+ROT(H(),8);
  153. IF MSK(x, C) = 0 THEN (*normalize*)
  154. x := ROT(x, -31); xe := xe - C
  155. END;
  156. IF x < 0 THEN x := x + 1 (*round*) END;
  157. x := MSK(x, mant2) + xe + bias + sign;
  158. ELSE x := M;
  159. END
  160. ELSE x := 0;
  161. END ;
  162. RETURN SYSTEM.VAL(REAL,x)
  163. END MulR;
  164. PROCEDURE DivR*(l,r: REAL): REAL; (* float 32 / float 32 => float 32 *)
  165. VAR x,y,xe, ye, q, n, sign: LONGINT;
  166. BEGIN
  167. x := SYSTEM.VAL(LONGINT,l);
  168. y := SYSTEM.VAL(LONGINT,r);
  169. ASSERT(ABS(y) # 0,26);
  170. IF ~NULLF(x) THEN
  171. sign := MSK(x, S) + MSK(y, S);
  172. xe := MSK(x, expo) - bias; x := MSK(x, mant) + C;
  173. ye := MSK(y, expo) - bias; y := MSK(y, mant) + C;
  174. xe := xe - ye;
  175. IF x < y THEN x := ROT(x, -31); xe := xe - C END ;
  176. n := 25; q := 0;
  177. REPEAT q := ROT(q, -31);
  178. IF x >= y THEN x := x - y; INC(q) END ;
  179. x := ROT(x, -31); DEC(n)
  180. UNTIL n = 0;
  181. q := ROT(MSK(q+1, -2), -1); (*round*)
  182. IF xe < -bias THEN x := 0 (*underflow*)
  183. ELSIF (xe <= bias) THEN x := q - C + xe + bias + sign
  184. ELSE x := M;
  185. END
  186. ELSE x := 0
  187. END ;
  188. RETURN SYSTEM.VAL(REAL,x)
  189. END DivR;
  190. PROCEDURE AbsR*(x: REAL): REAL;
  191. BEGIN
  192. IF x < 0 THEN RETURN -x ELSE RETURN x END
  193. END AbsR;
  194. PROCEDURE DivModL(dividend, divisor: LONGINT; VAR quotient, remainder: LONGINT);
  195. VAR d: LONGINT;
  196. BEGIN
  197. ASSERT(dividend >=0); ASSERT(divisor > 0);
  198. remainder := dividend;
  199. quotient := 0;
  200. d := divisor;
  201. REPEAT d := ASH(d,1) UNTIL (d > dividend) OR (d < 0);
  202. REPEAT d := LSH(d,-1); quotient := ASH(quotient,1);
  203. IF remainder >= d THEN remainder := remainder - d; quotient := quotient+1 END
  204. UNTIL d = divisor;
  205. END DivModL;
  206. (* 32 bit integer instructions *)
  207. PROCEDURE DivL*(l,r: LONGINT): LONGINT;
  208. VAR quotient, remainder: LONGINT;
  209. BEGIN
  210. IF l < 0 THEN
  211. DivModL(-l,r,quotient,remainder);
  212. RETURN -quotient-1;
  213. ELSE
  214. DivModL(l,r,quotient,remainder);
  215. RETURN quotient
  216. END;
  217. END DivL;
  218. PROCEDURE ModL*(l,r: LONGINT): LONGINT;
  219. VAR quotient, remainder: LONGINT;
  220. BEGIN
  221. IF l < 0 THEN
  222. DivModL(-l,r,quotient,remainder);
  223. RETURN r - remainder;
  224. ELSE
  225. DivModL(l,r,quotient,remainder);
  226. RETURN remainder
  227. END;
  228. END ModL;
  229. (* 64 bit integer instructions *)
  230. PROCEDURE DivH*(l,r: HUGEINT): HUGEINT ;
  231. BEGIN HALT(200);
  232. END DivH;
  233. PROCEDURE ModH*(l,r: HUGEINT): HUGEINT ;
  234. BEGIN HALT(200);
  235. END ModH;
  236. PROCEDURE AbsH*(x: HUGEINT): HUGEINT;
  237. BEGIN IF x < 0 THEN RETURN -x ELSE RETURN x END;
  238. END AbsH;
  239. PROCEDURE AslH*(l,r: HUGEINT): HUGEINT ;
  240. BEGIN HALT(200);
  241. END AslH;
  242. PROCEDURE LslH*(l,r: HUGEINT): HUGEINT ;
  243. BEGIN HALT(200);
  244. END LslH;
  245. PROCEDURE AsrH*(l,r: HUGEINT): HUGEINT;
  246. BEGIN HALT(200);
  247. END AsrH;
  248. PROCEDURE LsrH*(l,r: HUGEINT): HUGEINT ;
  249. BEGIN HALT(200);
  250. END LsrH;
  251. PROCEDURE RorH*(l,r: HUGEINT): HUGEINT;
  252. BEGIN HALT(200);
  253. END RorH;
  254. PROCEDURE RolH*(l,r: HUGEINT): HUGEINT;
  255. BEGIN HALT(200);
  256. END RolH;
  257. (* currently unused 64 bit float support
  258. (* conversions such as ENTIER, SHORT or implicit *)
  259. PROCEDURE ConvertXR*(x: LONGREAL): REAL;
  260. BEGIN HALT(200);
  261. END ConvertXR;
  262. PROCEDURE ConvertRX*(x: REAL): LONGREAL ;
  263. BEGIN HALT(200);
  264. END ConvertRX;
  265. PROCEDURE ConvertIX*(x: LONGINT): LONGREAL;
  266. VAR xe: LONGINT; h: HUGEINT;
  267. CONST B = 1023; C=10000000000000H;
  268. BEGIN
  269. IF x # 0 THEN
  270. h := ABS(x); xe := 52;
  271. IF h >= 2*C THEN
  272. REPEAT h := h DIV 2; INC(xe) UNTIL h < 2*C
  273. ELSIF h < C THEN
  274. REPEAT h := 2*h; DEC(xe) UNTIL h >= C
  275. END ;
  276. h := (xe + B -1)*C + h;
  277. IF x < 0 THEN h := -h END
  278. END ;
  279. RETURN SYSTEM.VAL(LONGREAL,h)
  280. END ConvertIX;
  281. PROCEDURE ConvertXI*(x: LONGREAL): LONGINT ;
  282. BEGIN HALT(200);
  283. END ConvertXI;
  284. PROCEDURE ConvertXH*(x: LONGREAL): HUGEINT ;
  285. BEGIN HALT(200);
  286. END ConvertXH;
  287. (* 64 bit float instructions *)
  288. PROCEDURE AddX*(l,r: LONGREAL): LONGREAL ;
  289. BEGIN HALT(200);
  290. END AddX;
  291. PROCEDURE SubX*(l,r: LONGREAL): LONGREAL ;
  292. BEGIN HALT(200);
  293. END SubX;
  294. PROCEDURE MulX*(l,r: LONGREAL): LONGREAL;
  295. BEGIN HALT(200);
  296. END MulX;
  297. PROCEDURE DivX*(l,r: LONGREAL): LONGREAL;
  298. BEGIN HALT(200);
  299. END DivX;
  300. PROCEDURE AbsX*(x: LONGREAL): LONGREAL;
  301. BEGIN IF x < 0 THEN RETURN -x ELSE RETURN x END
  302. END AbsX;
  303. PROCEDURE ConvertHX*(x: HUGEINT): LONGREAL;
  304. BEGIN HALT(200);
  305. END ConvertHX;
  306. *)
  307. (* compare strings,
  308. returns 0 if strings are equal,
  309. returns +1 if left is lexicographic greater than right,
  310. returns -1 if left is lexicographics smaller than right
  311. traps if src or destination is not 0X terminated and comparison is not finished
  312. *)
  313. PROCEDURE CompareString*(CONST left,right: ARRAY OF CHAR): SHORTINT;
  314. VAR i: LONGINT; res: SHORTINT; l,r: CHAR;
  315. BEGIN
  316. i := 0; res := 0;
  317. LOOP
  318. l := left[i]; (* index check included *)
  319. r := right[i]; (* index check included *)
  320. IF (l > r) THEN
  321. res := 1; EXIT
  322. ELSIF (l<r) THEN
  323. res := -1; EXIT
  324. ELSIF l=0X THEN
  325. EXIT
  326. END;
  327. INC(i);
  328. END;
  329. RETURN res
  330. END CompareString;
  331. (* copy string from src to dest, emits trap if not 0X terminated or destination too short *)
  332. PROCEDURE CopyString*(VAR dest: ARRAY OF CHAR; CONST src: ARRAY OF CHAR);
  333. VAR i: LONGINT; ch :CHAR; l1,l2: LONGINT;
  334. BEGIN
  335. (*
  336. i := 0;
  337. REPEAT
  338. ch := src[i]; (* index check included *)
  339. dest[i] := ch; (* index check included *)
  340. INC(i);
  341. UNTIL ch=0X;
  342. *)
  343. (*! currently implemented: old PACO semantics *)
  344. l1 := LEN(dest);
  345. l2 := LEN(src);
  346. IF l2 < l1 THEN l1 := l2 END;
  347. SYSTEM.MOVE(ADDRESSOF(src[0]),ADDRESSOF(dest[0]),l1);
  348. dest[l1-1] := 0X;
  349. END CopyString;
  350. PROCEDURE EnsureAllocatedStack*(size: SIZE);
  351. VAR i,temp: ADDRESS;
  352. BEGIN
  353. FOR i := 0 TO size BY 4096 DO
  354. temp := SYSTEM.GET32(ADDRESSOF(i)-i);
  355. (*
  356. SYSTEM.PUT(ADDRESSOF(val)-i,0);
  357. *)
  358. END;
  359. (*
  360. CODE{SYSTEM.i386}
  361. MOV EAX, [EBP+size]
  362. SHR EAX,12 ; divide by 4096
  363. MOV ECX,-4
  364. start:
  365. MOV EDX,[EBP+ECX]
  366. SUB ECX,4096
  367. TST EAX
  368. DEC EAX
  369. JNZ start
  370. *)
  371. END EnsureAllocatedStack;
  372. (*! should not be used, linker cannot deal with fixup here -- late time code generation does not help because this is a code section *)
  373. (*
  374. PROCEDURE {NOPAF} LastAddress; (* empty procedure, linker places this always at the end of code memory *)
  375. CODE
  376. END LastAddress;
  377. *)
  378. BEGIN
  379. lastDataAddress := ADDRESSOF(emptyVariable);
  380. END Builtins.