diff --git a/tgt-vvp/eval_condit.c b/tgt-vvp/eval_condit.c index f3f3cc15b..508beb292 100644 --- a/tgt-vvp/eval_condit.c +++ b/tgt-vvp/eval_condit.c @@ -71,19 +71,39 @@ static int draw_condition_binary_compare(ivl_expr_t expr) if (ivl_expr_width(re) > use_wid) use_wid = ivl_expr_width(re); + /* If the le is constant, then swap the operands so that we + can possibly take advantage of the immediate version of the + %cmp instruction. */ + if (ivl_expr_width(le)==use_wid && test_immediate_vec4_ok(le)) { + ivl_expr_t tmp = le; + re = le; + le = tmp; + } + draw_eval_vec4(le); resize_vec4_wid(le, use_wid); - draw_eval_vec4(re); - resize_vec4_wid(re, use_wid); + if (ivl_expr_width(re)==use_wid && test_immediate_vec4_ok(re)) { + /* Special case: If the right operand can be handled as + an immediate operand, then use that instead. */ + draw_immediate_vec4(re, "%cmpi/u"); + } else { + draw_eval_vec4(re); + resize_vec4_wid(re, use_wid); + fprintf(vvp_out, " %%cmp/u;\n"); + } switch (ivl_expr_opcode(expr)) { + case 'n': /* != */ + fprintf(vvp_out, " %%flag_inv 4;\n"); + ; /* fall through.. */ case 'e': /* == */ - fprintf(vvp_out, " %%cmp/u;\n"); return 4; break; + case 'N': /* !== */ + fprintf(vvp_out, " %%flag_inv 6;\n"); + ; /* fall through.. */ case 'E': /* === */ - fprintf(vvp_out, " %%cmp/u;\n"); return 6; default: assert(0); @@ -174,17 +194,41 @@ static int draw_condition_binary_le(ivl_expr_t expr) } } +static int draw_condition_binary_lor(ivl_expr_t expr) +{ + ivl_expr_t le = ivl_expr_oper1(expr); + ivl_expr_t re = ivl_expr_oper2(expr); + + int lx = draw_eval_condition(le); + + if (lx < 8) { + int tmp = allocate_flag(); + fprintf(vvp_out, " %%flag_mov %d, %d;\n", tmp, lx); + lx = tmp; + } + + int rx = draw_eval_condition(re); + + fprintf(vvp_out, " %%flag_or %d, %d;\n", rx, lx); + clr_flag(lx); + return rx; +} + static int draw_condition_binary(ivl_expr_t expr) { switch (ivl_expr_opcode(expr)) { case 'e': /* == */ case 'E': /* === */ + case 'n': /* != */ + case 'N': /* !== */ return draw_condition_binary_compare(expr); case '<': case '>': case 'L': /* <= */ case 'G': /* >= */ return draw_condition_binary_le(expr); + case 'o': /* Logical or (||) */ + return draw_condition_binary_lor(expr); default: return draw_condition_fallback(expr); } diff --git a/vvp/codes.h b/vvp/codes.h index 9489b92c7..74733f849 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -103,6 +103,7 @@ extern bool of_EVCTLI(vthread_t thr, vvp_code_t code); extern bool of_EVCTLS(vthread_t thr, vvp_code_t code); extern bool of_FILE_LINE(vthread_t thr, vvp_code_t code); extern bool of_FLAG_GET_VEC4(vthread_t thr, vvp_code_t code); +extern bool of_FLAG_INV(vthread_t thr, vvp_code_t code); extern bool of_FLAG_MOV(vthread_t thr, vvp_code_t code); extern bool of_FLAG_OR(vthread_t thr, vvp_code_t code); extern bool of_FLAG_SET_IMM(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index a521b61ab..c1c58df44 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -152,6 +152,7 @@ static const struct opcode_table_s opcode_table[] = { { "%evctl/s",of_EVCTLS, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} }, { "%event", of_EVENT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%flag_inv", of_FLAG_INV, 1, {OA_BIT1, OA_NONE, OA_NONE} }, { "%flag_mov", of_FLAG_MOV, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%flag_or", of_FLAG_OR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%flag_set/imm", of_FLAG_SET_IMM, 2, {OA_NUMBER, OA_BIT1, OA_NONE} }, diff --git a/vvp/vthread.cc b/vvp/vthread.cc index ceab39474..ac5bf1adf 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2648,7 +2648,18 @@ bool of_FLAG_GET_VEC4(vthread_t thr, vvp_code_t cp) } /* - * %flag_mov , + */ +bool of_FLAG_INV(vthread_t thr, vvp_code_t cp) +{ + int flag1 = cp->bit_idx[0]; + + thr->flags[flag1] = ~ thr->flags[flag1]; + return true; +} + +/* + * %flag_mov , */ bool of_FLAG_MOV(vthread_t thr, vvp_code_t cp) { @@ -2971,7 +2982,7 @@ bool of_IX_GETV_S(vthread_t thr, vvp_code_t cp) static uint64_t vec4_to_index(vthread_t thr, bool signed_flag) { - vvp_vector4_t val = thr->pop_vec4(); + const vvp_vector4_t&val = thr->peek_vec4(); uint64_t v = 0; bool unknown_flag = false; @@ -2995,6 +3006,7 @@ static uint64_t vec4_to_index(vthread_t thr, bool signed_flag) } thr->flags[4] = unknown_flag? BIT4_1 : BIT4_0; + thr->pop_vec4(1); return v; }