Chapter Contents

Previous

Next
Inline Machine Code Interface

Functions

The following pages define the functions for the inline machine code interface.


_bbwd

Branch to a Previously Defined Label

SYNOPSIS

#include <code.h>

void _bbwd(unsigned short op, unsigned short target);


DESCRIPTION

_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.

The op argument must specify one of the following instructions:

BAL BCT
BAS BXH
BC (except NOP BXLE

The NOP instruction (0x4700) is not supported. Also note that any index register in the instruction must be specified as 0.

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.

CAUTIONS

If incorrect arguments are passed to _bbwd , the compiler produces a diagnostic, sets the return code to 8, and generates an EX 0,* instruction. This instruction causes an execute exception (OS ABEND code 0C3) if it is actually executed.

Do not use _bbwd to generate instructions that modify registers required by compiled code. See _code for a listing of these registers.

The _bbwd function should only be used to transfer control to a label defined in the same block of machine code as the branch. If this rule is disregarded, the results are unpredictable.

PORTABILITY

_bbwd is not portable.

EXAMPLE

#include <code.h>

   /* this code multiplies the integers i and j by */
   /* repeated addition                            */

_ldregs(R1+R2+R3, i, j, 0);
_label(1);           /* LABEL1 EQU * */
_code(R3,0x1a31);    /* AR  3,1      */
_bbwd(0x4620,1);     /* BCT 2,LABEL1 */


RELATED FUNCTIONS

_code , _ldregs , _bfwd , _branch , _label


_bfwd

Branch to a Label Defined Later

SYNOPSIS

#include <code.h>

void _bfwd(unsigned short op, unsigned short target)


DESCRIPTION

_bfwd causes the compiler to generate a branch instruction with a target that is a label defined later. The target argument is the _label number of the target label. The op argument specifies the first halfword of the instruction to generate. Both arguments to _bfwd must be compile-time constants.

The op argument must specify one of the following instructions:

BAL BCT
BAS BXH
BC (except NOP BXLE

The NOP instruction (0x4700) is not supported. Also note that any index register in the instruction must be specified as 0.

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.

CAUTIONS

If incorrect arguments are passed to _bfwd , the compiler produces a diagnostic, sets the return code to 8, and generates an EX 0,* instruction. This instruction causes an execute exception (OS ABEND code 0C3) if it is actually executed.

Do not use _bfwd to generate instructions that modify registers required by compiled code. See _code for a listing of these registers.

The _bfwd function should only be used to transfer control to a label defined in the same block of machine code as the branch. If this rule is disregarded, the results are unpredictable.

PORTABILITY

_bfwd is not portable.

EXAMPLE

#include <code.h>

   /* this code multiplies the integers i and j by */
   /* repeated addition.  unlike the _bbwd example,*/
   /* it behaves correctly when j is less than or  */
   /* equal to 0                                   */

_ldregs(R1+R2+R3, i, j, 0);
_code(0, 0x1222);    /*  LTR 2,2      */
_bfwd(0x4780, 2);    /*  BZ  LABEL2   */
_bfwd(0x4720, 1);    /*  BP  LABEL1   */
_code(R2, 0x1322);   /*  LCR 2,2      */
_code(R1, 0x1311);   /*  LCR 1,1      */
_label(1);           /* LABEL1 EQU *  */
_code(R3, 0x1a31);   /*  AR  3,1      */
_bbwd(0x4620, 1);    /*  BCT 2,LABEL1 */
_label(2);           /* LABEL2 EQU *  */


RELATED FUNCTIONS

_code , _ldregs , _bbwd , _branch , _label


_blabel

Reference a Backward Branch Target

SYNOPSIS

#include <code.h>

unsigned _blabel(int n);


DESCRIPTION

_blabel identifies a branch target occurring earlier in the compilation than the point at which _blabel is called. The argument n specifies the _label number of the branch target and must be a compile-time constant. A call to _blabel should be used only as an argument to the _branch function or to a macro that generates a call to this function.

RETURN VALUE

_blabel returns an encoded form of the target label that can be interpreted by the _branch function.

PORTABILITY

_blabel is not portable.

EXAMPLE

#include <code.h>
#include <genl370.h>

   /* this code multiplies the integers i and j by */
   /* repeated addition.  this code has the same   */
   /* effect as the _bbwd example, but uses macros */
   /* from genl370.h for readability               */

_ldregs(R1+R2+R3, i, j, 0);
_label(1);           /* LABEL1 EQU * */
AR(3,1);
BCT(2,0,_blabel(1))  /* BCT 2,LABEL1 */


RELATED FUNCTIONS

_bbwd , _branch , _flabel


_branch

Generate a Branch Instruction

SYNOPSIS

#include <code.h>

void _branch(unsigned mask, unsigned short op,
             unsigned int target);


DESCRIPTION

_branch provides a flexible method for generating branch instructions. All operands of _branch must be compile-time constants. Depending on the form of the target argument, the _branch function behaves as follows:


CAUTIONS

_branch is not intended for direct programmer use. It is implemented primarily as a tool for use by the macros in the SAS/C inline code header files.

When a 0x00BBzzzz or 0x00BFzzzz argument is passed to _branch , all restrictions applying to the use of _bbwd and _bfwd apply to _branch . In particular, only permitted branch instructions can be specified, and use of an index register is not allowed.

If incorrect arguments are passed to _branch , the compiler produces a diagnostic, sets the return code to 8, and generates an EX 0,* instruction. This instruction causes an execute exception (OS ABEND code 0C3) if it is actually executed.

The mask operand of _branch defines the registers that may be modified by the generated instruction, as with the _code function. If the mask is not specified correctly, the effects of _branch are unpredictable.

Do not use _branch to generate instructions that modify registers required by compiled code. See _code for a listing of these registers.

The _branch function should only be used to transfer control to a label defined in the same block of machine code as the branch. If this rule is disregarded, the results are unpredictable.

PORTABILITY

_branch is not portable.

RELATED FUNCTIONS

_bbwd , _bfwd , _blabel , _code , _flabel


_cc

Access Hardware Condition Code

SYNOPSIS

#include <svc.h>

int _cc(void);


DESCRIPTION

_cc enables you to access the condition code set by an SVC, DIAGNOSE, or machine instruction. The following table shows the hardware condition codes and their most common meanings, the _cc function codes, and the mnemonic macros that can be used instead of the actual values.

Hardware Condition Code Most Common Meaning of Code _cc Function Returns Symbolic Macros for _cc Function Return Codes
0 equal 0 CC0, CCZ, CCE
1 less - 1 CC1, CCL, CCM
2 greater 2 CC2, CCH, CCP
3 overflow 3 CC3, CCO

Note:    Making the _cc condition code 1 for the less condition (rather than 1) allows the result of _cc to be compared with 0 in a natural way.  [cautionend]

The condition code is not modified by the execution of _cc .

Declarations for _cc and the associated macros can be obtained by including (via #include ) either <code.h> or <svc.h> .

RETURN VALUE

_cc returns the current hardware condition code as one of the integers 0, 1, 2, or 3.

CAUTIONS

If, after an SVC, DIAGNOSE, or machine instruction, you need to store registers and also access the condition code, you should use _stregs to store the registers first. When it is followed by a call to _cc , _stregs does not modify the condition code, but in some cases, _cc may modify register contents in order to address the area where the condition code is to be stored.

PORTABILITY

_cc is not portable.

IMPLEMENTATION

In general, five instructions are required to reduce the hardware condition code to an integer value. However, if the only use of the value returned by _cc is in a comparison with 0, only a single BC instruction is generated.

EXAMPLE

#include <code.h>
#include <genl370.h>
#include <stdio.h>

   /* Add two binary integers together, and print a message */
   /* if the sum is negative.                               */
int sum;
short increment;                    /* halfword */

_ldregs(R2+R3, sum, &increment);

AH(2,0,0+b(3));                     /* AH 2,0(0,3) */

if (_cc() <0)
   printf("The sum is negative\n");


RELATED FUNCTIONS

_cms202 , _code , _diag , _ldregs , _ossvc , _stregs


_cms202

Generate CMS SVC 202 Instruction

SYNOPSIS

#include <svc.h>

void _cms202(void);


DESCRIPTION

_cms202 generates an SVC 202 instruction. It is intended to be used by programs executing under nonbimodal CMS. _cms202 takes no arguments. (See _ossvc for generating OS/390 supervisor calls; also see the descriptions of SVC202 and e_SVC202 for other methods of generating an SVC 202 instruction.)

Note:    The _ossvc built-in function may be used to generate an SVC 204 in bimodal CMS.  [cautionend]

RETURN VALUE

No value is returned by _cms202 . To access values returned in registers, including any return code, use the _stregs function.

CAUTIONS

Use the _ldregs function to set up registers correctly before issuing the SVC 202.

If your program executes under OS/390, you should use the _ossvc built-in function rather than _cms202 .

PORTABILITY

_cms202 is not portable.

IMPLEMENTATION

_cms202 first stores any values currently in use from general-purpose registers 0, 1, 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 202. _cms202 then saves the address of the SVC instruction as an aid to traceback production in case the SVC 202 causes an abend. It then issues an SVC 202 instruction followed by a fullword (unaligned) 1.

EXAMPLE

Note:    Refer to the CMS Command Reference for more details on nucleus extensions.  [cautionend]

#include <svc.h>
#include <lcio.h>
#include <stdio.h>
#include <lcstring.h>

   /* Use the CMS function NUCEXT to determine if the         */
   /* GLOBALV command is a nucleus extension.                 */
struct {                  /* NUCEXT QUERY parameter list.     */
   char cmd[8] ;          /* 'NUCEXT'                         */
   char name[8] ;         /* Nucleus extension name.          */
   char *scblock;         /* Receives pointer to SCBLOCK.     */
   char *query;           /* 0xffffffff  (identify QUERY)     */
   }nucx;


int rc;

   /* Copy in the name of the command, padded to */
   /* eight characters.                          */
memcpyp(nucx.cmd,"NUCEXT",8,6,' ');

   /* Copy in the name of the nucleus extension to be queried, */
   /* again padded to eight characters.                        */
memcpyp(nucx.name,"GLOBALV",8,7,' ');

nucx.query = (char *) -1;       /* Identify the QUERY function.*/

_ldregs(R1,&nucx);              /* R1 -> struct nucx.          */
_cms202();                      /* Issue SVC 202.              */
rc = _stregs(R15);              /* If rc == 0, GLOBALV is a    */
                                /* nucleus extension.          */

printf("Globalv %s a nucleus extension\n",
       rc == 0 ? "is" : "is not");


RELATED FUNCTIONS

_diag , _ldregs , _ossvc , _stregs , SVC202 , e_SVC202


_code

Generate a Machine Instruction or Inline Data

SYNOPSIS

#include <code.h>

void _code(unsigned mask, unsigned short data1, unsigned short data2,
           unsigned short data3, unsigned short data4);


DESCRIPTION

_code provides a flexible method for generating machine instructions or inline data. _code enables you to issue machine instructions directly from C without the overhead of a subroutine call. In many cases, you can use either _code or the code macros to generate machine instructions. In general, the code macros are easier to use, but the _code function is more flexible. _code generates one to four halfwords of data into the compiled code instruction stream. Usually this is a machine instruction, but any data can be specified. _code takes two to five arguments that must all be compile-time constants. 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, 2, 4, and 6 can be specified as F0 through F6, respectively. Multiple registers can be specified by adding (or logically ORing) the macros, for example, R0+R1 (or R0|R1). Refer to Bit Masks for Using Registers for more information on the mask argument.

After the register mask, the remaining arguments of _code are generated on a halfword boundary in the instruction stream. They are not validated in any way. Any bits in an argument that do not fit in a short are ignored.

The inline machine code interface provides macros for naming registers that make the register arguments to _code more readable when used to generate machine instructions. Refer to the listing of the <regs.h> header file in General Header Files for the macros that can be used with _code .

Use the _ldregs function to load registers used by _code ; use the _stregs function to store instruction results, and use the _cc function to access the condition code.

RETURN VALUE

_code returns no value. To access values returned in registers, use the _stregs function; to access the condition code, use the _cc function.

CAUTIONS

If you specify incorrect arguments for _code (for example, the wrong number of arguments or an invalid register mask), pass two of the compiler produces an error message, sets the return code to 8, and generates an EX 0,* instruction for _code . The generated instruction causes an execute exception (OS ABEND code 0C3) if it is actually executed.

Do not use _code to generate instructions that modify registers required by compiled code, specifically the following:
4 is used to address constants.
5 is the program base register.
12 accesses the C Run-Time Anchor Block (CRAB).
13 addresses the current automatic storage area.

If you modify any of these registers, the results are unpredictable but are likely to include an abend. See the register usage warning in Usage Notes.

PORTABILITY

_code is not portable.

IMPLEMENTATION

_code first stores any values currently in use from general-purpose registers specified by the register mask and then generates the requested instructions or data.

EXAMPLE

#include <code.h>

    /* Generate a call to the CMS DMSFREE macro, */
    /* consisting of an SVC 203 instruction,     */
    /* followed by a halfword of data.           */
 unsigned amt;
 char *storage;

 _ldregs(R0, amt/8);

 _code(R1, 0x0acb,         /* Issue SVC 203                */
           0x1e04);        /* specifying DMSFREE function. */

    /* store address of allocated memory */
 storage =(char *) _stregs(R1);


RELATED FUNCTIONS

_cc , _ldregs , _stregs


_diag

Generate DIAGNOSE Instruction

SYNOPSIS

#include <svc.h>

void _diag(int n);


DESCRIPTION

_diag generates a DIAGNOSE instruction, using 0 and 14 as the register arguments and n as the diagnose code. n must be a compile-time constant. It is intended to be used by programs executing under CMS or some other operating system running in a virtual machine under VM/SP, VM/XA, or VM/ESA.

RETURN VALUE

_diag returns no value. To access values returned in registers, including any return code, use the _stregs function. To access the condition code set by _diag , use the _cc function.

CAUTIONS

Use the _ldregs function to set up registers correctly before issuing the DIAGNOSE. Do not use _diag in a real machine or when in virtual problem state.

PORTABILITY

_diag is not portable.

IMPLEMENTATION

_diag first stores any values currently in use from general-purpose registers 0, 1, 14, and 15 and clears any information the compiler has about the contents of these registers. It assumes these registers are, or may be, altered by the DIAGNOSE. It then issues a DIAG 0 , 14 , n instruction, where n is the specified diagnose code.

EXAMPLE

#include <svc.h>
#include <stdio.h>

   /* Issue DIAGNOSE X'24' to obtain information about the */
   /* virtual console.                                     */
unsigned devaddr, vinfo, rinfo;

_ldregs(R0, -1);  /* Load -1 to get virtual console information. */

_diag(0x24);      /* Ask CP for location and information.        */


   /* store the results */
_stregs(R0+R14+R15, &devaddr, &vinfo, &rinfo);

switch(_cc()) {  /* check condition code */
   case CC0:
      printf("Console address is %x\n",
            (unsigned short) devaddr);
      break;
   case CC2:
      printf("Virtual console at %x, no real console\n",
            (unsigned short) devaddr);
      break;
   case CC3:
      printf("Virtual console does not exist\n");
      break;
}


RELATED FUNCTIONS

_cc , _cms202 , _ldregs , _ossvc , _stregs


_flabel

Reference a Forward Branch Target

SYNOPSIS

#include <code.h>

unsigned _flabel(int n);


DESCRIPTION

_flabel identifies a branch target occurring later in the compilation than the point at which _flabel is called. The argument n specifies the _label number of the branch target and must be a compile-time constant. A call to _flabel should be used only as an argument to the _branch function, or to a macro that generates a call to this function.

RETURN VALUE

_flabel returns an encoded form of the target label that can be interpreted by the _branch function.

PORTABILITY

_flabel is not portable.

EXAMPLE

#include <code.h>
#include <genl370.h>
   /* this code multiplies the integers i and j by   */
   /* repeated addition.  unlike the _blabel example,*/
   /* it behaves correctly when j is less than or    */
   /* equal to 0.  this code has the same effect as  */
   /* the _bfwd example, but uses macros  from       */
   /* genl370.h for readability                      */
_ldregs(R1+R2+R3, i, j, 0);
LTR(2,2);
BC(8, 0, _flabel(2));  /* BZ  LABEL2 */
BC(2, 0, _flabel(1));  /* BP  LABEL1 */
LCR(2,2);
LCR(1,1);
_label(1);             /* LABEL1 EQU * */
AR(3,1);
BCT(2, 0, _blabel(1)); /* BCT 2,LABEL1 */
_label(2);             /* LABEL2 EQU * */


RELATED FUNCTIONS

_bbwd , _branch , _blabel


_label

Define an Inline Machine Code Branch Target

SYNOPSIS

#include <code.h>

void _label(unsigned short n);


DESCRIPTION

_label identifies a location in an inline machine code block as a branch target and associates it with an integer n between 1 and 65535. n must be a compile-time constant. More than one definition using the same integer in a single compilation is permitted. The execution of _label has no effect; that is, _label defines a location in the object code but does not add any instructions there.

EXAMPLE

See the examples for _bbwd , _bfwd , _blabel and _flabel .

Related Functions

_bbwd , _bfwd , _blabel , _flabel


_ldregs

Load Registers

SYNOPSIS

#include <svc.h>

   /* Further arguments are any C expressions - see below. */
void _ldregs(unsigned mask,...);


DESCRIPTION

_ldregs is central to the interface between the SAS/C Compiler and inline machine code because it enables you to set up values in machine registers that are used by subsequent machine instructions.

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, 2, 4, and 6 can be specified as F0 through F6, respectively. Multiple registers can be specified by adding (or logically ORing) the macros, for example, R0+R1 (or R0|R1). Refer to Bit Masks for Using Registers for more information on the mask argument.

Remaining arguments specify the values to be placed in the registers (low to high) 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.

Each call to _ldregs starts a new inline machine code sequence. After the call, the contents of any register not explicitly specified in the mask are undefined.

Declarations for _ldregs and the associated macros are provided in <code.h> as well as <svc.h> ; either or both can be used.

RETURN VALUE

_ldregs returns no value.

CAUTIONS

You can safely use the following registers:
0 - 3, 14, 15 are general-purpose registers.
0, 2 are floating-point registers.

In addition, you can use floating-point registers 4 and 6 if they are not currently assigned to a register variable.

Do not specify any of the following registers:
4 is used to address constants.
5 is the program base register.
6 - 11 are used for register variables.
12 accesses the C Run-Time Anchor Block (CRAB).
13 addresses the current automatic storage area.

See the register usage warning in Usage Notes.

If you specify incorrect arguments for _ldregs (for example, the wrong number of parameters or an invalid register mask), the compiler produces an error message, sets the return code to 8, and generates an EX 0,* instruction for _ldregs . The generated instruction causes an execute exception (OS/390 ABEND code 0C3) if it is actually executed.

PORTABILITY

_ldregs is not portable.

IMPLEMENTATION

_ldregs first dumps any values currently in use from the specified registers back to memory. It then clears any information the compiler had about the contents of the registers. Finally, it loads the registers with the values of the specified C expressions. The order in which the registers are loaded is chosen by the compiler, and it is not necessarily the same as the order of the registers in the mask or the same for every invocation of _ldregs .

EXAMPLE

#include <regs.h>

   /* Set register 0 to the value 8 and register 14   */
   /* to the address of "field", after first clearing */
   /* any values currently in those registers.        */
long field;

   /* After macro expansion, the final effect of this */
   /* expression is:  _ldregs(0x80020000,8,&field);   */
_ldregs(R0+R14,8,&field);


RELATED FUNCTIONS

_cc , _cms202 , _code , _diag , _ossvc , _stregs


_osarmsvc

Generate OS/390 SVC Instruction without Changing Addressing Mode

SYNOPSIS

void _osarmsvc(int n);


DESCRIPTION

_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.

RETURN VALUE

_osarmsvc returns no value. To access values returned in registers, use the _stregs function.

CAUTIONS

If you specify incorrect arguments for _osarmsvc (such as the wrong number of arguments or an argument that is not a compile-time constant in the range 0 to 255), pass two of the compiler produces an error message, sets the return code to 8, and generates an EX 0,* instruction for _osarmsvc. The generated instruction causes an execute exception (OS/390 ABEND code 0C3) if it is executed.

PORTABILITY

_osarmsvc is not portable.

IMPLEMENTATION

_osarmsvc 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. _osarmsvc 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. Finally, _osarmsvc issues the requested SVC instruction.


_ossvc

Generate OS/390 or CMS SVC Instruction

SYNOPSIS

#include <svc.h>

void _ossvc(int n);


DESCRIPTION

The _ossvc function generates an SVC instruction that is executed in primary address space mode, even if the armode compiler option was specified. _ossvc 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.

RETURN VALUE

_ossvc returns no value. To access values returned in registers, use the _stregs function.

CAUTIONS

If you specify incorrect arguments for _ossvc (such as the wrong number of arguments or an argument that is not a compile-time constant in the range 0 to 255), pass two of the compiler produces an error message, sets the return code to 8, and generates an EX 0,* instruction for _ossvc . The generated instruction causes an execute exception (OS/390 ABEND code 0C3) if it is executed.

If your program executes under CMS, you may want to use the _cms202 or _diag function or both instead of _ossvc , depending on the service required.

PORTABILITY

_ossvc is not portable.

IMPLEMENTATION

_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 enter primary address space 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, if the armode compiler option is in effect, issue a SAC instruction to restore access register mode.

EXAMPLE

#include <svc.h>
#include <stdio.h>

   /* Use MVS SVC 11 to obtain the current time as an   */
   /* HHMMSShh GMT value.  Set register 1 to a bit mask */
   /* that requests this form.  HHMMSShh is returned in */
   /* register 0, and a return code is returned in      */
   /* register 15.                                      */
int rc = 0;                   /* return code */
char packed[4] ;       /* area for time in HHMMSShh format */

_ldregs(R1,0x82);             /* Set bit mask in reg 1. */
_ossvc(11);                   /* Issue SVC 11.          */
_stregs(R0+R15,&packed,&rc);  /* returned values        */

if (rc == 0)
printf("GMT is %2x:%02x:%02x:%02x\n",
       packed[0] ,packed[1] ,packed[2] ,packed[3] );

return rc;


RELATED FUNCTIONS

_cms202 , _diag , _ldregs , _stregs


_stregs

Store Values from Registers

SYNOPSIS

#include <svc.h>

   /* Further arguments are expressions */
   /* of pointer type - see below.      */
int _stregs(unsigned mask,...);


DESCRIPTION

_stregs enables you to save register values set by an SVC, DIAGNOSE, or machine instruction into memory accessible to the C program. The call to _stregs terminates the inline machine code sequence.

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, 2, 4, and 6 can be specified as F0 through F6, respectively. Multiple registers can be specified by adding (or logically ORing) the macros, for example, R0+R1 (or R0|R1). Refer to Bit Masks for Using Registers for more information on the mask argument.

Remaining arguments specify where each register is to be stored, in the order (low to high) specified by mask . These arguments can be either the address of a variable or a C pointer type. If you specify a pointer, the register is stored in the memory pointed to by the pointer.

If you specify the address of a C variable, the register is stored in that variable. Note that to store a register in a C variable, you must specify the address of the variable. If you specify the variable directly, the variable is treated as a pointer, and the contents of the register are stored in the area addressed by the pointer.

If you specify one more register in the mask than the number of arguments to the function, the value in the highest general-purpose register in the mask is not stored. Instead, it is returned as the value of the _stregs function call.

Declarations for _stregs and the macros for the register mask can be obtained by including either <code.h> or <svc.h> .

RETURN VALUE

_stregs returns the value contained in the highest numbered general-purpose register specified in the mask. If no general-purpose register is specified in the mask, the value returned is unpredictable.

To access the condition code set by an SVC, DIAGNOSE, or machine instruction, use the _cc function.

CAUTIONS

If you use _stregs to obtain the addresses of run-time control blocks (such as the CRAB), code, or data areas, and then modify the contents of the control blocks, code, or data areas, your program is no longer valid C and the results are entirely unpredictable.

Do not use complex expressions, especially ones involving array indexes, as operands of _stregs because register shortages can occur. If there is a register shortage, a register whose value was to be stored may be reused. To avoid the problem, assign a complex expression to a pointer variable and specify the variable as the _stregs argument. Alternately, you can use the _code function to generate ST (store) or STM (store multiple) instructions to store values based on one or more previously loaded addressing registers.

If you specify incorrect arguments for _stregs (for example, the wrong number of arguments or an invalid register mask), pass two of the compiler produces an error message, sets the return code to 8, and generates an EX 0,* instruction for _stregs . The generated instruction causes an execute exception (OS/390 ABEND code 0C3) if it is actually executed.

PORTABILITY

_stregs is not portable.

IMPLEMENTATION

_stregs stores the values from the specified registers in the places in memory addressed by the expressions. The sequence in which the registers are stored is determined by the compiler and is not necessarily the same as the order of the registers in the mask. Because the register values are not changed, the compiler retains the information it has about the contents of each register.

EXAMPLE

#include <svc.h>

   /* Store the value in register 1 in the C variable reg1, */
   /* store the value in register 15 in the area pointed    */
   /* to by the variable r15 area, and store the value in   */
   /* floating-point register 0 in the area pointed to      */
   /* by the variable dp.                                   */
long reg1;
long  r15area;
double * dp;
_ldregs(0);
   /* After macro expansion, the final effect of this        */
   /* expression is: r15area = _stregs(0x40018000,&reg1,dp); */
r15area = _stregs(R1+R15+F0,&reg1,dp);


RELATED FUNCTIONS

_cc , _cms202 , _code , _diag , _ldregs , _ossvc


SVC202, e_SVC202

Generate CMS SVC 202 Instruction with Arguments

SYNOPSIS

#include <svc.h>

   /* macro */
int SVC202(r1plist)

   /* macro */
int e_SVC202(r0plist, r1plist)


DESCRIPTION

SVC202 and e_SVC202 (extended SVC 202) generate an SVC 202 instruction. They are intended to be used by programs executing under nonbimodal CMS. SVC202 takes a pointer to a tokenized PLIST defined in your program. e_SVC202 takes both a pointer to an untokenized PLIST and a pointer to a tokenized PLIST, both defined in your program.

Note:    The _ossvc built-in function may be used to generate a SVC 204 in bimodal CMS.  [cautionend]

RETURN VALUE

If no error occurs, these functions return 0. If an error occurs, the value set by the SVC 202 (which is stored in register 15) is returned by the function.

PORTABILITY

SVC202 and e_SVC202 are not portable.

IMPLEMENTATION

SVC202 and e_SVC202 are implemented as the following macros:

#define SVC202(r1) (_ldregs(R1,r1),_cms202(),_stregs(R15))
#define e_SVC202(r0,r1) 
(_ldregs(R0|R1,r0,0x01000000|(unsigned) (r1)), 
_cms202(),_stregs(R15))


EXAMPLE

Refer to the description of _cms202 for an alternate version of this example. The VM/XA SP CMS Command Reference contains more details on nucleus extensions.

#include <svc.h>
#include <lcstring.h>
#include <stdio.h>

   /* Use the CMS function NUCEXT to determine if the GLOBALV */
   /* command is a nucleus extension.                         */
struct {             /* NUCEXT QUERY parameter list          */
   char cmd[8] ;      /* 'NUCEXT'                             */
   char name[8] ;     /* nucleus extension name               */

   char *scblock;     /* Receives pointer to SCBLOCK.         */
   char *query;       /* 0xffffffff  (identify QUERY)         */
   nucx;
}

int rc;

   /* Copy in the name of the command, padded to           */
   /* eight characters.                                    */
memcpyp(nucx.cmd,"NUCEXT",8,6,' ');

   /* Copy in the name of the nucleus extention            */
   /* to be queried, again padded to eight characters.     */
memcpyp(nucx.name,"GLOBALV",8,7,' ');

nucx.query = (char *) -1;  /* Identify the QUERY function. */

rc=SVC202(&nucx);          /* Issue SVC 202.               */

printf("Globalv %s a nucleus extension\n",
       rc == 0 ? "is" : "is not");


RELATED FUNCTIONS

_cms202 , _ossvc


Chapter Contents

Previous

Next

Top of Page

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