Post by jaybert on May 7, 2014 18:35:24 GMT -8
The DAA/DAS instruction does not execute as expected.
I found this trying to work out why ctmouse does not show sensible characters for the serial port address.
(It seems the DAA and DAS are not exactly the most commonly used instructions
The problem is in the interaction of the DAA/DAS macro with the
(extra) ? DAA_DAS(...) : DAA_DAS(...);
statement.
As the macro contains a comma operator with no parenthesis around it you effectively get:
(extra) ? statementa, statementb : statementa, statementb;
In C the operator precedence between ':' and ',' means that this is equivalent to the code:
((extra) ? (statementa, statementb) : (statementa)), statementb
which is not what I think was intended.
Also, there are some simplification to the macro you can make.
The pseudocode for these instructions is:
But,
((AL & 0xF0) > 90H)
and
(AL > 9FH)
Always give the same result for every value of AL, leading to an obvious optimisation.
I have fixed this as follows:
Redefine the macro to:
And in the code execution
I found this trying to work out why ctmouse does not show sensible characters for the serial port address.
(It seems the DAA and DAS are not exactly the most commonly used instructions
The problem is in the interaction of the DAA/DAS macro with the
(extra) ? DAA_DAS(...) : DAA_DAS(...);
statement.
As the macro contains a comma operator with no parenthesis around it you effectively get:
(extra) ? statementa, statementb : statementa, statementb;
In C the operator precedence between ':' and ',' means that this is equivalent to the code:
((extra) ? (statementa, statementb) : (statementa)), statementb
which is not what I think was intended.
Also, there are some simplification to the macro you can make.
The pseudocode for these instructions is:
DAA
IF (((AL AND 0FH) > 9) or AF == 1) THEN
AL = AL + 6;
CF = CF OR CarryFromLastAddition; (* CF OR carry from AL = AL + 6 *)
AF = 1;
ELSE
AF = 0;
FI;
IF ((AL AND F0H) > 90H) or CF == 1) THEN
AL = AL + 60H;
CF = 1;
ELSE
CF = 0;
FI;
DAS
IF (AL AND 0FH) > 9 OR AF == 1 THEN
AL = AL - 6;
CF = CF OR BorrowFromLastSubtraction; (* CF OR borrow from AL = AL - 6 *)
AF = 1;
ELSE
AF = 0;
FI;
IF ((AL > 9FH) or CF == 1) THEN
AL = AL - 60H;
CF = 1;
ELSE
CF = 0;
FI;
But,
((AL & 0xF0) > 90H)
and
(AL > 9FH)
Always give the same result for every value of AL, leading to an obvious optimisation.
I have fixed this as follows:
Redefine the macro to:
#define DAA_DAS(op1,op2) \
set_AF((((scratch_uchar = regs8[REG_AL]) & 0x0F) > 9) || regs8[FLAG_AF]) && (op_result = (regs8[REG_AL] op1 6), set_CF(regs8[FLAG_CF] || (regs8[REG_AL] op2 scratch_uchar))), \
set_CF((regs8[REG_AL] > 0x9f) || regs8[FLAG_CF]) && (op_result = (regs8[REG_AL] op1 0x60))
And in the code execution
OPCODE 28: // DAA/DAS
i_w = 0;
if (extra) DAA_DAS(-=, >); else DAA_DAS(+=, <)