HP OpenVMS Systems

OpenVMS Technical Journal V13
» 

HP OpenVMS Systems

OpenVMS information

» What's new on our site
» Upcoming events
» Configuration and buying assistance
» Send us your comments

HP OpenVMS systems

» OpenVMS software
» Supported Servers
» OpenVMS virtualization
» OpenVMS solutions and partners
» OpenVMS success stories
» OpenVMS service and support
» OpenVMS resources and information
» OpenVMS documentation
» Education and training

OpenVMS software

» Operating system
» OpenVMS clusters
» OpenVMS Galaxy
» e-Business products
» Opensource tools
» Networking
» System management
» Storage management
» Security products
» Application development and integration
» Software licensing
» SPD listings
» Whitepapers
» Ask the wizard
» Training
» OpenVMS books

Evolving business value

» Business Systems Evolution
» AlphaServer systems transition planning
» Alpha RetainTrust program

Related links

» HP Integrity servers
» HP Alpha systems
» HP storage
» HP software
» HP products and services
» HP solutions
» HP support
disaster proof
HP Integrity server animation
HP Integrity server animation
Content starts here

OpenVMS I64 TIE Internals: Emulating Alpha Control Instructions

Tim E. Sneddon

This article is the first of what will hopefully become a series of articles that describe the internals of the OpenVMS I64 Translated Image Environment.  In subsequent issues of the OpenVMS Technical Journal it is expected that there will be further articles covering topics such as:

  • Stack walking and unwinding

  • Floating -point emulation

  • The Alpha instruction emulator

  • TIE initialization and setup

  • Image translation

These are but a few of the topics that are likely to be covered in future articles. Suggestions are also always welcome.  See the end of this document for details on contacting the author.

Conventions

Table 1 lists some of the conventions used in this article.

Convention

Meaning

Foreign

This term is used to describe any code that cannot be run natively on OpenVMS I64.

Native

This term describes any code that runs natively on OpenVMS I64

AEST

Alpha Environment Software Translator. The binary translation utility that generates OpenVMS I64 images from OpenVMS Alpha images.

VEST

VAX Environment Software Translator. The binary translation utility that generates OpenVMS Alpha images from OpenVMS VAX images.

TIE

Translate Image Environment. The name given to the execution environment that allows user-mode programs from different OpenVMS supported architectures to be executed.

Procedure Descriptor

This term refers to an OpenVMS Alpha procedure descriptor. This is described in the Starlet module $PDSCDEF.

Function Descriptor

This term refers to an OpenVMS I64 function descriptor. This is described in the Starlet module $FDSCDEF.

Table 1 Conventions Used in this Article

What Has The Translator Generated?

Using certain qualifiers on the AEST translation utility it is possible to observe what happens to the original OpenVMS Alpha image after it has been translated.  Figure 1 demonstrates some of the output that can be seen.  This example shows the correlation between the original Alpha instructions and the equivalent Itanium instructions.

Figure 1 Listing of Alpha Instructions and Corresponding Translated Itanium Instructions

This output was generated using the command:

$ AEST/VERBOSE/LIST/DUMP=IA64=ALL <image>

For more information on the qualifiers accepted by AEST and how to use them, refer to the online DCL help.

Observing Image Execution

With the help of some debugging features built into the TIE run-time library it is possible to observe the execution of the translated image.  By defining the logical PRTCHK_PRT_ALL to “1” TIE$SHARE will begin producing a trace to SYS$OUTPUT.  If it is inconvenient to have this output written to SYS$OUTPUT, it is possible to define the logical PRTCHK_FILE to an alternate output file.  Not all routines generate output, but the important ones do. It is also possible to enable interpretation of all images, even those that had native code generated as part of the translation process.  To do this, define the logical TIE$INTERPRET to “1”.  Figure 2 shows a portion of the output from a simple MACRO-64 program that executes a collection of ZAP and ZAPNOT instructions.  It is annotated to give a brief description of the operations taking place.

Figure 2 TIE Run-Time Library Trace Output

  1. Execution has just transferred to the TIE$AXP_JUMP_TO glue routine.
  2. A lookup is being performed on the address 000000000002006C to determine what kind of code is to be executed.
  3. It was determined the code was native Alpha and no equivalent translated code was found.  Therefore the Alpha instruction emulator is called and used to execute the code.
  4. The last instruction to execute was a JSR.  The emulator is now determining how to proceed with execution.
  5. The TIE is now looking up the return address specified in the JSR instruction to determine how to procede.

Note: AEST also responds to the PRTCHK_PRT_ALL logical and generates quite a bit of output. Before translating an image it is usually a good idea to deassign this logical.

Alpha Register Mapping

To make it easier to understand some of the Itanium code samples, the following table shows the static register mapping used by the TIE to maintain the Alpha register file. 

Alpha Register

Usage

Itanium Register

R0

Function value register

R101

R1

Conventional scratch register

R102

R2-R15

Conventional saved registers

R54-R67

R16-R21

Argument registers

R32-R37

R22-R24

Conventional scratch registers

R103-R105

R25

Argument information (AI) register

R106

R26

Return address (RA) register

R68

R27

Procedure value (PV) register

R69

R28

Volatile scratch register

R107

R29

Frame pointer (FP) register

R70

R30

Stack pointer (SP) register

R12

R31

ReadAsZero/Sink (RZ) register

R0[1]

 

 

 

F0-F1

Floating-point function value register

F32-F33

F2-F9

Conventional saved registers

F16-F23

F10-F15

Conventional scratch registers

F34-F39

F16-F21

Argument registers

F8-F13

F22-F30

Conventional scratch registers

F40-F48

F31

ReadAsZero/Sink register

F0*

 

 

 

MBPR

Mailbox pointer register

R72

FPCR

Floating-point control register

R73

PS

Processor status register

R74

PC

Program counter

R75

 

 

 

 

Internal TIE scratch register

R3, R21-R24, R26-R31

 

Internal TIE local registers

R76-R80

 

Internal TIE translator flag register

R82

 

Internal TIE output registers

R108-R115

Table  2 Alpha Register Mapping

If some of these mappings don’t appear to follow a logical order it is because many of register mappings were changed late in the design of TIE.  Originally it was intended that Alpha registers sharing similar functions as Itanium registers would be mapped together (as was done with VAX registers on the Alpha platform).  However, this was eventually changed and so now all Alpha registers (with the exception of the stack pointer) exist in the register stack frame.

The mapping of VAX registers can be found in OpenVMS Alpha Internals and Data Structures: Scheduling and Process Control.  The mappings have been retained, so all VAX registers map to their original Alpha registers, which in turn map to the equivalent Itanium register.

 

Introduction

The Translated Image Environment (TIE) is the support environment which executes user mode images compiled and linked on OpenVMS VAX and OpenVMS Alpha that have been subsequently translated for execution on the OpenVMS I64 platform.  The translation is achieved using the Alpha Environment Software Translator (AEST) and, in the case of OpenVMS VAX images, the VAX Environment Software Translator (VEST) binary translation tools.  While the VEST translator is only available on OpenVMS Alpha, it is supported to translate a VEST’d image using the AEST translator.

These translation utilities generate native images that work with the TIE run-time library to emulate a native OpenVMS Alpha or VAX environment.  It is the responsibility of the translator to present the original image in such a fashion that the TIE run-time library can then execute the foreign code.  In most cases these utilities are able to generate equivalent native code from the foreign code.  It is the branching inside and between these environments that is the focus of this article.

In some areas VAX support is touched on.  However, the main focus of this article is the support of the Alpha control instructions.  The OpenVMS Alpha Internals & Data Structures manual is still a relevant reference as the TIE, present on OpenVMS Alpha for the support of the OpenVMS VAX environment, has been ported to OpenVMS I64 with minimal changes.

Taking a JuMP...

The Alpha architecture presents a collection of closely related control instructions.  In the Alpha Architecture Handbook, these are divided as ‘Conditional Branch’, ‘Unconditional Branch’ and ‘Jumps’.  While this division is important to the TIE, a more relevant way to divide them is ‘Local’ and ‘Non-Local’.

Although the two types of branch are handled differently in how they obtain their addresses, all branches within the Alpha environment use the regular conditional branch, ‘br’, instruction.  This is because the emulated environment is contained within a regular OpenVMS I64 frame.  The conditional procedure call, or ‘br.call’, instruction is only used for native calls.

This does make the process of stack walking and unwinding non-trivial.  However, by avoiding a true procedure call the emulated Alpha registers continue to be available across Alpha calls.  There is no need to consider the consequences of the ‘alloc’ instruction and how to maintain context.  The only time this needs to be considered is when switching environments and that is handled by jacketing procedures, discussed later in this article[1].

Local Branches

Local branches are described as those that are capable of branching forward or backwards a PC relative distance of +/-1M instructions.  It also happens that this encompasses all conditional branch instructions.  Table 3 summarizes the local control instructions.

Mnemonic

Operation

BEQ

Branch if Register Equal to Zero

BGE

Branch if Register Greater Than or Equal to Zero

BGT

Branch if Register Greater Than Zero

BLBC

Branch if Register Low Bit is Clear

BLBS

Branch if Register Low Bit is Set

BLE

Branch if Register Less Than or Equal to Zero

BLT

Branch if Register Less Than Zero

BNE Branch if Register Not Equal to Zero

BR

Unconditional Branch

BSR

Branch to Subroutine

Table  3 Local Alpha Control Instructions

These instructions are usually used within a single object module to handle local branching. As such when it comes to translating these instructions to a native instruction sequence there is almost always no execution time lost in the resulting image.  This is due to the fact that the branch target is known at the time of translation.  However, if the destination of these branch instructions cannot be located within the image being translated then the instruction will be emulated by TIE run-time library via the Alpha instruction emulator.

For all non-emulated branches a small native instruction sequence is generated. Figure 3 shows the sequence generated by AEST when translating an Alpha BNE instruction, it is annotated below.

Figure  3 Itanium Code Generated for Alpha BNE Instruction

  1. Here the compare part of the BNE instruction is performed.
  2. In the event that the comparison yields a positive result, the Alpha PC is set to the address of the branch target.
  3. If the comparison is not true, the Alpha PC is updated to point to the next instruction, following the BNE instruction.
  4. Lastly, the branch is taken if the result was positive.

All other conditional branches are of the same format, simply substituting the relevant compare instruction relation as necessary.

For the unconditional branches it is even simpler.  Figure 4 shows the sequence generated by AEST for a BSR instruction and is annotated below.  The only difference between it and a BR instruction is that BSR sets up a return address.

Figure 4 Itanium Code Generated for Alpha BSR Instruction

  1. Here the emulated Alpha R26 register is configured with the return emulated PC.
  2. The emulated Alpha PC is then updated to point to the first instruction of the destination.
  3. Lastly, the branch is taken.

Non-Local Branches

Non-local branches are described as those that take a register argument containing an absolute address, rather than a PC offset.  Table 4 summarises the non-local control instructions.

Mnemonic

Operation

JMP

Jump

JSR

Jump to Subroutine

RET

Return from Subroutine

JSR_COROUTINE

Jump to Subroutine Return

 Table  4 Non-Local Alpha Control Instructions

The emulation of these instructions does incur quite a bit of overhead as the destination is assumed to be unknown at translation time.  This means that these instructions cannot be handled with a small instruction sequence like local branches. It requires support from the TIE run-time library.  This comes in the form of the routine TIE$AXP_JUMP_TO. This routine is the first stop on all non-local branches with the exception of JSR.  All JSR instructions first branch to TIE$AXP_JSR_TO before falling through to the routine, TIE$AXP_JUMP_TO.

 JSR instructions require special pre-processing by TIE$AXP_JSR_TO because in some cases the destination PC for input to the JSR instruction is fetched from a procedure descriptor (see Figure 5b) and not a linkage pair (see Figure 5a).  This causes problems when the destination is a native routine as the procedure value register then points to a native function descriptor (see Figure 5c).  As can be seen from the illustrations there is no problem in the instance of a function descriptor being mistaken for a linkage pair as the offset to the address of the procedure entry point is the same.  However, in the case of the function descriptor being mistaken for a procedure descriptor the global data pointer (GP) for the native image is then loaded and used as the destination PC. 

Figure 6 compares the two instruction sequences.

    

 

Figure 5 Alpha and I64 Procedure Descriptors             

To remedy this when the TIE walks the list of activated images (IAC$GL_IMAGE_LIST) during initialisation gathering details for its own internal list of native images, it also gathers up the GPs and caches them in another list (TIE$CACHED_GPs).  When TIE$AXP_JSR_TO is called it attempts to match the destination PC with an entry in this list.  If a match is found, then the destination PC is altered by fetching the real entry point address from the function descriptor pointed at by the Alpha register, R27 (procedure value register).  At this point TIE$AXP_JSR_TO then falls through to TIE$AXP_JUMP_TO and continues as normal.

LDQ    R27, 20(R27)  ; Fetch procedure descriptor

LDQ    R26, 08(R27)  ; Fetch procedure entry point

JSR    R26, (R26)    ; Call procedure

LDQ    R26, 20(R4)    ; Fetch procedure entry point

LDQ    R27, 28(R4)    ; Fetch procedure descriptor

JSR    R26, (R26)     ; Call procedure

Figure 6a. Fetching Entry Point From Descriptor        b. Fetching Entry Point From Linkage Pair.

Finding a Place to Go

Jumping to an address may be one thing. However, locating that address to determine how to jump is entirely something else.  For the Alpha environment, all call address lookups go through the routine TIE$XXXX_LOOKUP.  For the VAX environment the equivalent routine is TIE$VESTED_LOOKUP.  It is these routines that have the job of determining what kind of code is at the specified address and locating any translated code that may be associated with it. 

For the rest of this section, TIE$XXXX_LOOKUP refers to both the Alpha environment TIE$XXXX_LOOKUP and the VAX environment TIE$VESTED_LOOKUP, unless otherwise specified.

Performing The Lookup

An address lookup begins with TIE$XXXX_LOOKUP first checking that the address being looked up is not the special return address used when returning from native code.  In this case the lookup terminates with a return status of TIE$CODE_N2T_RETURN and the caller (usually TIE$ALPHA_TO_IPF or TIE$VAX_TO_IPF) will then begin the process of translating arguments back to their respective environments.

The lookup continues by first checking that this address has not previously been requested. This is done by checking the lookup cache (TIE$GR_LOOKUP_CACHE).  To speed up the process of looking up a call address, all successful address lookups and their results are stored in a 4096 entry hash table.  This table is managed using the FNV-1a[1] hash algorithm. In the event that no match is found the lookup routine begins walking internal TIE data structures. 

The process starts by first looking up the list of pseudo images loaded by the TIE during initialization.  A pseudo image, as the name implies, is not a real image.  It exists only as a collection of data structures in memory.  Its purpose is to allow the native TIE to intercept lookups by translated or emulated code to TIE routines from previous TIE environments, such as the TIE$SHARE image used to support the VAX environment under OpenVMS Alpha.  An example of this is the substitution of the OpenVMS Alpha routine OTS$CALL_PROC with the internal TIE service, TIE$$AXP_OTS$CALL_PROC.  The original OTS$CALL_PROC from OpenVMS Alpha has no relevance on OpenVMS I64, so the TIE$$AXP_OTS$CALL_PROC service has been written to act as a substitute.  It is simply a wrapper that jumps to TIE$AXP_JUMP_TO.

Figure 7 TIE Pseudo Image Data Structures

Like almost all internal image data blocks the list of pseudo images is stored in a B-tree. The root of this tree is TIE$PAXP_IMG_DESC_ROOT.  Each node in the tree contains a pointer to a TIE pseudo image header (see Figure 7a).  These structures are queried using the routine TIE$FIND_PSEUDO_IMG.  In the event that the call address being looked up exists in the address space described by the pseudo image, then the routine TIE$FIND_PSEUDO_FP attempts to locate a matching function.

Figure  8 TIE Internal Image Descriptors

The next step is to try and find the call address in the list of loaded translated images.  This too is a B-tree list.  The root of this tree Is TIE$IMG_DESC_ROOT and is queried using the routine TIE$FIND_IMG.  If the call address exists in the address space of this image, then TIE$FIND_IMG returns a pointer to the TIE data header (see Figure 8a).  TIE$FIND_IMG_AREA then uses this structure to locate, using a binary search, the specific area containing the call address and return the corresponding TIE area header (see Figure 8b).  The type of code pointed at by the call address can then be determined based on the flags field of the TIE area header.  Table 5 shows possible values for the flags field. 

Value

Symbolic Name

Meaning

1

tie$vax_code_area_fl

Section contains VAX instructions

2

tie$axp_code_area_fl

Section contains Alpha instructions

4

tie$ipf_code_area_fl

Section contains Itanium instructions

8

tie$axp_nonshraddr_area_fl

Section contains Alpha non-shareable address data

Table  5  Tie Area Descriptor Type Flags

In the case that the call address is found to exist in an area containing foreign code (the flag tie$axp_code_area_fl is set) TIE$XXXX_LOOKUP calls TIE$FIND_AII_BB.  This routine performs a binomial search on the list of basic blocks pointed to by the field aii_bb_map.  This field points to an array of octawords containing the mapping between Alpha basic blocks and their corresponding native translated blocks.  The first quadword contains the address of the Alpha block and the second contains the address of the corresponding native block.  It is also possible to perform a reverse mapping using the array pointed at by the iia_bb_map field.

Return Status

Meaning

TIE$CODE_IPF_TRANSLATED

TIE$CODE_VAX_TRANSLATED#

The lookup address either points to translated native code, or a foreign basic block that had a corresponding translated block and TIE$INTERPRET is not active.  The address returned points to translated native code.

TIE$CODE_VESTED_AXP#

The lookup address points to VAX code that has corresponding translated Alpha code, but no valid native translated code.  The return address points to the Alpha code.

TIE$CODE_AXP

TIE$CODE_VAX

The lookup address points to foreign code that either has no corresponding translated code, or TIE$INTERPRET is in effect. The return address matches the lookup address.

TIE$CODE_OUTSIDE

The lookup address points to code outside of any translated image. The return address matches the lookup address.

TIE$CODE_PSEUDO_AXP

TIE$CODE_PSEUDO_VAX#

When the lookup address is in a pseudo image.

TIE$CODE_VAX_SYS_SERV#

When the lookup address points to a VAX system service entry point. The returned address is the corresponding native system service entry point.

TIE$CODE_AXP_TIE#

The lookup address points to an Alpha TIE image.

TIE$CODE_N2T_RETURN

The lookup address points to the return address used by TIE$NATIVE_TO_TRANSLATED

#These status codes are returned only by TIE$VESTED_LOOKUP.

Table  6  TIE$XXXX_LOOKUP and TIE$VESTED_LOOKUP Return Codes

For the VAX environment lookups are performed using the routine TIE$FIND_VAX_BB.  This routine performs a binomial search of the basic block mapping list pointed at by viai_bb_map in the TIE data header (not shown in Figure 8a).  

In the event that no match is found at all TIE$XXXX_LOOKUP assumes that the address is native and returns the status TIE$CODE_OUTSIDE.  Table 6 shows possible values returned by TIE$XXXX_LOOKUP and TIE$VESTED_LOOKUP. 

Switching Environments

The final stage in transferring control is the actual branch.  As stated in previous sections, transferring from one foreign procedure to another (in the same processor environment) is nothing special.  It is handled with a simple condition branch instruction.  The real complexity starts when transferring control to another environment and trying to hide that from translated software.

Translated to Native

If a call address is determined to exist in a native image TIE$AXP_JUMP_TO transfers control by branching to TIE$ALPHA_TO_IPF.  This routine is the final stepping stone for all translated code transferring control to the native OpenVMS I64 environment.  The process begins by extracting the call signature information [1] from the callee’s function descriptor. 

Figure 9 demonstrates the program logic that determines the final argument information that is used to process the argument list.

Figure  9  Logic to Determine Argument Information

As Figure 9 shows, in the event that the signature is deemed unusable the fail over is to use argument information from the Alpha AI register (R25). The difference between the call signature and the argument information register is that a signature provides complete details of all arguments and return values.  It is present purposefully for the translated environment and is usually only available in images that contain code that has been compiled with the /TIE qualifier.  Argument information from the AI register, on the other hand, is available in all calls.  However, it only details the format of the arguments present in registers.

The convention of using the argument information register as the default signature actually defies the calling standard.  It states that when transferring control from the Alpha TIE to a native I64 procedure the default signature specifies that it should be assumed that all register arguments are RASE$K_RA_I32 and all memory arguments are MASE$K_MA_I32 (32 bit integers, sign extended to 64 bits).  By using the argument information register, the default argument type is actually assumed to be AI$K_AR_I64 (64 bit integer).  The default function result is also assumed to be PSIG$K_FR_I64 (64 bit integer).

Once all argument information has been extracted it is now necessary to prepare the arguments for the call to a native procedure.  While both architectures employ similar methods in argument passing, the differences are still far too great.  Figure 10 shows the logic used to convert Alpha register arguments to their native I64 counterparts.

 

Figure  10  Register Argument Conversion Logic 

Floating point arguments on the Alpha, like the Itanium, are passed in the floating point registers.  However, the OpenVMS I64 calling standard requires that VAX floating point numbers (F_FLOAT, G_FLOAT and D_FLOAT) must be passed in general registers in memory format.  TIE translated code stores all floating point numbers in register format in native floating point registers.  Therefore all any arguments must be moved to general registers and converted.

It is also a requirement of the Itanium architecture that a rotating region of output registers be used to pass arguments to the callee.  Therefore it is necessary to copy all arguments in the Alpha registers R16-R21 (at least as many as the AI register dictates) into these output registers.

Lastly, there are less argument registers on the Alpha than there are on the Itanium.  How this is handled is not shown in Figure 10.  However, the process is quite simple.  The arguments in slots 7 and 8 (stacked on the Alpha) are fetched and stored in their corresponding output registers.  Again, it is necessary to consider the type of the argument to ensure it is stored in the correct register in the correct format.  Moving these two arguments into register does have an advantage.  The I64 calling standard requires that the caller leave a 16 byte scratch area before stacking any extra arguments passed to the callee.  The stack locations formerly held by arguments 7 and 8 can then be used for this region preventing the need to re-shuffle the remaining stacked arguments.  For calls with less than 8 arguments this scratch region is allocated by adjusting the stack pointer. 

Once the arguments have been prepared the Alpha procedure descriptor is examined to determine the exception mode.  Depending on the value in PDSC$V_EXCEPTION_MODE the call may pass through a wrapper that configures the floating point status application register (as.fpsr). 

The final step before making the actual call is to move the contents of the Alpha registers R0 and R1 into their corresponding Itanium register, R8 and R9.  Both of these registers can be used by compilers to pass information between calls.  R1 (R9 on the Itanium) is often used to pass a pointer to the callers automatic storage to support uplevel references.

On returning from the native routine it is necessary to go through the process of converting the return value to an acceptable format.  For return values the Itanium register R8 is copied into the Alpha register R0.  For return values specified as PSIG$K_FR_D64, this also means that the contents of Itanium register R9 are moved to Alpha register R9.  For all return values specified as VAX floating point they are converted back to register format and moved from the Itanium register F8 to Alpha register F0.  For all complex values, the contents of Itanium register F9 is also moved in to Alpha register R1.  For IEEE values there is no conversion.  The contents of the Itanium registers F8 and F9 are copied to their Alpha equivalents.  The register F9 is only copied in the case of a complex result. 

At this point TIE$ALPHA_TO_IPF has completed the native call.  The only thing left to do is to branch to the Alpha return address.  This is done by branching to TIE$AXP_JUMP_TO.

Native to Translated

Although branching from native code into TIE might not strictly be emulation of a JSR instruction, it certainly needs to appear that way to the TIE.  All transfers from native to translated code should be done through the routine OTS$CALL_PROC [1].  While this routine is largely a wrapper, it is the interface used by all OpenVMS compilers.  To call a native routine without using a compiler requires the call to be coded in Itanium assembly.

To begin, OTS$CALL_PROC calls TIE$NATIVE_TO_TRANSLATED which determines the environment it needs to transfer control to using the routine TIE$PROC_KIND**.  For calls destined for the Alpha environment this means a branch to TIE$IPF_TO_ALPHA (for the VAX environment it is TIE$IPF_TO_VAX).  This routine is responsible for the translation of all arguments and return values when going from native to translated code and back again.  It can be thought of as the reverse of TIE$ALPHA_TO_IPF.

 TIE$IPF_TO_ALPHA begins in much the same way as TIE$ALPHA_TO_IPF.  It fetches the procedure signature and verifies it.  If the signature is not found or invalid the argument information is retrieved from the Itanium argument information register (R25).  The next step is to translate all the arguments as required.  In the case of IEEE floating point and integer values there is no change.  VAX floating point numbers are converted to register format and stored in the relevant floating point register.  The 16 byte scratch region is used again.  This time it holds any values found in the last two general register argument slots.

Once all arguments and the stack are prepared some Alpha registers are configured.  The Alpha frame pointer is set and the Alpha return address is set to a special address that begins the process of converting return values.  The contents of the Itanium registers R8 and R9 are also copied into the Alpha registers R0 and R1.  The execution of the Alpha routine is then started by branching to TIE$AXP_JUMP_TO.

On return from the Alpha routine the return values are converted back to meet the requirements of the native OpenVMS I64 environment.  This is done in much the same way as TIE$ALPHA_TO_IPF.  The final action of TIE$IPF_TO_ALPHA is to branch back to the caller.

Routine Reference

The following are some quick notes on the calling details of the publicly defined TIE services mentioned in this article. 

TIE$PROC_KIND

            This routine determines the ‘kind’ of a procedure address.  This routine is used by OTS$CALL_PROC/TIE$NATIVE_TO_TRANSLATED to determine if it should transfer control to the TIE or not.

 Parameters:

ofd.rq.v            Address of an official function descriptor.  For native images this argument is the address of a function descriptor. In the case of translated Alpha images this is the address of a procedure descriptor. Lastly, for translated VAX images this is a pointer to the original VAX code.

Completion Codes:

The following table describes possible return values of this function.  The symbolic names are found in [IA64_TIE]TIE_DEFS.H and not publicly available.

 

Value

Symbolic Name

Description

0

TIE$K_PROC_NATIVE

Address points to a native function descriptor.

1

TIE$K_PROC_ALPHA

Address points to an Alpha procedure descriptor.

2

TIE$K_PROC_VAX

Address points to a VAX procedure.

 In the event that the function descriptor is not readable this routine will signal TIE$_WRONG_PV.

OTS$CALL_PROC/TIE$NATIVE_TO_TRANSLATED

            The routine OTS$CALL_PROC is used by all OpenVMS compilers when calling external routines and the /TIE qualifier is active.  In the event that the call is user mode and the TIE is active (CTL$GQ_TIE_SYMVECT) is non-zero) then OTS$CALL_PROC transfers control to TIE$NATIVE_TO_TRANSLATED (also known as TIE$CALL_PROC).

 Parameters:

p1, …pn          All arguments are passed as if directly calling the routine in
question. Floating point arguments are all passed in f16-f23. All  other arguments are passed in r32-r39.

sig.rr.r              Address of the call argument signature block.  This provides details of the arguments being passed.  This is passed in register r17.

ofd.rr.r              The destination function descriptor. This is passed in register r18.

ai.rq.v               Argument information.  This is passed in through register r25.

ra.ra.v              Return address. This is passed in the register b0.

In the case of calling a translated routine, registers r8 and r9 (up level environment value) are copied into R0 and R1 of the translated environment.  They are then copied back on return.

Completion Codes:

Only the completion codes of the routine being indirectly called.

Relevant Sources

The following list comprises the source modules from the OpenVMS I64 source tree that are discussed in this article.
• [IA64_TIE]AUX_CALLING_STANDARD.S
• [IA64_TIE]TIEDATA.H
• [IA64_TIE]TIE_CONT.C
• [IA64_TIE]TIE_CONT.H
• [IA64_TIE]TIE_DEFS.H
• [IA64_TIE]TIE_IMGSUP.C
• [IA64_TIE]TIE_JACKETS.S
• [IA64_TIE]TIE_JUMPS.S
• [LIBOTS]OTS$CALL_PROC_IA64.IAS
• [STARLET]FDSCDEF.SDL
• [STARLET]PDSCDEF.SDL
• [STARLET]PSIGDEF.SDL

For more information

Tim Sneddon can be contacted via email at tim.sneddon@bigpond.com

For further information regarding the OpenVMS Alpha TIE and the VEST binary translation tools, please see the following:

  • Goldenburg, R., Saravanan, S., Duma, D. OpenVMS Alpha Internals and Data Structures: Scheduling and Process Control: V7.0 (1997) Digital Press ISBN: 978-1555581565

  • Sites, R. L., Chernoff, A., Kirk, M. B., Marks, M. P., Robinson, S. G. Binary Translation, Digital Technical Journal Vol. 4 No.4 (1992)

  • HP OpenVMS Migration Software for VAX to Alpha Systems (OMSVA) Documentation

  • For those readers with access to the OpenVMS Alpha source listings (or the source itself), the source for the TIE$SHARE.EXE run-time library can be found in the [TIE] facility.

For further information regarding the VAX architecture and instruction set, please see the following:

  • VAX Architecture Reference Manual  (1991) Digital Press ISBN: 978-1555580575

For further information regarding the OpenVMS I64 TIE and the AEST binary translation tool, please see the following:

·         HP OpenVMS Calling Standard
o       
http://h71000.www7.hp.com/doc/os83_index.html

·         HP OpenVMS Migration Software for HP AlphaServer Systems to HP Integrity Servers (MSAIS) Documentation
o       
http://h71000.www7.hp.com/openvms/products/omsva/omsais.html

·         For those readers with access to the OpenVMS I64 source listings (or the source itself), the source for the TIE$SHARE.EXE run-time library can be found in the [IA64_TIE] facility.

For further information regarding the Alpha architecture, please see the following:

·         Alpha Architecture Committee, Witek, R. T., Alpha Architecture Reference Manual (Third Edition) (1998) Digital Press ISBN: 978-1555582029

For further information regarding the Itanium, please see the following:

·         Evans, J. S., Trimper, G. L. Itanium Architecture for Programmers: Understanding 64-bit Processors and EPIC Principles (2003) Hewlett-Packard Books ISBN: 0-13-101372-6

·         Intel® Itanium® Architecture Software Developer’s Manual (2006) Intel Corporation

o        http://www.intel.com/design/itanium/manuals/iiasdmanual.htm

For further information on the Fowler Noll Vo hashing algorithm, please see the following:

·         Wikipedia, Fowler Noll Vo hash

o        http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash

·         Noll, L. C., FNV hash

o        http://isthe.com/chongo/tech/comp/fnv/