Hacker News new | ask | show | jobs
by rep_lodsb 37 days ago
Slight 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

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
1 comments

That. 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