Document revision date: 30 March 2001

## OpenVMS RTL Library (LIB$) Manual

Previous | Contents | Index

## LIB$DECODE_FAULT

> The Decode Instruction Stream During Fault routine is a tool for building condition handlers that process instruction fault exceptions. It is called from a condition handler.

> Note No support for arguments passed by 64-bit address reference or for use of 64-bit descriptors, if applicable, is planned for this routine.

This routine is not available to native OpenVMS Alpha programs but is available to translated VAX images.

### Format

> LIB$DECODE_FAULT signal-arguments ,mechanism-arguments ,user-procedure [,unspecified-user-argument] [,instruction-definitions]

### RETURNS

> OpenVMS usage: | cond_value
> type: | longword (unsigned)
> access: | write only
> mechanism: | by value

### Arguments

> #### signal-arguments

> OpenVMS usage: | vector_longword_unsigned
> type: | unspecified
> access: | read only
> mechanism: | by reference, array reference

> Signal arguments array that was passed from the OpenVMS operating system to your condition handler. The signal-arguments argument is the address of the signal arguments array.

> #### mechanism-arguments

> OpenVMS usage: | vector_longword_unsigned
> type: | unspecified
> access: | read only
> mechanism: | by reference, array reference

> Mechanism arguments array that was passed from OpenVMS to your condition handler. The mechanism-arguments argument is the address of the mechanism arguments array.

> #### user-procedure

> OpenVMS usage: | procedure
> type: | procedure value
> access: | call after stack unwind
> mechanism: | by descriptor, procedure descriptor

> User-supplied action routine that LIB$DECODE_FAULT calls to handle the exception. The user-procedure argument is the address of a descriptor pointing to your user action routine. The user-procedure argument may be of type "procedure value" when called by languages with up-level addressing. If user-procedure is not of type "bound routine value," it is assumed to be the address of an entry mask.

> For further information on the user action routine, see the section called Call Format for a User Action Routine in the Description section.

> #### unspecified-user-argument

> OpenVMS usage: | user_arg
> type: | longword (unsigned)
> access: | read only
> mechanism: | by value

> Additional information passed from your handler without interpretation to your user action routine. The unspecified-user-argument argument contains the value of this additional information. The unspecified-user-argument argument is optional; if it is omitted, zero is used as the default.

> #### instruction-definitions

> OpenVMS usage: | vector_byte_unsigned
> type: | byte (unsigned)
> access: | read only
> mechanism: | by reference, array reference

> Array of bytes specifying instruction opcodes and operand definitions that are to replace or supplement the standard instruction definitions. The instruction-definitions argument is the address of this array.

> If instruction-definitions is omitted, only the standard instruction definitions are used. If supplied, instruction-definitions is searched first, followed by the standard definitions.

> Each instruction definition consists of a series of bytes, the first one or two of which is the instruction opcode. If the instruction is a 2-byte opcode, the escape byte, which must be hex FD, FE, or FF, is placed in the first of the two bytes. Following the opcode may be from 0 to 16 operand definition bytes. These bytes indicate the operand's access type and data type.

> The end of each instruction definition is denoted by a byte containing the value LIB$K_DCFOPR_END (zero). The list of instruction definitions is terminated by two bytes, each of which contains the value --1 (hexadecimal FF). For further information, see the section called Instruction Operand Definition Codes in the Description section.

### Description

> The Description section of the LIB$DECODE_FAULT routine is divided into the following parts:
> - Guidelines for Using LIB$DECODE_FAULT
> - Exceptions Recognized by LIB$DECODE_FAULT
> - Instruction Operand Definition Codes
> - Call Format for a User Action Routine
> - Call Format for a Signal Routine

> Guidelines for Using LIB$DECODE_FAULT

> LIB$DECODE_FAULT is a tool for building condition handlers that process instruction fault exceptions. Called from a condition handler, LIB$DECODE_FAULT performs the following actions:

> 1. Unwinds intermediate stack frames back to that of the exception
> 2. Decodes the instruction stream to determine the operation and its operands
> 3. Calls a user-supplied action routine and passes it a consistent and easy-to-access description of the instruction's context

> Your user action routine performs whatever tasks are necessary to handle the fault and returns to LIB$DECODE_FAULT. LIB$DECODE_FAULT then restores the context as modified by your user action routine and continues execution.

> Your condition handler must first decide whether or not it wants to handle the exception. The signal arguments list contains the exception code and the address of the program context (PC) that is usually sufficient for this determination. Once LIB$DECODE_FAULT is called, if the exception is a fault LIB$DECODE_FAULT can analyze, control does not return to the condition handler. Therefore, your handler must not depend on regaining control by a routine return once it has called LIB$DECODE_FAULT. With your user action routine, LIB$DECODE_FAULT makes the original fault disappear.

> Note Your user action routine is capable of generating a new exception, including one that looks identical to the original exception. Your user action routine may also resignal, but if the decision to resignal is made inside the user action routine, all post-signal stack frames are lost.

> Once your condition handler has decided that it wants to handle the exception, it calls LIB$DECODE_FAULT, passing as arguments the addresses of the signal and mechanism argument lists and a descriptor for your user action routine entry point. LIB$DECODE_FAULT then performs the following actions:

> 1. Determines if the exception is a fault it understands. If not, it returns SS$_RESIGNAL.
> 2. Determines the context in which the exception occurred, including register and processor status longword (PSL) contents, and saves it.
> 3. Unwinds all stack frames back to that frame in which the exception occurred.
> 4. Evaluates each operand's addressing mode, computing the resulting location for the operand. Immediate mode operands are expanded into their full form. If an invalid addressing mode is found, an SS$_RADRMOD exception is generated.
> 5. Unless the original exception was SS$_ACCVIO, tests each operand for accessibility. If necessary, an access violation is signaled as if the instruction had tried to execute normally. See the paragraph following this list for more information.
> 6. Unless the original exception was SS$_ROPRAND, tests each floating-point operand that is to be read for a reserved floating operand. If necessary, a reserved operand fault is signaled. See the paragraph following this list for more information.
> 7. Determines the address of the next sequential instruction.
> 8. Calls your user action routine with arguments as described below.
> 9. Upon return from your user action routine, reflects changes to the registers and PSL and continues execution at the instruction address specified by your user action routine. Optionally, your user action routine may resignal the original exception.

> Some instructions can generate more than one fault if evaluation of one operand causes a fault that occurs before a later operand (which would also cause a fault). An example of this is the possibility that a floating-point divide instruction might report a divide-by-zero fault upon seeing a zero divisor before noticing that the dividend was a reserved operand or was inaccessible.

> In these cases, operand-specific faults are signaled immediately by LIB$DECODE_FAULT in the expectation that another condition handler (or the same one) can repair the situation. This may reorder the sequence of exceptions as seen by a program. If the operand exception is corrected, the original exception reoccurs, and the proper action is taken.

> If at all possible, try to determine if a resignal is necessary inside the condition handler that calls LIB$DECODE_FAULT, rather than inside your user action routine. The reason for this is that LIB$DECODE_FAULT removes all post-signal stack frames before calling your user action routine.

> Your user action routine may fetch and store the operands, registers, and PSL as necessary for handling the exception. You should follow the VAX architecture rule of reading all input operands in left-to-right order, then writing all output operands in left-to-right order, to avoid inconsistent results with overlapping operands. This is especially necessary with register operands.

> PSL may be modified in a manner consistent with the VAX architecture. If the T-bit in the PSL was set at the beginning of the instruction, LIB$DECODE_FAULT sets the TP bit. To initiate tracing, you must set only the T bit. To disable tracing, you must clear both the T and TP bits. See the VAX Architecture Reference Manual for more information.

> If the first-part-done (FPD) bit in the PSL was set when the instruction faulted, LIB$DECODE_FAULT only advances the PC over the instruction; it does not reevaluate the operands, and it sets operand-count to zero. It is assumed that if FPD is set, the operands are in known locations (typically the registers).

> For the CASEB, CASEW, and CASEL instructions, only the selector, base, and limit operands are represented in operand-count and read-operand-locations. The element of registers that corresponds to the PC, described in the following text as R15, points to the first of the word-length displacements. Your user action routine must modify R15 to reflect the location of the next instruction to execute.

> The standard instruction definitions used by LIB$DECODE_FAULT specify the XFC instruction (which causes an SS$_OPCCUS fault) as having zero operands. You may redefine XFC if needed using the instruction-definitions argument to LIB$DECODE_FAULT.

> If you do not want instruction execution to resume with the next sequential instruction, you must modify R15 appropriately. Your user action routine then returns to LIB$DECODE_FAULT, which restores the registers and PSL, and resumes instruction execution. See also the LIB$_RESTART condition value in the section called Condition Values Returned from the User Action Routine.

> Note Vector context is not saved or restored.

> Exceptions Recognized by LIB$DECODE_FAULT

> LIB$DECODE_FAULT recognizes the following VAX faults:

> - SS$_ACCVIO, access violation.
> - SS$_BREAK, breakpoint fault.
> - SS$_FLTDIV_F, floating divide by zero.
> - SS$_FLTOVF_F, floating overflow.
> - SS$_FLTUND_F, floating underflow.
> - SS$_OPCCUS, opcode reserved to customers.
> - SS$_OPCDEC, opcode reserved to Compaq.
> - SS$_ROPRAND, reserved operand.
> - SS$_TBIT, T-bit pending trap. This is actually a fault caused by the TP bit being set at the beginning of instruction execution. It allows you to interpret all instructions by setting the PSL T-bit and allowing each instruction to trace-fault.

> All other exceptions, including SS$_COMPAT and SS$_RADRMOD, cause LIB$DECODE_FAULT to return immediately with the return status SS$_RESIGNAL.

> SS$_COMPAT is generated by compatibility-mode instructions. LIB$DECODE_FAULT does not handle compatibility-mode instructions.

> SS$_RADRMOD is generated by a reserved addressing-mode fault. LIB$DECODE_FAULT assumes that all instructions follow VAX addressing-mode specifications.

> Instruction Operand Definition Codes

> Each instruction operand has an access type (read, write, ...) and a data type (byte, word, ...) associated with it. The operand definition codes used in both the instruction-definitions argument passed to LIB$DECODE_FAULT and in the operand-types argument passed to the user action routine encode the access and data types in a byte. The fields and values for operand access and data types are described using the symbols in Table lib-3. These symbols are defined in definition libraries supplied by Compaq as macro or module name $LIBDCFDEF.

> Table lib-3 Symbols for Fields and Values for Operand Access and Data Types Using LIB$DECODE_FAULT
> Symbol | Description
> --- | ---
> LIB$V_DCFACC | The field of the operand description code that describes the operand access type (bits 0--2).
> LIB$S_DCFACC | The size of the access type field (3 bits).
> LIB$M_DCFACC | The mask for the access type field. This is a 3-bit field that can contain any binary value from 000 through 111. The integer value of these bit settings defines the operand access type code for the LIB$M_DCFACC field. Currently, six codes are defined. These codes have symbolic names and are explained below. It is important to remember that LIB$M_DCFACC is not a bit mask. The values 0 through 6 do not refer to bits 0 through 6. They represent the binary values 001 through 110 as contained in the 3-bit field. The operand access type codes defined for the LIB$M_DCFACC field are:
> LIB$K_DCFACC_R = 1 | Operand is read-only.
> LIB$K_DCFACC_M = 2 | Operand is to be modified.
> LIB$K_DCFACC_W = 3 | Operand is write-only.
> LIB$K_DCFACC_A = 4 | Operand is an address (must not be a register).
> LIB$K_DCFACC_V = 5 | Operand is the base of a bit field (same as address except that it may be a register).
> LIB$K_DCFACC_B = 6 | Operand is a branch address.
> LIB$V_DCFTYP | The field of the operand descriptor code that describes the operand data type (bits 3--7).
> LIB$S_DCFTYP | The size of the operand data type field (5 bits).
> LIB$M_DCFTYP | The mask for the operand data type field. This is a 5-bit field (bits 3--7) that can contain any binary value from 00000 through 11111. The integer value of these bit settings defines the operand access type code for the LIB$M_DCFACC field. Currently, nine codes are defined. These codes have symbolic names and are explained below. It is important to remember that LIB$M_DCFTYP is not a bit mask. The values 0 through 9 do not refer to bits 0 through 9. They represent the binary values 00001 through 01001 as contained in the 5-bit field. The operand access type codes defined for the LIB$V_DCFTYP field are:
> LIB$K_DCFTYP_B = 1 | Operand is a byte.
> LIB$K_DCFTYP_W = 2 | Operand is a word.
> LIB$K_DCFTYP_L = 3 | Operand is a longword.
> LIB$K_DCFTYP_Q = 4 | Operand is a quadword.
> LIB$K_DCFTYP_O = 5 | Operand is an octaword.
> LIB$K_DCFTYP_F = 6 | Operand is F_floating.
> LIB$K_DCFTYP_D = 7 | Operand is D_floating.
> LIB$K_DCFTYP_G = 8 | Operand is G_floating.
> LIB$K_DCFTYP_H = 9 | Operand is H_floating.

> Symbols of the form LIB$K_DCFOPR_xy, where x is the access type and y is the data type, are also defined. These combine the notions of access and data type. For example, LIB$K_DCFOPR_MF has the following value:

>     50 (2+(6*8))

> It denotes modify access of an F_floating item. For the branch access type, only the types BB, BW, and BL are defined; otherwise, all combinations are available.

> Call Format for a User Action Routine

> LIB$DECODE_FAULT calls the user action routine when it finds an exception to be handled. Your user action routine handles the exception in any manner that you specify and then returns to LIB$DECODE_FAULT.

> action-routine opcode ,instr-PC ,PSL ,registers ,operand-count
> ,operand-types ,read-operand-locations
> ,write-operand-locations ,signal-arguments
> ,signal-procedure ,context
> ,unspecified-user-argument ,original-registers

> > #### opcode

> > OpenVMS usage: | longword_unsigned
> > type: | longword (unsigned)
> > access: | read only
> > mechanism: | by reference

> > Opcode of the instruction that caused the fault. The opcode argument is the address of a longword that contains this opcode. LIB$DECODE_FAULT supplies this opcode when it calls the user action routine.

> > For 2-byte opcodes, the escape code (for example, hex FD) is in the low-order byte. You must use this argument to examine the opcode instead of reading the bytes pointed to by instr-PC. This is because if a debugger breakpoint has been set on the instruction, only opcode contains the original instruction.

> > #### instr-PC

> > OpenVMS usage: | longword_unsigned
> > type: | longword (unsigned)
> > access: | read only
> > mechanism: | by reference

> > Value of the PC for the instruction that caused the fault. The instr-PC argument is the address of a longword that contains the PC value.

> > Note the difference between this value and the contents of the registers array element that corresponds to the PC. R15 of the registers array element contains the address of the byte after the instruction that caused the fault.

> > #### PSL

> > OpenVMS usage: | longword_unsigned
> > type: | longword (unsigned)
> > access: | modify
> > mechanism: | by reference

> > Processor status longword (PSL) at the time of the fault. The PSL argument is the address of a longword that contains this PSL. Your user action routine may modify this PSL within the restrictions of the VAX architecture.

> > #### registers

> > OpenVMS usage: | vector_longword_unsigned
> > type: | longword (unsigned)
> > access: | modify
> > mechanism: | by reference, array reference

> > Contents of registers R0 through R15 (PC) at the time of the fault but after operand addressing-mode processing. This includes any autoincrements or autodecrements. The registers argument is the address of this 16-longword array. Each longword of the registers array contains the contents of one register.

> > Your user action routine may modify these values. If it does, the new values will be reflected when instruction execution continues.

> > To modify vector registers, execute a vector instruction. Executing a vector instruction in the handler modifies the state of the vector processor. The state of the vector processor is not restored when the handler returns. This has the effect of altering the state when the execution continues.

> > R15 denotes the sixteenth longword in the registers array, which corresponds to the PC. R15 contains the address of the next byte after the current instruction. Unless this value is modified by your user action routine, instruction execution will resume at that address. An exception is for the CASEB, CASEW, and CASEL instructions; R15 contains the address of the first displacement word. For these instructions, your user action routine must modify R15 to point to the next instruction to execute.

> > Upon instruction completion, registers R0-R15 are restored from this array. However, if signal-procedure is used to cause a fault or if instruction restart is specified by returning LIB$_RESTART, original-registers is used instead.

> > #### operand-count

> > OpenVMS usage: | longword_unsigned
> > type: | longword (unsigned)
> > access: | read only
> > mechanism: | by reference

> > Number of operands in the instruction currently being decoded. The operand-count is the address of a longword that contains this number.

> > #### operand-types

> > OpenVMS usage: | vector_longword_unsigned
> > type: | longword (unsigned)
> > access: | read only
> > mechanism: | by reference, array reference

> > Array of longwords, one element for each operand, that contains the type codes for the associated operand. The operand-types argument is the address of this array.

> > The operand type codes are further defined in the section called Instruction Operand Definition Codes.

> > #### read-operand-locations

> > OpenVMS usage: | vector_longword_unsigned
> > type: | longword (unsigned)
> > access: | read only
> > mechanism: | by reference, array reference

> > Array of longwords, one element for each operand, that contains the addresses of the operands to be read. The read-operand-locations argument is the address of this array.

> > The address given in the array may not be the actual address of the operand if the operand is not a memory location. If the operand is a register, the address indicates a copy of the register values at the time of operand evaluation. If the operand access type is ADDRESS or FIELD and the operand is not a register, the address is the address of the item. If the operand access type is FIELD and the operand is a register, the address refers to the appropriate element in the registers array. If the operand access type is BRANCH, the address is the destination PC of the branch. For WRITE access operands, the address value is zero.

> > #### write-operand-locations

> > OpenVMS usage: | vector_longword_unsigned
> > type: | longword (unsigned)
> > access: | read only
> > mechanism: | by reference, array reference

> > Array of longwords, one element for each operand, that contains the addresses of operands that are to be written. The write-operand-locations argument is the address of this array. If the operand access type is not MODIFY, WRITE, ADDRESS, or FIELD, the pointer value is zero.

> > #### signal-arguments

> > OpenVMS usage: | vector_longword_unsigned
> > type: | longword (unsigned)
> > access: | read only
> > mechanism: | by reference, array reference

> > Signal arguments list of the original exception, as passed from OpenVMS to your condition handler and then to LIB$DECODE_FAULT. The signal-arguments argument is the address of an array of longwords that contains these signal arguments.

> > #### signal-procedure

> > OpenVMS usage: | procedure
> > type: | procedure value
> > access: | call without stack unwinding
> > mechanism: | by reference

> > Entry mask of a routine that your user action routine must call if it wants to report an exception for the instruction that faulted. The signal-procedure argument is the address of this entry mask.

> > Previous | Next | Contents | Index

> > | privacy and legal statement |
> > 5932PRO_010.HTML