ARM.FPE64.Mod 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. MODULE FPE64;
  2. IMPORT SYSTEM;
  3. CONST
  4. B = 1023; M = 40000000H; C = 100000H; E = 800H; K = 400H;
  5. TYPE
  6. Float64* = RECORD
  7. low*, high*: LONGINT
  8. END;
  9. Float32* = LONGINT;
  10. PROCEDURE Addd(VAR x1, x0: LONGINT; y1, y0: LONGINT);
  11. CODE
  12. LDR R2, [FP, #+x1]; R2 := address of x1
  13. LDR R3, [FP, #+x0]; R3 := address of x0
  14. LDR R0, [FP, #+y1]; R0 := y1
  15. LDR R1, [FP, #+y0]; R1 := y0
  16. LDR R4, [R2, #+0]; R4 := value of x1
  17. LDR R5, [R3, #+0]; R5 := value of x0
  18. ADDS R5, R5, R1;
  19. ADCS R4, R4, R0;
  20. STR R5, [R3, #+0]; store new value at x0
  21. STR R4, [R2, #+0]; store new value at x1
  22. END Addd;
  23. PROCEDURE Subd(VAR x1, x0: LONGINT; y1, y0: LONGINT);
  24. CODE
  25. LDR R2, [FP, #+x1]; R2 := address of x1
  26. LDR R3, [FP, #+x0]; R3 := address of x0
  27. LDR R0, [FP, #+y1]; R0 := y1
  28. LDR R1, [FP, #+y0]; R1 := y0
  29. LDR R4, [R2, #+0]; R4 := value of x1
  30. LDR R5, [R3, #+0]; R5 := value of x0
  31. SUBS R5, R5, R1;
  32. SBCS R4, R4, R0;
  33. STR R5, [R3, #+0]; store new value at x0
  34. STR R4, [R2, #+0]; store new value at x1
  35. END Subd;
  36. PROCEDURE Muld(x0, y0: LONGINT; VAR z1, z0: LONGINT);
  37. CODE
  38. LDR R2, [FP, #+z0]; R2 := address of resultLow
  39. LDR R3, [FP, #+z1]; R3: = address of resultHigh
  40. LDR R4, [FP, #+x0] ; R4 := left
  41. LDR R5, [FP, #+y0] ; R5: = right
  42. UMULL R0, R1, R4, R5
  43. STR R0, [R2, #+0]
  44. STR R1, [R3, #+0]
  45. END Muld;
  46. PROCEDURE AddFloat64Sigs(CONST a, b: Float64; VAR z: Float64); (* (a >= 0 & b >= 0) OR (a <= 0 & b <= 0) *)
  47. VAR x0, x1, xe, s, y0, y1, ye: LONGINT;
  48. BEGIN
  49. x0 := a.low;
  50. x1 := a.high;
  51. y0 := b.low;
  52. y1 := b.high;
  53. IF ((x0 # 0) OR (x1 # 0)) & ((y0 # 0) OR (y1 # 0)) THEN
  54. s := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, a.high) * {31});
  55. xe := x1 DIV C MOD E; (* exponent with bias *)
  56. x1 := x1 MOD C + C;
  57. ye := y1 DIV C MOD E; (* exponent with bias *)
  58. y1 := y1 MOD C + C;
  59. IF xe < ye THEN
  60. ye := ye - xe;
  61. xe := xe + ye; (* exponent with bias *)
  62. IF ye < 32 THEN
  63. x0 := LSH(x0, -ye) + LSH(x1, 32 - ye);
  64. x1 := LSH(x1, -ye)
  65. ELSIF ye < 64 THEN
  66. x0 := LSH(x1, 32 - ye);
  67. x1 := 0
  68. ELSE
  69. x0 := 0;
  70. x1 := 0
  71. END
  72. ELSIF ye < xe THEN
  73. ye := xe - ye;
  74. IF ye < 32 THEN
  75. y0 := LSH(y0, -ye) + LSH(y1, 32 - ye);
  76. y1 := LSH(y1, -ye)
  77. ELSIF ye < 64 THEN
  78. y0 := LSH(y1, 32 - ye);
  79. y1 := 0
  80. ELSE
  81. y0 := 0;
  82. y1 := 0
  83. END
  84. END;
  85. Addd(x1, x0, y1, y0);
  86. IF x1 >= 2*C THEN
  87. x0 := x0 DIV 2 + LSH(x1, 31);
  88. x1 := x1 DIV 2;
  89. INC(xe)
  90. END;
  91. IF xe > 7FEH THEN (* check overflow and underflow *)
  92. z.high := LONGINT(7FEFFFFFH) + s;
  93. z.low := -1;
  94. ELSIF xe < 0 THEN
  95. z.high := 0;
  96. z.low := 0
  97. ELSE
  98. z.high := xe*C + (x1 - C) + s;
  99. z.low := x0;
  100. END
  101. ELSIF (x0 = 0) & (x1 = 0) THEN
  102. z.high := y1;
  103. z.low := y0
  104. ELSE
  105. z.high := x1;
  106. z.low := x0;
  107. END;
  108. END AddFloat64Sigs;
  109. PROCEDURE SubFloat64Sigs(CONST a, b: Float64; VAR z: Float64); (* (a >= 0 & b <= 0) OR (a <= 0 & b >= 0) *)
  110. VAR x0, x1, s, y0, y1, xe, ye, z0, z1: LONGINT;
  111. BEGIN
  112. x0 := a.low;
  113. x1 := a.high;
  114. y0 := b.low;
  115. y1 := b.high;
  116. IF ((x0 # 0) OR (x1 # 0)) & ((y0 # 0) OR (y1 # 0)) THEN
  117. s := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, a.high) * {31});
  118. xe := x1 DIV C MOD E; (* exponent with bias *)
  119. x1 := x1 MOD C + C;
  120. ye := y1 DIV C MOD E; (* exponent with bias *)
  121. y1 := y1 MOD C + C;
  122. IF xe < ye THEN
  123. ye := ye - xe;
  124. xe := xe + ye; (* exponent with bias *)
  125. IF ye < 32 THEN
  126. x0 := LSH(x0, -ye) + LSH(x1, 32 - ye);
  127. x1 := LSH(x1, -ye)
  128. ELSIF ye < 64 THEN
  129. x0 := LSH(x1, 32 - ye);
  130. x1 := 0
  131. ELSE
  132. x0 := 0;
  133. x1 := 0
  134. END;
  135. (* swap x and y *)
  136. z0 := x0; x0 := y0; y0 := z0;
  137. z1 := x1; x1 := y1; y1 := z1;
  138. (* result has inversed sign of x *)
  139. s := SYSTEM.XOR(s, LONGINT(80000000H))
  140. ELSIF ye < xe THEN
  141. ye := xe - ye;
  142. IF ye < 32 THEN
  143. y0 := LSH(y0, -ye) + LSH(y1, 32 - ye);
  144. y1 := LSH(y1, -ye)
  145. ELSIF ye < 64 THEN
  146. y0 := LSH(y1, 32 - ye);
  147. y1 := 0
  148. ELSE
  149. y0 := 0;
  150. y1 := 0
  151. END
  152. ELSE (* xe = ye, check if x > y *)
  153. IF LessThanUH(x0, x1, y0, y1) THEN (* x < y, swap x and y *)
  154. z0 := x0; x0 := y0; y0 := z0;
  155. z1 := x1; x1 := y1; y1 := z1;
  156. (* result has inversed sign of x *)
  157. s := SYSTEM.XOR(s, LONGINT(80000000H))
  158. END;
  159. END;
  160. Subd(x1, x0, y1, y0);
  161. IF (x0 # 0) OR (x1 # 0) THEN
  162. WHILE x1 < C DO x1 := 2*x1 + LSH(x0, -31); x0 := x0*2; DEC(xe) END;
  163. IF xe > 7FEH THEN (* check overflow and underflow *)
  164. z.high := LONGINT(7FEFFFFFH) + s;
  165. z.low := -1;
  166. ELSIF xe < 0 THEN
  167. z.high := 0;
  168. z.low := 0
  169. ELSE
  170. z.high := xe*C + (x1 - C) + s;
  171. z.low := x0;
  172. END
  173. ELSE
  174. z.low := 0;
  175. z.high := 0;
  176. END
  177. ELSIF (x0 = 0) & (x1 = 0) & ((y0 # 0) OR (y1 # 0)) THEN
  178. z.low := y0;
  179. z.high := SYSTEM.XOR(y1, LONGINT(80000000H)) (* inverse sign *)
  180. ELSE
  181. z.low := x0;
  182. z.high := x1
  183. END
  184. END SubFloat64Sigs;
  185. PROCEDURE Neg*(CONST a: Float64; VAR z: Float64);
  186. BEGIN
  187. z.low := a.low;
  188. z.high := SYSTEM.XOR(a.high, LONGINT(80000000H));
  189. END Neg;
  190. PROCEDURE Abs*(CONST a: Float64; VAR z: Float64);
  191. BEGIN
  192. z.low := a.low;
  193. z.high := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, a.high)-{31});
  194. END Abs;
  195. PROCEDURE Add*(CONST a, b: Float64; VAR z: Float64);
  196. VAR t: Float64;
  197. BEGIN
  198. IF SYSTEM.XOR(a.high, b.high) < 0 THEN
  199. t.high := SYSTEM.XOR(b.high, LONGINT(80000000H));
  200. t.low := b.low;
  201. SubFloat64Sigs(a, t, z)
  202. ELSE
  203. AddFloat64Sigs(a, b, z)
  204. END
  205. END Add;
  206. PROCEDURE Sub*(CONST a, b: Float64; VAR z: Float64);
  207. VAR t: Float64;
  208. BEGIN
  209. IF SYSTEM.XOR(a.high, b.high) < 0 THEN
  210. t.high := SYSTEM.XOR(b.high, LONGINT(80000000H));
  211. t.low := b.low;
  212. AddFloat64Sigs(a, t, z)
  213. ELSE
  214. SubFloat64Sigs(a, b, z)
  215. END
  216. END Sub;
  217. PROCEDURE Addd0(x1, x0, y1, y0: LONGINT; VAR z1, z0: LONGINT);
  218. CODE
  219. LDR R2, [FP, #+z1]; R2 := address of z1
  220. LDR R3, [FP, #+z0]; R3 := address of z0
  221. LDR R0, [FP, #+y1]; R0 := y1
  222. LDR R1, [FP, #+y0]; R1 := y0
  223. LDR R4, [FP, #+x1]; R4 := x1
  224. LDR R5, [FP, #+x0]; R5 := x0
  225. ADDS R5, R5, R1;
  226. ADCS R4, R4, R0;
  227. STR R5, [R3, #+0]; store new value at x0
  228. STR R4, [R2, #+0]; store new value at x1
  229. END Addd0;
  230. PROCEDURE Mul64To128(a1, a0, b1, b0: LONGINT; VAR z3, z2, z1, z0: LONGINT);
  231. VAR more1, more2: LONGINT;
  232. BEGIN
  233. Muld(a0, b0, z1, z0);
  234. Muld(a0, b1, z2, more2);
  235. Addd0(z2, more2, 0, z1, z2, z1);
  236. Muld(a1, b1, z3, more1);
  237. Addd0(z3, more1, 0, z2, z3, z2);
  238. Muld(a1, b0, more1, more2);
  239. Addd0(more1, more2, 0, z1, more1, z1);
  240. Addd0(z3, z2, 0, more1, z3, z2)
  241. END Mul64To128;
  242. PROCEDURE Mul*(CONST x, y: Float64; VAR z: Float64);
  243. VAR x0, x1, xe, y0, y1, ye, s, z0, z1, z2, z3: LONGINT;
  244. BEGIN
  245. x0 := x.low;
  246. x1 := x.high;
  247. y0 := y.low;
  248. y1 := y.high;
  249. (* sign of result *)
  250. s := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, SYSTEM.XOR(x1,y1)) * {31});
  251. IF ((x0 # 0) OR (x1 # 0)) & ((y0 # 0) OR (y1 # 0)) THEN
  252. xe := x1 DIV C MOD E; (* exponent with bias *)
  253. x1 := x1 MOD C + C;
  254. ye := y1 DIV C MOD E; (* exponent with bias *)
  255. y1 := y1 MOD C + C;
  256. xe := xe + ye - B; (* exponent with bias *)
  257. Mul64To128(x1, x0, y1, y0, z3, z2, z1, z0);
  258. IF z3 < 200H THEN
  259. z3 := z3*1000H + LSH(z2, -20);
  260. z2 := z2*1000H + LSH(z1, -20);
  261. ELSE
  262. z3 := z3*800H + LSH(z2, -21);
  263. z2 := z2*800H + LSH(z1, -21);
  264. INC(xe)
  265. END;
  266. IF xe > 7FEH THEN (* overflow *)
  267. z.high := LONGINT(7FEFFFFFH) + s;
  268. z.low := -1;
  269. ELSIF xe < 0 THEN (* underflow *)
  270. z.high := 0;
  271. z.low := 0;
  272. ELSE
  273. z.high := xe*C + (z3 - C) + s;
  274. z.low := z2;
  275. END
  276. ELSE
  277. z.high := 0;
  278. z.low := 0;
  279. END;
  280. END Mul;
  281. (* Less than unsigned LONGINT *)
  282. PROCEDURE LessThanUL(CONST x, y: LONGINT): BOOLEAN;
  283. BEGIN
  284. RETURN (LSH(x, -1) < LSH(y, -1)) OR ((LSH(x, -1) = LSH(y, -1)) & ODD(x) & ~ODD(y));
  285. END LessThanUL;
  286. (* Less than unsigned HUGEINT *)
  287. PROCEDURE LessThanUH(CONST x1, x0, y1, y0: LONGINT): BOOLEAN;
  288. BEGIN
  289. RETURN LessThanUL(x1, y1) OR ((x1 = y1) & LessThanUL(x0, y0));
  290. END LessThanUH;
  291. PROCEDURE LessThan*(CONST x, y: Float64): BOOLEAN;
  292. VAR z: Float64;
  293. BEGIN
  294. Sub(x, y, z);
  295. RETURN LSH(z.high, -31) # 0;
  296. END LessThan;
  297. PROCEDURE Div*(CONST x, y: Float64; VAR z: Float64);
  298. VAR x0, x1, y0, y1, s, xe, ye, q1, q0: LONGINT;
  299. BEGIN
  300. x0 := x.low;
  301. x1 := x.high;
  302. y0 := y.low;
  303. y1 := y.high;
  304. (* sign of result *)
  305. s := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, SYSTEM.XOR(x1,y1)) * {31});
  306. IF (x0 = 0) & (x1 = 0) THEN
  307. (* 0/y = 0 *)
  308. (* 0/0, 0/inf, 0/NaN, -0/... not handled *)
  309. z.high := 0;
  310. z.low := 0;
  311. ELSIF (y0 = 0) & (y1 = 0) THEN
  312. (* inf/0, NaN/0, .../-0 not handled *)
  313. z.high := LONGINT(7FEFFFFFH) + s;
  314. z.low := -1;
  315. ELSE
  316. xe := x1 DIV C MOD E; (* exponent with bias *)
  317. ye := y1 DIV C MOD E; (* exponent with bias *)
  318. xe := xe - ye + B; (* exponent with bias *)
  319. x1 := x1 MOD C + C;
  320. y1 := y1 MOD C + C;
  321. IF LessThanUH(x1, x0, y1, y0) THEN
  322. (* x < y *)
  323. (* x := 2x *)
  324. x1 := 2*x1 + LSH(x0, -31);
  325. x0 := 2*x0;
  326. DEC(xe);
  327. END;
  328. IF xe < 0 THEN (* underflow *)
  329. z.high := 0;
  330. z.low := 0;
  331. ELSIF xe > 7FEH THEN (* overflow *)
  332. z.high := LONGINT(7FEFFFFFH) + s;
  333. z.low := -1;
  334. ELSE (* divide *)
  335. q1 := 0;
  336. q0 := 0;
  337. WHILE q1 < LONGINT(200000H) DO
  338. (* q := 2q *)
  339. q1 := 2*q1 + LSH(q0, -31);
  340. q0 := 2*q0;
  341. IF ((y1 = x1) & (y0 = x0)) OR LessThanUH(y1, y0, x1, x0) THEN
  342. (* y <= x *)
  343. (* x := x - y *)
  344. x1 := x1 - y1; (* no underflow since x1 >= y1 *)
  345. IF LessThanUL(x0, y0) THEN
  346. DEC(x1);
  347. END;
  348. x0 := x0 - y0; (* underflow is handled above *)
  349. (* INC(q) *)
  350. INC(q0); (* no overflow since bit0 is always 0 *)
  351. END;
  352. (* x := 2x *)
  353. x1 := 2*x1 + LSH(x0, -31);
  354. x0 := 2*x0;
  355. END;
  356. (** round **)
  357. (* INC(q) *)
  358. INC(q0);
  359. IF q0 = 0 THEN (* overflow *)
  360. INC(q1);
  361. END;
  362. (* q := q DIV 2 *)
  363. q0 := LSH(q0, -1) + LSH(q1, 31);
  364. q1 := LSH(q1, -1);
  365. z.low := q0;
  366. z.high := xe*C + (q1 - C) + s;
  367. END;
  368. END;
  369. END Div;
  370. PROCEDURE FloatInt64*(i: HUGEINT; VAR z: Float64);
  371. VAR x0, x1, xe: HUGEINT;
  372. BEGIN
  373. x1 := i;
  374. x0 := 0;
  375. IF x1 # 0 THEN
  376. IF x1 = HUGEINT(8000000000000000H) THEN
  377. x1 := HUGEINT(4000000000000000H);
  378. xe := 63+B;
  379. ELSE
  380. IF x1 < 0 THEN
  381. x1 := -x1
  382. END;
  383. xe := 62+B;
  384. WHILE x1 < HUGEINT(4000000000000000H) DO x1 := x1*2; DEC(xe) END;
  385. END;
  386. x1 := ASH(x1, -32); (*x1 DIV 100000000H;*)
  387. z.low := LONGINT(x1)*400000H;
  388. x1 := LSH(x1, -10);
  389. z.high := LONGINT(xe*C) + (LONGINT(x1)-C) + SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ASH(i, -32)) * {31});
  390. ELSE
  391. z.low := LONGINT(x0);
  392. z.high := LONGINT(x1)
  393. END
  394. END FloatInt64;
  395. PROCEDURE Float*(i: LONGINT; VAR z: Float64);
  396. VAR x0, x1, xe: LONGINT;
  397. BEGIN
  398. x1 := i;
  399. x0 := 0;
  400. IF x1 # 0 THEN
  401. IF x1 = LONGINT(80000000H) THEN
  402. x1 := LONGINT(40000000H);
  403. xe := 31+B;
  404. ELSE
  405. IF x1 < 0 THEN
  406. x1 := -x1
  407. END;
  408. xe := 30+B;
  409. WHILE x1 < LONGINT(40000000H) DO x1 := x1*2; DEC(xe) END;
  410. END;
  411. z.low := x1*400000H;
  412. x1 := LSH(x1, -10);
  413. z.high := xe*C + (x1-C) + SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, i) * {31});
  414. ELSE
  415. z.low := x0;
  416. z.high := x1
  417. END
  418. END Float;
  419. PROCEDURE FixInt64*(CONST a: Float64): HUGEINT;
  420. (*VAR x0, x1, xe: LONGINT;
  421. x: LONGINT;
  422. BEGIN
  423. x0 := a.low;
  424. x1 := a.high;
  425. IF (x0 # 0) OR (x1 # 0) THEN
  426. xe := x1 DIV C MOD E - B;
  427. IF x1 > 0 THEN
  428. x := (x1 MOD C + C)*K;
  429. x := LSH(x0, -22) + x
  430. ELSE
  431. x := -(x1 MOD C + C)*K;
  432. x := x - LSH(x0, -22)
  433. END;
  434. IF xe < 0 THEN x := ASH(x, -31)
  435. ELSIF xe <= 30 THEN x := ASH(x, xe - 30)
  436. ELSIF x > 0 THEN x := HUGEINT(7FFFFFFFFFFFFFFFH)
  437. ELSE x := HUGEINT(8000000000000000H)
  438. END
  439. END;
  440. RETURN x1*)
  441. VAR
  442. x: HUGEINT;
  443. xe: LONGINT;
  444. BEGIN
  445. x := SYSTEM.GET64(ADDRESSOF(a));
  446. IF x # 0 THEN
  447. xe := LONGINT(LSH(x, -32)) DIV C MOD E - B;
  448. x := LSH(LSH(x, 12), -12) + 10000000000000H;
  449. IF a.high < 0 THEN
  450. x := -x
  451. END;
  452. IF xe < 0 THEN x := ASH(x, -53)
  453. ELSIF xe <= 52 THEN x := ASH(x, xe -52)
  454. ELSIF x > 0 THEN x := HUGEINT(7FFFFFFFFFFFFFFFH)
  455. ELSE x := HUGEINT(8000000000000000H)
  456. END
  457. END;
  458. RETURN x
  459. END FixInt64;
  460. PROCEDURE Fix*(CONST a: Float64): LONGINT;
  461. VAR x0, x1, xe: LONGINT;
  462. BEGIN
  463. x0 := a.low;
  464. x1 := a.high;
  465. IF (x0 # 0) OR (x1 # 0) THEN
  466. xe := x1 DIV C MOD E - B;
  467. IF x1 > 0 THEN
  468. x1 := (x1 MOD C + C)*K;
  469. x1 := LSH(x0, -22) + x1
  470. ELSE
  471. x1 := -(x1 MOD C + C)*K;
  472. x1 := x1 - LSH(x0, -22)
  473. END;
  474. IF xe < 0 THEN x1 := ASH(x1, -31)
  475. ELSIF xe <= 30 THEN x1 := ASH(x1, xe - 30)
  476. ELSIF x1 > 0 THEN x1 := LONGINT(7FFFFFFFH)
  477. ELSE x1 := LONGINT(80000000H)
  478. END
  479. END;
  480. RETURN x1
  481. END Fix;
  482. (* do not return floating point values in a register: on platforms supporting FPU this will be misinterpreted *)
  483. PROCEDURE Single*(VAR a: Float64): Float32;
  484. VAR x0, x1, s, xe, m: LONGINT; i: Float32;
  485. BEGIN
  486. x0 := a.low;
  487. x1 := a.high;
  488. s := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, x1) * {31});
  489. xe := x1 DIV C MOD E - B + 127; (* exponent with bias *)
  490. IF xe > 0FEH THEN (* overflow *)
  491. i := LONGINT(7F7FFFFFH) + s;
  492. ELSIF xe < 0 THEN (* underflow *)
  493. i := 0;
  494. ELSE
  495. (* extract mantissa and compute 1 + mantissa *)
  496. m := (x1 MOD C)*10H + x0 DIV 10000000H MOD 10H;
  497. INC(m);
  498. m := m DIV 2;
  499. (* make short float value *)
  500. i := xe*800000H + m + s;
  501. END;
  502. RETURN i;
  503. END Single;
  504. PROCEDURE Double*(x: REAL; VAR z: Float64);
  505. VAR i, m, xe: LONGINT;
  506. BEGIN
  507. SYSTEM.GET(ADDRESSOF(x), i);
  508. IF i = 0 THEN
  509. z.high := 0;
  510. z.low := 0;
  511. ELSE
  512. m := i MOD 800000H;
  513. xe := i DIV 800000H MOD 100H - 127 + B;
  514. z.high := xe*C + LSH(m, -3) + SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, i) * {31});
  515. z.low := m*20000000H;
  516. END
  517. END Double;
  518. END FPE64.
  519. nan = FFF8'0000'0000'0000
  520. inf = 7FF0'0000'0000'0000
  521. max = 7FEF'FFFF'FFFF'FFFF
  522. 1.5 = 3FF8'0000'0000'0000