1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- S Y S T E M . V A X _ F L O A T _ O P E R A T I O N S --
9 -- Copyright (C) 1997-2011, Free Software Foundation, Inc. --
10 -- (Version for Alpha OpenVMS) --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 3, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. --
19 -- As a special exception under Section 7 of GPL version 3, you are granted --
20 -- additional permissions described in the GCC Runtime Library Exception, --
21 -- version 3.1, as published by the Free Software Foundation. --
23 -- You should have received a copy of the GNU General Public License and --
24 -- a copy of the GCC Runtime Library Exception along with this program; --
25 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
26 -- <http://www.gnu.org/licenses/>. --
28 -- GNAT was originally developed by the GNAT team at New York University. --
29 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 ------------------------------------------------------------------------------
34 with System.Machine_Code; use System.Machine_Code;
36 package body System.Vax_Float_Operations is
38 -- Ensure this gets compiled with -O to avoid extra (and possibly
39 -- improper) memory stores.
41 pragma Optimize (Time);
43 -- Declare the functions that do the conversions between floating-point
44 -- formats. Call the operands IEEE float so they get passed in
47 function Cvt_G_T (X : T) return T;
48 function Cvt_T_G (X : T) return T;
49 function Cvt_T_F (X : T) return S;
51 pragma Import (C, Cvt_G_T, "OTS$CVT_FLOAT_G_T");
52 pragma Import (C, Cvt_T_G, "OTS$CVT_FLOAT_T_G");
53 pragma Import (C, Cvt_T_F, "OTS$CVT_FLOAT_T_F");
55 -- In each of the conversion routines that are done with OTS calls,
56 -- we define variables of the corresponding IEEE type so that they are
57 -- passed and kept in the proper register class.
59 Debug_String_Buffer : String (1 .. 32);
60 -- Buffer used by all Debug_String_x routines for returning result
66 function D_To_G (X : D) return G is
70 Asm ("ldg %0,%1", T'Asm_Output ("=f", A), D'Asm_Input ("m", X));
71 Asm ("cvtdg %1,%0", T'Asm_Output ("=f", B), T'Asm_Input ("f", A));
72 Asm ("stg %1,%0", G'Asm_Output ("=m", C), T'Asm_Input ("f", B));
80 function F_To_G (X : F) return G is
84 Asm ("ldf %0,%1", T'Asm_Output ("=f", A), F'Asm_Input ("m", X));
85 Asm ("stg %1,%0", G'Asm_Output ("=m", B), T'Asm_Input ("f", A));
93 function F_To_S (X : F) return S is
98 -- Because converting to a wider FP format is a no-op, we say
99 -- A is 64-bit even though we are loading 32 bits into it.
101 Asm ("ldf %0,%1", T'Asm_Output ("=f", A), F'Asm_Input ("m", X));
103 B := S (Cvt_G_T (A));
111 function G_To_D (X : G) return D is
115 Asm ("ldg %0,%1", T'Asm_Output ("=f", A), G'Asm_Input ("m", X));
116 Asm ("cvtgd %1,%0", T'Asm_Output ("=f", B), T'Asm_Input ("f", A));
117 Asm ("stg %1,%0", D'Asm_Output ("=m", C), T'Asm_Input ("f", B));
125 function G_To_F (X : G) return F is
130 Asm ("ldg %0,%1", T'Asm_Output ("=f", A), G'Asm_Input ("m", X));
131 Asm ("cvtgf %1,%0", S'Asm_Output ("=f", B), T'Asm_Input ("f", A));
132 Asm ("stf %1,%0", F'Asm_Output ("=m", C), S'Asm_Input ("f", B));
140 function G_To_Q (X : G) return Q is
144 Asm ("ldg %0,%1", T'Asm_Output ("=f", A), G'Asm_Input ("m", X));
145 Asm ("cvtgq %1,%0", Q'Asm_Output ("=f", B), T'Asm_Input ("f", A));
153 function G_To_T (X : G) return T is
156 Asm ("ldg %0,%1", T'Asm_Output ("=f", A), G'Asm_Input ("m", X));
165 function F_To_Q (X : F) return Q is
167 return G_To_Q (F_To_G (X));
174 function Q_To_F (X : Q) return F is
178 Asm ("cvtqf %1,%0", S'Asm_Output ("=f", A), Q'Asm_Input ("f", X));
179 Asm ("stf %1,%0", F'Asm_Output ("=m", B), S'Asm_Input ("f", A));
187 function Q_To_G (X : Q) return G is
191 Asm ("cvtqg %1,%0", T'Asm_Output ("=f", A), Q'Asm_Input ("f", X));
192 Asm ("stg %1,%0", G'Asm_Output ("=m", B), T'Asm_Input ("f", A));
200 function S_To_F (X : S) return F is
204 A := Cvt_T_F (T (X));
205 Asm ("stf %1,%0", F'Asm_Output ("=m", B), S'Asm_Input ("f", A));
213 function T_To_D (X : T) return D is
215 return G_To_D (T_To_G (X));
222 function T_To_G (X : T) return G is
227 Asm ("stg %1,%0", G'Asm_Output ("=m", B), T'Asm_Input ("f", A));
235 function Abs_F (X : F) return F is
239 Asm ("ldf %0,%1", S'Asm_Output ("=f", A), F'Asm_Input ("m", X));
240 Asm ("cpys $f31,%1,%0", S'Asm_Output ("=f", B), S'Asm_Input ("f", A));
241 Asm ("stf %1,%0", F'Asm_Output ("=m", C), S'Asm_Input ("f", B));
249 function Abs_G (X : G) return G is
253 Asm ("ldg %0,%1", T'Asm_Output ("=f", A), G'Asm_Input ("m", X));
254 Asm ("cpys $f31,%1,%0", T'Asm_Output ("=f", B), T'Asm_Input ("f", A));
255 Asm ("stg %1,%0", G'Asm_Output ("=m", C), T'Asm_Input ("f", B));
263 function Add_F (X, Y : F) return F is
267 Asm ("ldf %0,%1", S'Asm_Output ("=f", X1), F'Asm_Input ("m", X));
268 Asm ("ldf %0,%1", S'Asm_Output ("=f", Y1), F'Asm_Input ("m", Y));
269 Asm ("addf %1,%2,%0", S'Asm_Output ("=f", R),
270 (S'Asm_Input ("f", X1), S'Asm_Input ("f", Y1)));
271 Asm ("stf %1,%0", F'Asm_Output ("=m", R1), S'Asm_Input ("f", R));
279 function Add_G (X, Y : G) return G is
283 Asm ("ldg %0,%1", T'Asm_Output ("=f", X1), G'Asm_Input ("m", X));
284 Asm ("ldg %0,%1", T'Asm_Output ("=f", Y1), G'Asm_Input ("m", Y));
285 Asm ("addg %1,%2,%0", T'Asm_Output ("=f", R),
286 (T'Asm_Input ("f", X1), T'Asm_Input ("f", Y1)));
287 Asm ("stg %1,%0", G'Asm_Output ("=m", R1), T'Asm_Input ("f", R));
295 procedure Debug_Output_D (Arg : D) is
297 System.IO.Put (D'Image (Arg));
304 procedure Debug_Output_F (Arg : F) is
306 System.IO.Put (F'Image (Arg));
313 procedure Debug_Output_G (Arg : G) is
315 System.IO.Put (G'Image (Arg));
322 function Debug_String_D (Arg : D) return System.Address is
323 Image_String : constant String := D'Image (Arg) & ASCII.NUL;
324 Image_Size : constant Integer := Image_String'Length;
326 Debug_String_Buffer (1 .. Image_Size) := Image_String;
327 return Debug_String_Buffer (1)'Address;
334 function Debug_String_F (Arg : F) return System.Address is
335 Image_String : constant String := F'Image (Arg) & ASCII.NUL;
336 Image_Size : constant Integer := Image_String'Length;
338 Debug_String_Buffer (1 .. Image_Size) := Image_String;
339 return Debug_String_Buffer (1)'Address;
346 function Debug_String_G (Arg : G) return System.Address is
347 Image_String : constant String := G'Image (Arg) & ASCII.NUL;
348 Image_Size : constant Integer := Image_String'Length;
350 Debug_String_Buffer (1 .. Image_Size) := Image_String;
351 return Debug_String_Buffer (1)'Address;
358 function Div_F (X, Y : F) return F is
362 Asm ("ldf %0,%1", S'Asm_Output ("=f", X1), F'Asm_Input ("m", X));
363 Asm ("ldf %0,%1", S'Asm_Output ("=f", Y1), F'Asm_Input ("m", Y));
364 Asm ("divf %1,%2,%0", S'Asm_Output ("=f", R),
365 (S'Asm_Input ("f", X1), S'Asm_Input ("f", Y1)));
366 Asm ("stf %1,%0", F'Asm_Output ("=m", R1), S'Asm_Input ("f", R));
374 function Div_G (X, Y : G) return G is
378 Asm ("ldg %0,%1", T'Asm_Output ("=f", X1), G'Asm_Input ("m", X));
379 Asm ("ldg %0,%1", T'Asm_Output ("=f", Y1), G'Asm_Input ("m", Y));
380 Asm ("divg %1,%2,%0", T'Asm_Output ("=f", R),
381 (T'Asm_Input ("f", X1), T'Asm_Input ("f", Y1)));
382 Asm ("stg %1,%0", G'Asm_Output ("=m", R1), T'Asm_Input ("f", R));
390 function Eq_F (X, Y : F) return Boolean is
393 Asm ("ldf %0,%1", S'Asm_Output ("=f", X1), F'Asm_Input ("m", X));
394 Asm ("ldf %0,%1", S'Asm_Output ("=f", Y1), F'Asm_Input ("m", Y));
395 Asm ("cmpgeq %1,%2,%0", S'Asm_Output ("=f", R),
396 (S'Asm_Input ("f", X1), S'Asm_Input ("f", Y1)));
404 function Eq_G (X, Y : G) return Boolean is
407 Asm ("ldg %0,%1", T'Asm_Output ("=f", X1), G'Asm_Input ("m", X));
408 Asm ("ldg %0,%1", T'Asm_Output ("=f", Y1), G'Asm_Input ("m", Y));
409 Asm ("cmpgeq %1,%2,%0", T'Asm_Output ("=f", R),
410 (T'Asm_Input ("f", X1), T'Asm_Input ("f", Y1)));
418 function Le_F (X, Y : F) return Boolean is
421 Asm ("ldf %0,%1", S'Asm_Output ("=f", X1), F'Asm_Input ("m", X));
422 Asm ("ldf %0,%1", S'Asm_Output ("=f", Y1), F'Asm_Input ("m", Y));
423 Asm ("cmpgle %1,%2,%0", S'Asm_Output ("=f", R),
424 (S'Asm_Input ("f", X1), S'Asm_Input ("f", Y1)));
432 function Le_G (X, Y : G) return Boolean is
435 Asm ("ldg %0,%1", T'Asm_Output ("=f", X1), G'Asm_Input ("m", X));
436 Asm ("ldg %0,%1", T'Asm_Output ("=f", Y1), G'Asm_Input ("m", Y));
437 Asm ("cmpgle %1,%2,%0", T'Asm_Output ("=f", R),
438 (T'Asm_Input ("f", X1), T'Asm_Input ("f", Y1)));
446 function Lt_F (X, Y : F) return Boolean is
449 Asm ("ldf %0,%1", S'Asm_Output ("=f", X1), F'Asm_Input ("m", X));
450 Asm ("ldf %0,%1", S'Asm_Output ("=f", Y1), F'Asm_Input ("m", Y));
451 Asm ("cmpglt %1,%2,%0", S'Asm_Output ("=f", R),
452 (S'Asm_Input ("f", X1), S'Asm_Input ("f", Y1)));
460 function Lt_G (X, Y : G) return Boolean is
463 Asm ("ldg %0,%1", T'Asm_Output ("=f", X1), G'Asm_Input ("m", X));
464 Asm ("ldg %0,%1", T'Asm_Output ("=f", Y1), G'Asm_Input ("m", Y));
465 Asm ("cmpglt %1,%2,%0", T'Asm_Output ("=f", R),
466 (T'Asm_Input ("f", X1), T'Asm_Input ("f", Y1)));
474 function Mul_F (X, Y : F) return F is
478 Asm ("ldf %0,%1", S'Asm_Output ("=f", X1), F'Asm_Input ("m", X));
479 Asm ("ldf %0,%1", S'Asm_Output ("=f", Y1), F'Asm_Input ("m", Y));
480 Asm ("mulf %1,%2,%0", S'Asm_Output ("=f", R),
481 (S'Asm_Input ("f", X1), S'Asm_Input ("f", Y1)));
482 Asm ("stf %1,%0", F'Asm_Output ("=m", R1), S'Asm_Input ("f", R));
490 function Mul_G (X, Y : G) return G is
494 Asm ("ldg %0,%1", T'Asm_Output ("=f", X1), G'Asm_Input ("m", X));
495 Asm ("ldg %0,%1", T'Asm_Output ("=f", Y1), G'Asm_Input ("m", Y));
496 Asm ("mulg %1,%2,%0", T'Asm_Output ("=f", R),
497 (T'Asm_Input ("f", X1), T'Asm_Input ("f", Y1)));
498 Asm ("stg %1,%0", G'Asm_Output ("=m", R1), T'Asm_Input ("f", R));
506 function Ne_F (X, Y : F) return Boolean is
509 Asm ("ldf %0,%1", S'Asm_Output ("=f", X1), F'Asm_Input ("m", X));
510 Asm ("ldf %0,%1", S'Asm_Output ("=f", Y1), F'Asm_Input ("m", Y));
511 Asm ("cmpgeq %1,%2,%0", S'Asm_Output ("=f", R),
512 (S'Asm_Input ("f", X1), S'Asm_Input ("f", Y1)));
520 function Ne_G (X, Y : G) return Boolean is
523 Asm ("ldg %0,%1", T'Asm_Output ("=f", X1), G'Asm_Input ("m", X));
524 Asm ("ldg %0,%1", T'Asm_Output ("=f", Y1), G'Asm_Input ("m", Y));
525 Asm ("cmpgeq %1,%2,%0", T'Asm_Output ("=f", R),
526 (T'Asm_Input ("f", X1), T'Asm_Input ("f", Y1)));
534 function Neg_F (X : F) return F is
538 Asm ("ldf %0,%1", S'Asm_Output ("=f", A), F'Asm_Input ("m", X));
539 Asm ("cpysn %1,%1,%0", S'Asm_Output ("=f", B), S'Asm_Input ("f", A));
540 Asm ("stf %1,%0", F'Asm_Output ("=m", C), S'Asm_Input ("f", B));
548 function Neg_G (X : G) return G is
552 Asm ("ldg %0,%1", T'Asm_Output ("=f", A), G'Asm_Input ("m", X));
553 Asm ("cpysn %1,%1,%0", T'Asm_Output ("=f", B), T'Asm_Input ("f", A));
554 Asm ("stg %1,%0", G'Asm_Output ("=m", C), T'Asm_Input ("f", B));
562 procedure pd (Arg : D) is
564 System.IO.Put_Line (D'Image (Arg));
571 procedure pf (Arg : F) is
573 System.IO.Put_Line (F'Image (Arg));
580 procedure pg (Arg : G) is
582 System.IO.Put_Line (G'Image (Arg));
589 function Return_D (X : D) return D is
592 -- The return value is already in $f0 so we need to trick the compiler
593 -- into thinking that we're moving X to $f0.
594 Asm ("cvtdg $f0,$f0", Inputs => D'Asm_Input ("g", X), Clobber => "$f0",
596 Asm ("stg $f0,%0", D'Asm_Output ("=m", R), Volatile => True);
604 function Return_F (X : F) return F is
607 -- The return value is already in $f0 so we need to trick the compiler
608 -- into thinking that we're moving X to $f0.
609 Asm ("stf $f0,%0", F'Asm_Output ("=m", R), F'Asm_Input ("g", X),
610 Clobber => "$f0", Volatile => True);
618 function Return_G (X : G) return G is
621 -- The return value is already in $f0 so we need to trick the compiler
622 -- into thinking that we're moving X to $f0.
623 Asm ("stg $f0,%0", G'Asm_Output ("=m", R), G'Asm_Input ("g", X),
624 Clobber => "$f0", Volatile => True);
632 function Sub_F (X, Y : F) return F is
637 Asm ("ldf %0,%1", S'Asm_Output ("=f", X1), F'Asm_Input ("m", X));
638 Asm ("ldf %0,%1", S'Asm_Output ("=f", Y1), F'Asm_Input ("m", Y));
639 Asm ("subf %1,%2,%0", S'Asm_Output ("=f", R),
640 (S'Asm_Input ("f", X1), S'Asm_Input ("f", Y1)));
641 Asm ("stf %1,%0", F'Asm_Output ("=m", R1), S'Asm_Input ("f", R));
649 function Sub_G (X, Y : G) return G is
653 Asm ("ldg %0,%1", T'Asm_Output ("=f", X1), G'Asm_Input ("m", X));
654 Asm ("ldg %0,%1", T'Asm_Output ("=f", Y1), G'Asm_Input ("m", Y));
655 Asm ("subg %1,%2,%0", T'Asm_Output ("=f", R),
656 (T'Asm_Input ("f", X1), T'Asm_Input ("f", Y1)));
657 Asm ("stg %1,%0", G'Asm_Output ("=m", R1), T'Asm_Input ("f", R));
665 -- For now, convert to IEEE and do Valid test on result. This is not quite
666 -- accurate, but is good enough in practice.
668 function Valid_D (Arg : D) return Boolean is
669 Val : constant T := G_To_T (D_To_G (Arg));
678 -- For now, convert to IEEE and do Valid test on result. This is not quite
679 -- accurate, but is good enough in practice.
681 function Valid_F (Arg : F) return Boolean is
682 Val : constant S := F_To_S (Arg);
691 -- For now, convert to IEEE and do Valid test on result. This is not quite
692 -- accurate, but is good enough in practice.
694 function Valid_G (Arg : G) return Boolean is
695 Val : constant T := G_To_T (Arg);
700 end System.Vax_Float_Operations;