For real expressions evaluate non-real sub-exprs as bits and convert.
When processing procedural real expressions we need to evaluate non-real sub-expressions as bit based expressions and then convert the result to a real value. This is particularly import for integer division.
This commit is contained in:
parent
1d2577b2fd
commit
e592b52515
|
|
@ -22,9 +22,6 @@
|
||||||
*/
|
*/
|
||||||
# include "vvp_priv.h"
|
# include "vvp_priv.h"
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
#ifdef HAVE_MALLOC_H
|
|
||||||
# include <malloc.h>
|
|
||||||
#endif
|
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
@ -55,9 +52,6 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
int l, r = -1;
|
int l, r = -1;
|
||||||
|
|
||||||
/* If the opcode is a vector only opcode then the sub expression
|
|
||||||
* must not be a real expression, so use vector evaluation and
|
|
||||||
* then convert that result to a real value. */
|
|
||||||
switch (ivl_expr_opcode(expr)) {
|
switch (ivl_expr_opcode(expr)) {
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'N':
|
case 'N':
|
||||||
|
|
@ -70,22 +64,8 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
case 'A':
|
case 'A':
|
||||||
case 'O':
|
case 'O':
|
||||||
case 'X':
|
case 'X':
|
||||||
{
|
/* These should be caught in draw_eval_real(). */
|
||||||
struct vector_info vi;
|
assert(0);
|
||||||
int res;
|
|
||||||
const char*sign_flag;
|
|
||||||
|
|
||||||
vi = draw_eval_expr(expr, STUFF_OK_XZ);
|
|
||||||
res = allocate_word();
|
|
||||||
sign_flag = ivl_expr_signed(expr)? "/s" : "";
|
|
||||||
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
|
|
||||||
sign_flag, res, vi.base, vi.wid);
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
|
|
||||||
|
|
||||||
clr_vector(vi);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l = draw_eval_real(ivl_expr_oper1(expr));
|
l = draw_eval_real(ivl_expr_oper1(expr));
|
||||||
|
|
@ -121,15 +101,19 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
int lab_r = local_count++;
|
int lab_r = local_count++;
|
||||||
/* If r is NaN, the go out and accept l as result. */
|
/* If r is NaN, the go out and accept l as result. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||||
|
lab_out);
|
||||||
/* If l is NaN, the go out and accept r as result. */
|
/* If l is NaN, the go out and accept r as result. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||||
|
lab_r);
|
||||||
/* If l <= r then go out. */
|
/* If l <= r then go out. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l);
|
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
|
||||||
|
lab_out);
|
||||||
/* At this point we know we want r as the result. */
|
/* At this point we know we want r as the result. */
|
||||||
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r);
|
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count,
|
||||||
|
lab_r, l, r);
|
||||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -139,15 +123,19 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
int lab_r = local_count++;
|
int lab_r = local_count++;
|
||||||
/* If r is NaN, the go out and accept l as result. */
|
/* If r is NaN, the go out and accept l as result. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||||
|
lab_out);
|
||||||
/* If l is NaN, the go out and accept r as result. */
|
/* If l is NaN, the go out and accept r as result. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||||
|
lab_r);
|
||||||
/* if l >= r then go out. */
|
/* if l >= r then go out. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r);
|
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
|
||||||
|
lab_out);
|
||||||
|
|
||||||
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r);
|
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count,
|
||||||
|
lab_r, l, r);
|
||||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -508,8 +496,10 @@ static int draw_unary_real(ivl_expr_t expr)
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub);
|
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n",
|
||||||
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub);
|
ivl_expr_opcode(expr), sub);
|
||||||
|
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n",
|
||||||
|
ivl_expr_opcode(expr), sub);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -517,6 +507,27 @@ int draw_eval_real(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
|
/* If this expression/sub-expression is not real then we need
|
||||||
|
* to evaluate it as a bit value and then convert the bit based
|
||||||
|
* result to a real value. This is required to get integer
|
||||||
|
* division to work correctly. */
|
||||||
|
if (ivl_expr_value(expr) != IVL_VT_REAL) {
|
||||||
|
struct vector_info vi;
|
||||||
|
int res;
|
||||||
|
const char*sign_flag;
|
||||||
|
|
||||||
|
vi = draw_eval_expr(expr, STUFF_OK_XZ);
|
||||||
|
res = allocate_word();
|
||||||
|
sign_flag = ivl_expr_signed(expr)? "/s" : "";
|
||||||
|
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", sign_flag, res,
|
||||||
|
vi.base, vi.wid);
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
|
||||||
|
|
||||||
|
clr_vector(vi);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ivl_expr_type(expr)) {
|
switch (ivl_expr_type(expr)) {
|
||||||
|
|
||||||
case IVL_EX_BINARY:
|
case IVL_EX_BINARY:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue