Compiler
Hardware Built-in Functions
A built-in function is inline code that is generated in place of an actual function call. These functions correspond to z/OS instructions, such as store clock extended (STCKE), add decimal (AP), etc.
Sometimes the function inserts extra instructions to load the parameters for the operation and to store the result. Use of these instructions is not limited to Metal-C, as they can be used in any z/OS C program.
Using a built-in hardware instruction does not guarantee that a hardware instruction will be generated. The compiler can decide that it is not necessary to generate the code, and in some cases, the instruction will be generated as data before it is executed via an EX instruction.
As an example, the move character extended instruction which has an instruction format:
MVCLE R1,R3,D2(B2) [RS-a]
For reference here is part of the instruction description as described in z/Architecture Principles of Operation:
All or part of the third operand is placed at the first operand location. The remaining rightmost byte positions, if any, of the first-operand location are filled with padding bytes. The operation proceeds until the end of the first-operand location is reached or a CPU-determined number of bytes have been placed at the first-operand location, whichever occurs first. The result is indicated in the condition code.
The R1 and R3 fields each designate an even-odd pair of general registers and must designate an even numbered register; otherwise, a specification exception is recognized.
The second-operand address is not used to address data; instead, the rightmost eight bits of the second operand address, bits 56-63, are the padding byte. Bits 0-55 of the second-operand address are ignored.
The C prototype for the builtin version of this instruction is:
int __mvcle(char *op1,unsigned long op1_len,unsigned char op2, char *op3,unsigned long op3_len);
Operands
- op1 and op1_len represent the first operand in the hardware instruction.
- op3 and op3_len represent the third operand in the hardware instruction.
- op2 specifies the byte for padding the first operand on the right, in the event that it is shorter than the third operand.
Conditions
If the LP64 compiler option is in effect, the op1_len and op3_len operands are 64-bit unsigned integers. Otherwise, op1_len and op3_len are 32-bit unsigned integers.The return value is the condition code set by the MVCLE instruction.
Note: When the condition code is 3, the condition is handled by the compiler-generated code.
Below is a contrived example to show how a built-in instruction could be used.. It consists of a simple C function which can be called, passing character fields and lengths. The purpose of this function is to move a source field of length op3_len to a destinatiion field of length op1_len. The example is not meant to necessarily be useful, but is for illustrative purposes.
#pragma export(move) #include#include #include #include int move(char *op1, unsigned long op1_len, unsigned char op2, char *op3, unsigned long op3_len) { int cc = 0; cc = __mvcle(op1, op1_len, op2, op3, op3_len); return cc; }
Below is a portion of the generated Assembler code with ILP32 in effect:
* {
*
* int cc = 0;
*
* cc = __mvcle(op1, op1_len, op2,
* op3, op3_len);
USING @@PARMD@1,1
L 2,@77op1@219
L 3,@78op1_len@220
LLGC 4,@79op2@221+3
L 14,@80op3@222
L 15,@81op3_len@223
@@LAB@1 MVCLE 2,14,0(4)
BRO @@LAB@1
IPM 15
SRL 15,28
*
*
* return cc;
* }
@1L27 DS 0H
LMH 14,4,80(13)
DROP
L 13,4(,13)
L 14,12(,13)
LM 1,4,24(13)
BR 14
Below is a list of some of the many hardware instructions available for use in a C program. There are many more instructions available, including decimal floating point, perform locked operation, hexadecimal floating-point instructions, and transactional memory.
| Prototype | Pseudo Assembly |
|---|---|
| int __ap(unsigned char*, unsigned char, unsigned char*, unsigned char) | AP Op1D(len1, Op1B),Op2D(len2, Op2B) |
| int __cds1(void* Op1, void* Op2, void* Op3) | CDS Op1,Op3,Op2D(Op2B) |
| int __cp(unsigned char*, unsigned char, unsigned char*, unsigned char) | CP Op1D(len1, Op1B),Op2D(len2, Op2B) |
| int __cs1(void* Op1, void* Op2, void* Op3) | CS Op1,Op3,Op2D(Op2B) |
| int __cvb(char *op2) | CVB R1, Op2D(Op2X, Op2B) |
| void __cvd(int op1, char *op2) | CVD Op1, Op2D(Op2X, Op2B) |
| void __dp(unsigned char*, unsigned char, unsigned char*, unsigned char) | DP Op1D(len1, Op1B),Op2D(len2, Op2B) |
| int __ed (unsigned char *OP1, unsigned char *OP2, unsigned char length) | ED Op1D(len,Op1B), Op2D(Op2B) |
| int __edmk (unsigned char*, unsigned char*, unsigned char, unsigned char**) | EDMK Op1D(len,Op1B),Op2D(Op2B) |
| void __mp(unsigned char*, unsigned char, unsigned char*, unsigned char) | MP Op1D(len1, Op1B),Op2D(len2, Op2B) |
| int __nc (unsigned char*, unsigned char*, unsigned char) | NC Op1D(len,Op1B),Op2D(Op2B) |
| int __oc (unsigned char*, unsigned char*, unsigned char) | OC Op1D(len,Op1B),Op2D(Op2B) |
| void __pack (unsigned char*, unsigned char,unsigned char*, unsigned char) | PACK Op1D(len1,Op1B),Op2D(len2,Op2B) |
| int __sp(unsigned char*, unsigned char, unsigned char*, unsigned char) | SP Op1D(len1, Op1B),Op2D(len2, Op2B) |
| int __srp(unsigned char*, unsigned char, signed char, unsigned char) | SRP Op1D(len1, Op1B),Op2D(Op2B), Op3 |
| int __stcke(void *Op1) | STCKE Op1D(Op1B) |
| int __stck (unsigned long long *) | STCKE Op1D(Op1B) |
| void __tr (unsigned char *Op1, const unsigned char *Op2,unsigned char len) | TR Op1D(len,Op1B),Op2D(Op2B) |
| int __tre(char *op1, unsigned long op1_len, char *op2, unsigned char test_char) | TRE R1, Op2 |
| int __trt (unsigned char*, const unsigned char*, unsigned char, unsigned char*, unsigned char**) | TRT Op1D(len,Op1B),Op2D(Op2B) |
| void __unpk (unsigned char *OP1, unsigned char len1,unsigned char *OP2, unsigned char len2) | UNPK Op1D(len1,Op1B),Op2D(len2,Op2B) |
| int __xc (unsigned char*, unsigned char*, unsigned char) | XC Op1D(len,Op1B),Op2D(Op2B) |
| int __zap (unsigned char *op1, unsigned char len1,unsigned char *op2, unsigned char len2 ) | ZAP Op1D(len1, Op1B),Op2D(len2, Op2B) |
References
- z/OS V2R2 XL C/C++ Programming Guide - Chapter 33. Using hardware built-in functions
- z/Architecture Principles of Operation
All references copyright© IBM Corporation.