cgen: f64 compare consults parity flag for NaN, 4 relops (both stages, #97)
UCOMISD/UCOMISS set PF=ZF=CF=1 on unordered (a NaN operand). The old arms keyed on ZF/CF only, so 4 of the 6 relops mishandled NaN: `nan != nan` was false (JNE keys on ZF=0), `nan == nan` was true, and `<`/`<=` (JB/JBE) fired on the unordered CF=1. IEEE-754: any relop with a NaN operand is unordered — `!=` true, the rest false. `!=` now jumps to true on JNE OR JP; `==`/`<`/`<=` jump to false on JP before the ordered Jcc. `>`/`>=` (JA/JAE) are LEFT UNCHANGED: they require CF=0, which an unordered UCOMISD never produces, so they already reject NaN correctly. Adding a PF guard there would only churn their .s (an extra JP on every >/>= float compare) for no correctness gain, so their arm stays byte-identical to the pre-#97 single template. Bundles the cgen fix with JP-mnemonic support in both assemblers (w6c enum/printer + w6a/w6a_ww parse+encode, 0F 8A). They can't split: the cgen emits JP, which has no encoding without the assembler change, so a cgen-only commit would not build. JP is the only PF-sensitive jump on amd64 — there is no alternative instruction.
This commit is contained in:
@@ -811,7 +811,8 @@ a_encode(Asm *a)
|
||||
break;
|
||||
case A_JE: case A_JNE: case A_JL: case A_JLE:
|
||||
case A_JG: case A_JGE: case A_JB: case A_JBE:
|
||||
case A_JA: case A_JAE: case A_JZ: case A_JNZ: {
|
||||
case A_JA: case A_JAE: case A_JZ: case A_JNZ:
|
||||
case A_JP: {
|
||||
u8 cc = 0;
|
||||
switch (p->as) {
|
||||
case A_JE: case A_JZ: cc = 0x84; break;
|
||||
@@ -824,6 +825,7 @@ a_encode(Asm *a)
|
||||
case A_JBE: cc = 0x86; break;
|
||||
case A_JA: cc = 0x87; break;
|
||||
case A_JAE: cc = 0x83; break;
|
||||
case A_JP: cc = 0x8A; break;
|
||||
default: break;
|
||||
}
|
||||
a_emit_byte(a, 0x0F);
|
||||
|
||||
Reference in New Issue
Block a user