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:
2026-05-25 12:40:23 +09:00
parent 2f2a73bd41
commit fa136d0b88
12 changed files with 214 additions and 44 deletions

View File

@@ -88,6 +88,7 @@ anames(int op)
case A_JAE: return "JAE";
case A_JZ: return "JZ";
case A_JNZ: return "JNZ";
case A_JP: return "JP";
case A_SYSCALL: return "SYSCALL";
}
return "??";
@@ -184,6 +185,7 @@ txt_emit(FILE *f, Prog *head)
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_JP:
fprintf(f, "\t%s\t", anames(p->as));
prAdr(f, p->to);
fputc('\n', f);