Chapter Contents |
Previous |
Next |
SAS/C Compiler Changes in Release 7.50 |
IEEE and 64-Bit Updates to the Inline Machine Code Interface |
The SAS/C support for IEEE Floating-Point computation and 64-Bit processing
requires several changes to the documentation for the inline machine code
interface. The following sections contain details about these changes. All
of the following section names refer to sections in Chapter 13, "Inline
Machine Code Interface."
In the section titled "Overview," add the following entry to the table under "Built-in functions:"
_ospc |
generate an OS/390 PC instruction |
Several built-in functions issue specific supervisor call instructions:
_diag
, _cms202
, _ossvc
, and _ospc
.
<gen164.h>
These header files provide appropriate macros for all IBM 370 machine
instructions except UPT, SIE, and PC. These three instructions cannot be supported
because of conflicts in register use between the instructions and the compiled
C code. Note that most uses of the PC instruction in OS/390 can be generated
using the _ospc
function.
_ldregs
conflicts with the compiler's assignment of registers
to register variables, the generated code might be less than optimal. General-purpose
registers 0 through 3 and 14 through 15 can be used freely, as well as floating-point
registers 0 and 2. If the compiler option ARCHLEVEL(C)
is specified, you can use floating-point registers 0 through 7 in inline machine
code.
Type of Register | Register Number | Name of Macro | Bit in Mask |
---|---|---|---|
general-purpose | 0-15 | R0-R15 | 0-15 |
floating-point | 0-15 | F0-F15 | 16-31 |
The
_stregs
function is defined to return int
. This allows the _stregs
function to be used to store an integer or a pointer from a single register.
Three alternate forms of _stregs
are available
to store other types of data. The function _stfregs
returns double, the function _stpregs
returns _ _far void *
and the function _stllregs
returns
long long
. Except
for the difference in return type, these functions behave the same as _stregs
.
Note:
_stfregs
function stores its
return value in the highest floating register in the mask.
_stllregs
function is only
available if the ARCHLEVEL(D)
option has been
specified.
_stllregs
function, through
use of a cast, can be used to store a _ _huge
pointer value as well as a long long
.
_bbwd
function
description:
#include <code.h> void _bbwd(unsigned short op, unsigned short target,...);
_bbwd
causes the compiler to generate
a branch instruction whose target is the previously defined label whose _label
number is specified by target
.
The op
argument specifies the first halfword
of the instruction to generate. Both arguments to _bbwd
must be compile-time constants. If _bbwd
is
used to generate a 6-byte branch instruction (BCTG, BXHG or BXLEG), a third
unsigned short argument must be passed to _bbwd
specifying the last 2 bytes of the instruction. For other branch operations,
this argument must be omitted.
BCTG | |
BXHG | |
BXLEG |
Optimizations, such as branch folding, may cause the instructions generated
as a result of _bbwd
to differ from those expected.
However, any such optimizations will not change the effects of the instructions.
Also, if ARCHLEVEL(B)
or higher has been specified,
the compiler may generate a relative branch instruction equivalent to the
branch specified.
The following changes should be made to the _bfwd
function description:
#include <code.h> void _bfwd(unsigned short op, unsigned short target,...);
_bfwd
causes the compiler to generate
a branch instruction whose target is the previously defined label whose _label
number is specified by target
.
The op
argument specifies the first halfword
of the instruction to generate. Both arguments to _bfwd
must be compile-time constants. If _bfwd
is
used to generate a 6-byte branch instruction (BCTG, BXHG or BXLEG), a third
unsigned short argument must be passed to _bfwd
specifying the last 2 bytes of the instruction. For other branch operations,
this argument must be omitted.
BCTG | |
BXHG | |
BXLEG |
Optimizations, such as branch folding, may cause the instructions generated
as a result of _bfwd
to differ from those expected.
However, any such optimizations will not change the effects of the instructions.
Also, if ARCHEVEL(B)
or higher has been specified,
the compiler may generate a relative branch instruction equivalent to the
branch specified.
The following changes should be made to the _branch
function description:
#include <code.h> void _branch(unsigned mask, unsigned short op, unsigned short target,...);
Note that if _branch
is used to generate
a 6-byte branch instruction (operation code BCTG, BXLEG or BXHG), a third
unsigned short argument must be specified to complete the instruction.
The first argument, MASK, is a 32-bit mask. This argument must be a
compile-time constant because the compiler has to know which registers are
needed. General purpose registers can be specified using the macros R0 through
R15, and floating point registers 0 through 15 can be specified using the
macros F0 through F15. (Only F0, F2, F4 and F6 can be used if the ARCHLEVEL
option is not C
or
greater.) Multiple registers can be specified by adding (or logically ORing)
the macros, for example, R0+R1 (or R0|R1). Refer to the "Bit Masks for
Using Registers" section in the "Inline Machine Code Interface"
chapter of the
SAS/C Compiler and Library User's Guide for more information on the MASK argument.
Remaining arguments specify the values to be placed in the registers
(low to high) that are specified by MASK. Any C expression that has an integer,
pointer, or floating-point type may be used. The number of arguments, excluding
MASK, must be equal to the number of one-bits in MASK; that is, you must supply
an expression for each register. The type of each expression must be valid
for the register in which the value is to be loaded. For example, the effect
of attempting to load a pointer into a floating-point register is unpredictable.
If the ARCHLEVEL(D)
option has been specified,
you can load an 8-byte value (long
, long long
, or _ _huge pointer
)
into a 64-bit register. If the ARMODE
option
has been specified, you can load a _ _far
pointer into a 32-bit general register and the corresponding access register.
All other loads of a general register will load only the low-order 32 bits.
You can safely use the following registers:
0 - 3, 14, 15 | are general-purpose registers. |
0, 2 | are floating-point registers. |
With text that reads:
You can safely use the following registers:
0 - 3, 14, 15 | are general-purpose registers. |
0, 2 | are floating-point registers, if the ARCHLEVEL option is less than C . |
0 - 7 | are floating-point registers, if the ARCHLEVEL option is C or
greater. |
In addition, you can use floating-point registers 4 and 6 if they are not currently assigned to a register variable.
With text that reads:
In addition, if the ARCHLEVEL
specification
is less than C
, you can use floating-point
registers 4 and 6 if they are not currently assigned to a register variable.
Add the new function, _ospc
, to the "Functions"
section.
_ospc
#include <svc.h> void _ospc(void);
_ospc
generates a program
call (PC) instruction, specifically, PC 0(14)
.
This PC instruction is used to link to several MVS services. It is the caller's
responsibility to set up arguments for the program call appropriately, using _ldregs
or inline code functions.
Note: The generated
code assumes that the program call will not modify registers other than 14
through 1. This function should not be used to invoke system calls which
do not honor this restriction.
_ospc
incorrectly
(for instance, if you pass any arguments), the second pass of the compiler
produces an error message, sets the MVS return code to 8, and generates an EX 0,*
instruction for _ospc
.
The generated instruction causes an execute exception (MVS ABEND code 0C3)
if it is executed.
_ospc
is not portable.
_ospc
first stores any values
currently in use from general-purpose registers 0, 1, 14 and 15 and clears
any information the compiler had about the contents of those registers. It
assumes these registers may be altered by the program call. If necessary, _ospc
then issues a SAM31 instruction to exit 64-bit mode.
_ospc
then saves the address of the PC instruction
in the C Run-Time Anchor Block (CRAB) as an aid in traceback production in
case the PC causes an ABEND. Next, _ospc
issues
the PC instruction. Finally, if the HUGEPTRS
option was specified, _ospc
issues the SAM64
instruction to resume 64-bit mode execution.
STORAGE OBTAIN,LENGTH=len,ADDR=addr,SP=sp,COND=YES #include <code.h> #include <genl370.h> #include <svc.h> #define STORAGE_OBTAIN(len,sp,addr) \ (_ldregs(R0+R14+R15, (len), 16, (sp) << 8), \ L(14, 0+b(14)), \ L(14, 772+b(14)), \ L(14, 160+b(14)), \ _ospc(), \ _stregs(R1+R15, (addr)))
_ldregs
, _ossvc
,
_stregs
The description of _osarmsvc
should
read:
_osarmsvc
generates a supervisor call
(SVC) instruction. _osarmsvc
takes one argument
(n) that specifies the number of the SVC to generate; n is an execution-time constant in the range of 0 to 255. No code is
generated to change the addressing mode. The SVC will be issued in AR mode
if the compiler armode
option has been specified,
and otherwise will be issued in primary address space mode. If _osarmsvc
is issued in a program compiled with the HUGEPTRS
option,
execution is switched to 31-bit addressing
before the SVC is issued, and restored to 64-bit addressing after the SVC
completes.
The implementation section of the _ossvc
function should read:
_ossvc
first stores any values currently
in use from general-purpose registers 0, 1, 14, and 15 and clears any information
the compiler had about the contents of those registers. It assumes that these
registers are, or may be, altered by the SVC. If needed, _ossvc
then issues a SAC instruction to cancel access-register
mode and/or a SAM31 instruction to cancel 64-bit addressing mode. _ossvc
then saves the address of the SVC instruction in the
C Run-Time Anchor Block (CRAB) as an aid to traceback production in case the
SVC causes an ABEND. _ossvc
then issues the
requested SVC instruction. Finally, _ossvc
issues a either a SAC or a SAM64 instruction, or both, to restore the program's
original addressing mode.
Add the following paragraph after the fourth paragraph of the description
of the _stregs
function:
Each argument other than the mask to _stregs
must have a type of pointer. The pointer must address a data type which is
appropriate to the register being stored. For instance, it is erroneous to
attempt to store a general purpose register via a pointer to double. In access
register mode, you can store both a general register and the corresponding
access register if the argument is a pointer to a _ _far
pointer. Similarly, if ARCHLEVEL(D)
has been specified you can store all 64-bits of a general purpose register
if the corresponding _stregs
argument is a
pointer to long
, long long
,
or a _ _huge
pointer. It is permitted
but not recommended for an argument to _stregs
to have type void *
. In this case, the amount
of data stored is determined by the size of the register.
Updates for Floating-Point Support |
The following sections contain information about specific changes to
the
SAS/C Compiler and Library User's Guide for floating-point support.
In Chapter 2, "Source Code Conventions," under the section titled, "Numerical Limits," replace the tabled labeled "Integral Type Sizes" with the following table:
Type | Length in Bytes | Range |
---|---|---|
char |
1 | 0 to 255 (EBCDIC character set) |
signed char |
1 | -128 to 127 |
short |
2 | -32768 to 32767 |
unsigned short |
2 | 0 to 65535 |
int |
4 | -2147483648 to 2147483647 |
unsigned int |
4 | 0 to 4294967295 |
long (NOHUGEPTRS) |
4 | -2147483648 to 2147483647 |
unsigned long (NOHUGEPTRS) |
4 | 0 to 4294967295 |
long (HUGEPTRS) |
8 | -9223372038854775808 to 9223372036854775807 |
unsigned long (HUGEPTRS) |
8 | 0 to 18446744073709551615 |
long long |
8 | -9223372038854775808 to 9223372036854775807 |
unsigned long long |
8 | 0 to 18446744073709551615 |
In Chapter 2, "Source Code Conventions," under the section titled, "Numerical Limits," replace the tabled labeled "Float and Double Type Sizes" with the following table:
Type | Length in Bytes | Range |
---|---|---|
float |
4 | +/-5.4E-70 to +/-7.2E75 (_ _hexfmt)+/-1.4E-45 to +/-3.4E38 (_ _binfmt) |
double |
8 | +/-5.4E-70 to +/-7.2E75 (_ _hexfmt)+/-4.9E-324 to +/-1.8E308 (_ _binfmt) |
long double |
8 | +/-5.4E-70 to +/-7.2E75 (_ _hexfmt)+/-4.9E-324 to +/-1.8E308 (_ _binfmt) |
In Chapter 2, "Source Code Conventions," under the section titled, "Language Extensions," the section titled, "Specifying floating-point constants in hexadecimal," should read:
SAS/C now supports the C99 hexadecimal format for floating-point numbers. The syntax is
0x<hexdecimal-digits>.<hexdecimal digits>P<binary exponent><suffixes>
A simple example of a C99 hexadecimal floating point constant is 1.AP-12.
This constant has the value of 1+(10/16) times two to the minus twelfth power.
The hexadecimal point is optional in the format, and only one of the two
sequences of digits shown is required. For instance, 0xABCP14, 0xABC.P14
and 0x.ABCP14 are all valid hexadecimal floating-point constants. The hexadecimal
digits and the letter P can appear in either upper or lower case. A suffix
of F or L can follow a constant to indicate a float
or long double
constant. As a SAS/C extension,
a suffix of B or H can also be used to indicate a _ _binfmt
or _ _hexfmt constant
.
You can use both a C99 suffix and a SAS/C suffix on the same constant, for
example, 0x0.C04P0FB.
Note: If you use both suffixes, the SAS/C suffix
must appear after the C99 suffix.
Additionally, SAS/C continues to support its previous format for specifying floating-point numbers in hexadecimal. This format enables specification of the exact bit pattern of a floating-point constant. Unlike the C99 format, this format can be used to describe NaNs and infinities. The syntax is
0.x<hexadecimal digits>[.<suffixes>]
The indicated digits are stored exactly as specified in memory. If
there are fewer than eight digits (for a float) or fewer than sixteen digits
(for a double or long double), the remaining digits are considered to be zero.
If any suffixes are present, they must be preceded by a period. A suffix
of B or H can be used to specify the floating point format, and one of F or
L can be used to specify float or long double. As with the C99 format, if
both suffixes are used, the format suffix must come last. If there are no
suffixes, the constant is assumed to be of type double, and to have the
default format. A simple example of a SAS/C-format floating-point constant
is 0.x7ff8.B, which represents the binary floating-point default quiet NaN.
In Chapter 2, "Source Code Conventions," under the section titled, "Language Extensions," following the section titled, "The #pragma map statement," add a new section titled "Using both IBM and IEEE floating-point formats" that contains the following text:
Most SAS/C programs will use only one format of floating-point number,
either the traditional IBM mainframe format or the IEEE format. The choice
between formats is made by specifying or omitting the BFP
option. However, advanced programs and libraries might need to use both formats
in a single compilation, or to support callers that use either format. This
section describes the rules and special considerations required to use both
floating-point formats.
The type modifiers _ _binfmt
and _ _hexfmt
can be used in floating-point type specifiers
to indicate the floating-point format. Floating-point types without an explicit
format specification have the default format, as determined by whether the BFP
option was specified.
Floating-point constants can be specified with an H or B suffix to indicate hexadecimal or binary format respectively. Constants without a suffix are assumed to have the default format. A format suffix can appear in combination with a type suffix (F or L), but the format suffix must always come last.
A floating-point value can be converted from one format to another using
a cast, assignment, or initialization. Conversion can also occur when an
argument is passed to a function with a prototype, or when a function value
is returned. Format conversions do not otherwise occur. For instance,
adding a _ _binfmt
double to a _ _hexfmt
double is invalid. You should use a cast
to clarify such expressions.
Conversions from hexadecimal format to binary format are performed according to the current IEEE rounding mode. Conversions from binary to hexadecimal format are exact for doubles, and for floats they are rounded according to the normal hexadecimal format rules. If the conversion cannot be performed, for example, the source is out of range or a NaN, the results are undefined and no signal or exception is raised.
When a function can be used from both BFP
and NOBFP
programs, its prototype should specify _ _binfmt
or _ _hexfmt
for each floating-point argument or for a floating-point return type. This
will force a conversion to occur when the function is called from a compilation
with the incorrect default.
The SAS/C math library is compatible with both formats. When a mathematical
function such as exp
is called, the version
of the function used is the one specified by the BFP
or NOBFP
option. This is true whether or not math.h
is included. If math.h
is included, each floating-point function argument will be converted to the
default format. If math.h
is not included,
it is the programmer's responsibility to pass data of the correct floating-point
format. For a few low-level functions that are not particularly meaningful
for hexadecimal floating point, such as isnan
,
if math.h
is not included, the binary version
is always called. Because C99 defines these functions as macros, it is technically
undefined what happens if you attempt to use them without including the corresponding
header file.
The symbols defined by the float.h
header
file always reference the default floating-point format, as determined by
the presence or absence of the BFP
option.
In Chapter 2, "Source Code Conventions," under the section titled, "Implementation-defined Behavior," add the following updates to the section titled, "Floating Point (G.3.6).
When an integer is converted to a floating-point type that cannot
accurately
represent every value of the source type (for instance, int
to float
or long long
to
double
), the result
depends on the floating-point format. For binary floating point, the result
is rounded according to the current rounding mode. For hexadecimal floating
point, the result is rounded. In the latter case, if the value is exactly
halfway between two possible results, the result is the one that is larger
in magnitude.
When a floating-point number is converted to a narrower number, the result depends on the format. For binary format, the result is rounded according to the current rounding mode. For hexadecimal floating point, the result is rounded, rounding away from 0 when the wider number is equally distant from the two nearest numbers of the narrower format.
In Chapter 2, "Source Code Conventions," under the section titled, "Implementation-defined Behavior," the first sentence in the section titled, "Registers (G.3.8)" should read:
There can be up to six integer or pointer register variables, and up
to two floating-point register variables (up to eight if the ARCHLEVEL(C)
compiler option is in effect).
In Chapter 2, "Source Code Conventions," under the section titled, "Implementation-defined Behavior," under the section titled, "Library Functions (G.3.14)," make the following changes to the list:
The null pointer constant to which the macro NULL
expands is 0L
if HUGEPTRS
is specified.
Otherwise, it is 0
.
When the second argument of the fmod
function is 0, fmod
returns 0 for hexadecimal
floating point, and a NaN for binary floating point.
In Chapter 3, "Code Generation Conventions," in the section titled, "Arithmetic Data Types," change the table labeled, "Data Type Characteristics," to the following:
Type | Length | Alignment | Range |
---|---|---|---|
char
|
1 | byte | 0 to 255 (EBCDIC character set) |
signed char
|
1 | byte | - 128 to 127 |
unsigned char
|
1 | byte | 0 to 255 (EBCDIC character set) |
short
|
2 | halfword | - 32768 to 32767 |
unsigned short
|
2 | byte | 0 to 65535 |
int
|
4 | word | - 2147483648 to 2147483647 |
unsigned int
|
4 | word | 0 to 4294967295 |
long (NOHUGEPTRS) |
4 | word | - 2147483648 to 2147483647 |
unsigned long (NOHUGEPTRS) |
4 | word | 0 to 4294967295 |
long (HUGEPTRS) |
8 | doubleword | -9223372038854775808 to 9223372036854775807 |
unsigned long (HUGEPTRS) |
8 | doubleword | 0 to 18446744073709551615 |
long long |
8 | doubleword | -9223372038854775808 to 9223372036854775807 |
unsigned long long |
8 | doubleword | 0 to 18446744073709551615 |
float |
4 | word | =/ - 5.4E - 79 to =/ - 7.2E75 |
double |
8 | doubleword | =/ - 5.4E - 79 to =/ - 7.2E75 |
long double |
8 | doubleword | =/ - 5.4E - 79 to =/ - 7.2E75 |
char
|
defines an 8-bit unsigned integer
|
||
signed char
|
defines an 8-bit signed integer
defines a 16-bit signed integer |
||
unsigned short
|
defines a 16-bit unsigned integer
|
||
int |
defines a 32-bit signed integer | ||
long
|
defines a 32-bit signed integer if the HUGEPTRS
option is not specified, or a 64-bit signed integer if HUGEPTRS is specified.
|
||
unsigned
|
defines a 32-bit unsigned integer
|
||
unsigned long unsigned long int |
defines a 32-bit unsigned integer if the HUGEPTRS
option is not specified, or a 64-bit unsigned integer if HUGEPTRS is specified.
|
||
unsigned unsigned int |
defines a 32-bit unsigned integer
|
||
long long |
defines a 64-bit unsigned integer | ||
unsigned long long |
defines a 64-bit unsigned integer | ||
_ _hexfmt float |
defines a 32-bit signed floating-point number in the standard 370 representation, that is, a sign bit, a 7-bit biased hexadecimal exponent, and a 24-bit fractional part. The exponent bias is 64. All constants and results generated by compiled code are normalized (except for constants specified in hexadecimal notation). This representation is equivalent to approximately 6 or 7 decimal digits of precision. | ||
_ _binfmt float |
defines a 32-bit signed floating-point number in IEEE binary format, that is, a sign-bit, an 8-bit biased binary exponent, and a 23-bit fractional part with an implied leading 1. The exponent bias is 127. See the IBM 390 Principles of Operation for details on the representation of NaNs, infinities, denormalized numbers, etc. This representation is equivalent to approximately 6 or 7 decimal digits of precision. | ||
_ _binfmt double _ _binfmt long double |
defines a 64-bit signed floating-point number in IEEE binary format, that is, a sign bit, an 11-bit biased binary exponent, and a 52-bit fractional part with an implied leading 1. The exponent bias is 1023. See the IBM 390 Principles of Operation for details on the representation of NaNs, infinities, denormalized numbers, etc. This representation is equivalent to approximately 16 decimal digits of precision. | ||
_ _hexfmt double _ _hexfmt long double |
defines a 64-bit signed floating-point number in the standard 370 representation, that is, a sign bit, a 7-bit biased hexadecimal exponent, and a 56-bit fractional part. The exponent bias is 64. All constants and results generated by compiled code are normalized (except for constants specified in hexadecimal notation). This representation is equivalent to approximately 16 or 17 decimal digits of precision |
In the same section, the two paragraphs following the table labeled, "Data Type Characteristics," should read:
Note that in contrast to the signed integer representations, negative floating-point numbers are not represented in two's complement notations; positive and negative numbers differ only in the sign bit.
In both floating-point formats, there are multiple representations of
0; in hexadecimal floating point, any value with a 0 fractional part is treated
as zero, regardless of the exponent. Code that checks float or double objects
for 0 by means of type punning (that is, examining the objects as if they
were a nonfloating-point type such as int
)
might fail when the value is an unusual representation of 0, such as an IEEE
negative zero.
In Chapter 3, "Code Generation Conventions," under the section titled, "Arithmetic Exceptions," add the following updates:
Hexadecimal floating-point exceptions produce a program interrupt that causes abnormal program termination (program interruption codes 000D or 000F) if no arithmetic signal handler is defined.
Usually, binary floating-point exceptions do not cause program
interrupts.
The library function fesettrapenable
can be
used to cause certain binary floating-point exceptions to trap with a program
interrupt. Any such trap will indicate program interruption code 0007. See
the
SAS/C Library Reference, Volume 1 for more information on fesettrapenable
.
See the IBM Principles of Operation manual for more information
about binary floating-point exception handling.
In Chapter 3, "Code Generation Conventions," under the section titled, "Register Conventions," the second item in the list should read:
If the compiler option ARCHLEVEL(B)
(or
greater) is not specified, register 5 is the base register for the current
function. If ARCHLEVEL(B)
is in effect, register
5 is not reserved by the compiler, except during the prolog, and is assigned
usage dynamically.
Updates to the CENTRY Macro |
In Chapter 11, "Communication with Assembler Programs," add the following information to the section titled, "The CENTRY macro."
Change the form of a call to the CENTRY macro to:
label CENTRY DSA=dsa-size, BASE=base-reg, FNM=function-name, STATIC=NO/YES, INDEP=NO/YES, LASTREG=last-reg, STKBELOW=YES/NO, BFP=YES/NO, HUGEPTR=YES/NO, AFPSAVE=afp-save-area, AFPLAST=last-afp-reg, HGRSAVE=hgr-save-area, HGRLAST=last-hgr-reg
Add the following entries to the list of keywords:
printf
or sqrt
.
HUGEPTR
keyword matters only if the assembler routine calls a C library
function whose behavior depends on how its caller was compiled, such as printf
or strtol
. Note that
CENTRY does not change the program's addressing mode. If your assembler code
requires 64-bit addressing, you should change addressing mode yourself after
completion of CENTRY.
AFPSAVE
keyword. The save area must be specified by a symbolic name, and must be
allocated on a fullword boundary in the first 1024 bytes of the DSA. (If
CENTRY specifies DSA=0, the save area must be located within the CRABTAUT
work area.) The area must be large enough to save all the registers specified
by the AFPLAST
keyword. If you modify any
of the non-volatile AFP registers, but do not specify the AFPSAVE
keyword, ABENDs or floating-point errors are likely
in any C code which executes after the assembler routine has returned.
HGRSAVE
keyword. The save area must be specified by a symbolic name, and must be allocated
on a fullword boundary in the DSA. (If CENTRY specifies DSA=0, the save area
must be located within the CRABTAUT work area.) The area must be large enough
to save the high-order portions of all the registers specified by the HGRLAST
keyword. If you modify the high-order part of any
register, but do not specify the HGRSAVE
keyword,
ABENDs are likely in any C code which executes after the assembler routine
has returned.
AFPLAST=6
, the high-order portion of registers 14, 15 and
0 through 6 will be saved by CENTRY.
In Chapter 11, "Communication with Assembler Programs," add the following information to the section titled, "The CEXIT macro."
Change the form of a call to the CEXIT macro to:
label CEXIT RC=return-info/(reg), DSA=YES/0, INDEP=NO/YES, LASTREG=lastreg, MPSAFE=NO/YES, AFPSAVE=afp-save-area, AFPLAST=last-afp-reg, HGRSAVE=hgr-save-area, HGRLAST=last-hgr-reg, HUGERC=NO/YES
Add the following entries to the list of keywords:
MPSAFE=NO
. MPSAFE=YES
guarantees
correct results even in the presence of asynchronous signals, but increases
the overhead of CEXIT.
AFPSAVE
keyword of CENTRY for more
information.
HGRSAVE
keyword of CENTRY
for more information.
HUGERC=YES
is specified, the HGRSAVE
and HGRLAST
keywords
must also be specified.
Note: The
CEXIT macro does not change addressing modes. CEXIT cannot be executed in
64-bit addressing mode. It is the responsibility of the assembler routine
to return to 31-bit addressing before issuing the CEXIT macro. Failure to
observe this restriction is likely to cause difficult to diagnose ABENDs.
Updates to the AR370 Archive Utility |
In Appendix 2, "The AR370 Archive Utility," in the section
titled, "Combinations of command and command modifier charecters,"
update the table labeled "Command and Command Modifier Combinations"
with the -y
command modifier as indicated below:
Command | Accepted Modifiers and Commands |
---|---|
d
|
e, f, j, q, t, v, y
|
m
|
e, f, j, q, t, v, y
and
a | b
|
r
|
e, f, j, q, t, v, y
and
a | b
|
t
|
d, e, f, j, m, r, v, x, y
|
x
|
e, f, j, t, v, y
|
In the section titled "AR370 INCLUDE Statements,"add the following caution at the end of the text.
In the section titled "Optional Modifier Characters," add the following entry to the list of characters:
w |
Used in conjunction with the replace (r ) command to allow truncation
of member names at 18 characters. |
Update to the SYSARWRK Data Definition |
In Appendix 2, "The AR370 Archive Utility," under the section titled, "AR370 JCL requirements," add the following text at the end of the section:
If SYSARWRK is not specified, a temporary work data set will be used that is defined with the minimum size that is allowed. To avoid running out of space in this temporary data set, allocate SYSARWRK with adequate space to handle your data set. SYSARWRK will be used then instead of the default work data set.
Enhancements to the All-Resident C Programs |
In Chapter 10, "All-Resident C Programs," update the the section titled, "Restrictions," with the following information:
Under an extended architecture system, all-resident programs may not be linked with RMODE(ANY). However, they may be linked RMODE(SPLIT), in which case all of the load module except for certain portions of the run-time library can be loaded above the 16-megabyte line. Note that RMODE(SPLIT) is suitable only for AMODE(31) applications.
The use of the NOSMPXIVEC
link-time (COOL)
option is not permitted.
Update to the _branch, _bbwd, and _bfwd Functions |
In Chapter 13, "Inline Machine Code Interface," in the section
titled, "Functions," update the CAUTIONS sections of the _branch
, _bbwd
, and _bfwd
functions
with the text indicated for each function.
_branch
Note: The _branch
function should not
be used to branch to a label defined in a different built-in code sequence,
especially one in a different block. This action may cause a compiler error
or incorrect results at execution time.
_bbwd
Note: The _bbwd
function should not be
used to branch to a label defined in a different built-in code sequence, especially
one in a different block. This action may cause a compiler error or incorrect
results at execution time.
_bfwd
Note: The _bfwd
function
should not be used to branch to a label defined in a different built-in code
sequence, especially one in a different block. This action may cause a compiler
error or incorrect results at execution time.
Update to the oeabntrap Function Description |
In Chapter 14, "Systems Programming with the SAS/C Compiler,"
in the section titled, "The SPE Library," replace the oeabntrap
example with the following example:
#include <oespe.h> #include <unistd.h> #include <lclib.h> #include <string.h> #include <setjump.h> #include <signal.h> jmp_buf ABEND_escape; /* where to run to after an ABEND */ static int ABEND_trapped; void trace_out(char *line) { /* this function writes a btrace output line to file descriptor 2 */ write(2, line, strlen(line)); write(2, "\n", 1); } void ABEND_handler(int signum) { char buf[60]; sprintf(buf, "Interrupted by signal %d!\n", signum); write(2, buf, strlen(buf)); btrace(&trace_out); longjmp(ABEND_escape, 1); } int ptrvalid(int *ptr) { /* return whether storage addressed by ptr can be read */ struct sigaction segv_action, prev_action; int ok; volatile int value; if (ABEND_trapped == 0) { oeabntrap(TRAP_AUTO); /* possibility of error ignored */ ABEND_trapped = 1; } if (setjmp(ABEND_escape) != 0) goto failed; /* set up retry from handler */ segv_action.sa_handler = &ABEND_handler; sigemptyset(&segv_action.sa_mask); segv_action.sa_flags = 0; sigaction(SIGSEGV, &segv_action, &prev_action); /* we'll try to access the storage even if sigaction fails... */ value = *ptr; /* force reference to *ptr */ ok = 1; /* it must be valid */ goto complete; failed: ok = 0; /* the pointer is no good */ complete: sigaction(SIGSEGV, &prev_action, 0); /* restore previous SIGSEGV handling */ return ok; }
Updates to the pow Function Example |
In Chapter 4, "Optimization," in the section titled, "Using
inline functions to generate optimized code," replace the example code
for the pow
function with the following code:
#include <lcdef.h> [1] #include <math.h> [2] #undef pow [3] #define pow(x, p) power(x, p, isnumconst(p)) [4] static __inline double power(double a, double p, int p_is_constant) { /* Test the exponent to see if it's */ /* - a compile-time integer constant */ /* - a whole number */ /* - nonnegative */ if (p_is_constant && (int) p == p && (int) p >= 0) { [5] int n = p; /* Handle the cases for 0 <= n <= 4 directly. */ [6] if (n == 0) return 1.0; else if (n == 1) return a; else if (n == 2) return a * a; else if (n == 3) return a * a * a; else if (n == 4) return (a * a) * (a * a); /* Handle 5 <= n <= 16 by calling power */ /* recursively. */ /* Note that power is invoked directly, specifying */ /* 1 as the value of the p_is_constant argument. */ /* This is because the isnumconst macro returns */ /* "false" for the expressions (n/2) and */ /* ((n+1)/2), which would defeat the optimization. */ [7] else if (n <= 16) return power(a, (double)(n/2), 1) * power(a, (double)((n+1)/2), 1); /* Handle n > 16 via a loop. The loop below */ /* calculates (a ** (2 ** x)) */ /* for 2 <= x <= n and sums the results for each */ /* power of 2 that has the corresponding bit set */ /* in n. */ [8] else { double prod = 1.0; for (; n != 0; a *= a, n >>= 1) if (n & 1) prod *= a; return prod; } } /* Finally, if p is negative or not a whole number, */ /* call the library pow function. The pow macro */ /* is defeated by surrounding the name "pow" with */ /* parentheses. */ else [9] return (pow)(a, p); }
Update to the description of the long long Data Type |
In Chapter 2, "Source Code Conventions," replace the tenth and eleventh paragraghs of the section titled, "Description of the long long Data Type," with the following text.
One way in which the SAS/C long long
implementation differs from the
C99 standard is
in the interpretation of decimal constants. According to C99, a decimal constant
that is too large to fit into a long
, such
as 3000000000
on the mainframe, should be assumed
to be a long long
. According to the 1989 ANSI/ISO standard,
the type of this constant is unsigned long
. SAS/C continues
to treat any such constant within the range of unsigned long
as unsigned long
, to avoid
changing the meaning of existing programs. This behavior is compatible with
most compilers for other platforms that support a long long
type.
The C99SUBSET
option will cause unsuffixed
decimal constants to be interpreted with C99 rules, that is, they can never
be unsigned. You can use the standard C language suffixes to control the
type of a decimal constant. For example, 3000000000UL
will have a type of unsigned long
regardless
of compiler options, but 3000000000
will have
a type that depends on compiler option settings: long long (C99SUBSET, NOHUGEPTRS)
, long
(HUGEPTRS)
, or unsigned
long (default options)
.
Update to the rtconst Option Description |
In Chapter 7, "Linking C Programs," under the section titled, "COOL
Options," add the following text to the description of the rtconst
option.
Usually the run-time constant section can be removed without affecting
normal program execution. However, a very large function compiled with the archlevel(b)
option (or greater) may require the run-time
constant CSECT to be present to execute correctly. COOL will preserve the
run-time constant section for a compilation including such a function, even
if rtconst
has been specified.
Update to the enforce, mention, and suppress Option Descriptions |
In Chapter 6, "Compiler Options," in the section titled, "Option
Descriptions," the descriptions of the enforce
, mention
, and suppress
options
need to be updated to remove the information stating that "Only warnings
in the range 0-199 and 300-499 are affected."
enforce
with the
following text:
treats one or more warning conditions as error conditions. Each warning condition is identified by its associated message number. Conditions whose numbers have been specified are treated as errors, and the compiler return code is set to 12 instead of 4.
mention
with the following text:
specifies that
the warnings whose numbers are specified as n1, n2, and so on, are not to
be suppressed. See also suppress
.
suppress
with the following
text:
Each warning condition is identified by its associated message number, n. Conditions whose numbers have been specified are suppressed. No message is generated, and the compiler return code is changed.
Updates to the #pragma Options |
In Chapter 6, "Compiler Options," in the section titled, "The
#pragma options statement," add the following options to the list of #pragma options
:
armode | |
indep | |
sname(value) |
Update to the ENXREF COOL Option Description |
In Chapter 7, "Linking C Programs," in the section titled, "COOL
Options," replace the third paragraph of the enxref
description with the following text.
You can use the references
option (-Areferences
under USS) to modify the behavior of the
sname
, cid
, or linkid
cross-reference listing so that unresolved external
references are included in the cross-references listing. You must use the references
option in conjunction with one or more of these
listing options: sname
, cid
, or linkid
. For example:
enxref(sname references)
specifies an sname
cross-reference listing that includes cross-references
for external symbols that are declared but not defined.
Updates to the COOL Options Tables |
The following table contains corrections to the table labeled, "COOL Options Equivalents," in Chapter 7, "Linking C Programs."
Long Form | Short Form |
---|---|
auto
|
-a
|
clet
|
-m
|
clet(all)
|
-m
|
clet(noex)
|
-mn
|
continue
|
-zc
|
cxx
|
-cxx
|
dupsname
|
-zd
|
endisplaylimit
|
-ynnnn
|
enexit
|
-xt
|
enexitdate
(xxx) |
-xt
xxx |
enxref (cid)
|
-xxx
|
enxref (linked)
|
-xxe
|
enxref (references)
|
-xxy
|
enxref (sname)
|
-xxs
|
extname
|
-xn
|
files
(xxx) |
-f
xxx |
gmap
|
-yg
|
inceof
|
-zi
|
libe
|
-b
|
lineno
|
-l
|
list
|
-yl
|
noenxref
|
-!xx
|
output
fileid |
-o
fileid |
pagesize
(nn) |
-s
nn |
prem
|
-p
|
print
|
-h
|
prmap
|
-yp
|
rtconst
|
-r
|
smpjclin
|
-sj
|
smponly
|
-sxo
|
smpxivec
|
-sx
|
term
|
-t
|
upper
|
-u
|
verbose
|
-zv
|
warn
|
-w
|
xfnmkeep
|
-xf
|
xsymkeep
|
-xe
|
The following table contains corrections to the table labeled, "COOL Options," in Chapter 7, "Linking C Programs."
Option | TSO | CMS | OS/390 Batch | USS |
---|---|---|---|---|
-Agather
|
X | |||
-Ainsert
|
X | |||
allresident
|
X | X | X | |
arlib
|
X | |||
auto
|
X | X | X | |
-Bep
|
X | |||
-Blib
|
X | |||
cics
|
X | X | X | |
cicsvse
|
X | X | X | |
clet
|
X | X | X | X |
clet(all)
|
X | X | X | X |
clet(noex)
|
X | X | X | X |
continue
|
X | X | X | X |
cxx
|
X | X | ||
dupsname
|
X | X | X | X |
endisplaylimit
|
X | X | X | X |
enexit
|
X | X | X | X |
enexitdata
|
X | X | X | X |
entry
|
X | |||
enxref
|
X | X | X | X |
extname
|
X | X | X | X |
files
|
X | |||
genmod
|
X | |||
global
|
X | |||
gmap
|
X | X | X | X |
gos
|
X | X | ||
inceof
|
X | X | X | X |
-1
|
X | |||
-L
|
X | |||
lib
|
X | |||
libe
|
X | |||
lineno
|
X | X | X | X |
list
|
X | X | X | X |
lked
|
X | |||
lkedname
|
X | X | ||
load
|
X | X | ||
loadlib
|
X | |||
nocool
|
X | X | ||
output
|
X | |||
pagesize
|
X | X | X | X |
prem
|
X | X | X | X |
print
|
X | X | X | |
prmap
|
X | X | X | X |
rtconst
|
X | X | X | X |
smpjclin
|
X | X | X | X |
smponly
|
X | X | X | X |
smpxivec
|
X | X | X | X |
spe
|
X | X | X | |
start
|
X | |||
term
|
X | X | X | |
upper
|
X | X | X | X |
verbose
|
X | X | X | X |
warn
|
X | X | X | X |
xfnmkeep
|
X | X | X | X |
xsymkeep
|
X | X | X | X |
Update to the _O_SNAME Symbol |
In Chapter 6, "Compiler Options," in the section titled, "Preprocessor
Symbols," add the following text to the explanation of the _O_SNAME
option that follows the table labeled, "Preprocessor
Symbols."
If you use the compiler sname
option
to set the _O_SNAME
preprocessor symbol, it
has an affect similar to using a #define
preprocessor
directive to define the symbolic name _O_SNAME
.
You cannot actually use a #define
directive
to define _O_SNAME
. You must use the compiler sname
option. Attempting to set the _O_SNAME
symbol with a
#define
preprocessor
directive will result in an LSCC133 error.
Update to the <resident.h> Documentation |
In Chapter 10, "All-Resident C Programs," in the section
titled, "Using <resident.h>
,"
remove the note at the end of the section that reads,
Note: The dollars
compiler option must be used when compiling a C++
source file that contains <resident.h>
.
and replace it with the following text.
The dollars
compiler option
is no longer
required when compiling a C++ source file that includes <resident.h>
.
Updates to the SPE Functions |
In Chapter 14, "Systems Programming with the SAS/C Compiler," in the section titled "The SPE Library," add the following functions to the table of SPE functions.
gethostbyaddr* |
gethostbyname* |
htonl |
htons |
IARV64 |
inet_addr |
inet_lnaof |
inet_makeaddr |
inet_netof |
inet_network |
inet_ntoa |
ntohl |
ntohs |
osdltok |
osgttok |
ossttok |
WTP |
After the section titled "HFS Access," create a new section titled "TCP/IP Access," and move the last paragraph of the section titled "HFS Access" into the new section. The paragraph to be moved reads:
SPE supports access to USS integrated sockets using the standard UNIX
socket interface functions such as socket
, accept
, read
, write
, and so on.
Note that only integrated sockets can be
accessed. Starting with z/OS 1.2, the TCP/IP resolver functions; gethostbyname
and gethostbyaddr
are supported. However, other resolver type functions such as res_init
and getservbyname
are not supported because USS does not provide system calls for these functions.
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2004 by SAS Institute Inc., Cary, NC, USA. All rights reserved.