w6c: float-aware unary minus (fix -1.0 emitting +1.0 bit pattern)

This commit is contained in:
2026-05-11 17:52:29 +09:00
parent e50849d5ec
commit 579cc39f9b
3 changed files with 40 additions and 22 deletions

View File

@@ -622,7 +622,29 @@ cgexpr(Cg *c, Node *n, Local *locals)
case N_UN:
cgexpr(c, n->lhs, locals);
switch (n->op) {
case TK_MINUS: ins1(c, A_NEGQ, areg(D_AX)); break;
case TK_MINUS:
if (node_isfloat(n->lhs)) {
/* Float negate: X0 = 0 - X0. cgexpr left the
* value in X0; AX-only NEGQ wouldn't touch it. */
int isf32 = node_isf32(n->lhs);
int mov = isf32 ? A_MOVSS : A_MOVSD;
int sub = isf32 ? A_SUBSS : A_SUBSD;
/* save orig X0 → stack */
ins2(c, A_SUBQ, aimm(8), areg(D_SP));
ins2(c, mov, areg(D_X0), amem(D_SP, 0));
/* load 0.0 into X0 (zero bit pattern == 0.0) */
ins2(c, A_MOVQ, aimm(0), areg(D_AX));
ins1(c, A_PUSHQ, areg(D_AX));
ins2(c, mov, amem(D_SP, 0), areg(D_X0));
ins2(c, A_ADDQ, aimm(8), areg(D_SP));
/* X1 = orig; X0 = X0 - X1 = -orig */
ins2(c, mov, amem(D_SP, 0), areg(D_X1));
ins2(c, A_ADDQ, aimm(8), areg(D_SP));
ins2(c, sub, areg(D_X1), areg(D_X0));
} else {
ins1(c, A_NEGQ, areg(D_AX));
}
break;
case TK_TILDE: ins1(c, A_NOTQ, areg(D_AX)); break;
case TK_NOT: {
ins2(c, A_CMPQ, aimm(0), areg(D_AX));