  | 
		
		
      
        
        
            | 
          
             | 
            |  
        
            | 
          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 
            
              - Execution has just transferred to the 
              TIE$AXP_JUMP_TO glue routine. 
              
 - A lookup is being performed on the address 
              000000000002006C to determine what kind of code is to be executed. 
              
 - 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. 
              
 - The last instruction to execute was a JSR. 
               The emulator is now determining how to proceed with 
              execution. 
              
 - 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  |  
              
                | 
                      | 
                
                      | 
                
                      |  
              
                | 
                   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. 
               |  
        
            |   
      
        
        
            | 
          
             |  
        
            |  
        
            | 
          
            
            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.   |  
        
            |   
      
        
        
            | 
          
             |  
        
            |  
        
            | 
          
             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. 
            
            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 
            
              - Here the compare part of the BNE instruction 
              is performed. 
              
 - In the event that the comparison yields a 
              positive result, the Alpha PC is set to the address of the branch 
              target. 
              
 - If the comparison is not true, the Alpha PC is 
              updated to point to the next instruction, following the BNE 
              instruction. 
              
 - 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 
            
              - Here the emulated Alpha R26 register is 
              configured with the return emulated PC. 
              
 - The emulated Alpha PC is then updated to point 
              to the first instruction of the destination. 
              
 - 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.  |  
        
            |   
      
        
        
            | 
          
             |  
        
            |  
        
            | 
          
             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 
            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.   |  
        
            |   
      
        
        
            | 
          
             |  
        
            |  
        
            | 
          
             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. 
            
            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 from the callee’s 
            function 
			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. 
            
            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.   |  
        
            |   
      
        
        
            | 
          
             |  
        
            |  
        
            | 
          
             The following are some quick notes on the calling 
            details of the publicly defined TIE services mentioned in this 
            article.  
            
                        
            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. 
            
                        
            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.   |  
        
           
        
  
  
      | 
    
       |  
  
      |  
  
      | 
    
       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  |  
  
     
  
  
  
      | 
    
       |  
  
      |  
  
      | 
    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: 
      
      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/ 
         |  
   
   |   
         |    |