Systems Programming Language
Systems Programming Language, often shortened to SPL but sometimes known as SPL/3000, was a procedurally-oriented programming language written by Hewlett-Packard for the HP 3000 minicomputer line and first introduced in 1972. SPL was used to write the HP 3000's primary operating system, Multi-Programming Executive (MPE). Similar languages on other platforms were generically referred to as system programming languages, confusing matters.

Originally known as Alpha Systems Programming Language, named for the development project that produced the 3000-series, SPL was designed to take advantage of the Alpha's stack-based processor design. It is patterned on ESPOL, a similar ALGOL-derived language used by the Burroughs B5000 mainframe systems, which also influenced a number of 1960s languages like PL360 and JOVIAL.

Through the mid-1970s, the success of the HP systems produced a number of SPL offshoots. Examples include ZSPL for the Zilog Z80 processor, and Micro-SPL for the Xerox Alto. The later inspired Action! for the Atari 8-bit family, which was fairly successful. The latter more closely followed Pascal syntax, losing some of SPL's idiosyncrasies.

SPL was widely used during the lifetime of the original integrated circuit-based versions HP 3000 platform. In the 1980s, the HP 3000 and MPE were reimplemented in an emulator running on the PA-RISC-based HP 9000 platforms. HP promoted Pascal as the favored system language on PA-RISC and did not provide an SPL compiler. This caused code maintenance concerns, and 3rd party SPL compilers were introduced to fill this need.

History
Hewlett-Packard introduced their first minicomputers, the HP 2100 series, in 1967. The machines had originally been designed by an external team working for Union Carbide and intended mainly for industrial embedded control uses, not the wider data processing market. HP saw this as a natural fit with their existing instrumentation business and initially pitched it to those users. In spite of this, HP found that the machine's price/performance ratio was making them increasingly successful in the business market.

During this period, the concept of time sharing was becoming popular, especially as core memory costs fell and systems began to ship with more memory. In 1968, HP introduced a bundled system using two 2100-series machine running HP Time-Shared BASIC, which provided a complete operating system as well as the BASIC programming language. These two-machine systems, collectively known as HP 2000s, were an immediate success. HP BASIC was highly influential for many years, and its syntax can be seen in a number microcomputer BASICs, including Palo Alto TinyBASIC, Integer BASIC, North Star BASIC, Atari BASIC, and others.

Designers at HP began to wonder "If we can produce a time-sharing system this good using a junky computer like the 2116, think what we could accomplish if we designed our own computer." To this end, in 1968 the company began putting together a larger team to design a new mid-sized architecture. New team members included those who had worked on Burroughs and IBM mainframe systems, and the resulting concepts bore a strong resemblance to the highly successful Burroughs B5000 system. The B5000 used a stack machine processor that made multiprogramming simpler to implement, and this same architecture was also selected for the new HP concept.

Two implementations were considered, a 32-bit mainframe-scale machine known as Omega, and a 16-bit design known as Alpha. Almost all effort was on the Omega, but in June 1970, Omega was canceled. This led to an extensive redesign of Alpha to differentiate it from the 2100's, and it eventually emerged with plans for an even more aggressive operating system design. Omega had intended to run in batch mode and use a smaller computer, the "front end", to process interactions with the user. This was the same operating concept as the 2000 series. However, yet-another-2000 would not be enough for Alpha, and the decision was made to have a single operating for batch, interactive and even real time operation.

To make this work, it needed an advanced computer bus design with extensive direct memory access (DMA) and required an advanced operating system (OS) to provide quick responses to user actions. The B5000 was also unique, for its time, in that its operating system and core utilities were all programmed in a high-level language, ESPOL. ESPOL was a derivative of the ALGOL language tuned to work on the B5000's, a concept that was highly influential in the 1960s and led to new languages like JOVIAL, PL/360 and BCPL. The HP team decided they would also use an ALGOL-derived language for their operating systems work. HP's similar language was initially known as the Alpha Systems Programming Language.

Alpha took several years to develop before emerging in 1972 as the HP 3000. The machine was on the market for only a few months before it was clear it simply wasn't working right, and HP was forced to recall all 3000's already sold. It was reintroduced in late 1973 with most of its problems having been fixed. A major upgrade to the entire system, the CX machine, and MPE-C to run on it, reformed its image and the 3000 went on to be another major success during the second half of the 1970s.

This success made SPL almost as widespread as the 2000 series' BASIC, and like that language, SPL resulted in a number of versions for other platforms. Notable among them was Micro-SPL, a version written for the Xerox Alto workstation. This machine had originally used BCPL as its primary language, but dissatisfaction with its performance led Henry Baker to design a non-recursive language that he implemented with Clinton Parker in 1979. Clinton would then further modify Micro-SPL to produce Action! for the Atari 8-bit family in 1983.

HP reimplemented the HP 3000 system on the PA-RISC chipset, running a new version of the operating system known as MPE/iX. MPE/iX had two modes, in "native mode" it ran applications that had been recompiled for the PA-RISC using newer Pascal compilers, while under "compatible mode" it could run all existing software via emulation. HP did not supply a native mode compiler for MPE/iX so it was not an easy process to move existing software to the new platform. To fill the need, Allegro Consultants wrote an SPL-compatible language named "SPLash!" that could compile to original HP 3000 code to run within the emulator, or to native mode. This offered a porting pathway for existing SPL software.

Language

Basic syntax
SPL generally follows ALGOL 60 syntax conventions, and will be familiar to anyone with experience in ALGOL or its descendants, like Pascal and Modula-2. Like those languages, program statements can span multiple physical lines and end with a semicolon. Comments are denoted with the  keyword, or by surrounding the comment text in << and >>.

Statements are grouped into blocks using BEGIN and END, although, as in Pascal, the END of a program must be followed by a period. The program as a whole is surrounded by BEGIN and END., similar to Pascal, but lacking a PROGRAM keyword or similar statement at the top. The reason for this is that SPL allows any block of code to be used as a program on its own, or compiled into another program to act as a library. The creation of code as a program or subprogram was not part of the language itself, handled instead by placing the  compiler directive at the top of the file.

The language used the INTRINSIC keyword to allow external code to be called directly by giving it a local name. For instance, a machine language library exposing a function to run the console bell could be imported to an SPL program as  and then the bell could be operated by using the keyword  as if it was a native command.

In contrast to Pascal, where  and  were separate concepts, SPL uses a more C-like approach where any  can be prefixed with a type to turn it into a function. In keeping with the syntax of other ALGOL-like languages, the types of the parameters were listed after the name, not part of it. For instance:

 INTEGER PROCEDURE FACT(N); VALUE N; INTEGER N;

Declares a function FACT that takes a value N that is an integer. The  indicates that this variable is also the return value for the procedure.

Although frowned upon, ALGOL and Pascal allowed code to be labeled using a leading name ending with a colon, which could then be used for the target of loops and  statements. One minor difference is that SPL required the label names to be declared in the variable section using the  keyword.

SPL added to this concept with the  statement which allowed these labels to be further defined as "entry points" that could be accessed from the command line. Labels named in the entry statement(s) were exposed to the operating system and could be called from the RUN command. For instance, one could write a program containing string functions to convert to uppercase or lowercase, and then provide ENTRY points for these two. This could be called from the command line as .

Data types
Where SPL differs most noticeably from ALGOL is that its data types are very machine specific, based on the 3000's 16-bit big endian word format.

The  type is a 16-bit signed type, with 15 bits of value and the least significant bit as the sign.  is a 32-bit integer, not a floating-point type.  is a 32-bit floating-point value with 22 bits for the mantissa and 9 for the exponent, while  is a 64-bit floating-point value with 54 bits of mantissa and 9 bits exponent.

 is used for character processing, consisting of a 16-bit machine word holding two 8-bit characters.  is a boolean type that stores a single bit in the most significant bit. There is no equivalent of a  modifier as found in Pascal, so  is somewhat wasteful of memory.

Like C, data is weakly typed, memory locations and variable storage are intermixed concepts, and one can access values directly through their locations. For instance, the code:

 INTEGER A,B,C
 LOGICAL D=A+2

defines three 16-bit integer variables, A, B and C, and then a LOGICAL, also a 16-bit value. The , like Pascal, means "is equivalent to", not "gets the value of", which uses  in Algol-like languages. So the second line states "declare a variable D that is in the same memory location as A+2", which in this case is also the location of the variable C. This allows the same value to be read as an integer via C or a logical through D.

This syntax may seem odd to modern readers where memory is generally a black box, but it has a number of important uses in systems programming where particular memory locations hold values from the underlying hardware. In particular, it allows one to define a variable that points to the front of a table of values, and then declare additional variables that point to individual values within the table. If the table location changes, only a single value has to change, the initial address, and all of the individual variables will automatically follow in their proper relative offsets.

Pointers were declared by adding the  modifier to any variable declaration, and the memory location of a variable dereferenced with the . Thus  declares a pointer whose value contains the address of the variable A, not the value of A.  can be used on either side of the assignment;  puts the value of A into P, likely resulting in a dangling pointer,  makes P point to A, while  puts the value of A into the location currently pointed to by P.

In a similar fashion, SPL includes C-like array support in which the index variable is a number-of-words offset from the memory location set for the initial variable. Unlike C, SPL only provided one-dimensional arrays, and used parentheses as opposed to brackets. Variables could also be declared , in which case no local memory was set aside for them and the storage was assumed to be declared in another library. This mirrors the  keyword in C.

Literals can be specified with various suffixes, and those without a suffix are assumed to be . For instance,  would be interpreted as an , while  was a .  denoted a  and  a . String constants were delimited by double-quotes, and double-quotes within a line were escaped with a second double-quote.

Variable declarations could use constants to define an initial value, as in . Note the use of the assign-to rather than is-a. Additionally, SPL had a  keyword that allowed a string of text to be defined as a variable, and then replaced any instances of that variable in the code with the literal string during compiles. This is similar to the  keyword in C.

Memory segmentation
As was common in the era, the HP 3000 used a byte-oriented segmented memory model in which an address was a single 16-bit word, allowing code to access up to 65,536 bytes (or as they termed it, "half-words"). To allow larger amounts of memory to be accessed, a virtual memory system was used. When memory was accessed, the 16-bit address was prefixed with one of two 8-bit segment values, one for the program code (PB) and another for variable data. The result was a 24-bit address. Thus, while each program had access to a total of 128 kB at any one time, it could swap the segments to access a full 16 MB memory space.

SPL included a variety of support systems to allow programs to be easily segmented and then make that segmentation relatively invisible in the code. The primary mechanism was to use the  compiler directive which defined which segment the following code should be placed in. The default was , but the programmer could add any number of additional named segments to organize the code into blocks.

Other features
SPL included a "bit-extraction" feature that allowed simplified bit fiddling. Any bit, or string of bits, in a word could be accessed using the  syntax, where x and y were the start and end bit positions from 0 to 15. Thus  returned the lower byte of the word storing A. This format could be used to split and merge bits as needed. Additionally, additional operations were provided for shifts and rotates, and could be applied to any variable with the , for instance .

Example
This simple program, from the 1984 version of the reference manual, shows most of the features of the SPL language.

The program as a whole is delimited between the  and . It begins with the definition of a series of global variables, A, B and C, defines a single procedure and then calls it twenty times. Note that the procedure does not have a BEGIN and END of its own because it contains only one line of actual code,  the  is not considered part of the code itself, it is indicating the type of the three parameters being passed in on the line above and is considered part of that line.

  BEGIN
      INTEGER A:=0, B, C:=1;
      PROCEDURE N(X,Y,Z);
          INTEGER X,Y,Z;
          X:=X*(Y+Z);
      FOR B:=1 UNTIL 20 DO
          N(A,B,C);
  END.

References

Citations

Bibliography
 
 
 

Systems programming languages
HP software