Chapter Contents

Previous

Next
Code Generation Conventions

Access Register Mode Support

As part of its systems-programming support, SAS/C allows a C function to execute in access register mode, and to access data in dataspaces or other address spaces. This facility is presently supported only in an OS/390 SPE environment (see Chapter 14, "Systems Programming with the SAS/Compiler" in the SAS/C Compiler and Library User's Guide). See the IBM ESA/390 Principles of Operation publication (SA22-7201) for more information on access registers and access register mode.

Access to data in a dataspace or another address space is accomplished through the use of far pointers. A far pointer is an 8-byte object that contains an ALET (an address space identifier) as well as an address. When a far pointer is dereferenced, the ALET is loaded into the hardware access register corresponding to the general register containing the address part of the pointer. The ALET is stored in the first word of the far pointer, and the address in the second word.

Note:    When a regular (near) pointer is dereferenced, an ALET of 0, specifying the primary address space, is loaded into the appropriate access register.  [cautionend]

Far pointers are declared using the _ _far keyword. This keyword is syntactically similar to the const keyword, but applies only to data pointer types. The _ _near keyword can be used to explicitly declare a pointer as a near pointer. Here are some examples of declarations using the _ _near and _ _far keywords.

_ _far char *keyptr;

keyptr is a far pointer to character.

_ _far char **nearfar;

nearfar is a near pointer to a far pointer to character.

char *_ _far *farnear;

farnear is a far pointer to a near pointer to character.

int cache(_ _near void *, _ _far
void *);

cache is a function taking two arguments -- a near pointer and a far pointer.

  _ _far struct udata *lookup(char *uname);

lookup is a function that returns a far pointer to a structure. Its argument is a near pointer to character.

The following uses of _ _far will fail to compile for the indicated reason:

_ _far double[40000];  /* Error: _ _far is only meaningful for pointers */
int (_ _far *service)(int);
                      /* Error: only data pointers, not function
                         pointers, can be far */

The result of the address operator (&) is normally a near pointer. However, the address of an object accessed via a far pointer is itself a far pointer. For example, &(a->b) is a near pointer if a is near, and a far pointer if a is far. This distinction is important mostly when passing arguments to functions without prototypes, or with a variable number of arguments.

Far pointers may be converted to near pointers and vice versa. When a far pointer is converted to near, its ALET is discarded; when a near pointer is converted to far, a zero ALET is implied. Note that converting from a far pointer to a near pointer is ordinarily "safe" only when its ALET is known to be 0.

Far pointers may be subtracted. The result is a ptrdiff_t, and the ALET portions of the pointers are ignored during the subtraction. Because far pointers are 8-byte pointers, they can be converted to a long long integer without loss of information. Conversion to a shorter integer type will cause the ALET information to be lost.

The armode compiler option is required for any C function that uses the value of a far pointer. Code that is compiled with the armode option runs entirely in access register mode, except that function entry, function exit, and subroutine calls take place in primary address space mode. This allows code compiled with the armode option and code compiled without it to be freely mixed.

The SAS/C compiler's access register mode support uses a callee saves convention for the access registers. This means that a called access register mode routine saves the access registers on entry and restores them on exit. Note that this implies that any assembler language routine that might be called, directly or indirectly, from a caller compiled with the armode option must restore any access registers it uses before returning.

When a far pointer is passed to a function, the pointer is doubleword-aligned in the argument list. (Far pointers in static or auto storage, on the other hand, need only be fullword-aligned.) When a function returns a far pointer, the address is returned in general register 15 and the ALET in access register 15.

Note that obtaining access to data in dataspaces or other address spaces remains the responsibility of the user program. Stack and heap memory, as well as control blocks like the PRV are always allocated in the primary address space. The library routines dspserv, aleserv, and falloc, which are described in SAS/C Library Reference, Volume 2, can be used to create a dataspace and to allocate space in a dataspace. This functionality can also be performed in assembler language.


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.