- 27A59F78F058FCD385EC1B2E7EDEF7D2A8936EE3BF81338A64C786BC5B208BEFA8FB424EABD630F4042E4B32FFC5D6222778837BD04EAD9BFF096BA12BC32EA1+ A207AFCFF3ED13797843CA0F376E2E78404E8A2D695E06F4C8C1D3346FDAFB75B6BD507AEEB85CFD93D9CFF955FCD312C60BAFA2AA869EAB10500BBD6CB800EEffa/libffa/fz_arith.adb(19 . 9)(19 . 52)
24
25 with Word_Ops; use Word_Ops;
26
27
28 -- Fundamental Arithmetic operators on FZ:
29 package body FZ_Arith is
30
31 -- Destructive Add: X := X + Y; Overflow := Carry; optional OF_In
32 procedure FZ_Add_D(X : in out FZ;
33 Y : in FZ;
34 Overflow : out WBool;
35 OF_In : in WBool := 0) is
36 Carry : WBool := OF_In;
37 begin
38 for i in 0 .. Word_Index(X'Length - 1) loop
39 declare
40 A : constant Word := X(X'First + i);
41 B : constant Word := Y(Y'First + i);
42 S : constant Word := A + B + Carry;
43 begin
44 X(X'First + i) := S;
45 Carry := W_Carry(A, B, S);
46 end;
47 end loop;
48 Overflow := Carry;
49 end FZ_Add_D;
50 pragma Inline_Always(FZ_Add_D);
51
52
53 -- Destructive Add: X := X + W; Overflow := Carry
54 procedure FZ_Add_D_W(X : in out FZ;
55 W : in Word;
56 Overflow : out WBool) is
57 Carry : Word := W;
58 begin
59 for i in X'Range loop
60 declare
61 A : constant Word := X(I);
62 S : constant Word := A + Carry;
63 begin
64 X(i) := S;
65 Carry := W_Carry(A, 0, S);
66 end;
67 end loop;
68 Overflow := Carry;
69 end FZ_Add_D_W;
70 pragma Inline_Always(FZ_Add_D_W);
71
72
73 -- Sum := X + Y; Overflow := Carry
74 procedure FZ_Add(X : in FZ;
75 Y : in FZ;
(29 . 13)(72 . 13)
77 Overflow : out WBool) is
78 Carry : WBool := 0;
79 begin
80 for i in X'Range loop
81 for i in 0 .. Word_Index(X'Length - 1) loop
82 declare
83 A : constant Word := X(I);
84 B : constant Word := Y(I);
85 A : constant Word := X(X'First + i);
86 B : constant Word := Y(Y'First + i);
87 S : constant Word := A + B + Carry;
88 begin
89 Sum(i) := S;
90 Sum(Sum'First + i) := S;
91 Carry := W_Carry(A, B, S);
92 end;
93 end loop;
(103 . 4)(146 . 49)
95 end FZ_Sub;
96 pragma Inline_Always(FZ_Sub);
97
98
99 -- Destructive: If Cond is 1, NotN := ~N; otherwise NotN := N.
100 procedure FZ_Not_Cond_D(N : in out FZ;
101 Cond : in WBool)is
102
103 -- The inversion mask
104 Inv : constant Word := 0 - Cond;
105
106 begin
107
108 for i in N'Range loop
109
110 -- Invert (or, if Cond is 0, do nothing)
111 N(i) := N(i) xor Inv;
112
113 end loop;
114
115 end FZ_Not_Cond_D;
116 pragma Inline_Always(FZ_Not_Cond_D);
117
118
119 -- Subtractor that gets absolute value if underflowed, in const. time
120 procedure FZ_Sub_Abs(X : in FZ;
121 Y : in FZ;
122 Difference : out FZ;
123 Underflow : out WBool) is
124
125 O : Word := 0;
126 pragma Unreferenced(O);
127
128 begin
129
130 -- First, we subtract normally
131 FZ_Sub(X, Y, Difference, Underflow);
132
133 -- If borrow - negate,
134 FZ_Not_Cond_D(Difference, Underflow);
135
136 -- ... and also increment.
137 FZ_Add_D_W(Difference, Underflow, O);
138
139 end FZ_Sub_Abs;
140 pragma Inline_Always(FZ_Sub_Abs);
141
142
143 end FZ_Arith;