4 ms·
The Z80 does have a DAA (decimal adjust arithmetic) instruction to facilitate BCD arithmetic. I don't think I ever used it in my Z80 years and I'm not familiar
by billforsternz 4mo ago
The Z80 does have a DAA (decimal adjust arithmetic) instruction to facilitate BCD arithmetic. I don't think I ever used it in my Z80 years and I'm not familiar with the details. Sadly I have much less experience with the 6502, I didn't even know it had a BCD mode.
- adrian_b 4mo agoIntel 8080 already had DAA, so it could add BCD numbers. Because there was no BCD subtraction, that had to be done by an indirect method, e.g. by doing a nines' complement before a BCD addition. Zilog Z80 improved this, so that on it DAA could also be used after a subtraction, when it would correctly adjust the result for implementing BCD subtraction. This was one of the Z80 improvements that were considered important at the time of its launch. While I have never considered worthwhile to do BCD arithmetic instead of converting the decimal numbers to binary numbers, the DAA instruction on all Intel 8080 successors, including on IBM PC compatible computers, was very convenient for converting binary numbers to their ASCII character string hexadecimal representation, for printing or display purposes (because the decimal adjusting happens to add the correct ASCII offset between '0' ... '9' and 'A' ... 'F', so the conversion to ASCII can be done branchless).
- rep_lodsb 4mo agoSlight correction, the correct offset is 7, and DAA only adds 6. But the trick is also adding the carry bit. This works on the 6502 in decimal mode too, e.g. https://news.ycombinator.com/item?id=6342286 https://news.ycombinator.com/item?id=6342286 On the Z80 and 8086, the code can be made one byte shorter by taking advantage of adjust-after-subtraction, which the 8080 didn't have (and on 6502 worked differently): CP 10 / CMP AL,10 ;set carry if valid decimal digit SBC A,69H / SBB AL,69H ;0..9 => 96h..9Fh (auxC=1), 10..15 => A1h..A6h (auxC=0) DAA / DAS ;subtract 66h if auxC set, 60h if clear
- gdevic 4mo agoThat. I blatantly "stole" those from Z80 since they are elegant and effective. I have BF (flag) that gets set in ALU when the result is > 9, then DAA/DAS that add 6 or 10 (the latter wraps around as -6 since registers are 4-bit wide). 12'b0000_0000_001?: begin : instr_daas // DAA, DAS if (flags[BF_BIT]) rx[0] <= rx[0] + (op_is_daa ? 4'd6 : 4'd10); flags[CF_BIT] <= flags[BF_BIT]; state <= FETCH; end : instr_daas