On 2016-Jan-28, at 5:30 PM, Kyle Owen wrote:
I'm currently writing a bit of code for the 4004
at the moment, and playing
with it in the online Javascript emulator found here:
http://e4004.szyc.org/emu/
According to
http://e4004.szyc.org/iset.html (which I believe is copied
straight from the MCS-4 Users Manual), the DAA instruction should increment
the accumulator by 6 if carry is set or if the accumulator is greater than
9. Carry should be set following the instruction if the resulting addition
generated a carry; otherwise it's unaffected.
Let's say the accumulator is currently 9, carry is not set. I add another
9. Accumulator is now 2 with a carry. Running DAA should turn this into 8
with carry set, indicating that 9+9=(1)8. Am I thinking through this
correctly?
I ask, because according to the simulator's source code, DAA won't do that,
if I'm following it correctly:
function opDAA() { //DAA Decimal Adjust Accumulator
if(A_reg > 9) A_reg += 6;
C_flag=0; if (A_reg & 0xf0) {A_reg&=0xf; C_flag=1;}
incPC();
}
It says that it'll only add 6 if the accumulator is greater than 9, not if
a carry is already set. It will then reset carry and set it if and only if
there was a carry.
Have I found a bug in the simulator? Am I misreading the MCS-4 Users
Manual?
In any event, this is my proposed fix to better match what the instruction
description says:
function opDAA() { //DAA Decimal Adjust Accumulator
if((A_reg > 9) | (C_flag)) A_reg += 6;
if (A_reg & 0xf0) {A_reg&=0xf; C_flag=1;}
incPC();
}
Seems to work as I would expect it to.
The original looks correct to me.
I think you or the documentation are confusing the hardware carry flag with the carry out
of the 4th bit (nibble carry).
A binary addition of two BCD digits will require correction either if the result is in the
range 0xA to 0xF or if there was a carry out of the 4th bit.
The hardware carry flag is the carry out of the 8th bit and is irrelevant immediately
after the addition.
Note whether or not correction is needed is synonymous with the state of *decimal* carry
from the addition.
To rephrase the original code:
- If the 8-bit result of a preceding binary addition of two BCD digits located in the
lower nibble of the source operands is > 0x9 then add 0x6 to the result.
This corrects results which were both in the range 0xA to 0xF and 0x10 to 0x12 (the max
result of adding two BCD digits is 9+9=0x12).
The lower nibble of the acc now correctly reflects the desired decimal digit value.
- We now need to adjust the hardware carry flag to reflect whether there was a decimal
carry (so it is valid for input to a subsequent BCD digit addition).
Because of the conditional addition of the 'correcting 6', all results which
required correction are now > 0xF in the acc (have overflowed into the higher nibble)
(0xA+6=0x10),
so we set the hardware carry flag accordingly, as well as clear out the extraneous bits
in the higher nibble of the acc so it contains only our desired decimal digit.
I've been through this binary-BCD addition correction stuff numerous times in reverse
engineering discrete and SSI calculators -
it's far more fun when it's being done with serial bit-streams in hardware.