United States |
Previous | Contents | Index |
The following sections describe the Compaq C built-in functions
available on OpenVMS Alpha systems.
6.2.1.1 Translation Macros for VAX C Built-in Functions
On Compaq C for OpenVMS Alpha Systems, the <builtins.h> header file contains macro definitions that translate some VAX C built-in functions to the equivalent Compaq C for OpenVMS Alpha built-in functions. Consequently, the following VAX C built-in functions are effectively supported:
_BBCCI
_BBSSI
_INSQHI
_INSQTI
_INSQUE
_REMQHI
_REMQTI
_REMQUE
_PROBER
_PROBEW
For more detail on any of these functions, see
<builtins.h>
or the description of the corresponding native Alpha function
in this chapter. For example, for a description of _INSQHI, see
__PAL_INSQHIL.
6.2.1.2 In-line Assembly Code---ASMs
Compaq C supports in-line assembly code, commonly called ASMs on UNIX platforms.
Like builtin-functions, ASMs are implemented with a function-call syntax. But unlike built-in functions, to use ASMs you must include the <c_asm.h> header file containing prototypes for the three types of ASMs, and the #pragma intrinsic preprocessor directive.
These functions have the following format:
__int64 asm(const char *, ...); /* for integer operations, like MULQ */ float fasm(const char *, ...); /* for single precision float instructions, like MULS */ double dasm(const char *, ...); /* for double precision float instructions, like MULT */ #pragma intrinsic (asm, fasm, dasm) |
const char *
The first argument to the asm , fasm , or dasm function contains the instruction(s) to be generated inline and the metalanguage that describes the interpretation of the arguments....
The source and destination arguments (if any) for the instruction being generated, and any other values used in the generated instructions.These values are made available to the instructions through the normal argument passing conventions of the calling standard (the first integer argument is available in register R16).
The #pragma intrinsic directive in the <c_asm.h> header file is required when using ASMs. It notifies the compiler that:
The metalanguage for the argument references has the following form:
<metalanguage_sequence> : <register_alias> | <register_number> | <register_macro> ; <register_number> : "$" number ; <register_macro> : "%" <macro_sequence> ; <macro_sequence> : number | <register_name> | "f" number | "F" number | "r" number | "R" number ; <register_name> : /* argument registers: R16-R21 */ "a0" | "a1" | "a2" | "a3" | "a4" | "a5" /* return value: R0 or F0, depending on type */ | "v0" /* scratch registers: R1, R22-R24, R28 */ | "t0" | "t1" | "t2" | "t3" | "t4" /* save registers: R2-R15 */ | "s0" | "s1" | "s2" | "s3" | "s4" | "s5" | "s6" | "s7" | "s8" | "s7" | "s8" | "s9" | "s10" | "s11" | "s12" | "s13" /* stack pointer: R30 */ | "sp" | "SP" | "$sp" | "$SP" | "RA" | "ra" /* return addr: R26 */ | "PV" | "pv" /* procedure value: R27 */ | "AI" | "ai" /* arg info: R25 */ | "FP" | "fp" /* frame pointer: R29 */ | "RZ" | "rz" | "zero" /* sink/source: R31 == zero */ |
Syntactically, the metalanguage can appear anywhere within an instruction sequence.
The literal string that contains instructions, operands, and metalanguage must follow the general form:
<string_contents> : <instruction_seq> | <string_contents> ";" <instruction_seq> | error | <string_contents> error ; <instruction_seq> : instruction_operand | directive ; |
An instruction_operand is generally recognized as an assembly language instruction separated by whitespace from a sequence of comma-separated operands.
You can code multiple instruction sequences into one literal string, separating them by semicolons.
Since the C language concatentates adjacent string literals into a single string, successive instructions can be written as separate strings, one per line (as is normally done in assembly language) as long as each instruction is terminated by a semicolon (as shown in the examples).
There are semantic and syntax rules associated with ASMs:
The first
argument to an ASM call is interpreted as the instructions to be
assembled in the metalanguage, and must be fully understood by the
compiler at compile time. Therefore, it must be a literal string (or a
macro expanding to a literal string) and must not be a run-time value
containing a string. Therefore, the following are not allowed:
indirections, table lookups, structure dereferences, and so on.
The
remaining arguments are loaded into the argument registers like normal
function arguments, except that the second argument to the ASM
call is treated as the first argument for purposes of the
calling standard.
For example, in the following test, the six
arguments are loaded into arg registers a0 through a5, and the result
of each subexpression is stored in the value return register v0. Since
v0 is the calling standard's return value register (R0 for an integer
function), the result of the final MULQ is the value returned by the
"call":
if (asm("mulq %a0, %a1, %v0;" "mulq %a2, %v0, %v0;" "mulq %a3, %v0, %v0;" "mulq %a4, %v0, %v0;" "mulq %a5, %v0, %v0;", 1, 2, 3, 4, 5, 6) != 720){ error_cnt++; printf ("Test failed\n"); } |
z = fasm("mulq %r2, %a1 %r5", x=10, y=5); |
z = fasm("mulq %a0, %a1, %a1;" "stq %a1, 0(%a2);" "ldt %f0, 0(%a2);" "cvtqf %f0, %f0;", x=10, y=5, &temp); |
asm("MB"); |
The __ABS built-in is functionally equivalent to its counterpart, abs , in the standard header file <stdlib.h> .
Its format is also the same:
#include <stdlib.h> int __ABS (int x); |
This built-in does, however, offer performance improvements because there is less call overhead associated with its use.
If you include
<stdlib.h>
, the built-in is automatically used for all occurrences of
abs
. To disable the built-in, use
#undef abs
.
6.2.1.4 Acquire and Release Longword Semaphore (__ACQUIRE_SEM_LONG, __RELEASE_SEM_LONG)
The __ACQUIRE_SEM_LONG and __RELEASE_SEM_LONG functions provide a counted semaphore capability where the positive value of a longword is interpreted as the number of resources available.
The __ACQUIRE_SEM_LONG function loops until the longword has a positive value and then decrements it within a load-locked/store-conditional sequence; it then issues a memory barrier. This function returns 1 if the resource count was successfully decremented within the specified number of retries, and 0 otherwise. With no explicit retry count, the function does not return until it succeeds.
The __RELEASE_SEM_LONG function issues a memory barrier and then does an __ATOMIC_INCREMENT_LONG on the longword.
The __ACQUIRE_SEM_LONG function has one of the following formats:
int __ACQUIRE_SEM_LONG (volatile void *address); int __ACQUIRE_SEM_LONG_RETRY (volatile void *address, int retry); |
The __RELEASE_SEM_LONG function has the following format:
int __RELEASE_SEM_LONG (volatile void *address); |
address
The longword-aligned address of the resource count.retry
A retry count of type int that indicates the number of times the operation is attempted (which is at least once, even if the retry argument is 0). If the operation cannot be performed successfully in the specified number of retries, the function returns without updating the longword.
The __ADAWI function adds its source operand to the destination. This function is interlocked against similar operations by other processors or devices in the system.
This function has the following format:
int __ADAWI (short src, volatile short *dest); |
src
The value to be added to the destination.dest
A pointer to the destination. The destination must be aligned on a word boundary. (You can achieve alignment using the _align storage-class modifier.)
The __ADAWI function returns a simulated VAX processor status longword (PSL), the lower 4 bits of which are significant. These 4 bits are the condition codes and are defined as follows:
The __ADD_ATOMIC_LONG function adds the specified expression to the aligned longword pointed to by the address parameter within a load-locked/store-conditional code sequence.
This function has the following format:
int __ADD_ATOMIC_LONG (void *address, int expression, ...); |
address
The address of the aligned longword.expression
An integer expression....
An optional retry count of type int . If specified, the retry count indicates the number of times the operation is attempted (which will be at least once, even if the count argument is 0). If the operation cannot be performed successfully in the specified number of retries, a value of 0 is returned. If the operation is successful, a value of 1 is returned.
If the optional retry count is omitted, this function loops back for a retry unconditionally on failure. In this case, the function can never return a failure value. It either returns a value of 1 upon successful completion, or hangs in an endless failure loop. |
The __ADD_ATOMIC_QUAD function adds the specified expression to the aligned quadword pointed to by the address parameter within a load-locked/store-conditional code sequence.
This function has the following format:
int __ADD_ATOMIC_QUAD (void *address, int expression, ...); |
address
The address of the aligned quadword.expression
An integer expression....
An optional retry count of type int . If specified, the retry count indicates the number of times the operation is attempted (which will be at least once, even if the count argument is 0). If the operation cannot be performed successfully in the specified number of retries, a value of 0 is returned. If the operation is successful, a value of 1 is returned.
If the optional retry count is omitted, this function loops back for a retry unconditionally on failure. In this case, the function can never return a failure value. It either returns a value of 1 upon successful completion, or hangs in an endless failure loop. |
The __ALLOCA function allocates n bytes from the stack.
This function has the following format:
void *__ALLOCA (unsigned int n); |
n
The number of bytes to be allocated.
A pointer to the allocated memory is returned.
6.2.1.9 AND Atomic Longword ( __AND_ATOMIC_LONG)
The __AND_ATOMIC_LONG function performs a logical AND of the specified expression with the aligned longword pointed to by the address parameter within a load-locked/store-conditional code sequence.
This function has the following format:
int __AND_ATOMIC_LONG (void *address, int expression, ...); |
address
The longword-aligned address of the data segment.expression
An integer expression....
An optional retry count of type int . If specified, the retry count indicates the number of times the operation is attempted (which will be at least once, even if the count argument is 0). If the operation cannot be performed successfully in the specified number of retries, a value of 0 is returned. If the operation is successful, a value of 1 is returned.
If the optional retry count is omitted, this function loops back for a retry unconditionally on failure. In this case, the function can never return a failure value. It either returns a value of 1 upon successful completion, or hangs in an endless failure loop. |
The __AND_ATOMIC_QUAD function performs a logical AND of the specified expression with the aligned quadword pointed to by the address parameter within a load-locked/store-conditional code sequence.
This function has the following format:
int __AND_ATOMIC_QUAD (void *address, int expression, ...); |
address
The address of the aligned quadword.expression
An integer expression....
An optional retry count of type int . If specified, the retry count indicates the number of times the operation is attempted (which will be at least once, even if the count argument is 0). If the operation cannot be performed successfully in the specified number of retries, a value of 0 is returned. If the operation is successful, a value of 1 is returned.
If the optional retry count is omitted, this function loops back for a retry unconditionally on failure. In this case, the function can never return a failure value. It either returns a value of 1 upon successful completion, or hangs in an endless failure loop. |
The __ATOMIC_ADD_LONG function adds the specified expression to the aligned longword pointed to by the address parameter within a load-locked/store-conditional code sequence and returns the value of the longword before the addition was performed.
This function has one of the following formats:
int __ATOMIC_ADD_LONG (volatile void *address, int expression); int __ATOMIC_ADD_LONG_RETRY (volatile void *address, int expression, int retry, int *status); |
address
The longword-aligned address of the data segment.expression
An integer expression.retry
A retry count of type int that indicates the number of times the operation is attempted (which is at least once, even if the retry argument is 0). If the operation cannot be performed successfully in the specified number of retries, the function returns without updating the longword.status
A pointer to an integer that is set to 0 if the operation did not succeed within the specified number of retries, and set to 1 if the operation succeeded.
The non-RETRY form of this function loops back for a retry unconditionally on failure. This means this function can hang in an endless failure loop. |
The __ATOMIC_ADD_QUAD function adds the specified expression to the aligned quadword pointed to by the address parameter within a load-locked/store-conditional code sequence and returns the value of the quadword before the addition was performed.
This function has one of the following formats:
int __ATOMIC_ADD_QUAD (volatile void *address, int expression); int __ATOMIC_ADD_QUAD_RETRY (volatile void *address, int expression, int retry, int *status); |
address
The quadword-aligned address of the data segment.expression
An integer expression.retry
A retry count of type int that indicates the number of times the operation is attempted (which is at least once, even if the retry argument is 0). If the operation cannot be performed successfully in the specified number of retries, the function returns without updating the quadword.status
A pointer to an integer that is set to 0 if the operation did not succeed within the specified number of retries, and set to 1 if the operation succeeded.
The non-RETRY form of this function loops back for a retry unconditionally on failure. This means this function can hang in an endless failure loop. |
Previous | Next | Contents | Index |
|