With the METAL option, an AR-mode function can access data stored in data spaces by using the hardware access registers. For more information about AR-mode, see z/OS MVS Programming: Assembler Services Guide. A non-AR-mode function is said to be in primary mode.
The following sections describe the compiler options, language constructs, and built-in functions that support AR-mode programming.
void armode_func() __attribute__((armode));
You
can also use the ARMODE compiler option to declare that all functions
in the source program to be AR-mode functions. If you use the ARMODE
compiler option and you want to single out the functions in the source
program to be primary mode functions you can declare the function
with the noarmode attribute. The syntax is: void nonarmode_func() __attribute__((noarmode));
int * __far my_far_pointer;
Language Construct | Effect |
---|---|
Implicit or explicit cast from normal to far pointer | Because the normal pointer is assumed to point to primary address space, the ALET of the far pointer is set to 0. |
Explicit cast from far pointer to normal pointer | The offset of the far pointer is extracted and used to form the normal pointer. Unless the ALET of the far pointer was 0, the normal pointer is likely to be invalid. |
Operators !=, == | If either operand is a far pointer, the other operand is implicitly cast to a far pointer before the operands are compared. The comparison is performed on both the ALET and offset components of a far pointer. |
Operators <, <=, >, >= | Only the offset of the far pointer is used in the comparison. Unless the ALETs of the far pointers were the same, the result might be meaningless. |
Compare to NULL | Because of the implicit cast of NULL to a far pointer, the != and == operators compare both the ALET and the offset to zero. A test of !(p>NULL) is not sufficient to ensure that the ALET is also 0. |
Pointer arithmetic | The effects of pointer arithmetic are applied to the offset component of a far pointer only. The ALET component remains unchanged. |
Address of Operator, operand of & | The result is a normal pointer, except in the
following cases:
|
In addition to explicitly specifying ALETs that use far pointers to access data in data spaces, the compiler must associate those ALETs with all the memory references contained in the AR-mode function.
Variable type | Implied ALET |
---|---|
File-scope variable | ALET 0 (primary data space) |
Stack variables (function local variable) | The ALET that is in AR 13 at the time of function entry. This points to the stack frame. |
Parameters (function formal parameters) | The ALET that is in AR 1 at the time of function entry. This points to the parameter list. |
Data pointed to by regular pointers | ALET 0 (primary data space). |
Data pointed by far pointer | ALET contained in far pointer. |
The Metal C Runtime Library does not provide functions for allocating or deallocating alternative data spaces. You can use the DSPSERV and ALESERV HLASM macros to allocate space and obtain a valid ALET and offset. For an example, see Figure 5. For more information, see z/OS MVS Programming: Assembler Services Guide.
void * __far __set_far_ALET_offset(unsigned int alet, void * offset);
void * __far __set_far_ALET(unsigned int alet, void * __far offset); 1
void * __far __set_far_offset(void * __far alet, void * offset); 2
unsigned int __get_far_ALET(void * __far p);
void * __get_far_offset(void * __far p);
For information about ARMODE built-in functions, see Using hardware built-in functions in z/OS XL C/C++ Programming Guide.
The XL C compiler provides far versions of some of the standard C string and memory library functions. The far versions can be called by either AR-mode or primary-mode functions. If these functions are called by an AR mode function, the compiler will generate inline code for them.
The semantics of these functions, listed in Figure 4, are identical to the standard version.
void * __far __far_memcpy(void * __far s1, const void * __far s2, size_t n);
int __far_memcmp(const void * __far s1, const void * __far s2, size_t n);
void * __far __far_memset(void * __far s, int c, size_t n);
void * __far __far_memchr(const void * __far s, int c, size_t n);
char * __far __far_strcpy(char * __far s1, const char * __far s2); See Note
char * __far __far_strncpy(char * __far s1, const char * __far s2, size_t n);
int __far_strcmp(const char * __far s1, const char * __far s2);
int __far_strncmp(const char *__far s1, const char * __far s2, size_t n);
char * __far __far_strcat(char * __far s1, const char * __far s2);
char * __far __far_strncat(char * __far s1, const char * __far s2, size_t n);
char * __far __far_strchr(const char * __far s, int c);
char * __far __far_strrchr(const char * __far s, int c);
size_t __far_strlen(const char * __far s);
If the calling function is in non-AR mode, the DSA and parameter areas are assumed to be located in the primary address space.
Figure 5 provides examples of routines for allocating and deallocating data space.
Figure 5. Allocation and deallocation routines
|
|
|
Figure 6 provides an example of using a built-in function to copy a C string pointer to a far pointer.
/*****************************************************/
/* __far_strcpy example */
/*****************************************************/
char *__far far_strcpy_example() __attribute__((armode));
char *__far far_strcpy_example()
{
char *__far far_string;
char * near_string;
near_string = "Hello World!\n";
far_string = allocate_far(1024);
__far_strcpy(far_string,near_string);
return far_string; /* Assume caller will free allocated data space */
}
The Metal C Runtime Library does not provide functions for allocating or deallocating alternative data spaces. Figure 7 provides an example of code that dereferences a far pointer.
/*****************************************************/
/* Simple dereference example */
/*****************************************************/
char get_ith_character(char *__far s, int i) __attribute__((armode));
char get_ith_character(char *__far s, int i)
{
return s[i];
}
int main()
{
char c;
char *__far far_string;
far_string = far_strcpy_example();
c = get_ith_character(far_string,1);
free_far(far_string);
return c;
}