forked from KolibriOS/kolibrios
498da3221e
git-svn-id: svn://kolibrios.org@8859 a494cfbc-eb01-0410-851d-a64ba20cac60
460 lines
7.7 KiB
Plaintext
460 lines
7.7 KiB
Plaintext
(*
|
|
BSD 2-Clause License
|
|
|
|
Copyright (c) 2020-2021, Anton Krotov
|
|
All rights reserved.
|
|
*)
|
|
|
|
MODULE FPU;
|
|
|
|
|
|
CONST
|
|
|
|
INF = 07F800000H;
|
|
NINF = 0FF800000H;
|
|
NAN = 07FC00000H;
|
|
|
|
|
|
PROCEDURE div2 (b, a: INTEGER): INTEGER;
|
|
VAR
|
|
n, e, r, s: INTEGER;
|
|
|
|
BEGIN
|
|
s := ORD(BITS(a) / BITS(b) - {0..30});
|
|
e := (a DIV 800000H) MOD 256 - (b DIV 800000H) MOD 256 + 127;
|
|
|
|
a := a MOD 800000H + 800000H;
|
|
b := b MOD 800000H + 800000H;
|
|
|
|
n := 800000H;
|
|
r := 0;
|
|
|
|
IF a < b THEN
|
|
a := a * 2;
|
|
DEC(e)
|
|
END;
|
|
|
|
WHILE (a > 0) & (n > 0) DO
|
|
IF a >= b THEN
|
|
INC(r, n);
|
|
DEC(a, b)
|
|
END;
|
|
a := a * 2;
|
|
n := n DIV 2
|
|
END;
|
|
|
|
IF e <= 0 THEN
|
|
e := 0;
|
|
r := 800000H;
|
|
s := 0
|
|
ELSIF e >= 255 THEN
|
|
e := 255;
|
|
r := 800000H
|
|
END
|
|
|
|
RETURN (r - 800000H) + e * 800000H + s
|
|
END div2;
|
|
|
|
|
|
PROCEDURE mul2 (b, a: INTEGER): INTEGER;
|
|
VAR
|
|
e, r, s: INTEGER;
|
|
|
|
BEGIN
|
|
s := ORD(BITS(a) / BITS(b) - {0..30});
|
|
e := (a DIV 800000H) MOD 256 + (b DIV 800000H) MOD 256 - 127;
|
|
|
|
a := a MOD 800000H + 800000H;
|
|
b := b MOD 800000H + 800000H;
|
|
|
|
r := a * (b MOD 256);
|
|
b := b DIV 256;
|
|
r := LSR(r, 8);
|
|
|
|
INC(r, a * (b MOD 256));
|
|
b := b DIV 256;
|
|
r := LSR(r, 8);
|
|
|
|
INC(r, a * (b MOD 256));
|
|
r := LSR(r, 7);
|
|
|
|
IF r >= 1000000H THEN
|
|
r := r DIV 2;
|
|
INC(e)
|
|
END;
|
|
|
|
IF e <= 0 THEN
|
|
e := 0;
|
|
r := 800000H;
|
|
s := 0
|
|
ELSIF e >= 255 THEN
|
|
e := 255;
|
|
r := 800000H
|
|
END
|
|
|
|
RETURN (r - 800000H) + e * 800000H + s
|
|
END mul2;
|
|
|
|
|
|
PROCEDURE add2 (b, a: INTEGER): INTEGER;
|
|
VAR
|
|
t, e, d: INTEGER;
|
|
|
|
BEGIN
|
|
e := (a DIV 800000H) MOD 256;
|
|
t := (b DIV 800000H) MOD 256;
|
|
d := e - t;
|
|
|
|
a := a MOD 800000H + 800000H;
|
|
b := b MOD 800000H + 800000H;
|
|
|
|
IF d > 0 THEN
|
|
IF d < 24 THEN
|
|
b := LSR(b, d)
|
|
ELSE
|
|
b := 0
|
|
END
|
|
ELSIF d < 0 THEN
|
|
IF d > -24 THEN
|
|
a := LSR(a, -d)
|
|
ELSE
|
|
a := 0
|
|
END;
|
|
e := t
|
|
END;
|
|
|
|
INC(a, b);
|
|
|
|
IF a >= 1000000H THEN
|
|
a := a DIV 2;
|
|
INC(e)
|
|
END;
|
|
|
|
IF e >= 255 THEN
|
|
e := 255;
|
|
a := 800000H
|
|
END
|
|
|
|
RETURN (a - 800000H) + e * 800000H
|
|
END add2;
|
|
|
|
|
|
PROCEDURE sub2 (b, a: INTEGER): INTEGER;
|
|
VAR
|
|
t, e, d, s: INTEGER;
|
|
|
|
BEGIN
|
|
e := (a DIV 800000H) MOD 256;
|
|
t := (b DIV 800000H) MOD 256;
|
|
|
|
a := a MOD 800000H + 800000H;
|
|
b := b MOD 800000H + 800000H;
|
|
|
|
d := e - t;
|
|
|
|
IF (d > 0) OR (d = 0) & (a >= b) THEN
|
|
s := 0
|
|
ELSE
|
|
e := t;
|
|
d := -d;
|
|
t := a;
|
|
a := b;
|
|
b := t;
|
|
s := 80000000H
|
|
END;
|
|
|
|
IF d > 0 THEN
|
|
IF d < 24 THEN
|
|
b := LSR(b, d)
|
|
ELSE
|
|
b := 0
|
|
END
|
|
END;
|
|
|
|
DEC(a, b);
|
|
|
|
IF a = 0 THEN
|
|
e := 0;
|
|
a := 800000H;
|
|
s := 0
|
|
ELSE
|
|
WHILE a < 800000H DO
|
|
a := a * 2;
|
|
DEC(e)
|
|
END
|
|
END;
|
|
|
|
IF e <= 0 THEN
|
|
e := 0;
|
|
a := 800000H;
|
|
s := 0
|
|
END
|
|
|
|
RETURN (a - 800000H) + e * 800000H + s
|
|
END sub2;
|
|
|
|
|
|
PROCEDURE zero (VAR x: INTEGER);
|
|
BEGIN
|
|
IF LSR(LSL(x, 1), 24) = 0 THEN
|
|
x := 0
|
|
END
|
|
END zero;
|
|
|
|
|
|
PROCEDURE isNaN (a: INTEGER): BOOLEAN;
|
|
RETURN (a > INF) OR (a < 0) & (a > NINF)
|
|
END isNaN;
|
|
|
|
|
|
PROCEDURE isInf (a: INTEGER): BOOLEAN;
|
|
RETURN LSL(a, 1) = 0FF000000H
|
|
END isInf;
|
|
|
|
|
|
PROCEDURE isNormal (a, b: INTEGER): BOOLEAN;
|
|
RETURN (LSR(LSL(a, 1), 24) # 255) & (LSR(LSL(a, 1), 24) # 0) &
|
|
(LSR(LSL(b, 1), 24) # 255) & (LSR(LSL(b, 1), 24) # 0)
|
|
END isNormal;
|
|
|
|
|
|
PROCEDURE add* (b, a: INTEGER): INTEGER;
|
|
VAR
|
|
r: INTEGER;
|
|
|
|
BEGIN
|
|
zero(a); zero(b);
|
|
|
|
IF isNormal(a, b) THEN
|
|
|
|
IF a > 0 THEN
|
|
IF b > 0 THEN
|
|
r := add2(b, a)
|
|
ELSE
|
|
r := sub2(b, a)
|
|
END
|
|
ELSE
|
|
IF b > 0 THEN
|
|
r := sub2(a, b)
|
|
ELSE
|
|
r := add2(b, a) + 80000000H
|
|
END
|
|
END
|
|
|
|
ELSIF isNaN(a) OR isNaN(b) THEN
|
|
r := NAN
|
|
ELSIF isInf(a) & isInf(b) THEN
|
|
IF a = b THEN
|
|
r := a
|
|
ELSE
|
|
r := NAN
|
|
END
|
|
ELSIF isInf(a) THEN
|
|
r := a
|
|
ELSIF isInf(b) THEN
|
|
r := b
|
|
ELSIF a = 0 THEN
|
|
r := b
|
|
ELSIF b = 0 THEN
|
|
r := a
|
|
END
|
|
|
|
RETURN r
|
|
END add;
|
|
|
|
|
|
PROCEDURE sub* (b, a: INTEGER): INTEGER;
|
|
VAR
|
|
r: INTEGER;
|
|
|
|
BEGIN
|
|
zero(a); zero(b);
|
|
|
|
IF isNormal(a, b) THEN
|
|
|
|
IF a > 0 THEN
|
|
IF b > 0 THEN
|
|
r := sub2(b, a)
|
|
ELSE
|
|
r := add2(b, a)
|
|
END
|
|
ELSE
|
|
IF b > 0 THEN
|
|
r := add2(b, a) + 80000000H
|
|
ELSE
|
|
r := sub2(a, b)
|
|
END
|
|
END
|
|
|
|
ELSIF isNaN(a) OR isNaN(b) THEN
|
|
r := NAN
|
|
ELSIF isInf(a) & isInf(b) THEN
|
|
IF a # b THEN
|
|
r := a
|
|
ELSE
|
|
r := NAN
|
|
END
|
|
ELSIF isInf(a) THEN
|
|
r := a
|
|
ELSIF isInf(b) THEN
|
|
r := INF + ORD(BITS(b) / {31} - {0..30})
|
|
ELSIF (a = 0) & (b = 0) THEN
|
|
r := 0
|
|
ELSIF a = 0 THEN
|
|
r := ORD(BITS(b) / {31})
|
|
ELSIF b = 0 THEN
|
|
r := a
|
|
END
|
|
|
|
RETURN r
|
|
END sub;
|
|
|
|
|
|
PROCEDURE mul* (b, a: INTEGER): INTEGER;
|
|
VAR
|
|
r: INTEGER;
|
|
|
|
BEGIN
|
|
zero(a); zero(b);
|
|
|
|
IF isNormal(a, b) THEN
|
|
r := mul2(b, a)
|
|
ELSIF isNaN(a) OR isNaN(b) OR (isInf(a) & (b = 0)) OR (isInf(b) & (a = 0)) THEN
|
|
r := NAN
|
|
ELSIF isInf(a) OR isInf(b) THEN
|
|
r := INF + ORD(BITS(a) / BITS(b) - {0..30})
|
|
ELSIF (a = 0) OR (b = 0) THEN
|
|
r := 0
|
|
END
|
|
|
|
RETURN r
|
|
END mul;
|
|
|
|
|
|
PROCEDURE _div* (b, a: INTEGER): INTEGER;
|
|
VAR
|
|
r: INTEGER;
|
|
|
|
BEGIN
|
|
zero(a); zero(b);
|
|
|
|
IF isNormal(a, b) THEN
|
|
r := div2(b, a)
|
|
ELSIF isNaN(a) OR isNaN(b) OR isInf(a) & isInf(b) THEN
|
|
r := NAN
|
|
ELSIF isInf(a) THEN
|
|
r := INF + ORD(BITS(a) / BITS(b) - {0..30})
|
|
ELSIF isInf(b) THEN
|
|
r := 0
|
|
ELSIF a = 0 THEN
|
|
IF b = 0 THEN
|
|
r := NAN
|
|
ELSE
|
|
r := 0
|
|
END
|
|
ELSIF b = 0 THEN
|
|
IF a > 0 THEN
|
|
r := INF
|
|
ELSE
|
|
r := NINF
|
|
END
|
|
END
|
|
|
|
RETURN r
|
|
END _div;
|
|
|
|
|
|
PROCEDURE cmp* (op, b, a: INTEGER): BOOLEAN;
|
|
VAR
|
|
res: BOOLEAN;
|
|
|
|
BEGIN
|
|
zero(a); zero(b);
|
|
|
|
IF isNaN(a) OR isNaN(b) THEN
|
|
res := op = 1
|
|
ELSE
|
|
IF (a < 0) & (b < 0) THEN
|
|
INC(op, 6)
|
|
END;
|
|
|
|
CASE op OF
|
|
|0, 6: res := a = b
|
|
|1, 7: res := a # b
|
|
|2, 10: res := a < b
|
|
|3, 11: res := a <= b
|
|
|4, 8: res := a > b
|
|
|5, 9: res := a >= b
|
|
END
|
|
END
|
|
|
|
RETURN res
|
|
END cmp;
|
|
|
|
|
|
PROCEDURE flt* (x: INTEGER): INTEGER;
|
|
VAR
|
|
n, y, s: INTEGER;
|
|
|
|
BEGIN
|
|
IF x = 0 THEN
|
|
s := 0;
|
|
x := 800000H;
|
|
n := -126
|
|
ELSIF x = 80000000H THEN
|
|
s := 80000000H;
|
|
x := 800000H;
|
|
n := 32
|
|
ELSE
|
|
IF x < 0 THEN
|
|
s := 80000000H;
|
|
x := -x
|
|
ELSE
|
|
s := 0
|
|
END;
|
|
n := 0;
|
|
y := x;
|
|
WHILE y > 0 DO
|
|
y := y DIV 2;
|
|
INC(n)
|
|
END;
|
|
IF n > 24 THEN
|
|
x := LSR(x, n - 24)
|
|
ELSE
|
|
x := LSL(x, 24 - n)
|
|
END
|
|
END
|
|
|
|
RETURN (x - 800000H) + (n + 126) * 800000H + s
|
|
END flt;
|
|
|
|
|
|
PROCEDURE floor* (x: INTEGER): INTEGER;
|
|
VAR
|
|
r, e: INTEGER;
|
|
|
|
BEGIN
|
|
zero(x);
|
|
|
|
e := (x DIV 800000H) MOD 256 - 127;
|
|
r := x MOD 800000H + 800000H;
|
|
|
|
IF (0 <= e) & (e <= 22) THEN
|
|
r := LSR(r, 23 - e) + ORD((x < 0) & (LSL(r, e + 9) # 0))
|
|
ELSIF (23 <= e) & (e <= 54) THEN
|
|
r := LSL(r, e - 23)
|
|
ELSIF (e < 0) & (x < 0) THEN
|
|
r := 1
|
|
ELSE
|
|
r := 0
|
|
END;
|
|
|
|
IF x < 0 THEN
|
|
r := -r
|
|
END
|
|
|
|
RETURN r
|
|
END floor;
|
|
|
|
|
|
END FPU. |