Developing AMODE(64) assembler language programs

CICS® Transaction Server supports non-Language Environment® (LE) assembler language programs that run in 64-bit addressing mode (AMODE(64)) and thereby access up to 16 exabytes (EB) of virtual storage. This support allows you to develop non-LE assembler language programs, which are able to process large amounts of data.

Because CICS also allows linkage between AMODE(64) and AMODE(31) or even AMODE(24) programs, it is possible to provide service routines that handle data in 64-bit storage without rewriting other parts of the application.

CICS AMODE(64) native assembler application programming

Writing a CICS AMODE(64) native assembler application program is very similar to writing a CICS AMODE(31) native assembler application program. The same CICS macros that are included in the AMODE(31) version of the application program are included in an AMODE(64) application program.

There are a number of differences between writing in AMODE(64) and writing in AMODE(31), as follows:

  • The z/OS® SYSSTATE macro must specify AMODE64=YES. The CICS macros DFHEISTG, DFHEIEND, DFHEIENT, DFHEIRET and DFHECALL are SYSSTATE aware and generate AMODE(64) assembler when SYSSTATE AMODE64=YES has been specified. The SYSSTATE macro must be invoked before any of the SYSSTATE aware CICS macros are invoked.
  • Macro DFHEIENT must use relative addressing. To specify that relative addressing is to be used, CODEREG=0 must be specified and STATREG and STATIC values must be supplied.
  • The AMODE(64) version of the CICS stub must be included in the Binder (Link-edit) step in a similar way that the AMODE(31) CICS stub must be included in the Binder step for an AMODE(31) or AMODE(24) application. The AMODE(64) CICS stub is DFHEAG.

When writing AMODE(64) assembler, whether for CICS or batch, you must ensure that the registers used to reference storage have valid addresses. There are assembler instructions that ensure that a clean 31-bit address is loaded into a 64-bit register. These instructions are LLGT and LLGTR. LLGT loads a 31-bit address into a registers and clears the top 33 bits of the registers. LLGTR loads a register from another register and clears the top 33 bits. Instruction LLGF can be used to load a fullword into a 64-bit register; the fullword is loaded into the bottom 32 bits of the register and the top 32 bits of the registers are cleared.

EXEC CICS 64-bit commands

To allow AMODE(64) programs to use above-the-bar storage, CICS provides 64-bit variants of some of the CICS API commands to manipulate data in 64-bit storage (also referred to as above the bar). These commands are as follows:

GETMAIN64
To get storage above the bar (by default: other storage locations can be explicitly specified)
FREEMAIN64
To release storage that was acquired by a program running in AMODE(64), typically used to free storage above the bar
PUT64 CONTAINER
To put data from 64-bit storage into a named channel container
GET64 CONTAINER
To get data from a named channel container into 64-bit storage

EXEC CICS assembler language macros

If the application is declared as AMODE(64), the following CICS-supplied macros generate AMODE(64) code:
DFHEIENT
For AMODE(64) programs, the DFHEIENT macro calls the AMODE(64) PROLOG program, which allocates working storage to hold any user variables and for CICS use. The PROLOG program sets up the CICS portion of this storage. When the PROLOG program returns, this code sets up the registers specified by the DFHEIENT parameters. For more information, see Coding the DFHEIENT macro for AMODE(64) assembler language programs.
DFHEISTG
For AMODE(64) programs, the DFHEISTG macro generates an AMODE(64) DSECT. At translation, the translator inserts the DFHEISTG macro immediately following your DFHEISTG DSECT instruction. In this way, the DSECT describes dynamic storage needed for the parameter list, for the command-level interface, and for any user variables. For more information, see Extending dynamic storage for assembler language programs.
DFHEIRET
For AMODE(64) programs, the DFHEIRET macro calls the AMODE(64) EPILOG program to release the working storage of the application program. For more information, see Coding the DFHEIRET macro for assembler language programs.
DFHECALL
For an assembler language application program, when the CICS translator detects a CICS command, each command is replaced by an invocation of the DFHECALL macro. The DFHECALL macro sets up the command parameters and calls the initial CICS command processor to handle the command. For more information, see DFHECALL macro.

Procedure

The following procedure summarizes the information that relates specifically to developing AMODE(64) assembler language programs.

  1. Use the z/OS Assembler SYSSTATE macro to declare that an application is AMODE(64).
    1. Include a SYSLIB statement for the SYS1.MACLIB macro library (which contains the SYSSTATE macro) in your compile JCL.
    2. Ensure one of the following:
      • The SYSSTATE macro with parameter AMODE64=YES is placed immediately after the CICS translator options statement. For example:
        *ASM   XOPTS(NOPROLOG NOEPILOG)
               SYSSTATE AMODE64=YES 
        
      • If the program does not specify CICS translator options, the SYSSTATE macro with parameter AMODE64=YES is the first statement.

      The SYSSTATE statement must be on one line, because CICS does not support continuation for this statement. For more information about the SYSSTATE macro, see SYSSTATE - Identify system state in z/OS MVS Programming: Assembler Services Reference IAR-XCT.

    Note: If the SYSSTATE macro is not specified, or is specified without parameter AMODE64=YES, when any of the CICS-supplied macros, DFHEIENT, DFHEISTG, DFHEIRET, and DFHECALL, first generates code, these macros generate AMODE(24) or AMODE(31) code.
  2. Specify the DFHEIENT macro with the appropriate parameters for relative addressing. See Coding the DFHEIENT macro for AMODE(64) assembler language programs.

    For information about the DFHEISTG storage, see Extending dynamic storage for assembler language programs.

  3. If you are not using EXEC CICS RETURN, specify the DFHEIRET macro, or use the translator-inserted version. See Coding the DFHEIRET macro for assembler language programs.
  4. Translate, assemble and link-edit the program. See Translating, assembling, and link-editing assembler language application programs.

    For information about the DFHECALL macro, see DFHECALL macro.

    For information about link-editing the stub programs, see Using the EXEC interface modules for AMODE(64) applications.

CICS AMODE(64) assembler example

Here is an example of a CICS AMODE(64) native assembler application program. The source code has been augmented with annotations. There are many styles in which assembler code can be written, and no one is better than any other, it is just a matter of the writer’s preference. This example illustrates a possible style for writing AMODE(64) assembler in CICS.

The example shows how to obtain shared storage located above the bar and save the address of the shared storage address in the CWA. The example does not show how data is loaded into the shared storage, as there are many ways in which this could be done. For example, you might want to read data from a VSAM file or from a Db2® database.

The data stored in the shared storage above the bar in this example cannot be accessed by AMODE(31) or AMODE(24) applications, but an AMODE(64) assembler program called by the AMODE(31) or AMODE(24) application would be able to access this data and then return all, or portions of, the data to its caller.

There are several ways in which the data could be returned to the AMODE(31) or AMODE(24) caller, including:

  • CICS COMMAREA
  • CICS container, within a channel
  • A buffer supplied by the caller

The *ASM XOPTS statement is used to pass options to the translator. In this case NOPROLOG and NOEPILOG are specified to stop the translator inserting PROLOG and EPILOG instructions.

*ASM XOPTS(NOPROLOG NOEPILOG) Translator options

The SYSSTATE macro tells SYSSTATE aware macros that the AMODE is 64 and also specifies the architecture level of the machine that the program will execute on. The CICS native assembler macros are SYSSTATE aware so will generate AMODE 64 code when AMODE64=YES is set.


         SYSSTATE AMODE64=YES,ARCHLVL=4   Sysstate AMODE 64, Z10  
***********************************************************************  
*        Register equates.                                               
***********************************************************************  
r0       equ   0                                                         
r1       equ   1                                                         
r2       equ   2                                                         
r3       equ   3                                                         
r4       equ   4                                                         
r5       equ   5                                                         
r6       equ   6                                                         
r7       equ   7                                                         
r8       equ   8                                                         
r9       equ   9                                                         
r10      equ   10                                                        
r11      equ   11                                                        
r12      equ   12                                                       
r13      equ   13                                                       
r14      equ   14                                                       
r15      equ   15                                                       
*********************************************************************** 
*        Module’s working storage.                                       
*********************************************************************** 

Macros DFHEISTG and DFHEIEND are SYSSTATE aware. These macros define DSECT DFHEISTG. As the SYSSTATE macro specified AMODE64=YES the CICS portion of this DSECT is defined for an AMODE 64 application.

The CICS portion of the DSECT defines a format-four save area, the 64-bit address of the COMMAREA and EIB, and other fields used by CICS when the application program issues a CICS command.

The application’s working storage variables are defined after the DFHEISTG macro and before the DFHEIEND macro. In this case these variables are wk_shared_storage_addr, wk_cwa_address and wk_flength.

The DFHEIEND indicates the end of the DSECT.


         dfheistg ,                                                     
         ds    0ad                                                      
wk_shared_storage_addr   ds  ad      Shared storage address             
wk_cwa_addr              ds  ad      CWA address                        
wk_flength               ds  f       Getmain64 flength                  
         dfheiend                                                       
The next two DSECTs (cwa_mapping and shared_data) map the CWA and the shared data storage area.
*********************************************************************** 
*        CWA dsect.                                                     
*********************************************************************** 
cwa_mapping  dsect                                                      
cwa_shared_storage_addr  ds  ad      Shared storage address             
*********************************************************************** 
*        Shared data dsect.                                             
*********************************************************************** 
shared_data  dsect                                                      
shared_thing ds   xl1000             Shared data object                 
shared_data_length equ *-shared_data Length of shared data 

The following statements name the CSECT and its AMODE and RMODE.


AMODE64X csect                                                          
AMODE64X amode 64                                                       
AMODE64X rmode 31  

Macro DFHEIENT generates the program’s entry code. This code:

  • Saves the caller’s registers in the format-four save area pointed to be R13.
  • Makes a call to DFHEAG0 is obtain the program’s working storage. This storage must be obtained below the bar to allow all CICS command processors to function correctly.
  • Sets up the working storage, static and EIB registers. The working storage register is R13, the static register is R12 and the EIB register is R11.

                                                     
         DFHEIENT CODEREG=0,           Relative addressing             -
               DATAREG=R13,            Data register                   -
               EIBREG=R11,             EIB register                    -
               STATREG=R12,            Static register                 -
               STATIC=STATIC_AREA      Static label                     
*********************************************************************** 
*        Obtain above the bar shared storage.                           
*********************************************************************** 

The CICS command below obtains above the bar shared storage. The address of the shared storage obtained is returned in R2 if the command is successful.


         EXEC CICS GETMAIN64                                           -
               FLENGTH(LENGTH_OF_SHARED_STORAGE)                       -
               SET(R2)                                                 -
               SHARED                                                  -
               NOHANDLE

The code below checks the EIB response and if it is not normal jumps to label abend1.


         clc  eibresp,dfhresp(normal)                                   
         jne  abend1

If the response to the command is normal the address of the shared storage is saved in the program’s working storage.


         stg  r2,wk_shared_storage_addr  Save shared storage address   

Insert code here to load data into the shared storage. Data could be read from many sources including VSAM files or databases.


*********************************************************************** 
*        Obtain address of CWA.                                         
*********************************************************************** 

The CICS command below returns the address of the CWA in R3 if the command is successful.


         EXEC CICS ADDRESS CWA(R3) NOHANDLE 

The code below checks the EIB response and if it is not normal jumps to label abend2.


         clc  eibresp,dfhresp(normal)                                   
         jne  abend2 

If the response to the command is normal, the address of the CWA is saved in the program’s working storage.


         stg  r3,wk_cwa_addr             Save CWA address               
*********************************************************************** 
*        Save shared storage address in CWA.                            
*********************************************************************** 

The code below uses the CWA mapping to save the address of the shared data area in the CWA.


         using cwa_mapping,r3                                           
         stg  r2,cwa_shared_storage_addr Save shared storage addr       
         drop r3                         Drop r3                        
*********************************************************************** 
*        Return to CICS.                                                
*********************************************************************** 
return   ds   0h

The command below returns control to CICS. In fact the DFHEIRET macro could have been used instead the of the CICS return command.


         EXEC CICS RETURN                                               
*********************************************************************** 
*        Issue abend.                                                   
*********************************************************************** 

The CICS command below issues abend ERR1 if the CICS GETMAIN command is not successful.


Abend1   ds   0h                                                        
         EXEC CICS ABEND ABCODE('ERR1')                                 
The CICS command below issues abend ERR2 if the CICS ADDRESS command is not successful. 
Abend2   ds   0h                                                        
         EXEC CICS ABEND ABCODE('ERR2')                               
*********************************************************************** 
*        Static   
*********************************************************************** 

The program’s static area


static_area   ds  0fd                                                   
length_of_shared_storage  dc  al4(shared_data_length)                   
*********************************************************************** 
*        Ltorg                                                          
*********************************************************************** 
         ltorg                                                          
         end   

Using AMODE(64) native assembler programs

An AMODE(64) program such as the example shown above could be used to store large amounts of data, and return portions of this to other programs within an application. In this scenario, the AMODE(64) program could act as a service routine which is called by programs in other addressing modes to manipulate large storage areas on their behalf.

One particularly valuable way of using an AMODE(64) program could be to put data from a 64-bit storage area directly into a container within a channel (either a named channel or the default current channel). This data in this container can then be accessible to an AMODE(31), or even AMODE(24), program by using the container API. The EXEC CICS GET CONTAINER command will return the 64-bit data into a 31-bit (or 24-bit) storage area provided by the invoking program. This can be a useful way of sharing data between 64-bit ‘service’ routines and other programs in the application, without the need to convert all of the application to AMODE(64) native assembler.

To invoke an AMODE(64) program from a program in another addressing mode, use EXEC CICS LINK or XCTL.