| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- (*
- 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.
|