ARM.FPE64.Mod 12 KB

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