HP OpenVMS Systemsask the wizard |
The Question is:
Problem using Vax Float and IEEE float on the same executable.
I faced a problem while trying to use two API libraries. One is compiled
using /IEEE option and the other one uses vax floats.
I have done similar things with other API libraries and it works on other
libraries.
I wrote a test program to duplicate the problem.
The same behavior is also seen on OVMS/AXP 7.1
Problem is: a floating point value passed to the function (which is compiled
with vax float option) the high and low order words are swapped. Main
program is compiled with IEEE option.
floating point is converted to VAX format and it does not work.
The value passed to the subfunction is not right even if conversion is not
applied.
restriction: I have to pass a float by value. I cannot pass pointers
(since I cannot modify the Third party API)
Here's the source files.
------- test5.c Start ------
#include <stdio.h>
#include <stdlib.h>
#include <cvtdef.h>
#include <cvt$routines.h>
int testsub(float);
main()
int st,err;
float fval=50.0;
float ieeefval=50.0;
printf("main: Initial (%e:%#x)\n\n", fval, *((int*)&fval));
err = testsub((float)fval);
st=CVT$CONVERT_FLOAT(&ieeefval, CVT$K_IEEE_S, &fval, CVT$K_VAX_F,
CVT$M_VAX_ROUNDING);
printf("main: ieeefval:%e:%#x fval:%e:%#x\n\n", (double)ieeefval,
*((int*)&ieeefval), (double)fval, *((int*)&fval));
err = testsub((float)fval);
---- end ------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cvtdef.h>
#include <cvt$routines.h>
int testsub(float value)
float ieeefval=0.0;
float fval=0.0;
int st=0;
printf(" Initial: testsub(%e:%#x)\n", value, *((int*)&value));
fval=value;
st=CVT$CONVERT_FLOAT(&fval, CVT$K_VAX_F, &ieeefval, CVT$K_IEEE_S,
CVT$M_ROUND_TO_NEAREST);
printf(" = : ieeefval:%e:%#x fval:%e:%#x\n", (double)ieeefval,
*((int*)&ieeefval), (double)fval, *((int*)&fval));
memcpy((void*)&fval, (void*)&value, sizeof(float));
st=CVT$CONVERT_FLOAT(&fval, CVT$K_VAX_F, &ieeefval, CVT$K_IEEE_S,
CVT$M_ROUND_TO_NEAREST);
printf(" memcpy : ieeefval:%e:%#x fval:%e:%#x\n", (double)ieeefval,
*((int*)&ieeefval), (double)fval, *((int*)&fval));
printf(" Exiting: testsub(%e:%#x)\n\n", value, *((int*)&value));
return 0;
---- end ----
--- The output file ---
ALPHA1$ cc testsub.c /debug=all/noopt/list/float=g_float/ansi/extern=strict
ALPHA1$ CC
TEST5.C/list/noopt/debug=(all)/float=ieee/ieee_mode=DENORM_RES/ansi/exter=st
rict
ALPHA1$ LINK /ALPHA /debug TEST5.OBJ, testsub.obj
ALPHA1$ r test5
main: Initial (5.000000e+01:0x42480000)
Initial: testsub(1.250000e+01:0x4248)
= : ieeefval:0.000000e+00:0x41480000 fval:1.250000e+01:0x4248
memcpy : ieeefval:0.000000e+00:0x41480000 fval:1.250000e+01:0x4248
Exiting: testsub(1.250000e+01:0x4248)
main: ieeefval:5.000000e+01:0x42480000 fval:0.000000e+00:0x4348
Initial: testsub(0.000000e+00:0x43480000)
= : ieeefval:0.000000e+00:000 fval:0.000000e+00:0x43480000
memcpy : ieeefval:0.000000e+00:000 fval:0.000000e+00:0x43480000
Exiting: testsub(0.000000e+00:0x43480000)
------------------
If /noprefix used
------------------
ALPHA1$ CC
TEST5.C/list/noopt/debug=(all)/float=ieee/ieee_mode=DENORM_RES/ansi/exter=st
rict/noprefix
ALPHA1$ cc testsub.c
/debug=all/noopt/list/machine/float=g_float/extern=strict/noprefix
ALPHA1$ LINK /ALPHA /debug TEST5.OBJ, testsub.obj,
sys$library:vaxcrtlt.olb/lib, sys$library:vaxcrtl.olb/lib
ALPHA1$ r test5
main: Initial (5.000000e+01:0x42480000)
Initial: testsub(8.130838e-320:0x4248)
= : ieeefval:6.763991e-316:0x41480000 fval:8.130838e-320:0x4248
memcpy : ieeefval:6.763991e-316:0x41480000 fval:8.130838e-320:0x4248
Exiting: testsub(8.130838e-320:0x4248)
main: ieeefval:5.000000e+01:0x42480000 fval:0.000000e+00:0x4348
Initial: testsub(6.971217e-316:0x43480000)
= : ieeefval:0.000000e+00:000 fval:6.971217e-316:0x43480000
memcpy : ieeefval:0.000000e+00:000 fval:6.971217e-316:0x43480000
Exiting: testsub(6.971217e-316:0x43480000)
---------------
Listing file
---------------
Source Listing 13-APR-1999
17:08:31 DEC C V5.5-002 Page 1
13-APR-1999
16:21:08 [000000.APITEST]TEST5.C;7
1 #include <stdio.h>
673 #include <stdlib.h>
1581 #include <cvtdef.h>
1646 #include <cvt$routines.h>
1712
1713 int testsub(float);
1714
1715 main()
1716 {
1717 int st,err;
1718 float fval=50.0;
1719 float ieeefval=50.0;
1720
1721
1722 printf("main: Initial (%e:%#x)\n\n", fval, *((int*)&fval));
1723
1724 err = testsub((float)fval);
1725
1726
1727 st=CVT$CONVERT_FLOAT(&ieeefval, CVT$K_IEEE_S, &fval,
CVT$K_VAX_F, CVT$M_VAX_ROUNDING);
1728 printf("main: ieeefval:%e:%#x fval:%e:%#x\n\n",
(double)ieeefval, *((int*)&ieeefval), (double)fval, *((int*)&fval))
1728 ;
1729
1730 err = testsub((float)fval);
1731
1732 }
Command Line
------- ----
CC
TEST5.C/LIST/NOOPT/DEBUG=(ALL)/FLOAT=IEEE/IEEE_MODE=DENORM_RES/ANSI/EXTER=ST
RICT
These macros are in effect at the start of the compilation.
----- ------ --- -- ------ -- --- ----- -- --- ------------
__VMS_VERSION="V6.2 " __DECC_MODE_RELAXED=1 __vms_version="V6.2 "
VMS_VERSION="V6.2 " __ALPHA=1 _IEEE_FP=1 __Alpha_AXP=1 vms=1
__D_FLOAT=0 __DECC=1 __alpha=1 __32BITS=1 __X_FLOAT=1 VMS=1
vms_version="V6.2 " __IEEE_FLOAT=1 __vms=1 __G_FLOAT=0 CC$gfloat=0
__BIASED_FLT_ROUNDS=2 __DECC_VER=50590002 __INITIAL_POINTER_SIZE=0
__VMS=1 __VMS_VER=60200022 __PRAGMA_ENVIRONMENT=1
Source Listing 13-APR-1999
17:08:17 DEC C V5.5-002 Page 1
13-APR-1999
16:19:40 [000000.APITEST]TESTSUB.C;7
1 #include <stdio.h>
673 #include <stdlib.h>
1581 #include <string.h>
1982 #include <cvtdef.h>
2047 #include <cvt$routines.h>
2113
2114 int testsub(float value)
2115 {
2116 float ieeefval=0.0;
2117 float fval=0.0;
2118 int st=0;
2119
2120 printf(" Initial: testsub(%e:%#x)\n", value,
*((int*)&value));
2121
2122 fval=value;
2123 st=CVT$CONVERT_FLOAT(&fval, CVT$K_VAX_F, &ieeefval,
CVT$K_IEEE_S, CVT$M_ROUND_TO_NEAREST);
2124 printf(" = : ieeefval:%e:%#x fval:%e:%#x\n",
(double)ieeefval, *((int*)&ieeefval), (double)fval, *((int*)
2124 &fval));
2125
2126 memcpy((void*)&fval, (void*)&value, sizeof(float));
2127 st=CVT$CONVERT_FLOAT(&fval, CVT$K_VAX_F, &ieeefval,
CVT$K_IEEE_S, CVT$M_ROUND_TO_NEAREST);
2128 printf(" memcpy : ieeefval:%e:%#x fval:%e:%#x\n",
(double)ieeefval, *((int*)&ieeefval), (double)fval, *((int*)
2128 &fval));
2129
2130 printf(" Exiting: testsub(%e:%#x)\n\n", value,
*((int*)&value));
2131
2132 return 0;
2133 }
Command Line
------- ----
CC TESTSUB.C/DEBUG=ALL/NOOPT/LIST/FLOAT=G_FLOAT/ANSI/EXTERN=STRICT
These macros are in effect at the start of the compilation.
----- ------ --- -- ------ -- --- ----- -- --- ------------
__VMS_VERSION="V6.2 " __DECC_MODE_RELAXED=1 __vms_version="V6.2 "
VMS_VERSION="V6.2 " __ALPHA=1 __Alpha_AXP=1 vms=1 __D_FLOAT=0
__DECC=1 __alpha=1 __32BITS=1 __X_FLOAT=1 VMS=1 vms_version="V6.2 "
__IEEE_FLOAT=0 __vms=1 __G_FLOAT=1 CC$gfloat=1 __BIASED_FLT_ROUNDS=2
__DECC_VER=50590002 __INITIAL_POINTER_SIZE=0 __VMS=1 __VMS_VER=60200022
__PRAGMA_ENVIRONMENT=1
------ end output ------
I also experimented with following options
/ansi vs /standard=vaxc
/prefix=all vs /noprefix
/float=g_float vs none
I don't know if I'm going overboard but I just linked it with full options.
I'm sending that output too.
Thanks
--------------- LINK OUTPUT ---------
13-APR-1999
17:59 Linker A11-20 Page 1
+------------------------+
! Object Module Synopsis !
+------------------------+
Module Name Ident Bytes File
Creation Date Creator
----------- ----- ----- -----
------------- -------
TEST5 V1.0 750 TEST5.OBJ;12
13-APR-1999 17:08 DEC C V5.5-002
TESTSUB V1.0 617 TESTSUB.OBJ;12
13-APR-1999 17:08 DEC C V5.5-002
LIBRTL X01-001 0 SYS$COMMON:[SYSLIB]LIBRTL.EXE;1
4-MAY-1995 22:30 Linker A11-12
DECC$SHR T06.2-05 0 SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1
4-MAY-1995 22:33 Linker A11-12
SYS$PUBLIC_VECTORS
X-33 0 [SYSLIB]SYS$PUBLIC_VECTORS.EXE;1
4-MAY-1995 22:29 Linker A11-12
USERDISK2:[000000.APITEST]TEST5.EXE;9 13-APR-1999 17:59
Linker A11-20 Page 2
+------------------------+
! Image Section Synopsis !
+------------------------+
Cluster Type Pglts Base Addr Disk VBN PFC Protection and Paging
Global Sec. Name Match Majorid Minorid
------- ---- ----- --------- -------- --- ---------------------
---------------- ----- ------- -------
DEFAULT_CLUSTER 0 1 00010000 3 0 READ WRITE
NON-SHAREABLE ADDRESS DATA
0 2 00020000 4 0 READ ONLY
EXECUTABLE
0 1 00030000 6 0 READ WRITE FIXUP
VECTORS
253 20 7FFF0000 0 0 READ WRITE DEMAND
ZERO
LIBRTL 3 1136 00000000-R 0 0 READ ONLY
EXECUTABLE LIBRTL_001 LESS/EQUAL 1 1
2 100 00090000-R 0 0 READ WRITE COPY ON
REF LIBRTL_002 LESS/EQUAL 1 1
2 8 000A0000-R 0 0 READ WRITE COPY ON
REF LIBRTL_003 LESS/EQUAL 1 1
3 94 000B0000-R 0 0 READ ONLY
LIBRTL_004 LESS/EQUAL 1 1
4 1 P-000C0000-R 0 0 READ WRITE COPY ON
REF LIBRTL_005 LESS/EQUAL 1 1
2 8 000D0000-R 0 0 READ WRITE DEMAND
ZERO LIBRTL_006 LESS/EQUAL 1 1
2 11 000E0000-R 0 0 READ WRITE FIXUP
VECTORS LIBRTL_007 LESS/EQUAL 1 1
DECC$SHR 3 2281 00000000-R 0 0 READ ONLY
EXECUTABLE DECC$SHR_001 LESS/EQUAL 1 1
2 216 00120000-R 0 0 READ WRITE COPY ON
REF DECC$SHR_002 LESS/EQUAL 1 1
2 77 00140000-R 0 0 READ WRITE COPY ON
REF DECC$SHR_003 LESS/EQUAL 1 1
3 39 00150000-R 0 0 READ ONLY
DECC$SHR_004 LESS/EQUAL 1 1
4 1 P-00160000-R 0 0 READ WRITE COPY ON
REF DECC$SHR_005 LESS/EQUAL 1 1
2 35 00170000-R 0 0 READ WRITE DEMAND
ZERO DECC$SHR_006 LESS/EQUAL 1 1
2 14 00180000-R 0 0 READ WRITE FIXUP
VECTORS DECC$SHR_007 LESS/EQUAL 1 1
SYS$PUBLIC_VECTORS
2 11 00000000-R 0 0 READ ONLY
EXECUTABLE SYS$PUBLIC_VECTO EQUAL 125 16186164
1 33 00004000-R 0 0 READ WRITE COPY ON
REF SYS$PUBLIC_VECTO EQUAL 125 16186164
2 1 0000C000-R 0 0 READ WRITE FIXUP
VECTORS SYS$PUBLIC_VECTO EQUAL 125 16186164
Key for special characters above:
+--------------------+
! R - Relocatable !
! P - Protected !
+--------------------+
USERDISK2:[000000.APITEST]TEST5.EXE;9 13-APR-1999 17:59
Linker A11-20 Page 3
+--------------------------+
! Program Section Synopsis !
+--------------------------+
Psect Name Module Name Base End Length
Align Attributes
---------- ----------- ---- --- ------
----- ----------
$LINK$ 00010000 0001010F 00000110 ( 272.)
OCTA 4 NOPIC,CON,REL,LCL,NOSHR,NOEXE,NOWRT,NOVEC, MOD
TEST5 00010000 000100BF 000000C0 ( 192.)
OCTA 4
TESTSUB 000100C0 0001010F 00000050 ( 80.)
OCTA 4
$LITERAL$ 00010110 000101FC 000000ED ( 237.)
OCTA 4 PIC,CON,REL,LCL, SHR,NOEXE,NOWRT,NOVEC, MOD
TEST5 00010110 00010151 00000042 ( 66.)
OCTA 4
TESTSUB 00010160 000101FC 0000009D ( 157.)
OCTA 4
$CODE$ 00020000 0002036B 0000036C ( 876.)
OCTA 4 PIC,CON,REL,LCL, SHR, EXE,NOWRT,NOVEC, MOD
TEST5 00020000 000201EB 000001EC ( 492.)
OCTA 4
TESTSUB 000201F0 0002036B 0000017C ( 380.)
OCTA 4
$BSS$ 00030000 00030000 00000000 ( 0.)
OCTA 4 NOPIC,CON,REL,LCL,NOSHR,NOEXE, WRT,NOVEC,NOMOD
TEST5 00030000 00030000 00000000 ( 0.)
OCTA 4
TESTSUB 00030000 00030000 00000000 ( 0.)
OCTA 4
$DATA$ 00030000 00030000 00000000 ( 0.)
OCTA 4 NOPIC,CON,REL,LCL,NOSHR,NOEXE, WRT,NOVEC,NOMOD
TEST5 00030000 00030000 00000000 ( 0.)
OCTA 4
TESTSUB 00030000 00030000 00000000 ( 0.)
OCTA 4
$READONLY$ 00030000 00030000 00000000 ( 0.)
OCTA 4 PIC,CON,REL,LCL, SHR,NOEXE,NOWRT,NOVEC,NOMOD
TEST5 00030000 00030000 00000000 ( 0.)
OCTA 4
TESTSUB 00030000 00030000 00000000 ( 0.)
OCTA 4
$READONLY_ADDR$ 00030000 00030000 00000000 ( 0.)
OCTA 4 PIC,CON,REL,LCL,NOSHR,NOEXE,NOWRT,NOVEC,NOMOD
TEST5 00030000 00030000 00000000 ( 0.)
OCTA 4
TESTSUB 00030000 00030000 00000000 ( 0.)
OCTA 4
USERDISK2:[000000.APITEST]TEST5.EXE;9 13-APR-1999 17:59
Linker A11-20 Page 4
+------------------------+
! Symbol Cross Reference !
+------------------------+
Symbol Value Defined By Referenced By
...
------ ----- ----------
-----------------
CVT$CONVERT_FLOAT 00001380-RX LIBRTL TEST5
TESTSUB
DECC$$SHELL_HANDLER 00003A20-RX DECC$SHR TEST5
DECC$EXIT 00002000-RX DECC$SHR TEST5
DECC$GXPRINTF 000046E0-RX DECC$SHR TESTSUB
DECC$MAIN 000007B0-RX DECC$SHR TEST5
DECC$TXPRINTF 00004960-RX DECC$SHR TEST5
MAIN 00010000-R TEST5
SYS$IMGSTA 00000340-RX SYS$PUBLIC_VECTORS
TESTSUB 000100C0-R TESTSUB TEST5
__MAIN 00010070-R TEST5
USERDISK2:[000000.APITEST]TEST5.EXE;9 13-APR-1999 17:59
Linker A11-20 Page 5
+------------------+
! Symbols By Value !
+------------------+
Value Symbols...
----- ----------
00000340 RX-SYS$IMGSTA
000007B0 RX-DECC$MAIN
00001380 RX-CVT$CONVERT_FLOAT
00002000 RX-DECC$EXIT
00003A20 RX-DECC$$SHELL_HANDLER
000046E0 RX-DECC$GXPRINTF
00004960 RX-DECC$TXPRINTF
00010000 R-MAIN
00010070 R-__MAIN
000100C0 R-TESTSUB
Key for special characters above:
+--------------------+
! * - Undefined !
! A - Alias Name !
! I - Internal Name !
! U - Universal !
! R - Relocatable !
! X - External !
! WK - Weak !
+--------------------+
USERDISK2:[000000.APITEST]TEST5.EXE;9 13-APR-1999 17:59
Linker A11-20 Page 6
+----------------+
! Image Synopsis !
+----------------+
Virtual memory allocated: 00010000 0003FFFF 00030000
(196608. bytes, 384. pages)
Stack size: 20. pages
Image header virtual block limits: 1. 2. (
2. blocks)
Image binary virtual block limits: 3. 6. (
4. blocks)
Image name and identification: TEST5 V1.0
Number of files: 7.
Number of modules: 5.
Number of program sections: 11.
Number of global symbols: 1767.
Number of cross references: 18.
Number of image sections: 21.
User transfer address: 00010070
Debugger transfer address: 00000340
Number of code references to shareable images: 7.
Image type: EXECUTABLE.
Map format: FULL WITH CROSS REFERENCE
in file USERDISK2:[000000.APITEST]TEST5.
Estimated map length: 250. blocks
+---------------------+
! Link Run Statistics !
+---------------------+
Performance Indicators Page Faults CPU Time
Elapsed Time
---------------------- ----------- --------
------------
Command processing: 23 00:00:00.00
00:00:00.09
Pass 1: 115 00:00:00.17
00:00:00.28
Allocation/Relocation: 8 00:00:00.02
00:00:00.08
Pass 2: 10 00:00:00.05
00:00:00.16
Map data after object module synopsis: 3 00:00:00.01
00:00:00.01
Symbol table output: 0 00:00:00.00
00:00:00.04
Total run values: 159 00:00:00.25
00:00:00.69
Using a working set limited to 6496 pages and 2703 pages of data storage
(excluding image)
Total number object records read (both passes): 341
of which 0 were in libraries and 31 were DEBUG data records containing
2685 bytes
1977 bytes of DEBUG data were written,starting at VBN 7 with 4 blocks
allocated
Number of modules extracted explicitly = 0
with 0 extracted to resolve undefined symbols
1 library searches were for symbols not in the library searched
A total of 5 global symbol table records was written
LINK/ALPHA/DEBUG/MAP/CROSS/FULL TEST5.OBJ,TESTSUB.OBJ
--------------
The Answer is :
This problem exists because you are lying to the compiler. The
subprogram declares its parameter to be of VAX-floating type, yet the
main program is passing it as IEEE-floating. This is no different
than passing a floating point number to a routine that expects an
integer -- it does not work. The C language definition is clear about
this -- if the type of the argument passed to a routine does not
match the type the routine expects, the behavior is undefined.
With that said, the OpenVMS Wizard will try to provide a additional
information about what is going on, and will try to provide ways to
get the desired result.
When stored in memory, VAX floating and IEEE floating have very
different formats (the words are swapped).
When a VAX floating point number is loaded into a register on an
Alpha, the words are swapped (and when stored back to memory, the
words are again swapped).
In testsub, the variable value is passed in a register. Because
the code performs the Alpha STF instruction to store the value to
the variable fval, the words are swapped as you have told the compiler
that the value uses VAX floating point.
There are several ways to make this work. One way would be to pass
the argument in memory instead of a register. You could do this
by passing six dummy argument first -- per the OpenVMS Alpha callling
standard, the first six arguments are passed via registers. Another
way would be to swap the words yourself after the store to fval. Yet
another would be in insert an asm that would store the item to memory
using an IEEE instruction so that no word swap would take place.
For example including the header file <c_asm.h>, and then replacing
fval = value with fasm("STS %f17,0(%r16)", &fval, value) should do
the trick.
To summarize, great care must be taken if you wish to pass one floating
type to a routine that expects another. One has to understand the
internal representations of the floating point numbers (in both register
and memory formats) in order to get this to work as desired.
|