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:
@@ -2805,6 +2805,10 @@ def A_JA: i32 = 55;
|
||||
def A_JAE: i32 = 56;
|
||||
def A_JZ: i32 = 57;
|
||||
def A_JNZ: i32 = 58;
|
||||
// 67 (next free above A_CQO=66): appended so the existing A_MOV*/
|
||||
// A_SYSCALL/A_DATAW/A_DATAR/A_CQO numbers stay put. Jump on
|
||||
// parity (PF=1): UCOMISD unordered (#97).
|
||||
def A_JP: i32 = 67;
|
||||
|
||||
def A_SYSCALL: i32 = 59;
|
||||
|
||||
@@ -3060,6 +3064,7 @@ fn opcodelookup(p: *u8, n: u64) i32 = {
|
||||
if (streqlit(p, n, "JAE")) { return A_JAE; };
|
||||
if (streqlit(p, n, "JZ")) { return A_JZ; };
|
||||
if (streqlit(p, n, "JNZ")) { return A_JNZ; };
|
||||
if (streqlit(p, n, "JP")) { return A_JP; };
|
||||
if (streqlit(p, n, "SYSCALL")) { return A_SYSCALL; };
|
||||
if (streqlit(p, n, "TEXT")) { return A_TEXT; };
|
||||
if (streqlit(p, n, "DATA")) { return A_DATA; };
|
||||
@@ -4370,7 +4375,8 @@ export fn encode(a: *asm_) i32 = {
|
||||
else { if (op == A_JBE) { cc = 134u8; }
|
||||
else { if (op == A_JA) { cc = 135u8; }
|
||||
else { if (op == A_JAE) { cc = 131u8; }
|
||||
else { isjcc = false; };};};};};};};};};};};};
|
||||
else { if (op == A_JP) { cc = 138u8; } // 0x8A, UCOMISD unordered (#97)
|
||||
else { isjcc = false; };};};};};};};};};};};};};
|
||||
if (isjcc) {
|
||||
emitbyte(a, 15u8);
|
||||
emitbyte(a, cc);
|
||||
|
||||
Reference in New Issue
Block a user