Generate better code for condition expressions.
This commit is contained in:
parent
c71ab5869a
commit
a9db765f98
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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} },
|
||||
|
|
|
|||
|
|
@ -2648,7 +2648,18 @@ bool of_FLAG_GET_VEC4(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
/*
|
||||
* %flag_mov <flag1>, <flag2)
|
||||
* %flag_inv <flag1>
|
||||
*/
|
||||
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 <flag1>, <flag2>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue