SPLash!

The Native Mode SPL Compiler for MPE/iX

Programmer's Guide

This guide is for programmers who are using the SPLash! Compiler to migrate SPL code to the MPE/iX platform or who want to continue writing code in SPL and have Native Mode performance.

This document assumes a firm foundation in SPL syntax and methodology. Much of the information in this document stresses the differences between SPLash! and SPL, so you may want to prepare for your compilation project by studying your SPL documentation in addition to this manual. Reference documents for SPL are listed in the section called "Other Sources of Information" in the first chapter of this manual.

Copyright c 1995-2003 Allegro Consultants, Inc.

ALLEGRO CONSULTANTS, INC. MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Allegro Consultants, Inc. shall not be liable for errors contained herein or for incidental or consequential damages in connection with the furnishing, performance or use of this material.

HP-UX, MPE V, MPE XL, and MPE/iX are trademarks of Hewlett- Packard Company.

UNIX is a trademark of AT&T Bell Laboratories.

Allegro Consultants, Inc. 20111 Stevens Creek Blvd., Suite 245 Cupertino, CA 95014-2397 USA (408) 252-2330 voice (408) 200-4488 fax support@allegro.com www.allegro.com

2004-01-01


 

Table of Contents

(top) (index)


1   Introduction


Overview

The SPLash! Native Mode Compiler is a compiler for SPL (Systems Programming Language), Hewlett-Packard's powerful block-structured programming language. SPL was originally developed to run under the MPE V operating system and to take advantage of the hardware features of the original family of HP3000 computers. With the advent of Hewlett-Packard Precision Architecture and a new generation of HP3000s, SPLash! offers the features of the original SPL language and the opportunity to take advantage of the full native mode capabilities of the new machines.

SPLash! is a powerful tool for migrating existing SPL applications to Hewllett-Packard's Precision Architecture (HPPA). With SPLash!, there is no need to recode your programs using a different language, nor do you need to maintain original and translated versions of your object code. SPLash! gives you access to native mode performance on HP Precision Architecture machines.

SPLash! was designed for maximum compatibility with its MPE V counterpart. Since the original SPL language was highly dependent on the hardware environment of the MPE V-based HP3000, SPLash! emulates the addressing scheme of these older machines. All constructs supported by SPL are supported by SPLash!, including most ASSEMBLEs, all stack references (such as TOS and stack decrements), and all other statements. The features that SPLash! does not support generally depend on the old 16-bit architecture or other hardware features that do not exist in HP Precision Architecture. Throughout the manual, these differences are discussed as they arise.

Using SPLash!

Program development with SPLash! involves the usual cycles of editing, compiling, linking, and testing. There are two approaches to choose from in compiling your programs. One approach is based on UDCs that are provided with the product. The second approach is to use command files in the same manner that you would use for any HP compiler product. These approaches are discussed next.

Using SPLash! UDCs

Two UDC files are provided with the SPLash! compiler. The default UDCs are geared towards program development on the Spectrum, while the alternate UDCs (contained in SPLASHV.PUB.SPLASH ) function like the SPL UDCs (SPL, SPLPREP). The installation job builds the necessary account structure and initializes the default UDC file, SPLASHU.PUB.SPLASH .

When compiling with the default UDCs, SPLash! uses two groups for storage of intermediate code. These groups are ASM and O. The ASM group contains the direct output of SPLash!, the assembly language. The O group is used by the assembler. This is where the assembled output is stored. The files that are stored in the O group are native mode object files, (filecode NMOBJ). These files can be linked together with the LINKEDIT program to produce native mode programs, native mode executable libraries, or native mode relocatable libraries.

Using Command Files

If you want to use command files for SPLash! development, you can choose any one of the four command files provided for that purpose. These command files are modeled after the command file format that the HP compilers use. The command files are listed next.

Compilation Command Files

Regardless of the approach you take, it is recommended that you review at a minimum the chapters Before you start , Compiling with SPLash! , and Beyond SPL .

In most cases, very few changes are required to successfully compile your original SPL source with SPLash!. If you do need to implement source code changes, you have several resources to work with. First, SPLash! CONTROL options are provided that ease migration analysis and testing of SPL code. Second, a cross-reference utility program, XREF, is provided to help with the analysis of your SPL code. Third, several SPLash! debug macros are provided for use with the HP debugger (see Appendix E). Appendix A discusses native mode and privileged mode Assemble instructions. And finally, Appendix B covers intrinsic differences between MPE V and MPE/iX.

(top) (index)


About This Manual

This document introduces SPLash! and provides a detailed reference for programmers. Whether you are migrating existing SPL applications to HP Precision Architecture machines or whether you are taking advantage of SPLash!'s powerful language features to develop new programs, use this document along with Hewlett-Packard's SPL documentation to obtain the information you need to successfully implement your design.

The information in this document is organized into eight chapters and several appendices. Depending on your technical background and on your purpose for using SPLash!, you may want to concentrate on certain sections and skip others.


Chapter 1, Introduction, describes SPLash! at a high level. It also lists relevant Hewlett Packard publications that you may want to review as companions to this document.


Chapter 2, Installation, discusses the account structure and step by step instructions on how to install your SPLash! software.


Chapter 3, Before you start, highlights important differences between the MPE V and MPE/iX operating systems and identifies conceptual differences between the original SPL and SPLash!.


Chapter 4, Compiling with SPLash!, provides detailed information on the compilation process.


Chapter 5, Parameters, Procedures & Conventions, introduces SPLash! procedure and parameter calling mechanisms and other conventions. In addition, it lists important SPLash! register conventions that you may need to know to successfully debug your code.


Chapter 6, Beyond SPL, describes the options and features that extend SPLash! beyond the capabilities of the original SPL language.


Chapter 7, Using XREF, provides an introduction to this useful cross-reference tool for SPL programs, including a several examples to get you started.


Chapter 8, Migration Issues, provides information to help you successfully migrate an existing SPL application to your HP Precision Architecture machine using SPLash!. Porting to HP-UX is also covered in this chapter. Differences in data types, data formats, and intrinsics are also explained.


Chapter 9, Run Time Error Recovery, describes the methods supported by SPLash! for this purpose.


Appendix A, Assemble Instructions, discusses how Assemble instructions can affect your migration when language features are not supported in SPLash!.


Appendix B, Intrinsic Changes lists the intrinsics that are not supported under MPE/iX.


Appendix C, Messages , lists General Messages, Warning Messages, Error Messages and Internal Error Messages.


Appendix D, SPLash! Debugger, introduces the internal SPLash! Debugger


Appendix E, SPLash! & Debug/iX Macros, provides support for the material on Debugging with a discussion on the SPLash! Debug macros, highlighting important points as required. Included also is an introduction to Debug/iX.


Appendix F, Sample Code, provides sample programs to illustrate techniques for migrating with SPLash! and creating new applications using SPLash! extensions.


Appendix G, Technical Background, discusses the basic structure in the new architecture and the differences between MPE V and MPE/iX.

(top) (index)


Other Sources of Information

This document is intended to supplement, not replace, Hewlett-Packard's SPL documentation. For all practical purposes, it is assumed that SPLash! users have a firm foundation in SPL. The thrust of this document, then, is to educate on the differences between these two languages and to provide the knowledge necessary for migrating SPL-based code to the MPE/iX platform.

Detailed descriptions of SPL syntax and usage can be found in the following Hewlett-Packard documentation:

 

(top) (index)


Typeface Conventions

The following conventions are used throughout this document.

Terminology

With the introduction of release 4.0 of the MPE/iX operating system, HP changed the name of the operating system from MPE XL to MPE/iX. Throughout this manual, we have tried to be consistent in our use of MPE/iX versus MPE XL. In most cases, the two words are interchangeable.

(top) (index)


2   Installation


Introduction

This chapter guides you through the installation process, step by step. There are two methods for installing SPLash! so that you can choose the installation procedure that best suits your needs.

Updates can be installed over the existing SPLASH account. Or, SPLash! can be installed in a uniquely named account. The advantage of the later is that the update can be tested before being rolled into a production environment.

(top) (index)


Overwriting the SPLASH account (default)

Before updating the SPLASH account, remove any cataloged SPLASH UDCs. UDC files may be modified from update to update.

1. Logon as MANAGER.SYS

2. Mount the SPLash! update tape and place the tape drive online.

3. Restore the file SPLASH.PUB.SYS by entering the following commands:

4. Edit the passwords in line #1 for MANAGER.SYS in the file SPLASH.PUB.SYS.

5. Stream the installation job by entering the following command:

When the job for MANAGER.SYS logs off, check the $STDLIST for errors. If no errors are reported, then SPLash! is ready to use. By default, the SPLash! UDCs are only set for MGR.SPLASH, however, this is easily changed by using the SETCATALOG command.

(top) (index)


Install in Uniquely Named Account

These instructions are very similar to the above with one exception. Insert the following instruction after step 4.

4.5 After the file SPLASH.PUB.SYS is restored, use a text editor to change the line specifying the account name to the name of the account where SPLash! will be installed. Initially, this looks like the following:

 
For example, if you want to install SPLash! in the account named SPLTEST, you would change the setvar line to the following:

Only valid MPE account names can be used.

Note —The installation job will automatically edit the UDC and command files so that they can be used from the account that you specify.

(top) (index)


3   Before you start


Introduction

When SPLash! was designed, one of the primary objectives was to achieve maximum compatibility with the MPE V based HP3000 environment. Almost all hardware dependent features were implemented, including:

As good as SPLash! is at maintaining the MPE V-based HP3000 environment, some facets of the traditional HP3000 architecture were not implemented because they were too specific, required too much overhead at run time, depended upon a property which is non-existent or meaningless in Hewlett-Packard Precision Architecture, or were obsolete. SPLash! will flag these few constructs, should they exist in your code, and outline ways in which you might change your code in order for it to compile and execute in native mode.

An example of how SPLash! flags these constructs is shown below. A line from an SPL program is shown, along with the error message that would be generated by SPLash!.

In this case, the ABSOLUTE construct, which is used to reference bank 0 of memory on an MPE V-based HP3000, is flagged as being privileged. The discussion on flagged instructions that follows describes the use of the ABSOLUTE function and why it is not recommended for use in SPLash!

Note —Almost all of the features not implemented by SPLash! are instructions accessed by the ASSEMBLE statement. These features are enumerated in the discussions that follow. Furthermore, the constructs presented in these discussions are probably the least commonly used constructs in the SPL language.

(top) (index)


The Role of Privileged Mode in SPL Environments

Over the years, much SPL code has been written to run in privileged mode (PM). The rational for this was to eliminate the normal checks of HP3000 microcode or the MPE operating system, opening up the opportunity for data to be read or modified anywhere in the system. The dangers of using PM were, in these cases, outweighed by the ability to programmatically determine information about the runtime environment. Given the constraints of the environment, such information was simply not available through standard MPE interfaces. Introducing PM code solved the information gap problem.

PM operations in the SPL environment are extremely difficult, if not impossible, for SPLash! to support. Fortunately, the paucity of PM support SPLash! isn't a problem in most cases. Standard intrinsics, as well as AIF intrinsics, offer standard, replacement solutions to outdated PM code. The primary focus of this chapter, then, is pointed towards those rare occurrences where adequate solutions are either tricky to implement or simply not available. Background information is provided, however, that may assist you in developing an optimal solution.

Compatibility Mode & Privileged Mode

Many of the HP3000 PM operations are supported by the compatibility mode (CM) emulator on MPE/iX, and are therefore supported by SPLash!. However, a general problem with PM has always been determining the function and format of the system data structures being accessed.

For a long time, information on where system data resided, how it was structured, and exactly what it was used for was unavailable until HP published the Systems Tables Manual , the MPE System Tables Diagram and other documentation. Even with these resources available, HP reserved (and still reserves) the right to change these data structures when it deems necessary.

Because of these changes to the operating system, simply updating to a new version of MPE could cause a PM program to run incorrectly or, at best, give erroneous results. It could also cause system failures and/or data corruption. This constant necessity to validate the functions of PM code is one of the prices that is paid for the added functionality and performance possible by using these programming techniques. Often, new versions of the operating system contain new functionality which negates the need for the PM code. For example, many routines have been written which programmatically determine the job/session number of the calling program. The necessity to code this function via PM was removed when the JOBINFO intrinsic was introduced a few years ago. More recently, the advent of the AIF intrinsics eliminated similar needs. Both JOBINFO and the AIF intrinsics are fully supported in SPLash!.

Philosophically, PM operations in SPL are very different from other types of statements because their semantics are totally dependent upon the surrounding environment, the data being passed to them, and the MPE system tables and other objects being accessed. For example, a standard SPL MOVE statement is very easy to understand. The concept of moving strings of data from one area of memory to another is common to all computer systems, and can be generated on the Series 900 very easily. However, the machine instruction MFDS (Move From Data Segment) relies upon the existence of data segments, a concept very specific to the HP3000 hardware architecture. Additionally, it is impossible to determine from the source code exactly what is the intended purpose of the MFDS instruction without also examining elements external to the SPL language itself, such as what system table is being used and what data within the table is being read. A MOVE statement, on the other hand, is totally self-contained and easy to understand both by humans and by the compiler.

In migrating SPL code to the Series 900 machines running under MPE/iX, it must be realized that this code is being moved to an environment totally different from that of the traditional stack-based HP3000. Not only is the hardware environment dissimilar, but the operating system (MPE/iX) has been heavily rewritten to run on this new hardware architecture.

Although the functionality of most of the MPE V tables has been duplicated in the MPE/iX tables, it cannot be assumed that these two sets of tables have the same format. Until Hewlett-Packard publishes an MPE/iX tables manual or its equivalent, these tables will remain inaccessible. A larger issue also exists: as of this writing it is uncertain how MPE/iX will map the HP3000 two-level PM scheme (user or privileged) into the four-layer ring security structure of Hewlett-Packard Precision Architecture. Until these issues are resolved, a straight migration of some SPL code running in privileged mode is impossible.

The compatibility mode emulator running under MPE/iX does simulate most privileged operations. Every attempt has been made to allow SPLash! to support those privileged operations that are present in the emulator. However, most are flagged as errors to point out the use of privileged mode in your code.

Note that although the operations included in the discussions below (unless otherwise noted) are not supported in the full release version of SPLash!, all other operations are supported. Any privileged operations not explicitly discussed in this documentation are supported by SPLash!.

In summary, migrating privileged SPL code to the Series 900 will generally require a close examination of the specific functionality desired by the code. With this understanding, the following questions should be asked:

If the answer to question 2 is yes, then those small portions of SPL code which employ PM coding techniques should be rewritten to take advantage of the new MPE/iX functionality. If the answer is no, then you may have to work with a migration specialist (perhaps from Allegro or Hewlett-Packard), to resolve the specific issues encountered in your code migration.

(top) (index)


Unsupported CM Instructions

This section documents those CM Instructions that SPLash! does not support.

Read Switch Register (RSW) Instruction

The Read Switch Register instruction was implemented originally for the Series II and III HP3000 models. The front panel on these models contained displays for two registers: the Current Instruction Register and the Switch Register. For each bit in the switch register there was a rocker switch, which allowed the operator to toggle specific bits on and off at will. When the RSW instruction was executed, it read which switches had been set on, and pushed this as a 16-bit data word to top of stack. The most common use of this instruction was by INITIAL, the system startup program. The operator would toggle in different combinations of bits, which varied with the startup method (tape or disc).

In a very few, highly specific cases, the switch register was used as a signal to applications.

On HP-IB systems, the RSW changed slightly and was used to read the channel and device word from the thumbwheel switch that corresponded to the button used for system startup. The RSW instruction was of much less use at this time.

For the 900 Series, no such toggled register exists. Applications which use this instruction as a signal must be re-coded to provide this functionality another way. Using message files and soft interrupts (which did not exist when the Series II/III were originally created) can provide this signaling capability. A description of using message files is documented in the File System Reference Manual , HP Part Number 30000-90236.

Memory Instructions


   LDEA    LLSH    LSEA    SDEA    SSEA    XCHD

These instructions all depend upon the fact that the HP3000's memory was partitioned into banks of 64K words each in an attempt to overcome the 16-bit address limitation. All are privileged, and most are typically used only by low level system code.

Code employing any of these instructions will have to be re-examined and may need re-coding per the recommendations in the previous discussion titled "The Role of Privileged Mode in SPL Environments". SPLash! supports LDEA, LSEA, SDEA, and SSEA. The file MDS.INC.SPLASH contains details on these instructions.

Hardware Dependent Instructions


   DISP     IXIT     LOCK     PAUS     PCN      PSDB     PSEB
   RCLK     RMSK     SCLK     SED      SMSK     UNLK

These instructions are also highly privileged. These however, depend upon architectural features of the MPE V-based HP3000's rather than the memory structure. Some, such as UNLK and LOCK, were implemented to support multiple CPU's. Others, such as PSDB, PSEB, DISP, and IXIT interact with the dispatcher and ICS in a way that is highly specific to the MPE V-based HP3000's. The dispatcher under MPE/iX is not launched by microcode (there is none), and therefore these instructions have no meaning. The others are typically used by low level code in the operating system kernel. These particular opcodes are not even simulated by the compatibility mode emulator in MPE/iX.

Code employing any of these instructions will have to re-examined and re-coded per the recommendations in the discussion (above) titled "The Role of Privileged Mode in SPL Environments".

Obsolete Instructions


   CIO      CMD      HALT     RIO      SIN      TIO      WIO

Be sure to read the discussion titled "The Role of Privileged Mode in SPL Environments" in this document if you have any of the instructions listed above in your code. These instructions are all privileged and fall into the category of instructions that were implemented for specific HP3000 models. For example, the WIO, RIO, CIO and TIO instructions only existed on the HP3000 Series II/III.

If code employs these instructions, it is highly specific to a particular HP3000 series and is not transferable to a newer machine, much less to an HPPA based Series 900. It is suggested that migration assistance be employed with this type of code.

Limited Support for XEQ Instruction

The XEQ instruction allows a 16-bit word of data to be loaded on the stack, then executed by the microcode as a 16-bit HP3000 machine instruction word. This is useful for a variety of tasks.

However, fully implementing this instruction would require that SPLash! generate a run-time HP3000 machine code interpreter. On MPE V-based HP3000's, this interpreter is contained within the system microcode. No such interpreter exists in HPPA, and it was felt that the overhead was not a cost effective use of machine resources, given the number of times this instruction is used.

There exists one fairly common use of XEQ which is to build an EXIT instruction in a Control-Y handler. On stack-based HP3000's, the operating system deposits a number of words to delete from the stack when calling a Control-Y handler. The opcodes corresponding to the EXIT instruction is placed on TOS, the number of words to decrement is added to it, and XEQ 0 is executed. For this commonly encountered case, SPLash! will assume that the procedure containing the XEQ 0 is a Control-Y handler, and handle the procedure accordingly. See the section on Control-Y in Chapter 8, Migration Issues , for detailed information.

The native mode (NM) Control-Y handling is much simpler to program, and is armed with the intrinsic XCONTRAP. Unlike the standard SPL Control-Y environment, the NM Control-Y handling portion of MPE/iX cleans up the stack automatically, removing the burden from the programmer. It is recommended that the Control-Y handler be rewritten to take advantage of this superior methodology, and thus remove the ASSEMBLE(XEQ 0) altogether.

Limited Support for PCAL Instruction

Another commonly used non-privileged instruction is PCAL. The PCAL instruction has three formats. The `PCAL label' format is used to perform a PCAL instruction to a specific procedure name. This format assumes the parameters for the procedure specified in PCAL label have already been loaded onto the stack. SPLash! fully supports this format.

The `PCAL n' (n > 0) format is used to call a procedure defined by an entry in the Segment Transfer Table (STT) for that segment. In this case, `n' is an index into this table. The STT is a table of 16-bit entries at the end of every code segment. It has a specific format, and different formats differentiate between internal and external procedures. This table is known to the system microcode, and is therefore tied closely to the hardware. In order for SPLash! to implement the PCAL n format, it would have to simulate the STT, a structure which does not exist under MPE/iX. Just like the XEQ 0, it was felt that the use of this format did not warrant simulating a structure so closely tied to the microcode of the MPE V-based HP3000. If this format is being used, the PCAL label format should be used instead.

A special format for PCAL, PCAL 0, is used when it is desirable to call a procedure whose identity is not known until runtime. Typically, the intrinsic LOADPROC is called to bind a procedure in an SL to the calling program. The LOADPROC intrinsic returns a procedure label (PLABEL) which is a 16-bit quantity exactly matching the format of an STT entry. Implementation of this format would combine the runtime complexities of interpreting the TOS word (like XEQ 0) and interpreting the STT format (as with PCAL n, above). PCAL 0 is not implemented by SPLash!, but the functionality of dynamic procedure loading and calling will be accommodated through a new type of procedure, OPTION DYNAMIC. Your application will need to be re-coded to use this new feature. See the file DYNAMIC.INC.SPLASH for several examples.

Loading & Branching Instructions



   BCC      BR       LDPN     LDPP (and related instructions)
Z

This includes the set of instructions which loads words of code onto the stack and all instructions which can do branches. The LDPP and LDPN instructions were created to allow constants to be loaded from code. This is done if a constant in a calculation is greater than 8 bits, in which case an immediate instruction could be used. Because code is not highly differentiated from data in HPPA, instructions which specifically load code literals do not exist. SPL code that uses these assemble instructions should be re-coded to employ a simple TOS := literal (or constant) statement.

The branching machine instructions absolutely depend upon the 16-bit orientation of MPE V-based HP3000 instruction words. For example, the statement BR P+20 branches from the current location to the location 20 machine instructions away. This could very well be outside of the assemble statement and in the SPL statements occurring after the assemble. There is no problem with the p-relative branch since in standard SPL, those subsequent statements are translated into 16-bit machine instructions.

The translation of this 16-bit machine instruction word format is very difficult in HPPA. For this reason, SPLash! does not attempt to interpret what would have been generated on a stack-based HP3000. SPL code that employs p-relative addressing must be changed to use a branch to a label. For example:


    ASSEMBLE (BR P+20); . . . I := 4 + J; << P + 20 >>

must be changed to:


    ASSEMBLE (BR LAB1); . . . LAB1: I := 4 + J;

This code is easily handled by SPLash!, in addition to being far more readable and maintainable.

Pushing & Setting Registers


   PUSH and SET    Statements
   PSHR and SETR   Machine Instructions

These statements are used to manipulate the registers resident on the HP3000 processor boards. As with any architecture, the use and philosophy of the registers describes to a large extent the machine architecture itself. Since HP Precision Architecture is quite different than the traditional HP3000 architecture, some of the registers do not translate well to the new architecture.

In order to simulate the SPL environment, SPLash! maintains simulated copies of most of the HP3000 registers. Thus, Q, S, Z, and the DL registers are all available for use by the SPLash! programmer. In standard SPL, pushing the DB register is a privileged operation. In addition, it pushes the bank number and absolute offset in the bank onto the stack. As presented in Discussion 1, these concepts have no meaning on the 32-bit HP Precision Architecture. Pushing of the DB register now causes SPLash! to push the 32-bit HPPA register pointing to the simulated DB area in the SPLash! program's native mode (NM) stack.

Pushing and setting of the Status register is partially supported. Some of the fields within the status register, such as the "right bit" (which stackop is being executed) are meaningless in HPPA. The same is true of the code segment number. The following shows the status register format on MPE V-based HP3000's with the fields that are supported under SPLash! when executing the PUSH statement or PSHR instruction:

M | I | T | R | O | C | CC | CST #

M     Set to 0 if NM exec level = 3  
      Set to 1 if NM exec level < 3
I     Always set to 1
T     Always set to 0
R     Always set to 0
O     Set as it would be on an MPE V-based HP3000
C     Set as it would be on an MPE V-based HP3000
CC    Set as it would be on an MPE V-based HP3000
CST # Always set to 0
Setting of the status register is commonly used for disabling/enabling arithmetic traps. This functionality is provided by an intrinsic under MPE/iX, and code which sets the T bit to turn off traps should be modified to use this method. Overflow, Carry, and Condition Code can be modified by the programmer and then set. All other fields are unaffected by the SET or SETR operations.

The CON Construct

 
   CON (EDIT,TR,ENDP,PARC,XBR)

The CON construct is partially supported by SPLash!. Using CON in standard SPL, it is possible to drop any sort of data into the code stream which is subsequently interpreted by the microcode. The most common uses for CON are to build PB arrays and to form machine instructions whose assemble mnemonics are not recognized by SPL.

In the case of using CON to assemble PB arrays, the large code addressing space of the /iX overcomes some of the shortcomings of PB arrays in standard SPL. For this reason, any uses of CON for PB arrays should be removed and the array be re-coded to a standard PB array declaration.

In the case of CON being used to implement other machine instructions, this need has been removed by the fact that SPLash! will now implement the commonly used COBOLII instructions as assembly opcodes. The opcodes that will be supported by SPLash! are TR (via two new opcodes: TRDB and TRPB), ENDP, PARC, XBR (but not EDIT). See the example file PARC.INC.SPLASH for more information.

LLBL Instruction

Like the PCAL 0 instruction, this instruction relies upon the hardware dependent Segment Transfer Table (STT), and is not supported by SPLash!. If it is being used, the code should be rewritten to use the SPLash! Dynamic procedure facility.

Flagged Instructions

   ABSOLUTE LST      MABS     MDS      MFDS
   MTDS     PLDA     PSTA     SST (and more)

Most of these privileged instructions are supported by SPLash! to the same extent that they are supported by the compatibility mode emulator on MPE/iX. They are flagged here as warnings that the semantics of their operation may change under MPE/iX. Please refer to the discussion titled "The Role of Privileged Mode in SPL Environments". See also the file called MDS.INC.SPLASH .

(top) (index)


4   Compiling with SPLash!


Overview

SPLash! can be used to compile standalone programs or individual modules. The output of a standalone program compilation is a native mode program file (NMPRG). While the output of an individual module compilation is a native mode object file (NMOBJ). SPLash! NMOBJs can call or be called from any other native mode language (except for procedures that are compiled with the $SPLASH compiler option). The sections that follow review the various SPLash! UDCs and command files. Several sample compilations using SPLash! are also offered.

SPLash! User Defined Commands (UDCs)

SPLash! is delivered with two different UDC files which are located in the SPLASH account: SPLASHU (default) and SPLASHV. Each UDC file contains several UDCs that can be used to compile, assemble, or link your SPLash! programs. The default UDCs are oriented towards program development on the /iX, while SPLASHV UDCs are similar in function to the SPL UDCS.

By default, the SPLASHU UDCs are cataloged when SPLash! is installed. Please refer to the HP MPE Command Reference manual for details on the SETCATALOG command if you wish to modify the SPLash! UDCs.

SPLASHU.PUB.SPLASH

The UDCs in SPLASHU allow SPLash! programs to be compiled, assembled, and linked as easily as —

Or, These UDCs make four assumptions that you must follow:

The "lk" suffix for the names of the two UDCs which link programs follows the examples of the other native mode compilers in MPE/iX. The ".O" suffix for the assembler output was inspired by the C language.

The UDCs in SPLASHU.PUB.SPLASH provide quick access to the SPLash! compiler, but they require that you first define the specific group structure outlined above and then follow the conventions for maintaining your source and output files.

If you installed the software using the steps outlined in the Installation chapter, these groups will have been created for you.

Each of the UDCs are described next.

SPLASHU UDC Descriptions

SPLASHU.PUB.SPLASH contains five UDCs for compiling, assembling, and linking SPLash! programs, as described later in the chapter.

 
SPLLK Compiles from <source>.<logon> to <source>.ASM and then links to <source>.PUB.

SPLASH Compiles from <source>.<logon> to <source>.ASM.

ASMLK Assembles <source>.ASM to <source>.O, then links to <source>. PUB.

ASMOBJ Assembles <source>.ASM to <source>.O.

SPLOBJ Compiles and Assembles from <source>.<logon> to <source>.O.

SPLASHV.PUB.SPLASH

The UDCs in SPLASHV closely parallel the MPE commands: SPL, SPLPREP, and PREP. They make no assumptions about naming conventions.

SPLASHV UDC Descriptions

SPLLK Compiles from <source>, assembles, links; the result is in $OLDPASS.

SPLASH Compiles from <source>, resulting in SPLASSM.

ASMLK Assembles <source> to $NEWPASS, then links $OLDPASS to $NEWPASS.

ASMOBJ Assembles <source> to $NEWPASS, for deferred linking.

UDC Parameters

This section discusses UDC parameters for all of the SPLash! UDCs.
Parameter Default Description
source The name of the file to be compiled or assembled. You must specify this parameter; there is no default value.
parm0This parameter is reserved for use by SPLash! developers. Do not specify a value other than the default. Note that this parameter is different from SPL's parameter of the same name. Unlike SPL, the SPLash! compiler automatically opens the formal files SPLTEXT, SPLLIST, and SPLASSM; you need not specify a compilation parameter to accomplish this.
priv3Specifies the privilege level to be assigned to your program's outer block. When your program runs, it willautomatically execute at this privilege level. Two values are allowed:

3 = User Mode
2 = Privileged Mode

Values 1 and 0, which represent more powerful privileged modes, are not allowed by Hewlett-Packard. The MPE/iX loader will not load a file linked with privilege level 1 or 0.
cap"ia,ba"Specifies the capabilities to be assigned to your program when it executes. When coding this parameter, you must specify one or more of the following capabilities, separated by commas and enclosed in quotes.

ia Process can run interactively.

ba Process can run in batch.

mr Process can access multiple system resources concurrently.

ds Process can create and use data segments.

ph Process has the ability to perform process handling. It can control or create other processes and can obtain information about executing processes.

pm Process can run in privileged mode (that is, at ring level 2) or can call procedures that run in privileged mode. Note that this is different from the priv parameter, described above, which specifies the default execution mode for a program's outer block. You can specify pm for modules as well as programs; they will not begin executing in privileged mode but will be able to switch to privileged mode execution or to call privileged procedures.

arecs40000Specifies the maximum size, in records, for the intermediate assembler file generated by the SPLash! compiler. If this file is not big enough, the compiler will complete its processing and then issue a message indicating how big the file should be.
orecs2000Specifies the maximum size, in records, for the native mode object (NMOBJ) file that the assembler produces after processing the SPLash! compiler output. In MPE/iX, the NMOBJ file is equivalent to SPL's USL file.
opt" "Specifies optional text that you wish to pass to the assembler.
info" "Specifies an optional text string that contains compiler directives. Code one or more compiler control options separated by commas; enclose the list in quotes. (See Chapter 6, Beyond SPL for a list of compiler control options.) Do not include a $ before the first option; the SPLash! compiler will automatically insert this symbol. The compiler will interpret this string as the first line of compiler input.
list$STDLISTThe default for the SPLASH UDCs in both SPLASHU and SPLASHV is $STDLIST, for the other UDCs (e.g. ASMLK, ASMOBJ, etc.) the default is $NULL.

(top) (index)


Compiling Standalone SPLash! Programs

This section shows, through examples, how to use the SPLash! UDCs to compile, assemble, and link a standalone program. These examples use the UDCs provided in SPLASHU which are described earlier in this Chapter. It may be helpful to review that section if you haven't already done so.

Compiling

Suppose you have created a SPLash! program by entering source code into a file named FOO in your logon group. To compile this program, just type:

The "splash" UDC compiles the source file and generates a file with the same name in your ASM group. This new file, FOO.ASM, contains assembly language code. The listing is routed to $STDLIST. Since no additional parameters are specified, the default values are used, as described earlier in this section. Note that, like SPL, SPLash! produces machine code even if syntax errors are found (although this means that the code generation process might fail).

If you wish to specify parameters, you can do so the same way that you would for any UDC: by coding positional values or by preceding values with parameter keywords. Note that if you use positional values, you must specify values in the proper order and separate them with commas. If you use keywords, you can specify the parameters in any order, but you must separate them with semicolons.

For example, using positional parameter values, you can compile the program FOO using a larger intermediate assembler file and send the listing to a deferred printer by typing:

Or, you can compile the program and suppress the listing, using keyword parameters, by specifying:

If you want to compile a larger assembler file (80000 records), and send the listing to a deferred line printer, you would issue the following commands:

Assembling & Linking

After successfully compiling the program FOO, you must assemble and link it before executing it. You can use the "asmlk" UDC to assemble from FOO.ASM to FOO.O, then link FOO.O to FOO.PUB, by typing:

To assemble FOO.ASM to FOO.O and then link FOO.O to FOO.PUB with privlevel 2 (privlev 2 corresponds to MPE V's PM) you would issue the following statement:

This is the privlevel needed to be able to perform "privileged" operations, like opening a file with a negative file code. Note that the MPE XL loader will refuse to load a file linked with privlev 0 or 1.

Alternatively, you can perform the same steps using the "asmobj" UDC with MPE/iX LINK command using the following statements:

When your program consistently compiles cleanly, you may want to compile, assemble, and link in a single step. To do this, use the "spllk" UDC, which is similar to the SPLPREP command. For example:

This UDC compiles FOO (in the logon group) into FOO.ASM, then assembles it to FOO.O, then links it as FOO.PUB.

(top) (index)


SPLash! Command Files

These command files are functionally similar to the compiler command files that HP provides with their compiler products. These command files are located in the PUB group. In order to use these files, you should either move them to PUB.SYS or to a group that is in the path (HPPATH) for SPLash! users.

Like HP's compiler command files, SPLash! command files do not rely on the presence of special groups nor are they limited to compiling files in the current group. There are 4 command files for the SPLash! compiler.

Compilation Command Files
SPLXLCompiles SPL source to assembler output file.
SPLOBJXLCompiles SPL source to native mode object file.
SPLLKXLCompiles & Links SPL source to native mode program file.
SPLXLGOCompiles & Links SPL source to $OLDPASS, and then runs $OLDPASS.

Unlike the HP compiler command files, the SPLash! command files have several parameters used during the assemble stage. These parameters, along with the standard parameters, are explained next.

Command File Usage

The contents of command file are listed next.


splxl    [text][,[asm]][,[list]][,[info]]
         [,[parm]][,arecs]

splobjxl [text][,[obj]][,[list]][,[info]] [,[parm]][,[arecs]][,orecs]

spllkxl [text][,[prog]][,[list]][,[info]] [,[parm]][,[arecs]][,[orecs]][,[cap]][,priv]

splxlgo [text][,[list]][,[info]] [,[parm]][,[arecs]][,[orecs]][,[cap]][,priv]

Command File Parameters

The following list describes each of the parameters used in the command files.

Note —Detailed information on these parameters is explained in the section called UDC Parameter.

Subprogram Compilations Using SPLash!

You can code a SPLash! module and then call it from a SPLash! program, another native mode language program, or both. This section describes which options to specify and how to compile your module.

Examples in this section assume we have a source module called UPSHIFT.MODULE which contains the following code:

Also, we have a program called UPPER.SOURCE which is:

    begin ! upshifts INFO text and prints it

    integer info'len = q - 6; byte pointer info'text' = q - 5; intrinsic print;

    procedure upshift (text', bytes); value bytes; byte array text'; integer bytes; option external, splash;

    upshift (info'text', info'len);

    print (info'text', - info'len, 0); ! gets a warning

    end.

In compiling and assembling a module (i.e., not a standalone program), the SPLOBJ UDC is useful.

The next examples illustrate this process using the UPSHIFT module and the program UPPER.SOURCE for both the UDC and the command file approaches to compilation.

Compiling & Assembling with the SPLash! UDCs

Compiling & Assembling with the SPLash! Command Files

Linking

Running

Mixed Language Compilations Using SPLash!

This section discusses using SPLash! to compile a module which will be used by another native mode language program.

Note —SPLash! prefers to pass its parameters on the stack via SPL, while most other native mode languages prefer to pass their parameters in a combination of registers and the stack.

Unlike other NM languages, SPLash! generates procedures with either type of parameter passing. The OPTION SPLASH and OPTION NATIVE syntax is used to state whether a particular procedure uses stack-based (splash) or register-based (Native) conventions.

The following example uses the same upshift procedure, but this time it is called from a Pascal/iX program called UPPAS.

The UPPAS Source File

The following commands prepare and run the program. Note that since we are now calling UPSHIFT from Pascal/iX, which uses the native mode conventions for calling procedures, we must identify UPSHIFT as a native mode procedure. We do this with a $CONTROL NATIVE option on the compile.

Compiling & Assembling with the SPLash! UDCs

Compiling & Assembling with the SPLash! Command Files

Linking

Running

Calling a Module

This section discusses compiling separate modules with SPLash! and then calling them from both SPLash! programs and from other native mode language programs.

In the previous example, if the UPSHIFT routine is compiled as:

Then, it can be easily used by other native mode language programs as shown earlier. But, it can also be called by SPLash! programs if the procedure is referenced by specifying "OPTION NATIVE" in its external declaration:

(top) (index)


5   Parameters, Procedures & Conventions


Native Mode Concepts

This section discusses concepts used throughout this manual. The information in this chapter will effect how you declare variables, procedures, and intrinsics. A table on SPLash! register usage is included at the end of this chapter.

Alignment

The HP Precision Architecture demands that data is "aligned" to a natural boundary. This means that a 32-bit data item must start at an address which is a multiple of 32 bits (or 4 bytes), and so on for 8, 16, 32, and 64-bit data items.

If a program tries to reference data that is not properly aligned, an "alignment trap" occurs, and the program is aborted. Most intrinsics with reference parameters are written to allow un-aligned parameters. This was necessary to be able to migrate MPE V programs with data that was only 16-bit aligned to native mode. One example is the FGETINFO intrinsic. The eleventh parameter, "eof", is a double (32-bit integer) by reference. Native mode programs that call FGETINFO to determine the eof of a file need only pass an address that is 16-bit aligned.

Unfortunately, a small number of intrinsics have parameters that must be 32-bit aligned. One example is the GETHEAP intrinsic. The by-reference pointer parameter (a 32-bit address) must be 32-bit aligned.

Intrinsic
 
In MPE/iX, an intrinsic is solely and specifically a procedure with a description in the SYSINTR file or the SPLINTR file. The code for intrinsics resides in NL.PUB.SYS or SL.PUB.SYS . Most, but not all, intrinsics are in the NL with uppercase names. In MPE V, the term "intrinsic" was used in a looser sense to mean any procedure that was in SL.PUB.SYS , including undocumented and uncallable procedures.

Passing Parameters
 
SPLash! provides two different methods for passing parameters to procedures: native-mode and splash-mode. You can choose one or the other, depending on the language used in the calling program and the procedure.

Native-Mode Procedures
 
A native-mode procedure expects to receive its first four parameters in registers and the remainder on the native-mode stack. This is the protocol used by the MPE/iX languages. For example, all procedures written in Pascal/iX, COBOL/iX, and FORTRAN/iX are native-mode procedures. While a native-mode procedure can be called from either a native-mode or splash-mode procedure, it can only call other native-mode procedures.

Refer to the HP manual Procedure Calling Conventions Reference Manual for a complete description of the parameter passing convention.

Splash-Mode Procedures
 
Splash-mode procedures expect to receive parameters via the SPLash!-supported stack. This is the convention established in SPL, and SPLash! implements this mode primarily to maintain backward compatibility with existing SPL applications. A splash-mode procedure can only be called by another splash-mode procedure. It can call either splash-mode or native-mode procedures, however.

Controlling the Mode with Compiler Options
 
SPLash! supports compiler control options that can be specified at compilation time to determine how the compiled program or subprogram will be called.
$control internal=native
Indicates that all internal procedures, i.e. all procedures actually coded within the module, are native-mode procedures. (Do not confuse the concept of an internal procedure, as defined above, with SPL's "option internal;". They are not related.)
$control external=nativeIndicates that all external procedures, i.e. procedures defined with the EXTERNAL procedure option, are native-mode procedures.
$control nativeSpecifies that all procedures, whetherinternal or external, are native-mode procedures. Specifying this option is equivalent to specifying:

$control internal=native, external=native
$control internal=splashIndicates that all internal procedures splash-mode procedures.
$control external=splashIndicates that all external procedures are splash-mode procedures.
$control splashSpecifies that all procedures, whether internal or external, are splash-mode procedures. Specifying this option is equivalent to specifying:

$control internal=splash, external=splash

Controlling the Mode with Procedure Options
 
You can also use procedure options to identify whether a particular procedure is a native-mode or splash-mode procedure. There are two procedure options that you can use:

   OPTION NATIVE   Indicates that you are declaring a native-mode procedure.

   OPTION SPLASH   Indicates that you are declaring a splash-mode procedure.

You can use one of these procedure options for either external or internal procedures. When you specify the parameter passing protocol with a procedure option, it overrides any compiler control options that you specify at compilation time. For example, if you code a procedure with OPTION NATIVE, it will be treated as a native-mode procedure, even if you specify $CONTROL SPLASH at compilation.

(top) (index)


Default Parameter Passing
 
If you do not explicitly identify a procedure as native-mode or splash-mode through a procedure option, SPLash! determines that it is one or the other based on the previously specified compiler control options. The following table lists program and subprogram procedure defaults.

If a particular procedure declaration does not specify "splash" or "native", a default is chosen depending on several considerations. The following table shows the various combinations. Defaults were selected based on how separate compilations would most likely be used.

In the following table, combinations that produce the same results for a given type of compilation are grouped together:

Note 1: This is the default for programs.

Note 2: This combination is not meaningful, as native-mode procedures cannot call splash-mode procedures.

Note 3: This is the default for subprograms.

(top) (index)


SPLash! HPPA Register Usage

The MPE/iX debugger can be a valuable tool for debugging SPLash! programs. In order to use the MPE/iX debugger most effectively, it is very helpful to know how SPLash! uses the native mode registers.

If you are comparing the running of a CM SPL program versus a SPLash! program with the debugger, prep the CM SPL program with ZERODB, otherwise the un-initialized areas in the CM program's stack may contain strange, misleading values.

Specifying the $CONTROL STMT option in SPLash! is vital when using the debugger to debug a program. This option helps you reference source lines in the SPL file.

 
Register usage:

(top) (index)


6   Beyond SPL


Extensions to SPL

This chapter describes the ways in which SPLash! extends the basic SPL language to provide complete access to the HP3000. Topics include variable declaration, procedure options, compiler dollar options, AIF usage, and non-local jump constructs.

(top) (index)


Variable Declaration: VIRTUAL & FULLVIRTUAL

SPLash! has two additional keywords that can be used to declare variables: VIRTUAL and FULLVIRTUAL. Variables can be declared as normal, or have an optional "virtual" or "fullvirtual" preceding them.

Type OPTION NATIVE procedures implicitly change all reference parameters to type "virtual" if neither "fullvirtual" nor "virtual" is explicitly specified.

VIRTUAL ( ) and FULLVIRTUAL ( ) accept constants and expressions. Constants and expressions are evaluated and treated as 16-bit addresses to be converted into 32-bit or 64-bit addresses. If the constant or expression in the parenthesis is a non-byte expression, then SPLash! performs a word-to-byte conversion before the 16-bit to 32/64-bit conversion.

Note 1 Converting negative constants or expressions into 32-bit addresses will not be very useful unless you have set $DL to a non-zero value.

Note 2 The constant value zero (0) is treated as a special case by VIRTUAL ( ) and FULLVIRTUAL ( ). The constant zero (0) is treated as 0d by VIRTUAL ( ), and 0L0 by FULLVIRTUAL ( ). All other constants are (possibly doubled then) added to R4 to convert them into 32/64 bit addresses. The special treatment of zero (0) preserves compatibility with earlier releases of SPLash! which allowed constructs like:

An example of using FULLVIRTUAL is shown below, comparing it to a similar Pascal/iX procedure:

Constants

SPLash! accepts the dollar sign as a hex constant specifier. For example, $1234 == %(16)1234. As usual, double precision is indicated by appending a blank, and then a "d". For example, $C0000000 d .

Parameter Types

Procedures with checkable ANYVAR parameters were passed "4" as the hidden size value, regardless of the size of the actual parameter. SPLash! will now pass a size of 1 for simple byte variables/pointers, 2 for logical and integer variables/pointers, 4 for real and double variables/pointers, 8 for long variables/pointers, and 4 for all array variables.

Although the ANYVAR parameter type was provided to CALLING Pascal/iX procedures, a SPLash! procedure with body code can have ANYVAR parameters, with one limitation: the parameters cannot be directly accessed (because SPLash! cannot detect parameter type). Furthermore, an actual parameter passed to an ANYVAR parameter is always passed as a 32-bit address.

The following code fragment shows an example of using ANYVAR parameters:

    
    

    integer ktr;

    byte b;

    procedure zap (foo); anyvar foo; begin

    double addr'foo = foo, sizeof'foo = foo + 2; virtual byte pointer foo' = foo; integer bytes;

    bytes := integer (sizeof'foo);

    if bytes > 0 then begin ! erase with a ripple-move... foo' := 0; move foo' (1) := foo', (bytes - 1); end;

    end <<zap proc>>;

    ... zap (ktr); zap (b);

 
 
SPLash! also allows "option uncheckable" as a procedure option.

DB and Q Addresses

In SPL the maximum DB address directly addressable was DB+255; in SPLash! it is DB+4095. This area is referred to as the "Primary DB" area. The total amount of DB storage area available is 65535 bytes.

In SPL the maximum Q address directly addressable was Q+127; in SPLash! it is Q+4095. This area is referred to as the "Primary Q" area. Note that SPLash! does not detect overflow of Q-relative storage.

Procedure Options

The following options are all available in the "option" statement of a procedure declaration.

DYNAMIC  
Allocates a 32-bit storage cell to hold a plabel. When a procedure marked "option dynamic" is called, SPLash! fetches the plabel from the storage cell and executes a dynamic procedure call on it. This is a high-level replacement for the "assemble (pcal 0)" construct.

Example:

The Dynamic option was a necessary enhancement to allow the dynamic calling of native-mode procedures, since (unlike SPL) SPLash! needs to know the exact calling sequence of a native-mode procedure to pass the parameters correctly.

EXTENSIBLE  
The Extensible option tells SPLash! to pass a "hidden" first parameter to the (native-mode) procedure which is the parameter number (1-based) of the last valid parameter of each procedure call. For example, a call on HPFOPEN with 6 parameters would pass a hidden "6" in register 26.

EXTERNAL

FORWARD

INTERNAL

INTRINSIC

NATIVE

NOCC PRIVILEGED QUICK SPLASH UNCALLABLE UNCHECKABLE UPPERCASE VARIABLE

SPLash! Compiler Dollar Options

SPLash! recognizes all of the compiler control statements of SPL as well as a number of new options.

SPLash! allows multiple dollar options on a single line. The word "CONTROL" is optional and all types of compiler options may be intermixed on a single line. For example, the following code segments are equivalent:

Or,

In a multiple-option statement, dollar signs ($) are treated like commas (,).

With the exception of quoted string parameters, options must be complete on a single line of input. Options using quoted strings (e.g., COPYRIGHT or TITLE) can be continued on subsequent lines terminating all lines but the last with an ampersand (&).

Dollar Options: INFO parameters and SPLASHG

If SPLash! is run with an INFO parameter, that text is used as the initial dollar options. Currently, SPLash! limits the INFO string to 72 bytes. If SPLash! detects more than this amount, a warning is generated. Examples of running SPLash! with an INFO parameter are:

Or,

In addition to using an INFO parameter to pass dollar options to SPLash!, dollar options may be placed in the file SPLASHG.PUB.SYS ("G" stands for Global). If SPLASHG.PUB.SYS exists, then SPLash! automatically uses its contents as input. Using SPLASHG provides a central location for placing site-wide, common directives.

If SPLASHG.PUB.SYS does not exist, no error message is given and no extra output appears on the compilation listing. However, if SPLASHG.PUB.SYS exists, then the records will be listed just as any other $INCLUDE file records would be listed (assuming $LIST is in effect). SPLASHG.PUB.SYS may be file equated to a different file.

During SPLash!'s first pass it looks at the INFO string for the option "NOSPLASHG". If the option isn't found, SPLash! opens and parses the option list in SPLASHG.PUB.SYS . Next, the INFO= string is parsed. After SPLASHG and INFO= are parsed SPLash! proceeds with processing the remaining code in the source file. Knowing the order in which SPLash! processes allows you to keep your "standard" options in SPLASHG, and then override them with INFO= when necessary.

Dollar Options: Reference Listing

This section lists each option. Descriptions, syntax, and examples are included as needed.

 

In showing the syntax of the options, brackets ([ ]) enclose optional parameters. Braces ({ }) enclose a list of parameters from which exactly one choice must be made. Most options may be preceded with "[NO]" at the start of the option name. For example:

In some of the options the phrase "at the end of compilation" is used. This means: "as of the time when the final END. is read.".

Comments in the form of "<<....>>" are allowed in compiler option lines. Comments of the form "!" throw away the rest of the option line.

Because SPLash! accepts multiple options on a single line, all options are listed below in a single alphabetic list, even though the SPL manual would have grouped "CONTROL" options separately from options like "IF" and "PAGE".

(top) (index)


8   Migration Issues


Introduction

The sections in this chapter address the topics that experience has shown to be common issues for users migrating programs to the HPPA platform. These topics include suggestions on how to deal with Control-y trap handlers, format differences between Classic and Spectrum real numbers, and the data types supported by SPLash!. A short section on how SPLash! can be used to port SPL programs to HP-UX concludes the chapter.

Control-Y

SPLash! users who are porting code that uses Control-Y will be forced to make some code changes. In most cases these coding modifications will be small, perhaps only the addition of one or two lines of compiler directives.

Unless told otherwise, SPLash! assumes that mainline source modules are intended to be compiled in SPLASH mode. SPLASH mode emulates the classical architecture's parameter passing and stack. However, with the new machine come new protocols for procedure calls. SPLash! is able to simulate the correct calling sequence protocol for calling NATIVE procedures from OPTION SPLASH procedures. However, it is not possible for operating system procedures to call OPTION SPLASH calls because the operating system does not know to use the classical protocol.

Since the operating system doesn't know about SPLash!'s classical protocol, trap handling procedures cannot be compiled using OPTION SPLASH.

The solution to the problem is to make trap handling procedures OPTION NATIVE, which will solve this problem in most cases. However, simply making this change may create an even larger problem. All procedures that the Control-Y trap handler calls must also be compiled OPTION NATIVE.

If there are only a few procedures which are called exclusively by the Control-Y trap handler, then these can be made OPTION NATIVE. Unfortunately, if the number of procedures is extensive, or if they do 16-bit address manipulation, then you may be faced with a major amount of work.

On MPE V, a Control-Y handler returns by building an EXIT instruction on the top of stack and then executes it. However, this is not necessary on MPE/iX because the operating system adjusts the stack when the procedure exits. Therefore, simply exiting an OPTION NATIVE Control-Y handler will return the program to its normal flow. So, whenever SPLash! sees an XEQ 0, it assumes that it is the exit code for a trap handling procedure. SPLash! will print a warning message stating that XEQ 0 will be treated as an exit. You may eventually decide to remove the ASSEMBLE (XEQ 0) from your code.

The following is an example which shows how a Control-Y trap handler can be converted.


 
    
    begin   ! SPL
    

    procedure do'control'y'stuff; begin . . . ! Standalone code (No calls to SPLASH procedures) end;

    procedure controly; begin

    integer sdec = Q + 1;

    do'control'y'stuff; tos := %31400 + sdec; ! Building an EXIT instruction. assemble (XEQ 0);

    end <<controly proc>>;


A possible change for MPE/iX would be:


 
    
    procedure do'control'y'stuff;
       option native;
            ! SPLASH -> NATIVE is okay, but NATIVE -> SPLASH isn't.
            ! The "controly" procedure is being converted to NATIVE
            ! so this one needs to be NATIVE as well. If this procedure
            ! called other procedures, those would need to be NATIVE too.
    begin
    . . . ! Standalone code (No calls to SPLASH procedures)
    end;
    

    procedure controly; option native; ! When Control-Y is pushed, execution is transferred to the ! Operating System. The Operating System then makes a ! call to this procedure using the NATIVE procedure protocol. begin

    do'control'y'stuff; return; ! Remove XEQ 0 and go to procedures end

    end;


 
 

Floating Point Format

An important issue that typically arises in a migration involves the floating point formats used by the MPE V based and MPE/iX based machines. HP decided early in the Spectrum project to standardize the format used to store and process floating point numbers, and the IEEE standard for floating point was adopted. Developing the means for format conversions is the topic of this section.

IEEE Reals & Classic Reals

Most floating point formats share several characteristics. First and foremost is that the number is stored in two parts, called the `mantissa' and the `exponent'. This can best be seen by using the scientific notation convention to express real numbers. For example, the number 4324.00 is expressed as 4.324 * 10 ** 3. Scientific notation always expresses the number as a mantissa between 1 and 9 with some number of decimal places multiplied by an exponent, which is 10 raised to some power. In the example, 4.324 is the mantissa and 3 is the exponent. Numbers less than 1 are expressed with negative exponents, indicating that the decimal place is shifted to the left instead of the right. In this case, the number .02334 would be expressed as 2.334 * 10 ** -2.

Second, an entire number can be negative, so a sign is associated with the mantissa. For any real (floating point) number format to be useful, the mantissa, exponent, and their associated signs must be stored.

Some adjustments are made in the number format to make the storage and manipulation easier in the computer. Typically, the first bit (from left to right) is the mantissa's sign bit. Unlike integer numbers, real numbers are not stored in two's complement format. The sign bit is a simple binary 1 or 0 to indicate whether or not the number is negative. Next usually comes the exponent. Instead of storing this number in the usual two's complement, the number is biased to a certain base value. Biasing involves adding some constant (always the absolute value of the largest negative exponent) to the real number. For example, if the exponent is biased by 127 and the exponent value is 0, the number stored as the exponent is 127. If the exponent is -45, the number 82 is stored, and an exponent of 54 will cause the number 181 to be stored.

What this accomplishes is to simplify comparison of real numbers. With the exponent stored as the leading bits in the storage area and properly biased, a simple byte comparison can determine the inequality of two numbers.

The mantissa is stored as an absolute value, since its sign is the leading digit of the real number. The other main difference in real number formats is the total number of bits used for storage and the number of bits assigned to the mantissa and the exponent.

The HP3000 stores real numbers in single precision (32 bits) or double precision (64 bits). Single precision uses 9 bits for the exponent and 22 bits for the mantissa. The IEEE standard also defines a short (32 bits) and a long (64 bits) format, and further defines a 128-bit format called a `quad real'. The IEEE format defines a single precision number to contain 8 bits for the exponent and 32 bits for the mantissa.

While the difference is small, it affects the size of the numbers that can be stored. Further, the IEEE standard defines the way error, exception, and trap handling are to be done to a very exact level. The HP3000 format does not, and the exception handling is defined by the microcode which performs the various floating point operations. On MPE/iX, all IEEE floating point operations are performed by the floating point coprocessor. If one does not exist, the hardware traps to software routines, which simulate the execution of this piece of hardware. MPE/iX uses software to perform HP3000 format floating point operations.

The floating point format can be a problem in migration if the format is used extensively in disc files and data bases. Two options exist for converting floating point code:

If your application uses floating point heavily, consider converting the data. TurboIMAGE and QUERY assume all real numbers are in HP3000 floating point format. This must be taken into account if NM languages are to access data bases.

The table below notes the differences between classic HP3000 and IEEE real formats.

$CONTROL OLDREALS

Classic HP3000 floating point has been implemented, for both 32 and 64-bit reals ("REAL" and "LONG"). At present, a given program or subprogram compilation may contain only one type of reals. It is possible, however, to combine several subprograms containing both types of reals, as shown in the following example. Note that the default is to use IEEE floating point.

The example shows how code might be written to fetch two 32-bit real numbers from a record in an IMAGE dataset, and then use either IEEE or Classic floating point arithmetic on the values, and then write the sum back to the dataset. It is only a fragment of code and leaves open the question of how the logical variable "using'ieee" got its value...that's up to you!

Source file SUB1:
 

Source file SUB2:
 
Source file OB:

 
    
    begin
    real
       x,
       y;
    

    ... real procedure add'classic (r1, r2); value r1, r2; real r1, r2; option external, native, nocc;

    real procedure add'ieee (r1, r2); value r1, r2; real r1, r2; option external, native, nocc;

    ... dbget (.... buffer ...); ... x := buffer'oldsalary; y := buffer'wageincrease; ... if using'ieee then buffer'newsalary := add'ieee (x, y) else buffer'newsalary := add'classic (x, y); ... dbupdate (...buffer...); ... end.

SUB1, SUB2, and OB are each separately compiled with SPLash!, assembled, and their corresponding object files are saved as (perhaps) SUB1.OBJ, SUB2.OBJ, and OB.OBJ. Then, the link command combines them into a single program, OB.PUB. For Example:

(top) (index)


Data Types & Equivalents

This section describes the data types supported by SPLash!, and their equivalences in other native mode languages.

The base SPLash! data types are:

byte

logical

integer

double

real

long

SPL and SPLash! allow integers, logicals, and bytes to be stored into each other with no warnings, conversions, or range checking. Within expressions, integers/bytes/logicals can be type-coerced into any of integer/byte/logical.

For storage compatibility, SPL and SPLash! require primarily that the left and right sides of the ":=" have the same number of bits. A byte variable is treated as though it were 16 bits in size, allowing byte:=integer, and integer:=byte. This requirement means that it is legal to assign a real to a double, and vice versa. SPL and SPLash! do not generate warnings OR conversion code when this is done.

Parameter passing has the same compatibility requirements as the assignment statement.

(top) (index)


Using Other Languages

This table maps data types between SPLash!, Pascal/iX, and C/iX. Some types map exactly. For inexact maps, equivalent SPLash! (or Pascal/iX) datatypes are suggested.


 
Exact:
 
Inexact:
 
No mappings known:
 
          

1 SPL and SPLash ! allow only single dimensioned arrays.

2 Pascal/iX may not result in a 16-bit variable, "integer" may be a better equivalent.

3 When Pascal/iX passes a longint or a longreal by value, it really passes the address of a copy of the data. A longint is a 64-bit integer, a longreal is a 128 bit real.

4 The SPLash! "pointer" data type assumes either a "virtual pointer" or an ordinary pointer within a Native-mode procedure. Such pointers, like the "^" pointers in Pascal/iX, are 32 bits in size. An ordinary pointer in a splash-mode procedure would be 16 bits in size and cannot be passed by reference to a Native-mode procedure.

5 A "label" in SPLash! can be passed into a procedure as a parameter. It currently takes 48 bits on the stack, just as in SPL.

6 A "byte" variable passed by value to a procedure is handled specially in SPL and SPLash !. In and in SPLash! splash-mode procedures, the 8 bits of data is found in the UPPER 8 bits of a 16-bit halfword. In SPLash!, Native-mode procedures and in all other native mode languages, the 8 bits of data is found in the lower 8 bits of a (typically) 32-bit word.

In addition to data type differences, the programmer should be aware of the ways a parameter can be passed to a procedure within Pascal/iX, and their reflections in SPLash! Pascal/iX allows parameters to be passed: (1) by value; (2) by "var"; (3) by "anyvar"; (4) by "readonly"; and (5) by "uncheckable anyvar".

The following describes how to pass SPLash! data into Pascal/iX procedures using each of the four methods.

value  
The programmer should be aware that Pascal/iX never truly passes by value data that is bigger than 64 bits. Instead, a copy of the data is made and the address of the copy is passed. Thus, for all simple variables (except longint and longreal), simply declaring them as "value" in SPLash! suffices. Larger variables (or records) must be declared in the external-declaration as being passed by reference.

"var"  
"var" is by reference, where the address passed is a 32-bit short pointer. Simply declaring the parameters to be reference in SPLash! suffices. (Remember: reference is the default in SPL and SPLash! if the "value" statement is not used.)

"anyvar"  
"anyvar" is a variation on the "var" mechanism. In addition to passing the address of the variable, a hidden following parameter is passed which tells the size of the actual parameter in bytes. At present, SPLash! does not support "anyvar". As a workaround, TWO formal parameters should be declared: first, the reference parameter; second, a double by value. When the procedure is called, the double by value should be given the size (in bytes) of the first parameter.

"readonly"  
"readonly" is identical to "var" and tells Pascal/iX that the programmer will not be changing the data. Simply declaring the parameters to be reference in SPLash! suffices.

"uncheckable anyvar"  
This is another variation on "var". From the SPLash!'s viewpoint, it should be treated as a "var".

At present, SPLash! will not correctly pass a pointer variable to a parameter that is marked "uncheckable anyvar" or "anyvar" unless the formal parameter is also a pointer. This restriction makes it necessary to fool the compiler when calling intrinsics that expect arbitrary parameters, some of which may be pointers by reference. The only example of this kind of intrinsic, at present, is HPFOPEN. If the programmer wants to use item # 21, which requests that a fullvirtual pointer be passed back, the following calling sequence would not work in the current version:

In the above call, SPLash! would try to pass the VALUE in ptr instead of the address of ptr. A workaround is:

(top) (index)


Porting to HP-UX

This section explains how you can use SPLash! to port SPL programs to the HP-UX platform. The steps involved in using SPLash! to port SPL programs to HP-UX are different than when you port to MPE/iX. Because SPLash! doesn't run on the HP9000, only the first part of the compilation process is done on the HP3000, translating the SPL into HPPA assembly language. Then, the assembly language file is transferred to the HP9000 where it is assembled and linked to create an HP9000 executable program. Once this is accomplished, you then need to provide replacement calls for all of the HP3000 intrinsics used in your application by using any of the several methods outlined in this section.

These replacement methods are discussed next.

(top) (index)


Method I. Intrinsic Intercept

This approach involves replacing HP3000 intrinsic declarations with functionally equivalent C or Pascal code on the HP9000. In your SPL program, include external declarations (instead of intrinsic declarations) for any HP3000 intrinsics that your program uses. Then, on the HP9000 intercept the external calls and replace them with C or Pascal functional equivalents.

Step 1: Include the following declarations in the SPL source

$set x8=on ! Denotes HP-UX compilation $native $if x8=on $unix $endif

begin byte array msg(0:79); integer i;

$if x8=off intrinsic print; $else procedure print(buffer,len,cctl); value len,cctl; integer len,cctl; byte array buffer; option external, native, uppercase; $endif

i := move msg := (13,10,"Hello world"); print (msg, -i, 0);

end.

Step 2: Compile the SPL on the HP3000 to create HPPA Assembly Language

! compile with SPLash, then transfer hello.asm to the HP9000 SPLXL hello, hello.asm, $null

Step 3: Intercept Intrinsic calls on the HP9000 using the C Intercept Library

        ! assemble
                as hello.asm hello.o
        ! compile C intercept library
                cc -Aa -c mpeint.c mpeint.o
        ! link into executable
                ld /lib/crt0.o hello.o mpeint.o -ohello.exe

! hello.exe is the ported SPL!

The C Intercept Library

The C intercept library and its associated files can be found in the SPLASH account. This intercept library contains C code for many commonly used HP3000 intrinsics. As it stands today, the intercept library is not exhaustive. Over time, however, it will eventually evolve into a complete, comprehensive library that provides equivalent intrinsic functionality for all HP3000 intrinsics for which a C equivalent can be created.

The following files are provided to assist in intercepting HP3000 intrinsics:

MPEINT.EXT Include this file in your SPL source, it contains external declarations for several HP3000 intrinsics.
 

        $native
        $if x8=on
        $unix
        $endif

begin ... $if x8=off intrinsic print, quit, ... $else $include mpeint.ext.splash ! external declarations $endif
 
To compile... :SPLXL source,,$null info="x8=on"

MPEINT.H Header file for MPEINT.C

FSERR.H Include file for MPEINT.C

SSTYPES.H Include file for MPEINT.C

MPEINT.C C source code. Contains intercept routines for all of the external declarations in MPEINT.EXT, plus several other general purpose functions. These functions are discussed next.

C Functions

The file MPEINT.C contains the following intrinsic intercept functions:

Plus, the following general purpose functions:

The general purpose functions are used internally (by the intercept functions). If you write additional intercept functions you will probably need to use them as well.

In several cases, a simple C library function that can be used to replace an intrinsic call may not exist. In this case, you will be required to follow a port path of Intrinsic Replacement.

(top) (index)


Method II. Intrinsic Replacement

The Intrinsic Replacement method is, as its name suggests, a porting approach that involves replacing HP3000 intrinsic calls with calls into the C or Pascal libraries. This approach to porting is more coding intensive than the previous approach. But, because HP has both a C and Pascal compiler available on both systems (HP3000 & HP9000), porting and testing can be performed to a large degree on the HP3000 and then transferred to the HP9000 for final development & testing.

When you use this approach, the C or Pascal replacement code should be constructed as subprograms and then linked with the NMOBJ file produced during the assembly phase of the SPLash! compilation.

Successful porting of a SPL program through this method will result in a SPL source with very little dependence on the environment in which it is run.

Method III. Code Replacement

An SPL to C translator is being actively developed as an extension to the SPLash! compiler. No release date has been announced. This will probably be a several pass process where the SPLash! compiler is the front end, followed by several processor passes until usable C code is produced. Call Allegro if you are interested in more information on this methodology.

(top) (index)


9   Run Time Error Recovery


Introduction

SPLash! run time error recovery includes intrinsic-based trap support and TRY-RECOVER blocks. These methods are discussed next.

Intrinsic Traps

The following intrinsics provide trap support for run time error recovery: XLIBTRAP, XARITRAP, and XCODETRAP. See the MPE/iX intrinsics manual for an explanation of how these work.

(top) (index)


TRY-RECOVER

SPLash! supports TRY-RECOVER blocks used for building efficient run time error handling into an application.

The TRY-RECOVER block begins with the keyword TRY. Following the TRY keyword can be any valid SPL statements. If a run time error occurs after a TRY statement has been encountered, control is passed to the associated RECOVER block. Syntactically associated TRY and RECOVER statements must reside in the same SPL procedure. TRY-RECOVER blocks can be nested, however.

For example:


Using TRY-RECOVER Programmatically

To use a TRY-RECOVER block in your program, include the control statement $TRY at the beginning of your source module. $NOTRY is the default.

When $TRY is active, the words TRY, RECOVER, ESCAPE, and ESCAPECODE become reserved keywords and can only be used in the context of a TRY-RECOVER block.

TRY-RECOVER Components

The components of a TRY-RECOVER block include the ESCAPE procedure, the ESCAPECODE function, and the TRY-RECOVER block.

ESCAPE Procedure
 
This is a system procedure that gets control when a run time error occurs or when called directly by your program. This procedure accepts a 32-bit integer (double in SPL) as its only parameter. This parameter is the error code that will be passed to the RECOVER block via the ESCAPECODE function. In the event of a run time error, the parameter is set by the operating system. Otherwise, your program will provide the value for the parameter. Note —If a run time error or escape are executed outside of a TRY-RECOVER block, the program will abort.

ESCAPECODE Function
 
This system function returns the last error code that was passed to the ESCAPE procedure. The error code is a 32-bit integer (double in SPL). See the section "System Escape Codes" that follows for a list of predefined system escape codes.

The TRY-RECOVER Block Structure
 
The general form of the try-recover block is:



The TRY keyword defines the beginning of the TRY-RECOVER block. Any run time errors or calls to escape from within this section will result in program control being passed to the RECOVER block. The TRY section can contain any valid SPL statements including compound statements, procedure calls, and TRY-RECOVER blocks. Note —The TRY-RECOVER mechanism is implemented like a stack. The last TRY-RECOVER block will be the first one called when an escape call is made.

The RECOVER keyword defines the beginning of the RECOVER block. This is the section of code that gets control when an escape is executed. Like the TRY section, the RECOVER section can contain any valid SPL statements including compound statements and other TRY-RECOVER blocks. Note —If a run time error or escape is executed within a RECOVER block, this will result in a program abort unless the current TRY-RECOVER block is contained within another TRY-RECOVER block.

SYSTEM ESCAPE CODES

The following list can be found in SYSESC.INC.SPLASH , which is a subset of the information from PASESC.PUB.SYS (provided by HP):


(top) (index)


Appendix A: Assemble


Assembler Instructions

This section describes various forms of the SPLash! ASSEMBLE statement and offers instructions on usage for native mode, compatibility mode and privileged operations.

P-relative Addressing

Currently, P-relative addressing within ASSEMBLE statements is not supported. Historically, this feature was used for three reasons:

1. An assemble (BCY * +1) cleared the carry bit. SPLash! provides a new opcode, CLCY, which has the same effect.

2. It offered the ability to define conversions from byte addresses to word addresses and vice versa. SPLash! provides the BTOW and WTOB opcodes as a replacement.

3. It was "neat" to code large ASSEMBLE statements with P-relative branching. SPLash!, as does SPL, allows labels within ASSEMBLE statements, which replaces most of the need for this type of branching.

CON pseudo-op

The CON pseudo-op of the ASSEMBLE statement is also not supported. CON was historically used in SPL programs for two purposes:

1. It provided a method for assembling instructions added to the HP3000 after the SPL compiler had been written. These instructions did not have opcode mnemonics recognizable to the compiler. SPLash! provides mnemonics for these instructions (e.g. TRDB, TRPB, EADD).

2. It provided a way "drop" constants (numeric or string) into the code. This objective can be achieved through PB-relative arrays which provide identical functionality coupled with better readability.

HPPA Instructions

The following HPPA assembler instructions have been implemented and are available through the ASSEMBLE statement.

PROBERDetermines whether read access to a given address is allowed.
Usage: assemble (PROBER (sr#, gr#), gr#, gr#);
PROBEWDetermines whether write access to a given address is allowed.
Usage: assemble (PROBEW (sr#, gr#), gr#, gr#);
MTSPMoves a value from a general register to a space register.
Usage: assemble (MTSP gr#, sr#);
MFSPMoves a value to a general register from a space register.
Usage: assemble (MFSP sr#, gr#);
RSYSG Reads a 32-bit value from the system globals area.
Usage: assemble (RSYSG #);

The # parameter (which must be a multiple of 4 in the range -8192..8191), is used as a byte offset from the base of the system globals area ($c0000000). A 32-bit word is fetched from this address. This 32-bit word is pushed onto the stack.

    
    

    Affect: R8 := $c0000000 (address of system globals) R8 := [R8 + #]; (fetch 32 bits) tos := R8;  

For example, in MPE XL 1.1, system globals + $DEC contains the "real_memory_size", which can be obtained through either of the following statements:

    double real'memory'size assemble (rsysg $DEC; std real'memory'size);

    Or,

    real'memory'size := double assemble (rsysg $DEC);  

MFVA / MTVA Move from/to virtual memory and the stack. These instructions expect a 16-bit DB relative address, a 32-bit virtual address, and a number of bytes to be moved.
KSOKnown System Object.
Usage: assemble (KSO #)

The 8 byte Known System Object (KSO) specified (#) is fetched and pushed onto the stack, with the space ID at S-3/S-2, and the offset portion at S-1/S-0. An example of using this opcode to quickly fetch the value of KSO 9 is:

    fullvirtual pointer kso9; double kso9'space = kso9, kso9'offset = kso9 + 2; assemble (kso 9; std kso9'offset; std kso9'space); or assemble (kso 9); @kso9 := tos;

If only the bottom 32 bits are desired, the KSO opcode can be used:

    virtual pointer kso9; assemble (kso 9; std kso9; ddel);



Classic instructions

The following assembler instructions are also available.

SCALSubroutine call.
Usage: assemble (scal 0);

This opcode will pop a 32-bit code address from the stack, and then branch to it, leaving the return address in register R2 (just like a regular subroutine call.)

BOVBranch on overflow.
BNOVBranch on no overflow.
TRDB/TRPBImplement the two flavors of the TR opcode, which translates byes via a DB-relative or a PB-relative table.
CLCY Clears the CARRY flag (higher level than: BCY *+1). An ASSEMBLE (BCY *+1) cleared the carry bit. SPLash! provides a new opcode, CLCY, which has the same affect.
CLOVClears the OVERFLOW flag.
BTOWConvert 16-bit byte address to 16-bit word address.
WTOBConvert 16-bit word address to 16-bit byte address.
Converts a 16-bit stacked byte address to a 16-bit word address, (and vice versa) taking into account the problems of byte addressing on the classic HP 3000 (i.e., if a byte address appears negative, is it below DB, or merely a large positive address?).


Privileged instructions

In MPE V/E "low" memory is referred to as "bank 0". This bank of 128KB contains many interesting tables and values. PM code can access this data via the following opcodes:

In the list above; "Single" means a 16-bit value, "Double" means a 32-bit value. "Extended Address" means a 16-bit bank number and a 16-bit half-word offset within the bank. "Half-word" means a 16-bit word.

SPLash! does not attempt to compile these opcodes because most applications involve accessing system tables that may have changed from MPE V/E to MPE/iX.

If your code contains any of these opcodes, use the replacement routines located in the file MDS.INC.SPLASH . These routines provide similar functionality, and are in most cases identical in function to using the most of the above opcodes with a stack decrement value of "delete all parameters".

Note —PRIV MODE must be enabled to use these routines, otherwise an error message, instruction memory protection trap , will be generated.

MPE/iX maintains a memory area that is equivalent to the Classic HP3000's bank 0. At present, and this may change , it is found at virtual address $80000000. However, this area is only 128KB long, which means that it is equivalent to bank 0, and no other banks are simulated.

The replacement routines that have bank parameters check to be sure that you are trying to access bank 0. If a bank other than 0 is passed in, the routine will call splash_abort (found in the MDS.INC.SPLASH file). The MOVE routines do not allow negative move lengths.

In the particular case of MDS, MTDS, and MFDS, many applications of these opcodes involved implementing a fast method of moving data to or from the stack and an extra data segment. Although it is still possible to do this (via these routines), we strongly recommend recoding to use the native-mode heap or a mapped file.

(top) (index)


Appendix B : Intrinsic Changes


Intrinsic Changes

There are several intrinsics that SPLash! recognizes as potentially needing programming attention. The reasons vary; for instance, some intrinsics no longer exist, or the name may have been changed. The following list describes these intrinsics, and what has changed.

SWITCHDB and EXCHANGEDB

The SWITCHDB intrinsic and the undocumented EXCHANGEDB procedure do not exist in native mode. The file XDB.INC.SPLASH contains code for a splash-mode EXCHANGEDB routine. It requires linking with GETOLDDB.MILLI.SPLASH .

If a program attempts to declare SWITCHDB via an intrinsic declaration (e.g. intrinsic switchdb), it will usually generate a syntax error since SWITCHDB is not found in SYSINTR.PUB.SYS .

The file XDB.INC acts as a replacement for SWITCHDB and EXCHANGEDB.

Hint Investigate why your code is using split-stack mode. Performance will probably be improved by simply allocating a chunk of memory on the NM heap (using the P_GETHEAP or GETHEAP intrinsics).

If access to a REAL extra data segment is essential, then this routine should work for you but this has not been verified.

Note —This routine produces a SPLASH-mode procedure! If you need a Native-mode procedure, then contact Allegro. A Native-mode EXCHANGEDB is harder because it must change the saved R4 value in the stack frame.

(top) (index)


Appendix C : Compiler Messages


The SPLash! message catalog may be found in the file SPLCAT.PUB.SPLASH .

(top) (index)


Appendix D : SPLash! Debugger


SPLash! Debugger

The material presented in this section is provided only for the sake of completeness. The SPLash! Debugger is used primarily by the designers of SPLash! for troubleshooting and requires significant knowledge of the internal workings of the program to be of real value to the average SPLash! user. But feel free to explore!

Note —If the JCW SPLASHDEBUG is set to a non-zero value then SPLash! will invoke it's debugger if an assertion error occurs.

SPLash! Debugger Commands

Commands may be abbreviated to just the uppercase portion. Whenever a node number is allowed, the words: ROOT, DAD, SON, NEXT, and TAIL are also accepted.

The debugger also contains a help subsystem. Typing HELP at the DEBUG prompt will display much of the text contained in this section. The text is contained in the file SPLASHHL.PUB.SPLASH .

The SPLash! debugger commands are listed next.

ABORT  
Aborts SPLash! by calling QUIT.

 
ASK [$] [c]  
Invokes the conversational debug-flag setter. If the optional "$" is specified, then the dialog pertains only to $CONTROL flags. If "c" is specified, only options starting with that letter (or greater) will be presented. This routine will loop until a slash(/) is entered, then it will return back to the debugger. Note — If a back slash (\) is entered, the routine exits and the debugger will exit.

 
Back [#nodes]  
Moves the "current node" backward #nodes nodes. (Default is 1 node)

 
BASE [8/10/16/Octal/Hex/Integer/Decimal]  
Sets the "base" to the specified value. The initial base is 8. If no parameter follows "BASE", then the current value is reported.

 
BREAK procname [PERM | TEMP]  
Sets a breakpoint to enter the SPLash! debugger when the specified procedure is called. The type of breakpoint, permanent or temporary, may also be specified (the default is permanent). This option is only available when running under the MPE V operating system.

 
Continue  
Exits the debugger, just like the slash (/) command.

 
CURrent  
Reports what the "current node" is, and whether or not it appears to be a valid node number.

 
DAD [#]  
Reports dad of specified node. If # is omitted, then the "current node" will be used. The dad becomes the new "current node". Thus, to print the tree for the grandfather of node 804 you could do:

 
DEBUG  
Calls Debug/iX, the HP debugger.

 
DEBUGGER text  
Recursively calls the debugger with the specified text. This command exists as a means of testing the programmatic interface to the debugger (i.e., debugger (buf, len))

 
DEBUGNOde [node#]  
Tells SPLash! you want to enter the debugger when this node is allocated or when it is prettyprinted.  
Note —Defaults to current node.

 
Display [ dbaddr# ] [#words] [base]  
Displays the specified range of DB-relative addresses in the chosen base (8/10/16/Octal/Decimal/Hex). Dbaddr defaults to the prior value (initially 0). #words defaults to 40. Base defaults to the prior base value (initially 8).  
Remember —prefix the address with "%" for octal!

 
DUMP Constants | Symbols | Nodes | Tree  
Dumps the desired item.

 
Exit  
Exits the debugger, just like the "/" command.

 
FLags [#1 [ [,] #2] ]  
If #1 is present, sets DB+0 to that value. If #2 is present, sets DB+1 to that value. The two debugging flags are stored at DB+0 and DB+1. A higher-level method of setting/resetting debugging bits is the SET/RESET command.

 
FORMfeed | FF  
Sends a form feed to the output device.

 
Forward [#nodes]  
Moves the "current node" forward #nodes nodes. (Default is 1 node)

 
HELP  
Gets this information.

 
MAP [lexlevel#] [ Sorted | Unsorted]  
Prints a symbol table map of the specified lex level (defaults to current lex level). If Sorted is specified, the map is sorted. Default is unsorted.

 
MODIFY dbaddr value  
Sets DB(dbaddr) := value. If the current node is the area modified, this command automatically sets the dirty bit for that node.

 
Next [#]  
Like DAD, but gets node'next.

 
NODEbuf [node#] [base]  
Dumps in the desired base the contents of the specified node. This is a "raw" dump.  
Note —Since a get'node is done, you could actually enter Debug/iX and modify the node buffer if you wanted to...but if you do that, be sure to mark it "dirty" with NODEDIRTY.

 
NODEDIRTY  
Marks the "current node" as dirty.

 
NODES [startnode] [endnode]  
Dumps the nodes array. Width defaults to 80 for interactive, 132 for batch.

 
NOSUPPress [warning# | SUPPress | NOSUPPress ] [...]  
See SUPPRESS.

 
OUTFile [text]  
Uses "text" as a file name and tries to FOPEN it. If successful, then all subsequent "send" output generated while within the debugger will be sent to the specified file. The file can be closed either by exiting the debugger or by entering "OUTFILE" with no parameters. (The default device is LP.)

 
PARMs [base]  
Prints a stack trace and, for every marker, shows the last 8 values prior to Q-3. Because this information takes room on the output line, only the name of the routine is shown. See also the STACK command. Base is one of: Hex, Integer, Octal. Default = Octal

 
PP [node#]  
Calls pretty-print starting at the specified (or current) node number.

 
PRIORITY [CS | DS | ES]  
Sets the execution priority for the SPLash! compiler.

 
PROCedure procname  
This command returns the address for the named procedure. This command is only available under MPE V.

 
PSCREEN  
Invokes the PSCREEN module which reads the terminal memory and dumps it to the line printer.

 
RESET [debugoption [debugoption ...]]  
Resets the specified debug options to true. These are the same options settable via ASK. RESET with no parameters will report the currently SET debug bits. RESET ALL resets trace'flag and trace'flag2 to 0.

 
Resume  
Exit the debugger, just like the slash (/) command.

 
Root [#levels]  
Prints the nodes tree starting at the root, for the specified number of levels (defaults to 1). Changes the "current node" to root.

 
SAVenode [#levels]  
Prints the nodes tree for 1 level, starting at the node last referenced before entering the debugger. SAVE makes "current node" be this value too.

Note —At entry to the debugger, "current node" has this value.

 
SEQ #  
Finds the first node with a sequence number (left 5 digits) >= the number you specified.

 
SET [debugoption [debugoption ...]]  
Sets the specified debug options to true. These are the same options settable via ASK. SET with no parameters will report the currently set bits. SET ALL sets trace'flag and trace'flag2 to $FFFF, which is probably not desirable.

 
SOn [#]  
Like DAD, but gets the first son.

 
STack [base]  
Prints a stack trace, so you can see who called what. (see also the PARMS command) Base is one of: Hex, Integer, Octal. Default = Octal

 
STATistics  
Displays the same statistics that $CONTROL STATISTICS shows.

 
SUPPress [warning # | SUPPress | NOSUPPress ] [...]  
Suppresses/unsuppresses the printing of specified warnings. For example, the command "NOSUPPRESS 5" allows warning #5 to be generated, which is "LOGICAL SHIFT LEFT EMITTED". After [un]suppressing specified warnings, the status of the warning suppression bit-map is reported.

 
SYMbol # [style]  
Displays the symbol for the specified symbol id. Style, which defaults, to 0, is used to specify the style in which the symbol is to be displayed:

 
SYMBUF symbol# [base]  
Dumps the symbol table node for the specified symbol id. This dump is in a raw format.

 
TAil [#]  
Like DAD, but gets node'tail.

 
TERMinate  
Calls terminate.

 
TRee [#1 [ [,] #levels]  
Prints the nodes tree for #levels (defaults to 1) Sets the "current node" to #1 (if specified, otherwise the old "current node" is used as #1).

 
WALK  
"Walks" all the nodes of the tree and then reports on it's findings.

 
WANTdebug  
Sets the "want'debugger" flag at exit of debugger. This will cause the next get'node to enter the debugger.

 
#1 [#levels]  
Identical to TREE #1 [#levels] Example: 48 2 dumps 2 levels starting at node 48

 
:mpecommand  
Calls the COMMAND intrinsic with the rest of the input.

 
/ (forward slash)  
Exits this debugger.

(top) (index)


Appendix E : SPLash! & Debug/iX Macros


Introduction

This appendix explains the SPLash! macros used for debugging with the native mode debugger, Debug/iX. Use these two facilities together to troubleshoot or analyze your programs.

SPLash! Macros for DEBUG

The following steps will guide you in using SPLash! macros with Debug/iX to locate variables.

Step 1 The first step in using SPLash! macros with the debugger, is to compile and link your program with SPLash! using the $MAP control option. Use the SPLash! output listing as your variable reference.

This will generate a variable map so you can locate variables within your program. Outer block variables will be located at positive offsets from DB. Procedure parameters will be as located at negative offsets from Q; procedure variables will be located at positive offsets from Q.  

Step 2 Start your program and load the SPLash! macro file. Use the following commands.

    : run progname;debug <<<<<<< start debug nmdebug> use splash.macro <<<<<<< load splash macros

Running your program with ";debug" invokes the debugger after loading your program. Next, at the debug prompt "nmdebug>", enter "use splash.macro" to load the SPLash! macro file into the debugger.  

Step 3 Locate the section of code that is of interest to you. Place a breakpoint there. Execute to that breakpoint. The following commands may be used to perform Step 3.

    nmdebug> dc program len <<<<<<< dc = dump code <<<<<<< program = program label <<<<<<< len = amount of code to dump nmdebug> b offset <<<<<<< set a breakpoint nmdebug> c <<<<<<< execute to the breakpoint

 

Step 4 Examine variables. There are several ways to do this. Two examples of examining variables using 2 of the SPLash! macros are presented here. These macros are:

Using your SPLash! map listing, locate a DB relative variable you want to examine. Then issue this command:

    nmdebug> dcmdb (offset,len)

Where offset is the number from the SPLash! variable map, and len is a halfword value.

Now let's look at a Q relative variable. Using your SPLash! map listing locate a Q relative variable you want to examine. Then issue the command:

Again, offset is the number from the SPLash! variable map, and len is a halfword value. Note that Q relative variables come and go with the execution of your program, so the procedure of interest must be active when viewing Q relative variables.

ms

Macro NameUse
dcmdb Display DB relative memory
dcmq Display Q relative memory
dcms Display S relative memory
j Jump PC+8, skips next two instructions
odd Return TRUE if byte address
cmdb Returns DB relative memory address
cmq Returns Q relative memory address
cms Returns S relative memory address
compare Compare memory
dcm Display 32 bit memory
dcm1 Display 16 bit memory
get16 Return 16 bit memory value
leftright Tell user which part of address is significant
armall Enable all breakpoints
disarmall Disable all breakpoints
untrap Disable a breakpoint

Macro Definitions

The armall, disarmall, and untrap macros are useful when a SPLash! program is compiled with one (or more) of the $BREAK= options.

If a SPLash! program was compiled with $BREAK=ALL, then conditional breakpoints are emitted at the entry and exit of every procedure and subroutine, at every label (e.g., LOOP:), and at the entry/exit of the program.

When the program is run, these conditional breakpoints cause the code to be interrupted, and the debugger is invoked (quietly). The debugger determines which type of conditional breakpoint was encountered. It then checks if the user wanted that breakpoint to interrupt the program (i.e., is that type of trap ARMed?), and (if armed) falls into the debug code.

    mac armall {trap trace arm; trap} mac disarmall {trap trace disarm; trap} mac untrap (trapname) {trap !trapname disarm; trap !trapname}

    /* Usage: =cmdb (3) returns value at DB+3 /* =cmq (-4) returns value at Q-4 /* =cms (-2) returns value at S-2

    mac cmdb (offset) {return get16 (r4 + 2 * offset) } mac cmq (offset) {return get16 (r5 + 2 * offset) } mac cms (offset) {return get16 (r6 + 2 * offset) }

    /* Usage: j Sets a temporary breakpoint 2 instructions forward. /* Useful for jumping around a BL instruction.

    mac j {env error 0; ignore quiet; b pc + $8, -1; if error = -#30 then { env error 0; ignore quiet; b pc + #12, -1; }; if error <> 0 then wl "Unable to set breakpoint" else c; } /* err -#30 is: breakpoint already in code at that spot

    /* Usage: compare (r4+10, r5+10, 10)

    mac compare (x1 : ptr, x2 : ptr, len : int) { while len > 0 do { if [x1] <> [x2] then & wl "Mismatch at WORD ",x1," = ",[x1], " vs ", x2," = ",[x2]; loc x1 = x1 + 4; loc x2 = x2 + 4; loc len = len - 4; }; }

    /* Usage: procname (pin)

    mac procname (i) {dv pibx (i) + $119c, $30/4, s}

    /* Usage: getproc (pc) --> returns procedure name (without "+...")

    var my_proc_name = " "

    mac getproc (addr : lptr) { var my_proc_name = nmproc (addr); var my_proc_name = str (my_proc_name, 1, strpos (my_proc_name + "+", "+") - 1) }

    /* Usage: ifstmt (pc) --> true if we are at a "Stmt" opcode

    mac ifstmt (addr : lptr) { if ([addr] band $ffff0000) = $20000000 then return true else return false}

    /* Usage: exstmt (pc) --> extracts the statement # of a "Stmt" opcode

    mac exstmt (addr : lptr = 0.0) { if lptr (addr) = 0.0 then loc addr = pc; return [addr] band $7fff}

    /* Usage: liststmts (pc) --> lists "Stmt" opcodes starting at addr /* stops when it hits end of routine.

    mac liststmts (addr : lptr = 0.0) { if lptr (addr) = 0.0 then loc addr = pc; getproc (addr); loc saveproc = my_proc_name; loc mypc = addr; wl my_proc_name; while my_proc_name = saveproc do { if ifstmt (mypc) then wl mypc," Stmt ", exstmt (mypc):"#"; loc mypc = mypc + 4; getproc (mypc); } }

    /* Returns "true" of instr at pc is a conditional breakpoint

    mac istrace (addr = 0.0) { if lptr (addr) = 0.0 then loc addr = pc; loc instr = [addr]; if (instr = $1600e) or (instr = $1400e) or & (instr = $1e00e) then return true else return false}

    mac finddl { var dlregister nmaddr ("_dl_register","data") - nmaddr("$global$","data") + r27; var dlsize [dlregister] }

    mac arg (n) {dv r6-(4*(!n))}

    mac listargs (argbase, maxn = 64) { var i = 3; var itemnum = 1; var itemval = 0; while (i < !maxn) and (itemnum <> 0) do { var itemnum = [!argbase - (4*i)]; var itemval = [!argbase - (4*(i+1))]; wl "Arg # ", i/2:"#", " = # ", itemnum:"#", ", value = ", itemval, " --> ", [itemval]; var i = i+2; } }

    mac init { var p_c pc ; var curseq 0 }

    if mode = 'nm' then init;

    mac next { var p_c p_c + 4; while [!p_c]>>$10 <> $2000 do var p_c p_c + 4; var curseq [!p_c] band $1fffff; wl !p_c; pj !p_c }

    mac prior { var p_c p_c - 4; while ([!p_c]>>$10 <> $2000) and (p_c > 0) do var p_c p_c - 4 ; var curseq [!p_c] band $1fffff; wl !p_c; pj !p_c }

    mac find (newseq) { if newseq > curseq then & while curseq < newseq do {next;wl "Seq # ",asc(curseq,"#")}& else & while curseq > newseq do {prior;wl "Seq # ", asc(curseq,"#")}}

(top) (index)


Using DEBUG on MPE/iX

This is a brief summary of the more basic commands available in Debug/iX. Debug/iX can be used to debug native mode (NM) code or compatibility mode (CM) code.

Debug/iX has an extensive amount of help information available. The HELP command describes the basic help facility. Using the HELP command, along with the CMDLIST, FUNCLIST, and ENVLIST commands, will generate information on almost any feature you are looking for.

The topics discussed in this section cover things like; using the LIST command to generate information, which commands can be used for displaying data, and how you can use the Singlestep and Breakpoint instructions for controlling the execution of your program. Lastly, an abbreviated list of commonly used Debug/iX commands is presented.

The LIST Command

The LIST Command, and it's variations, can be used to generate command names for functions that you may wish to use.

Frequently, commands ending with the letters "LIST" follow a similar pattern: the "IST" can be abbreviated (i.e., CMDL is equivalent to CMDLIST), and the first parameter is a wildcard, via the LISTF command (CMDLIST @Z@).

CMDLIST cmdpattern [category] [what]

FUNCLIST funcpattern [catogory] [what]

ENVLIST envpattern [category]

For a complete list of commands that "list" things, try: CMDLIST @LIST or ALIASLIST @LIST .

The ALIASLIST command is used because Debug/iX supports a synonym feature that it refers to as an "alias". The CMDLIST command is actually an alias for the CMDL command. Indeed, most of the apparent commands ending in "LIST" are simply predefined aliases for commands ending in "L".

(top) (index)


Displaying Data

The DISPLAY commands display information on your screen in a variety of formats.

DV address [#words] [base] [recw] [recb]

DDB dbaddr [#halfs] [base]

DQ qaddr [#halfs] [base]
DS saddr {#halfs] [base]

DR dr [register]

(top) (index)


Singlestep & Breakpoint

These instructions are useful for controlling the execution of your program.

Ss [#instructions]

B address [count] [<LOUD] | QUIET>] [cmd]