vvp: Add opcode for unary real minus

Currently the vvp target emits unary real minus as `0.0 - value`.
This is not the same operation for all real values. It loses the
negative zero result for `-(+0.0)` and does not reliably flip the sign
bit for NaN values whose bits are visible through `$realtobits`.

Add `%neg/wr` and use it for unary real minus. This performs a direct
negation of the real stack value, so zero, NaN and infinity all use the
same operation as unary minus instead of a binary subtraction from zero.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2026-06-19 12:33:31 -07:00
parent e9bc3488fb
commit 5311c0cd38
5 changed files with 16 additions and 2 deletions

View File

@ -812,6 +812,10 @@ result is pushed back on the vec4 stack.
This opcode multiplies two real words together.
* %neg/wr
This opcode negates the real value on top of the real stack.
* %nand
Perform the bitwise NAND of two vec4 vectors, and push the result. Each

View File

@ -453,9 +453,8 @@ static void draw_unary_real(ivl_expr_t expr)
}
if (ivl_expr_opcode(expr) == '-') {
fprintf(vvp_out, " %%pushi/real 0, 0; load 0.0\n");
draw_eval_real(sube);
fprintf(vvp_out, " %%sub/wr;\n");
fprintf(vvp_out, " %%neg/wr;\n");
return;
}

View File

@ -164,6 +164,7 @@ extern bool of_MOD_WR(vthread_t thr, vvp_code_t code);
extern bool of_MUL(vthread_t thr, vvp_code_t code);
extern bool of_MULI(vthread_t thr, vvp_code_t code);
extern bool of_MUL_WR(vthread_t thr, vvp_code_t code);
extern bool of_NEG_WR(vthread_t thr, vvp_code_t code);
extern bool of_NAND(vthread_t thr, vvp_code_t code);
extern bool of_NANDR(vthread_t thr, vvp_code_t code);
extern bool of_NEW_COBJ(vthread_t thr, vvp_code_t code);

View File

@ -219,6 +219,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand", of_NAND, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%nand/r", of_NANDR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%neg/wr", of_NEG_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%new/cobj", of_NEW_COBJ, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
{ "%new/darray",of_NEW_DARRAY,2, {OA_BIT1, OA_STRING,OA_NONE} },
{ "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} },

View File

@ -4288,6 +4288,15 @@ bool of_MOD_WR(vthread_t thr, vvp_code_t)
return true;
}
/*
* %neg/wr
*/
bool of_NEG_WR(vthread_t thr, vvp_code_t)
{
thr->poke_real(0, -thr->peek_real(0));
return true;
}
/*
* %pad/s <wid>
*/