The Museum of HP Calculators


HP CPU and Programming

The hardware technology used in HP calculators improved steadily over the years, moving from multichip to single chip designs with greater speeds and capabilities. However, the programming model remained much the same from the HP-35 though the HP-30E/C series. This document provides a brief description of the programming style of these early models. The HP-01, HP-41C and the Saturn processors were similar. Their differences are highlighted below.

56-bit Registers

The HP calculator CPUs were optimized for floating point numbers. Each main register consisted of 14 of 4 bits each (56 bits per register) This allowed each register to hold a 10 digit mantissa, a 2 digit exponent and signs for the mantissa and exponent. Each digit or sign occupied 4 bits. This is commonly referred to as Binary Coded Decimal (BCD) encoding. The 56-bit registers were:

Additional Registers

Field Selects

Many operations were controlled by a field select option. This allowed portions of each register to be accessed independently. The field select codes where:

M Mantissa
MS Mantissa and Sign
X Exponent
XS Exponent Sign
S (Mantissa) Sign
P Pointer (The nibble indicated by the P register)
W Word (the entire register)
WP Word up to and including nibble indicated by P register from right to left. For example, if P=3, WP would refer to nibbles 0, 1, 2, and 3.

The sign nibbles are set to 0 if positive and 9 if negative.

The Saturn processors added field selects for Byte and Address.

Addressing

The classic models used 8-bit instruction addresses plus ROM select instructions to activate the appropriate 256-word ROM. The 20 series used 12-bit addresses. The classics had a subroutine stack depth of one versus 2 for the 20 series.

The user stack was contained in on-chip memory, however, multiple user memories as found on the HP-45, financial memories and program memory all required additional data storage. To access registers in off-chip memory, the CPU first supplied the address to the storage chip using C-> DATA ADDRESS and then read or wrote the data at that address. 20 series machines added operations that allowed a read or write to off-chip memory with a single instruction.

Instructions

In general, registers (or portions) could be cleared, copied, exchanged, incremented or decremented. In addition, registers could be shifted left or right and tested. Portions of registers to act on were indicated by enclosing the field select code in brackets after the instruction. Each instruction occupied 10 bits.

The following symbols are used in the Instructions below:

fs field select (one of the codes above: M, MS, etc.)
gr general purpose register (A, B, or C)
lbl a label
bit a value of 0 or 1
digit a value between 0 and 9
stat a status register bit number (0 - 11)
ptr a pointer value (0-13)
rom a rom number (max depends on model)

Known Instructions:

CLEAR REGISTERS Set all 56-bit registers to zero.
0 -> gr[fs] Set the selected part of gr register to zero.
A -> B[fs]
B -> C[fs]
C -> A[fs]
M -> C
C -> M
Copy the selected part of the register on the left to the register on the right. Examples: B - > C[X]: copy the exponent part of B to the exponent part of C. A -> B[WP]: copy A to B from the right most nibble up through the nibble indicated by the P register.
A EXCHANGE B[fs]
A EXCHANGE C[fs]
C EXCHANGE B[fs]
C EXCHANGE M
Exchange the selected portions of the two registers. Note that transfers to/from M are always full word transfers.
A + B -> A[fs]
A + C -> A[fs]
A + C -> C[fs]
C + C -> C[fs]
A - B -> A[fs]
A - C -> C[fs]
A - C -> A[fs]
Perform math on the selected portions of the indicated registers
A + 1 -> A[fs] Increment the selected portion
C + 1 -> C[fs]
A - 1 -> A[fs] Decrement the selected portion
C - 1 -> C[fs]
-C -> C[fs] Negate C (tens complement)
-C -1 -> C[fs] Negate and decrement C (nines complement)
SHIFT RIGHT gr[fs] Shift selected portion of gr right
SHIFT LEFT A[fs] Shift selected portion of A left
IF B[fs] = 0
IF C[fs] = 0
IF A >= C[fs]
IF A >= B[fs]
IF A[fs] >= 1
IF B[fs] >= 1
Test for selected part of of register (Follow these with THEN GO TO)
      THEN GO TO lbl Go to label lbl if true (must follow one of the IFs above)
GO TO lbl Unconditional go to
IF NO CARRY GO TO lbl   Go to label if carry bit is not set
CLEAR STATUS Clear all 12 status bits
bit -> Sstat Set Status bit stat to bit (Example: 1 -> S10)
IF Sstat = 0 Test if status bit equal to 0 (follow with THEN GO TO)
IF Sstat # 1 Test if status bit not equal to 1 (same as above test)
ptr -> P Set P register to ptr (ptrth nibble for P field select or through ptr for WP)
P + 1 -> P
P -1 -> P
Increment and decrement P
IF P # ptr Test if P not equal to ptr (follow with THEN)
C -> STACK Push C onto the stack (E->F, D->E, C->D) always whole word
STACK -> A Pop stack into A (D->A, E->D, F->E) always whole word
ROTATE DOWN Move D to C, E to D, F to E and the original C to F (just like pressing the R↓ key.)
JSB lbl Jump to Subroutine labeled xyz (one level of subroutines on the Classics, 2 on 20 series.)
RETURN Return to the instruction after the JSB.
LOAD CONSTANT digit   digit -> C at the Pth nibble. P is then decremented so multiple digits can be loaded easily.
SELECT ROM rom Select ROM #rom for addressing.
KEYS -> ROM ADDRESS   Jump to the offset of the current keycode in the currently selected ROM.
DISPLAY OFF Turn the display off
DISPLAY TOGGLE Toggle the LED display on/off.
C -> DATA ADDRESS Set current data address to value in C* Precursor to reading or writing off-chip memory.
DATA -> C Read data in to C register*
C -> DATA Write data from C register*
NO OPERATION Does nothing.

* For example, to write the value in B into the address indicated by C, the program could do:

    C -> DATA ADDRESS
    B -> C[W]
    C -> DATA

George Weigt has provided an opcode map in the articles forum.

Programming Example - The HP-45

Eric Smith was able to piece together the entire HP-45 firmware listing by reading patent disclosures. In addition to reading the firmware, you can run and step through it on this HP-45 Microcode simulator.

Programming Example - The HP-65

This code segment normalizes numbers as keyed into the user. The user input in the A and B registers is normalized into the C register. This code segment is from the HP Journal (used with permission.) Sign nibbles are 0 if positive, 9 if negative.

L01063 .....111..           FIX5:  P - 1 -> P
L01064 .1111.1.1.                  C + 1 -> C[X]
L01065 ..111.11.1 -> L1073         JSB FIX7
         .
         .
         .
L01070 ..11.11.1.           FIX3:  0 -> C[XS]            ; restore + (0) sign after testing in FIX1
L01071 11.1..11..           FIX4:  13 -> P               ; Correct Exponent for decimal position
L01072 .1.11.1.1.                  C - 1 -> C[X]
L01073 ........1.           FIX7:  IF B[P] = 0
L01074 ..11..1111 -> L1063              THEN GO TO FIX5
L01075 11....11..                  12 -> P
L01076 1..11...1.           FIX6:  IF A[P] >= 1          ; Remove leading zeros & adjust exponent
L01077 .11111..11 -> L1174              THEN GO TO FIX2
L01100 .1.....11.                  SHIFT LEFT A[M]
L01101 .1.11.1.1.                  C - 1 -> C[X]
L01102 ..11111..1 -> L1076         JSB FIX6
         .
         .
         .
L01146 .111111.1.           FIX1:  C + 1 -> C[XS]        ; Exponent negative? (9 represents - sign)
L01147 ..111...11 -> L1070         IF NO CARRY GO TO FIX3
L01150 ..1.1.1.1.                  0 - C -> C[X]         ; Complement Exponent
L01151 ..111..1.1 -> L1071         JSB FIX4
         .
         .
         .
L01167 111.1.111.           FIX0:  A EXCHANGE C[W]        ; Set C equal to A
L01170 .11...111.                  C -> A[W]              ; (there is no A -> C instruction)
L01171 1..11..11.                  IF A[M] >= 1           ; A Mant # 0?
L01172 .11..11.11 -> L1146              THEN GO TO FIX1
L01173 1.111..11.                  0 -> A[M]              ; Zero normal form
L01174 111.1..11.           FIX2:  A EXCHANGE C[M] 

HP-01

The HP-01 was similar to the classic series except that its registers were only 48 bits wide.

The HP-41C

The HP-41C added additional capabilities such as:

Saturn

Saturn processors expanded on the HP-41C processor by widening the main registers to 64 bits, widening program addresses to 20 bits, expanding subroutines to 6 registers (plus two for the interrupt system.) and adding:

Additional information may be found on the Saturn page.

Go to the HP-45 Microcode Simulator
Go to classic series technology
Go to 20 series technology
Go to 30 series technology
Go to the main exhibit hall