9.3. Operation Definitions (OPDEF)

An operation definition (OPDEF) identifies a sequence of statements to be called later in the source program by an opdef call. Each time the opdef call occurs, the definition sequence is placed into the source program.

Opdefs resemble machine instructions and can be used to define new machine instructions or to redefine current machine instructions. Machine instructions map into opcodes that represent some hardware operation. When an operation is required that is not available through the hardware, an opdef can be written to perform that operation. When the opdef is called, the opdef maps into the opdef definition body and the operation is performed by the defined sequence specified in the definition body.

You can replace any existing machine instruction with an opdef. Although opdef definitions should conform to meaningful operations that are supported by the hardware, they are not restricted to such operations.

The opdef definition sets up the parameters into which the arguments specified in the opdef call are substituted. Opdef parameters are always expressed in terms of registers or expressions. The opdef call passes arguments to the parameters in the opdef definition. The syntax for the opdef definition and the opdef call are identical with two exceptions:

These two exceptions allow you to specify parameters in the place of registers and expressions for an opdef definition.

The syntax defining a register_parameter and an expression_parameter is case-sensitive. Every character that identifies the parameter in the opdef prototype statement must be identical to every character in the body of the opdef definition. This includes the case (uppercase, lowercase, or mixed case) of each character.

Because the opdef can accept arguments in many forms, it can be more flexible than a macro. Opdefs place a greater responsibility for parsing arguments on the assembler. When a macro is specified, the responsibility for parsing arguments is placed on the user in many cases. Parsing a macro argument can involve numerous micro substitutions, which greatly increase the number of statements required to perform a similar operation with an opdef.

Defined sequences (macros, opdefs, dups, and echos) are costly in terms of assembler efficiency. As the number of statements in a defined sequence increases, the speed of the assembler decreases. This decrease in speed is directly related to the number of statements expanded and the number of times a defined sequence is called.

Limiting the number of statements in a defined sequence improves the performance of the assembler. In some cases, an opdef can perform the same operation as a macro and use fewer statements in the process.

The following example illustrates that an opdef can accept many different kinds of arguments from the opdef call:

MANYCALL   OPDEF
      A.REG1   A.REG2|A.REG3
                           ; Opdef prototype statement.
      S1   A.REG2
      S2   A.REG3
      A.REG1   S3          ; OR of registers S1 and S2.
MANYCALL   ENDM            ; End of opdef definition. 

The following example illustrates the calls and expansions of the previous example:

      A1    A2|A3          ; First call to opdef MANYCALL.
      S1    A.2
      S2    A.3
      S3    S1|S2
      A.1   S3             ; OR of registers S1 and S2.
      A.1   A.2|A.3        ; Second call to opdef MANYCALL.
      S1    A.2
      S2    A.3
      S3    S1|S2
      A.1   S3             ; OR of registers S1 and S2.
ONE   =     1              ; Define symbols.
TWO   =     2
THREE =     3
      A.ONE A.TWO|A.THREE  ; Third call to opdef MANYCALL.
      S1    A.2
      S2    A.3
      S3    S1|S2
      A.ONE S3             ; OR of registers S1 and S2.
      A1    A.2|A.THREE    ; Fourth call to opdef MANYCALL.
      S1    A.2
      S2    A.3
      S3    S1|S2
      A.1   s3             ; OR of registers S1 and S2. 

In the first and second calls to opdef MANYCALL, the arguments passed to REG1, REG2, and REG3 are 1, 2, and 3, respectively. In the third call to opdef MANYCALL, the arguments passed to REG1, REG2, and REG3 are ONE, TWO, and THREE, respectively. The fourth call to opdef MANYCALL demonstrates that the form of the arguments can vary within one call to an opdef if they take a valid form. The arguments passed to REG1, REG2, and REG3 in the fourth call are 1, 2, and THREE, respectively.

The following example illustrates how to use an opdef to limit the number of statements required in a defined sequence:

     MACRO
     $IF    REG1,COND,REG2 ; Macro prototype statement.
     .
     .
     .
$IF  ENDM                 ; End of macro definition.
     .
     .
     .
     $IF    S6,EQ,S.3     ; Macro call.
     .
     .
     .
     $ELSE
     .
     .
     .
     $ENDIF      

Parsing the parameters (S6,EQ,S3) passed to the definition requires many micro substitutions within the definition body. These micros increase the number of statements within the definition body.

The same function is performed in the following example, but an opdef is specified instead of a macro. In this instance, specifying an opdef rather than a macro reduces the number of statements required for the function.

Because an opdef is called by its form, it is more flexible than a macro in accepting arguments. The opdef expects to be passed two S registers and the EQ mnemonic. You can specify the arguments for the registers in a number of ways and still be recognized as S register arguments by the opdef.

         opdef
example  $if  s.reg1,eq,s.reg2 ; Opdef definition statement.
_* Register1: reg1
_* Register2: reg2
example  endm                  ; End of opdef definition.
         list mac              ; Listing expansion. 

The following are the calls and expansions of the preceding example:

         $if              s6,eq,s.3
* Register1:  6
* Register2:  3    

If an opdef occurs within the global definitions part of a program segment, it is defined as global. Opdef definitions are local if they occur within a program module (an IDENT, END sequence). A global definition can be redefined locally, but the global definition is re-enabled and the local definition is discarded at the end of the program module. You can reference a global definition anywhere within an assembler program after it has been defined.

You can specify the OPDEF pseudo instruction anywhere within a program segment. If the OPDEF pseudo instruction is found within a definition, it is defined. If the OPDEF pseudo instruction is found within a skipping sequence, it is skipped and is not recognized as a pseudo instruction.

In the following example, the operand and comment fields of the expanded line are shifted two positions to the left (difference between reg and 1):

example  opdef
         s.reg        @exp  ; Prototype statement.
         a.reg        @exp  ; New machine instruction.
example  endm               ; End of opdef definition.
         list         mac   ; Listing expansion. 

The following are the calls and expansions of the preceding example:

s1            2     ; Opdef call.
a.1           2     ; New machine instruction. 

9.3.1. Opdef Definition

The OPDEF pseudo instruction is the first statement of an opdef definition. Although an opdef is constructed much like a macro, an opdef is defined by an opdef statement, not by a name.

Opdef syntax is uniquely defined on the result field alone, in which case, the operand field is not specified or on the result and operand fields. The OPDEF prototype permits up to five subfields within the result and operand fields. At least one subfield must be present within the result field. No subfields are required in the operand field.

The syntax for each of the subfields within the result and operand fields of the opdef prototype statement is identical. No special syntax forms exist for any of the subfields. The rules that apply for the first subfield in the result field apply to the remainder of the subfields within the result field and to all subfields within the operand field.

The format of the opdef definition is as follows:

name          OPDEF

[loc]          defsynres          defsynop

               LOCAL            [name][,[name]]

.

.

.

name          ENDM

The variables in the opdef definition are described as follows:

Note: The formal grammar for the Cray X1 assembly language has changed fairly significantly from the Cray PVP grammar. This section has been partially modified to reflect that, but more changes will be made. The intent is that the grammar reflected in the Cray X1 instruction set be generalized for opdefs. A formal grammar will be presented in the near future.

The elements of an initial register definition are as follows:

The complex registers are designated in the opdef definition in the form: register_designator.register_parameter. The register_designator for complex registers can be any of the following: A C M S T.

The register-parameter is a 1- to 8-character identifier composed of identifier characters.

When you specify a simple register or a complex register mnemonic on an opdef call, it is recognized by the opdef definition without regard to the case (uppercase, lowercase, or mixed case) in which it was entered.

The optional register-expression-separator can be designated by any of the following:

&  |  ^  ~  <<  >>  +  -  *  /  ?  :  =  <=  >=

The optional register-ending is specified using the following syntax form:

register [register-expression-separator register-or-expression]

The register and register-expression-separator elements are described previously under initial-register.

The optional register-or-expression can be a register or an expression. If register is not specified, expression is required. If expression is not specified, register is required.

expression has been redefined for the opdef prototype statement, as expression-parameter. expression-parameter is an identifier that must begin with the at symbol (@). The @ can be followed by 0 to 7 identifier characters.

expression-ending is specified as follows:

expression [register_
expression_separator [register-or-expression]

expression is required and has been redefined for the opdef prototype statement as follows:

expression-parameter

expression-parameter is an identifier that must begin with the at symbol (@). The @ can be followed by 0 to 7 identifier characters.

register_expression-separator is defined above.

The optional register-or-expression can be a register or an expression. If register is not specified, expression is required. If expression is not specified, register is required.

A mnemonic is a 1- to 8-character identifier that must begin with a letter (A through Z or a through z), a decimal digit (0 through 9), or one of the following characters: $, %, &, ',*, +, -, ., /, :, =, ?,, `, |, or ~. Optional characters 2 through 8 can be the at symbol (@) or any of the previously mentioned characters. Mnemonics are case-insensitive.

Initial-expression specifies an initial-expression on the opdef prototype statement, use one of the following syntax forms for initial-expressions:

prefixl [expression-prefix] expression [expression-separator [register-ending]]

[prefix] [expression-prefix] expression [expression-separator [expression-ending]]

expression [expression-separator [register-ending]]

expression [expression-separator [expression-ending]]

The elements of the initial expression are described as follows:

prefix is optional and can be either a right parenthesis or a right bracket ([).

expression-prefix is optional and can be any of the following:

<, >, #<, or #>

expression is required and has been redefined for the opdef prototype statement, as follows:

expression-parameter

expression-parameter is an identifier that must begin with the at symbol (@). The @ can be followed from 0 to 7 identifier characters.

expression-separator is optional and can be one of the following:

), ], &, |, \, <, >, #<, or #>

register-ending and expression-ending are the same for initial expressions as for initial registers.

9.3.2. Opdef Calls

An opdef definition is called by an instruction that matches the syntax of the result and operand fields as specified in the opdef prototype statement.

The arguments on the opdef call are passed to the parameters on the opdef prototype statement. The special syntax for registers and expressions that was required on the opdef definition does not extend to the opdef call.

The format of the opdef call is as follows:

locarg     callsynres    callsynop

The variables associated with the opdef call are described as follows:

The following rules apply for opdef calls:

The following opdef definition shows a scalar floating-point divide sequence:

fdv  opdef                      ; Scalar floating-point divide
                                ; prototype statement.
L    s.r1     s.r2/fs.r3
     errif    r1,eq,r2
     errif    r1,eq,r3
L    s.r1     /hs.r3
     s.r2     s.r2*fs.r1
     s.r3     s.r3*is.r1
     s.r1     s.r2*fs.r3
fdv  endm       

The following example illustrates the opdef call and expansion of the preceding example:

a    s4    s3/fs2           ; Divide s3 by s2, result to s4.
     errif  4,eq,3
     errif  4,eq,2
a    s.4   /hs.2
     s.3   s.3*fs.4
     s.2   s.2*is.4
     s.4   s.3*fs.2    

The following opdef definition, call, and expansion define a conditional jump where a jump occurs if the A register values are equal:

JEQ  OPDEF
L   JEQ    A.A1,A.A2,@TAG  ; Opdef prototype statement.
L   A0     A_A1-A_A2
_*  JAZ    @TAG            ; Expression is expected.
JEQ ENDM                   ; End of opdef definition.
    LIST   MAC             ; Listing expansion. 

The following example illustrates the opdef call and expansion of the preceding example (the expansion starts on line 2.):

      JEQ   A3,A6,GO           ; Opdef call.
      A0   A3-A5
*     JAZ  GO                  ; Expression is expected. 

The opdef in the following example illustrates how an opdef can redefine an existing machine instruction:

EXAMPLE  OPDEF
         S.REG            @EXP ; Opdef protype instruction.
         A.REG            @EXP ; New instruction.
EXAMPLE  ENDM                  ; End of opdef definition.
         LIST  MAC             ; Listing expansion. 

The following example illustrates the opdef call and expansion of the preceding example:

      S1  2           ; Opdef call.
      A.1  2          ; New instruction. 

The following example demonstrates how the expansion of an opdef is affected when the opdef call does not include a label that was specified in the opdef definition:

regchg opdef
lbl   s.reg1 s.reg2          ; Opdef prototype statement.
lbl   =    *                 ; Left-shift if lbl is left off.
      s.reg2 s.reg1          ; Register s2 gets register s1.
regchg endm                  ; End of opdef definition.
       list  mac             ; Listing expansion. 

The following example illustrates the opdef call and expansion of the preceding example:

           s1  s2         ; Opdef call.
       =   *              ; Left-shift if lbl is left off.
           s.2  s.1       ; Register s2 gets register s1. 

The label field parameter was omitted on the opdef call in the previous example. The result and operand fields of the first line of the expansion were shifted left three character positions because a null argument was substituted for the 3-character parameter, lbl.

If the old format is used, only one space appears between the label field parameter and result field in the macro definition. If a null argument is substituted for the location parameter, the result field is shifted into the label field in column 2. Therefore, at least two spaces should always appear between a parameter in the label field and the first character in the result field in a definition.

If the new format is used, the result field is never shifted into the label field.

The following example illustrates the case insensitivity of the register and register-prefix:

CASE   OPDEF
       S1     #Pa2            ; Prototype statement.
       .
       .
       .
CASE   ENDM      

The following example illustrates the opdef calls of the preceding example:

    S1  #pa2              ; Recognized by CASE.
    S1  #Pa2              ; Recognized by CASE.
    S1  #pA2              ; Recognized by CASE.
    S1  #PA2              ; Recognized by CASE.
    s1  #pa2              ; Recognized by CASE.
    s1  #Pa2              ; Recognized by CASE. 
    s1  #pA2              ; Recognized by CASE.
    s1  #PA2              ; Recognized by CASE.