Post Reply 
HP-45 Internal Pointer Operations
04-24-2023, 06:10 PM (This post was last modified: 04-24-2023 08:12 PM by Z80Sarah.)
Post: #1
HP-45 Internal Pointer Operations
(Slightly embarrassed to have to edit my first ever post, but I thought to check the original HP patent 4,001,569 after I'd submitted this post, and the answer is on page 24: the loadConstant operation does, indeed, skip loading the constant (but not decrementing the pointer) if the pointer is greater than 13.)

Hi,

tl;dr: Does the internal pointer carry values between 0 and 15, requiring a check for a value < 14 in the loadConstant operation or does it only hold values between 0 and 13, with no need for that check? Either answer seems curious.

Full version: I'm in the process of rewriting a previous HP-45 simulator of mine in Python (I'll post when it's done) and have a slightly abstruse question about the internal pointer. The pointer is used to point to the 14 nibbles of the internal registers, which are numbered 0 to 13. One operation which makes use of this is loadConstant, which puts a given value into the C register at a nibble determined by the pointer, and then decrements the pointer. My existing code (which works fine) has a couple of things going on with the pointer operations:

(1) if a decP operation is carried out on a pointer value of 0, the pointer is set to 15
(2) If a incP operation is carried out on a pointer value of 15, the pointer is set to 0
(3) If a loadConstant operation is attempted with a pointer value > 13, the load is skipped (but the pointer is still decremented).

I'm uncomfortable with (3), because it's in-effect adding an additional operation into the calculator: it should just perform the loadConstant, with no checks on the pointer value. The actual ROM code performs no such check elsewhere (i.e. to make sure that the pointer is < 14 before a loadConstant is even called).

Changing (1) and (2) would be an option, so that the pointer
'looped' to 13 on a decP on 0, and to 0 on an incP on 13. This seems neater (and reduces the number of operations required per calculator function), but also seems like odd behaviour for a 4-bit pointer.

Does anyone have any ideas?

(Also, first post, so a warm "hello" to everyone, too.)
Find all posts by this user
Quote this message in a reply
04-24-2023, 09:52 PM (This post was last modified: 04-24-2023 10:00 PM by teenix.)
Post: #2
RE: HP-45 Internal Pointer Operations
Welcome to the Forum

I wouldn't worry about post edits, I'd have a red face all the time if I did :-)

The P register will decrement if a Load Constant executes with P at any value and wrap around to 15 after decrementing at 0. However as you mention, the LC instruction will not execute if P > 13. Maybe it does, but there is nowhere in a register to hold the constant. Obviously, the programmers knew of this and the other LC limitations and did not violate them when writing the code.

The code had to be written with limited ROM space in mind, so sometimes a code segment may execute with P > 13 because this code segment is used from multiple sources, but the programmers would have known about this, and the following code won't be affected.

An example of this behavior in the HP-45 can be found when calculating SIN-1 at ROM address $0275.

A constant has to be loaded into the C register for part of the calculation. However, at the start of the loading this value, when C = 09999999999006, the P register = 15, then decrements to 14 and so on until P=1 then the code segment is complete. The segment loop uses Load Constant 6.

P = 15, Load Constant 6, C = 09999999999006
P = 14, Load Constant 6, C = 09999999999006
P = 13, Load Constant 6, C = 69999999999006
etc

The final value of C is 66666666666606

Yes, there are a few redundant instructions, but there might not have been a simple coding way around the P issue. My hat is off to the guys that wrote the original code with the ROM addressing limitations on the Classics. Try adding an instruction anywhere in the ROM code, and you'll see the mess that it can create.

cheers

Tony
Find all posts by this user
Quote this message in a reply
04-24-2023, 10:58 PM (This post was last modified: 04-25-2023 05:26 PM by brouhaha.)
Post: #3
RE: HP-45 Internal Pointer Operations
EDIT: With regard to the Classic series models including the HP-45, using the ARC & CTC chips, what I originally posted here was WRONG, and only applies to the later generation processsors (ACT in Woodstock, Spice, and Nut in 41C and Voyagers). Teenix posted the correct information. I have edited the following to hopefully make it clear that the pointer wrapping from 0 to 13 and vice versa does not apply to the Classic series. My apologies for any confusion.

As Teenix said, in the Classic series, P can have values of 14 and 15. Doing a "load constant" under those conditions has no effect.

For the newer HP 56-bit processors:

When p is decremented past 0, or incremented past 13, it wraps. It is never in a stable state of 14 or 15. There are some notes in internal HP docs that the pointer may "disappear" for one cycle when that happens, so executing "p=13; Inc p; lc 6" might give a different C register result than "p=13; inc p; nop; lc 6", but both result in p being 0. In the cycle immediately after the wrap, pointer comparisons can also be wonky, e.g. "p=13; Inc p; ?p=0" may give carry clear even though "p=13; Inc p; nop; ?p=0" gives carry set. The exact behavior has subtle variations depending on which generation of CPU is used, ACT,or Nut.

The programmable models in the Woodstock and later series, including the 67, very much depend on the wrap from 13 to 0, and vice versa, rather than going through 14 and 15. This is especially evident in the label search loops, which were highly optimized for speed.
Find all posts by this user
Quote this message in a reply
04-25-2023, 08:16 AM
Post: #4
RE: HP-45 Internal Pointer Operations
Thanks, Tony.

(04-24-2023 09:52 PM)teenix Wrote:  A constant has to be loaded into the C register for part of the calculation. However, at the start of the loading this value, when C = 09999999999006, the P register = 15, then decrements to 14 and so on until P=1 then the code segment is complete. The segment loop uses Load Constant 6.

Indeed. This is exactly where my code 'fell over' if I removed the the check in loadConstant, and prompted my question.

(04-24-2023 09:52 PM)teenix Wrote:  Yes, there are a few redundant instructions, but there might not have been a simple coding way around the P issue. My hat is off to the guys that wrote the original code with the ROM addressing limitations on the Classics. Try adding an instruction anywhere in the ROM code, and you'll see the mess that it can create.

When I wrote my first simulator, a couple of years ago, I created a disassembler in Excel so I could figure out how the byte contents decoded to instructions, and inevitably errors crept in the transfer over to code. That gave me a clear picture of (a) how beautiful the code is and (b) how 'unyielding' it is. The new simulator is being written because I wanted to get better at Python, but also because I wanted a better way to watch the code as it runs, winding its way through ROMs and bytes.

Thanks again,

Sarah
Find all posts by this user
Quote this message in a reply
04-25-2023, 08:23 AM (This post was last modified: 04-25-2023 02:58 PM by Z80Sarah.)
Post: #5
RE: HP-45 Internal Pointer Operations
(04-24-2023 10:58 PM)brouhaha Wrote:  When p is decremented past 0, or incremented past 13, it wraps. It is never in a stable state of 14 or 15. There are some notes in internal HP docs that the pointer may "disappear" for one cycle when that happens...

Thank you so much: I'll change my decP and incP code accordingly and remove the check in loadConstant. May I ask, is this unstable state what the patent is referring to in relation to loadConstant when it says, "When used with the pointer in position 14, the instruction has no effect."? Is it really saying, "The pointer should never be 14, but don't worry about it if it is."? (I did wonder why it didn't mention 15.) [edited for spelling]
Find all posts by this user
Quote this message in a reply
04-25-2023, 04:26 PM (This post was last modified: 04-25-2023 05:23 PM by brouhaha.)
Post: #6
RE: HP-45 Internal Pointer Operations
My apologies, everything I said was WRONG with regard to the Classic series (ARC/CTC), including the HP-45, and you shoul pay attention to what Teenix said instead.

In the Classic series, P can have values of 14 and 15, and doing a load constant under those conditions apparently does nothing, as Teenix said.

The wrapping of P on increment from 13 to 0, and on decrement from 0 to 13, was introduced in the Woodstock ACT processor.

The Classic series ARC/CTC was the first that I simulated, and I haven't dealt with it in so long that I'd forgotten that it behaves differently than the newer processors. I had to look at my source code (Nonpareil src/proc_classic.c).

Sorry for the confusion! My apologies to Teenix for contradicting his entirely correct statement.
Find all posts by this user
Quote this message in a reply
04-25-2023, 04:58 PM
Post: #7
RE: HP-45 Internal Pointer Operations
(04-25-2023 04:26 PM)brouhaha Wrote:  My apologies, everything I said was WRONG with regard to the Classic series (ARC/CTC), including the HP-45, and you shoul pay attention to what Teenix said instead.

No problem at all: thank you for the swift correction. I'll change my code back. No harm done. Plus, I learned new things on the way, which is always a bonus.
Find all posts by this user
Quote this message in a reply
04-25-2023, 09:57 PM (This post was last modified: 04-25-2023 09:58 PM by teenix.)
Post: #8
RE: HP-45 Internal Pointer Operations
(04-25-2023 08:16 AM)Z80Sarah Wrote:  When I wrote my first simulator, a couple of years ago, I created a disassembler in Excel so I could figure out how the byte contents decoded to instructions, and inevitably errors crept in the transfer over to code. That gave me a clear picture of (a) how beautiful the code is and (b) how 'unyielding' it is. The new simulator is being written because I wanted to get better at Python, but also because I wanted a better way to watch the code as it runs, winding its way through ROMs and bytes.

I wonder how many languages these emulators are in now.

You can use my emulator to view code execution if it's of any help. You can also modify the HP microcode and it will reassemble it and run with the changes. I used it myself to write the simulation code for the HP-10.

cheers

Tony
Find all posts by this user
Quote this message in a reply
04-27-2023, 10:37 AM
Post: #9
RE: HP-45 Internal Pointer Operations
(04-25-2023 09:57 PM)teenix Wrote:  I wonder how many languages these emulators are in now.

You can use my emulator to view code execution if it's of any help. You can also modify the HP microcode and it will reassemble it and run with the changes. I used it myself to write the simulation code for the HP-10.

cheers

Tony

Thanks, Tony: I'm really looking forward to using your simulator. Thankfully, most of the work for the simulator part of this code was done previously when I wrote a C version of it. At that time, I got the java simulator for the HP-45 working in a Windows virtual machine, so I could check if my code was doing what it should do. Most of the work on this version has been (re)learning Python (which, for me, was the point of the exercise).

My C version was compiled for a few environments. I think it's probably the only one which runs on a Z80 under CP/M, and also on a TRS-80 Model I (slooooowly).
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 1 Guest(s)