NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html) +--- Forum: General Forum (/forum-4.html) +--- Thread: NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) (/thread-21546.html) |
NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - ThomasF - 04-02-2024 10:20 AM 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) 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; 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 Subtracting with 1 can not be done with a similar approach, eg: Code: 00F --> 008 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 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 RE: NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - ThomasF - 04-02-2024 10:22 AM Added some more traces ... Cheers, Thomas RE: NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - Christoph Giesselink - 04-03-2024 09:54 AM TNX Thomas, verified the V41-Adder and fixed the Subtraction to base 10 with hexadecimal numbers. With your delivered tables it would be a shame to verify only single points, so I created my own tables to compare them with your references. Christoph RE: NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - ThomasF - 04-03-2024 11:34 AM (04-03-2024 09:54 AM)Christoph Giesselink Wrote: With your delivered tables it would be a shame to verify only single points, so I created my own tables to compare them with your references. Hi Christoph, Please let me know if you need to test some other corner cases! I tried to implement a BCD-adder, and addition worked fine (gives 100% same result as my traces), but I can't manage to crack the subtraction ... In general, a BCD subtraction is done by complementing (either by 9 or 10) one value and feed it to an adder (A - B = A + ~B). But, it doesn't work, there seems to be some special handling when e.g. hex:A is part of the value, so it is not as straight forward as addition. Cheers, Thomas RE: NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - Christoph Giesselink - 04-03-2024 05:26 PM (04-03-2024 11:34 AM)ThomasF Wrote: I tried to implement a BCD-adder, and addition worked fine (gives 100% same result as my traces), but I can't manage to crack the subtraction ... I haven't tried it to make it by boolean operations. It's just a fix of the existing code using BASECY as BASE overflow indicator (opcode examples incomplete). Code: ... Code: /****************************/ As old Z80 coder I remembered the Decimal Adjust (DAA) instruction in the Z80 CPU. So I had I look into a Zilog User Manual: Decimal Adjust Accumulator Flag The Decimal Adjust Accumulator (DAA) instruction uses this flag to distinguish between ADD and SUBTRACT instructions. For all ADD instructions, N sets to 0. For all SUBTRACT instructions, N sets to 1. Half Carry Flag The Half Carry Flag (H) is set (1) or cleared (0) depending on the Carry and Borrow status between bits 3 and 4 of an 8-bit arithmetic operation. This flag is used by the Decimal Adjust Accumulator (DAA) instruction to correct the result of a packed BCD add or subtract operation. The H Flag is set (1) or cleared (0) as shown in Table 23. So for coding DAA it needs 3 flags, N-Flag, H-Flag und C-Flag, quite complex. No further investigation. RE: NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - ThomasF - 04-04-2024 07:31 AM Thanks Christoph! It was arithmetics like these that fooled me (subtraction with F): Code: A10 --> 40B CARRY Anyhow, using the algorithm in Subtractor that you provided works correct, so that could be used to implement BCD subtraction. Using the following code, I could verify with all examples in previous traces! Code: byte Subtractor(byte nib1, byte nib2) Cheers, Thomas RE: NUT CPU BCD arithmetics in SETDEC mode (aka Goose hunt) - Christoph Giesselink - 04-24-2024 05:37 PM (04-04-2024 07:31 AM)ThomasF Wrote: Using the following code, I could verify with all examples in previous traces! On my request Thomas made an additional test with the ?A<C and ?A<B opcodes. Like on other CPU's the compare function base on a subtraction without saving the result. So ?A<C base on the subtraction of A-C and has the same side effects on the Carry Flag like A=A-C. So the less function for the NUT CPU could be implemented as: Code: void bcd_less(char *p1, char *p2, int n) The complete source code of V41 R9L with a reference implementation is now available. Christoph |