Post Reply 
NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt)
04-02-2024, 10:20 AM
Post: #1
NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt)
Hi all,

As have been noted in previous threads, the main reason for failing to fly the goose backwards in all emulators and simulators so far seems to be a shortage in the emulation of BCD arithmetics in the NUT CPU.

If the syntethic FIX 10 instruction is executed, this results in a hexadecimal value being decremented in decimal mode causing the emulators and simulators to differ from the real HP41 causing the goose to be missed!

I have tried to trace and understand the underlying logic (and as Christoph mentioned - this is of course the gate logic in the NUT CPU) when doing BCD arithmetics in decimal mode.

I have added some results taken from a real HP41. All arithmetic is done on the S&X field (12 bits) of register A.
I have added or subtracted 1, 5 and F from all possible values (000-FFF) and traced the result and checked if carry was set or not.

All logs have the same layout:
Code:
A[S&X] (original value)
 |
 v
A01 --> 400 CARRY
     ^   ^   ^
     |   |   +-- resulting in CARRY or not)
     |   +-- result in A[S&X]
     +-- instruction (e.g. A=A-1 [S&X])

The case with adding 1 was easy to understand. First the value is translated to decimal digit by digit (A=10, .. F=15)
Code:
  int d = 0;
  int n = 1;
  while( x ) {
    d += (x & 0xF) * n; // Hex to decimal and add to result
    n *= 10;
    x >>= 4;
  }
  return d;

The result is incremented by 1, and if the result overflows the field, then carry is set.
Some examples:
Code:
000 (000 + 00 + 0 = 000) --> 000 + 1 = 001 
012 (000 + 10 + 2 = 012) --> 011 + 1 = 013
00C (000 + 00 + 12 = 012) --> 012 + 1 = 013 
98E (900 + 80 + 14 = 994) --> 994 + 1 = 995
9A0 (900 + 100 + 0 = 1000) -> 1000 + 1 = 001 CARRY

Subtracting with 1 can not be done with a similar approach, eg:
Code:
00F --> 008
98E --> 987
A01 --> 400 CARRY
A00 --> 999

And adding/subtracting a different number makes it even worse.
E.g. adding 0xF in decimal mode results sometimes in hexadecimal values:
Code:
000 + 00F --> 015 
005 + 00F --> 01A 
01A + 00F --> 02F 
98F + 00F --> 994 
990 + 00F --> 005 CARRY

It is not too hard to come up with some code that will handle these cases, but I have trouble finding a common solution that will handle all cases and all fields.
Maybe someone with knowledge about BCD algorithms and/or gate logic can see some patterns here ... ?

Feel free to suggest some other tests that I could provide the results from.
(Will add some more traces in next post.)

Cheers,
Thomas


Attached File(s)
.txt  a-1.txt (Size: 59.5 KB / Downloads: 12)
.txt  a+1.txt (Size: 60 KB / Downloads: 5)
.txt  a-5.txt (Size: 59.5 KB / Downloads: 3)
.txt  a+5.txt (Size: 60.02 KB / Downloads: 3)
.txt  a-F.txt (Size: 59.5 KB / Downloads: 5)

[35/45/55/65/67/97/80 21/25/29C 31E/32E/33E|C/34C/38E 41C|CV|CX 71B 10C/11C/12C/15C|CE/16C 32S|SII/42S 28C|S 48GX/49G/50G 35S 41X]
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - ThomasF - 04-02-2024 10:20 AM



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