HP67 CALCULATOR EMULATOR Version 1A February 22, 1981 Paul Sorenson Department of Physiology Michigan State University E. Lansing, MI 48824 Current Address: Pulmonary Research S3, Mayo Clinic Rochester, MN 55904 (507)-284-8395 HP67 CALCULATOR EMULATOR--GENERAL DOCUMENTATION HP67 is a FORTRAN IV program designed to emulate the majority of functions available in the Hewlett-Packard series of programmable calculators (HP-65, 67, and 41C). All calculations are performed in double precision. In addition to the basic instruction set currently implemented, HP67 can be configured to execute a variety of special purpose instructions with only minor additions to the FORTRAN source files (see "Adding Commands to Command Set"). It is assumed that the reader is already familiar with the basic operation of an HP style calculator, since this documentation will be primarily concerned with specific differences/limitations of the HP67 program. The reader should consult the HP-67 Owner's Handbook and Programming Guide for a general description of calculator operations, and programming examples. COMMAND FORMAT: HP67 operates in one of two modes, "RUN" or "PROGRAM". In either case, HP67 indicates it is ready for a new command by displaying the "OK:" prompt on the user's terminal. "RUN" mode is distinguished by the presence of the " X = nnnn" line prior to the "OK:" prompt, and is the mode the program enters when it is first started. In "RUN" mode, the program behaves as if it were a standard non-programmable RPN (reverse polish notation) calculator, executing each valid command entered and displaying the contents of internal stack register "X" after each step is executed. "PROGRAM" mode is distinguished by the display " PC = nnn ; ASCII string" which shows the user the current program counter's internal memory location (1-1000) as well as the command stored at the current program step. In either mode, a command line consists of either; 1) a numeric entry, 2) a valid instruction, or 3) a leading numeric entry followed by a valid instruction. A numeric entry is any valid FORTRAN "E" format numeric string, and a valid instruction is the character string corresponding to the desired function selected from the current list of recognized instructions. All command lines are terminated by a carriage return, and only one instruction may be given on a command line. The following represent valid command lines: OK: CLX ;single instruction OK: 1.23E-2 STO 1 ;numeric entry followed by instruction OK: 6.5782 ;numeric entry alone The following would be illegal or misinterpretted command lines: OK: 5.6 * 4.3 ;numeric entry following "*" instruction OK: LN 1.7823E-3 ;numeric entry following "LN" OK: SIN RCL 6 ;2 instructions on a single command line NOTE: spaces within a command line are ignored by HP67, and may be used to separate subsections of a command line. Once a command line has been entered, HP67 will either execute the command when in "RUN" mode, or load the command into it's internal program memory when in "PROGRAM" mode. If the command is not recognized, the error message "Illegal or unrecognized command" will be displayed. When a command line consists of a numeric entry followed by an instruction, the command may be considered as two independent commands, i.e. it is possible for the number to be entered correctly, but have the instruction fail to be recognized. A command line consisting of a numeric entry alone is handled in a special way when in "RUN" mode. Unlike the "ENTER" ( ^ ) instruction, the number is placed in stack register X only, but the stack lift on the next mumeric entry is enabled. In this way, the next entry will push the stack up and place the new entry into stack register X. The "ENTER" instruction is similar, but places the number into stack registers X and Y while disabling the stack lift for the next numeric entry. A number keyed in following an "ENTER" instruction will then over write the current X register. As an example, consider the following sets of command lines: OK: 6.534E-2 OK: 6.534E-2 ^ OK: 1.453 OK: 1.453 ^ OK: -3.9813 OK: -3.9813 ^ Resulting stack register contents: T = ????? T = 6.534E-2 Z = 6.534E-2 Z = 1.453 Y = 1.453 Y = -3.9813 X = -3.9813 X = -3.9813 In the example on the right, the next number entered will over write the X register. In the example on the left, the next number entered will push contents of X to Y, etc., and place entry into X register. This is a subtle difference, but is an important point to consider when using "ENTER" to place a number into both the X and Y registers. A numeric entry in a command line in "PROGRAM" mode is considered a constant and is loaded into program memory. When encountered as a program step during execution, the constant is placed into the X stack register as if it were entered from the keyboard, and enables the stack lift for the next number entered. MAJOR DIFFERENCES BETWEEN HP67 PROGRAM AND HP-67 CALCULATOR: The biggest difference between the HP67 emulator and the HP-67 calculator is in the size and organization of storage registers and program memory. HP67 can directly address 256 storage registers ( 0 - 255 ) and, therefore, does not support any of the primary/ secondary storage register operations used by the HP-67 calculator. Additionally, any of the 256 registers may be used as an indirect register, thereby eliminating all references to the HP-67 calculator's "I" register. The HP67's program memory consists of 1000 storage locations. When HP67 is in "PROGRAM" mode, command lines are interpretted and loaded into program memory as a sequence of internally coded instructions. Each keyboard command may use several program memory locations as storage for the command. In "PROGRAM" mode, a value for the current program counter ( PC ) is displayed along with the instruction currently stored at this PC. A distinction should be made between a program step and a program memory location. A program step refers to the actual instruction entered in response to the "OK:" prompt. A program memory location is a unit of storage for program instructions. The value of the PC is displayed solely for monitoring the number of memory locations used when keying in a program. All program editing functions (e.g. single step, back step, go to step #) operate on program steps regardless of the number of memory locations occupied by a single program step. In addition to the extended register and program memories, HP67 recognizes a larger set of program labels. Valid label designators consist of either a single alphabetic character (A-Z, a-z) or a number (0-255). Numeric labels are predominantly used for labelling subsections within a program. Alphabetic labels are predominently used as entry points to the program from the keyboard. For example, entering a single alphabetic character as a keyboard instruction causes HP67 to search downward through program memory for the matching label designator, and, if found, begins program execution at that point. Similarly, if a program included a "GTO 35" instruction, program control would be unconditionally transferred to the program section following a LBL 35 instruction. Five instructions have been implemented in HP67 which have little or no equivalence to an HP-67 calculator's instruction set: SAVE filespec LOAD filespec PUTREG filespec GETREG filespec "prompt" These instructions allow access to the computer operating system's (e.g. RT-11, RSX-11M) file structure for permanent storage and retrieval of programs and data, and allow programmed prompting of the user with a message. It is assumed that the user has a knowledge of the file naming conventions for the appropriate operating system. SAVE and LOAD store or load program memory respectively to/from the designated file (filespec). PUTREG and GETREG store or load storage registers 0-224, respectively, to/from the designated file (see note on subroutine linkage for treatment of registers 225-256). Finally, a message may be executed as a program step and displayed on the user's terminal by placing the message or prompt (up to 37 characters) in quotes ("). One last major distinction between HP67 and the programmable calculator is in the handling of subroutine linking. In the HP-67 calculator, there may be no more than 3 pending return points. However, 3 returns will always be pending regardless of the number of subroutine calls executed. HP67 handles up to 128 pending return points, but will lose all return points on the 129th consecutive subroutine call. The user must also be aware that the subroutine return points are stored in general purpose storage registers 225-255. Each storage register may hold up to 4 return points, with the return points stored beginning in register 255 and working toward register 225. Programs that do not use subroutines have full use of registers 225-255. Programs that use subroutines should either avoid using registers 225-255, or recognize that every four pending return points require one storage register. Since the contents of registers 225-256 may contain a sequence of subroutine return pointers, these registers are not saved (PUTREG) or loaded (GETREG) to/from a file. Additionally, HP67 subroutines may be recursive, that is a subroutine may call itself, but be aware that this can result in an infinite execution loop. COMPARISON OF HP67 PROGRAM AND HP-67 CALCULATOR INSTRUCTION SETS: The reader should refer to pages 8 - 13 of the HP-67 Owner's Handbook and the HP67 COMMAND SET listing for the following discussion. This discussion deals only with differences between the two instruction sets. Items not mentioned can be assumed to function identically. Prefix keys: HP67 has no prefix keys, all instructions are keyed in as shown in the HP67 COMMAND SET listing, substituting an appropriate value where applicable. For example, to clear register 8, key in the CLREGn instruction substituting 8 for "n". Digit entry functions: Enter exponent (EEX) is not supported by HP67. Exponent entry is an integral part of keying in a number, and follows the rules for "E" format FORTRAN constants. Number alteration functions: Round mantissa (RND) is not supported by HP67. Storage functions: Store and recall from registers A-E and I are not supported. Registers are denoted by number from 0-255. Indirect register addressing is provided for all register manipulation functions by enclosing the register # in "()". Selective clearing of a single register ( CLREGn, CLREG(n) ) has been included. Interchange primary and secondary storage registers ( P>< -122 Interchange X and Y registers on stack. LSTX -121 Moves contents of LAST X register to X lifting rest of stack registers. STK -120 Displays current stack contents. CHS -119 Changes sign of # in X register. ABS -118 Replaces # in X with absolute value of # in X. INT -117 Truncates # in X to integer. FRAC -116 Replaces # in X with fractional portion of # in X. PI -115 Places pi (3.1415...) in X register. + -114 Adds X and Y registers. - -113 Subtracts X from Y register. * -112 Multiplies X and Y registers. / -111 Divides Y by X register. % -110 Replaces # in X with X percent of Y register. %CH -109 Computes percent of change from # in Y register to # in X register ( (X-Y)*100/Y ). N! -108 Computes factorial of integer portion of # in X register. /X -107 Computes reciprocal of # in X register. SQRE -106 Computes square of # in X register. SQRT -105 Computes square root of # in X register. Y^X -104 Raise # in Y register to power of # in X register. ^X -103 Raise 10 to power of # in X register; common anti-logarithm. E^X -102 Raise "e" to power of # in X register; natural anti-logarithm. LN -101 Computes natural (base "e") logarithm of # in X register. LOG -100 Computes common (base 10) logarithm of # in X register. DEG -99 Sets calculator to degree mode; all angular operands assumed to be in decimal degrees. RAD -98 Sets calculator to radians mode; all angular operands assumed to be in radians. GRD -97 Sets calculator to grads mode; all angular operands assumed to be in grads. COS -96 Computes cosine of # in X register. SIN -95 Computes sine of # in X register. TAN -94 Computes tangent of # in X register. ACOS -93 Computes arccosine of # in X register. ASIN -92 Computes arcsine of # in X register. ATAN -91 Computes arctangent of # in X register. >HMS -90 Converts decimal hours or degrees to hours, minutes, seconds in form HH.MMSSSS. >DMS -89 Identical to ">HMS". HMS+ -88 Adds Y register to X register assuming both registers are in form of HH.MMSSSS. DMS+ -87 Identical to "HMS+". >R -86 Converts # in X register from degrees to radians. D< -85 Converts # in X register from radians to degrees. H< -84 Converts # in X register from "HH.MMSSS" form to decimal degrees. >P -83 Converts x,y coordinates in X and Y registers to polar magnitude (r in X) and angle (theta in Y). R< -82 Converts polar magnitude and angle in X and Y registers to rectangular x,y coordinates. Following relational tests are only executed when under program control. NEY -81 Executes next program step if # in X register is not equal to # in Y register; otherwise next program step is skipped. NE0 -80 Executes next program step if X not equal to 0; else skip step. EQY -79 Executes next program step if X = Y; else skip step. EQ0 -78 Executes next program step if X = 0; else skip step. GTY -77 Executes next program step if X > Y; else skip step. GT0 -67 Executes next program step if X > 0; else skip step. GEY -75 Executes next program step if X > or = Y; else skip step. GE0 -74 Executes next program step if X > or = 0; else skip step. LTY -73 Executes next program step if X < Y; else skip step. LT0 -72 Executes next program step if X < 0; else skip step. LEY -71 Executes next program step if X < or = Y; else skip step. LE0 -70 Executes next program step if X < or = 0; else skip step. -69 to -21 Currently unassigned Following instructions only accepted when in "programming" mode. CLPRGM -20 "Clears" program memory; sets all steps to R/S instruction. BST -19 Backsteps program to previous step. DEL -18 Deletes current program step, moves all remaining steps up, bringing in R/S instructions at end of memory. INS -17 Inserts a "NOP" instruction by pushing current and trailing steps down, losing last instruction (currently force a R/S to be last program step). RUN -16 Exits programming mode, returns to normal keyboard control, i.e. run mode. Following instruction only accepted when in "run" mode. PRGM -15 Places calculator into programming mode. -14 to -6 Currently unassigned Following instructions accepted at all times. SST -5 When in run mode, executes next step from program memory and returns control to keyboard. When in program mode, skips over current program step and displays next program step. -4 Currently unassigned. PAUSE -3 When executed from keyboard, acts as "NOP". When executed from program memory, displays current # in X register, then resumes execution. NOP -2 No operation. RTN -1 When executed from the keyboard, resets program counter to program step #1. When encountered during program execution as the result of a "GSB" instruction, program execution resumes at step immediately following the GSB instruction; otherwise, program counter is set to step # 1 and control returned to keyboard. R/S 0 When encountered during program execution, returns control to the keyboard. When entered from the keyboard, resumes program execution at current program step. LBLa 1 Alphabetic (A-Z, a-z) label designator, defines beginning of a program section. LBLn 2 Numeric (0-255) label designator, defines beginning of a program section. 3 Reserved for future use. DSPn 4 Selects display of n digits to right of decimal point. Program automatically shifts to scientific notation for numbers which can not be represented with n decimal digits. DSP(n) 5 Uses the absolute value of integer portion of contents of register n (0-255) to select # displayed digits to right of decimal point. CFn 6 Clear flag # n (0-3). SFn 7 Set flag # n (0-3). TFn 8 Test flag # n (0-3). When encountered as program step, program execution continues with next sequential step if flag n is set, otherwise, next step is skipped. TF2 and TF3 automatically clear flag 2 or 3 after execution. Flag 3 is set following each numeric entry. Executes as NOP when entered from keyboard. DSZn 9 Decrement register n (0-255) and skip if 0. Subtracts 1 from register n and skips 1 program step if contents = 0. DSZ(n) 10 Indirect decrement and skip if 0. Subtracts 1 from register pointed to by contents of register n and skips 1 program step if result is 0. ISZn 11 Increment register n and skip if 0. Adds 1 to contents of register n and skips 1 program step if contents = 0. ISZ(n) 12 Indirect increment and skip if 0. Adds 1 to register pointed to by contents of register n and skips 1 program step if result is 0. GTOa 13 Go to alpha (A-Z, a-z) label designator. If executed from keyboard, positions program counter to program step immediately following the "LBLa" instruction, and returns control to keyboard. If executed as program step, finds "LBLa" instruction, and resumes execution with next program step. GTOn 14 Go to numeric (0-255) label designator. If executed from keyboard, positions program counter to program step immediately following the "LBLn" instruction, and returns control to the keyboard. If executed as a program step, finds "LBLn" instruction, and resumes execution with next program step. GTO(n) 15 Indirect go to numeric label. Searches for numeric label entry corresponding to contents of register n, then proceeds as GTOn. GSBa 16 Go to subroutine labeled "a". Executes as GTOa when entered from keyboard. When executed as a program step, program counter of next sequential step is loaded into a subroutine return point register, and program control is transfered to the program step immediately following "LBLa" instruction. GSBn 17 Go to subroutine labeled "n". Executes as GTOn when entered from keyboard. When executed as a program step, program counter of next sequential step is loaded into a subroutine return point register, and program control is transfered to the program step immediately following "LBLn" instruction. GSB(n) 18 Indirect go to subroutine. Executes as GTO(n) when entered from keyboard. When encountered as a program step, program counter of next sequential step is loaded into a subroutine return point register, and program control is transferred to the program step immediately following a numeric label entry corresponding to the contents of register n. 19 Currently unassigned. REGn 20 Displays current contents of register n. REG(n) 21 Displays current contents of register pointed to by contents of register n. CLREGn 22 Clears register n. CLREG(n) 23 Clears register pointed to by contents of register n. ><(n) 25 Interchanges contents of stack register X with contents of register pointed to by contents of register n. RCLn 26 Recalls contents of register n to stack register X, lifting previous stack elements. RCL(n) 27 Recalls contents of register pointed to by contents of register n to stack register X. Previous stack elements are lifted. STOn 28 Stores contents of stack register X in register n; stack remains unchanged. STO(n) 29 Stores contents of stack register X in register pointed to by contents of register n; stack remains unchanged. STO+n 30 Adds contents of stack register X to register n; stack remains unchanged. STO+(n) 31 Adds contents of stack register X to register pointed to by contents of register n; stack remains unchanged. STO-n 32 Subtracts contents of stack register X from register n; stack remains unchanged. STO-(n) 33 Subtracts contents of stack register X from register pointed to by contents of register n; stack remains unchanged. STO*n 34 Multiplies contents of stack register X by register n; stack remains unchanged. STO*(n) 35 Multiplies contents of stack register X by register pointed to by contents of register n; stack remains unchanged. STO/n 36 Divides register n by contents of stack register X, result placed in register n; stack remains unchanged. STO/(n) 37 Divides register pointed to by contents of register n by contents of stack register X; stack remains unchanged. 38 to 63 Currently unassigned. Following instruction only allowed under "programming" mode GTO.i 64 Steps program to absolute step # i (1-1000). Program steps do not necessarily correlate to program memory locations, e.g. LBLa instruction requires 2 memory locations. 65 to 119 Currently unassigned. d 120 Dummy instruction used for storing constants in program memory. When in programming mode, any numeric string not associated with an instruction is interpretted as a constant and prefixed by this code #. When executed as a program step, lifts stack and loads stack register X from program memory. 121-123 Currently unassigned. "prompt" 123 Types the character string enclosed by "'s for programmed prompting of user. LOADfilespec 124 When entered from keyboard, loads program memory from "filespec" and returns to keyboard control pointing at first program step. When encountered as a program step, loads program memory from "filespec" and begins execution at first program step. Following instruction only valid in "programming" mode SAVEfilespec 125 From programming mode, starts decoding current program memory into analogous character instructions and writing to "filespec". Control returns to keyboard in programming mode. GETREGfilespec 126 Loads registers 0 to 224 from specified file using list directed read format. PUTREGfilespec 127 Writes current contents of registers 0-224 to specified file, 3 #'s per line separated by commas in "E24.17" format. a = alphabetic character A-Z, a-z n = unsigned integer number in range 0-255 i = integer number (optionally signed) in range -32768 to 32767 d = double precision floating point number in range .29E-38 to .17E39 filespec = valid operating system file specification prompt = any valid ASCII string