Wrap up vecc4 support for left/right shift expressions.
This commit is contained in:
parent
6a93b6a7e4
commit
b0a9430e98
|
|
@ -1294,152 +1294,6 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t expr,
|
||||||
return lv;
|
return lv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Draw code to evaluate the << expression. Use the %shiftl/i0
|
|
||||||
* or %shiftr/i0 instruction to do the real work of shifting. This
|
|
||||||
* means that I can handle both left and right shifts in this
|
|
||||||
* function, with the only difference the opcode I generate at the
|
|
||||||
* end.
|
|
||||||
*/
|
|
||||||
static struct vector_info draw_binary_expr_lrs(ivl_expr_t expr, unsigned wid)
|
|
||||||
{
|
|
||||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
|
||||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
|
||||||
const char*opcode = "?";
|
|
||||||
|
|
||||||
struct vector_info lv;
|
|
||||||
|
|
||||||
/* Evaluate the expression that is to be shifted. */
|
|
||||||
switch (ivl_expr_opcode(expr)) {
|
|
||||||
|
|
||||||
case 'l': /* << (left shift) */
|
|
||||||
lv = draw_eval_expr_wid(le, wid, 0);
|
|
||||||
|
|
||||||
/* Shifting 0 gets 0, if we can be sure the shift value
|
|
||||||
contains no 'x' or 'z' bits. */
|
|
||||||
if ((lv.base == 0) && (ivl_expr_value(re) == IVL_VT_BOOL))
|
|
||||||
return lv;
|
|
||||||
|
|
||||||
if (lv.base < 4) {
|
|
||||||
struct vector_info tmp;
|
|
||||||
tmp.base = allocate_vector(lv.wid);
|
|
||||||
tmp.wid = lv.wid;
|
|
||||||
if (tmp.base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of left shift (<<).\n",
|
|
||||||
ivl_expr_file(expr), ivl_expr_lineno(expr),
|
|
||||||
wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
|
||||||
tmp.base, lv.base, lv.wid);
|
|
||||||
lv = tmp;
|
|
||||||
}
|
|
||||||
opcode = "%shiftl";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r': /* >> (unsigned right shift) */
|
|
||||||
|
|
||||||
/* with the right shift, there may be high bits that are
|
|
||||||
shifted into the desired width of the expression, so
|
|
||||||
we let the expression size itself, if it is bigger
|
|
||||||
then what is requested of us. */
|
|
||||||
if (wid > ivl_expr_width(le)) {
|
|
||||||
lv = draw_eval_expr_wid(le, wid, 0);
|
|
||||||
} else {
|
|
||||||
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shifting 0 gets 0, if we can be sure the shift value
|
|
||||||
contains no 'x' or 'z' bits. */
|
|
||||||
if ((lv.base == 0) && (ivl_expr_value(re) == IVL_VT_BOOL))
|
|
||||||
return lv;
|
|
||||||
|
|
||||||
if (lv.base < 4) {
|
|
||||||
struct vector_info tmp;
|
|
||||||
tmp.base = allocate_vector(lv.wid);
|
|
||||||
tmp.wid = lv.wid;
|
|
||||||
if (tmp.base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of right shift (>>).\n",
|
|
||||||
ivl_expr_file(expr), ivl_expr_lineno(expr),
|
|
||||||
lv.wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
|
||||||
tmp.base, lv.base, lv.wid);
|
|
||||||
lv = tmp;
|
|
||||||
}
|
|
||||||
opcode = "%shiftr";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'R': /* >>> (signed right shift) */
|
|
||||||
|
|
||||||
/* with the right shift, there may be high bits that are
|
|
||||||
shifted into the desired width of the expression, so
|
|
||||||
we let the expression size itself, if it is bigger
|
|
||||||
then what is requested of us. */
|
|
||||||
if (wid > ivl_expr_width(le)) {
|
|
||||||
lv = draw_eval_expr_wid(le, wid, 0);
|
|
||||||
} else {
|
|
||||||
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shifting 0 gets 0, if we can be sure the shift value
|
|
||||||
contains no 'x' or 'z' bits. */
|
|
||||||
if ((lv.base == 0) && (ivl_expr_value(re) == IVL_VT_BOOL))
|
|
||||||
return lv;
|
|
||||||
|
|
||||||
/* Similarly, sign extending any constant bit begets itself,
|
|
||||||
if this expression is signed. */
|
|
||||||
if ((lv.base < 4) && ivl_expr_signed(expr)
|
|
||||||
&& (ivl_expr_value(re) == IVL_VT_BOOL))
|
|
||||||
return lv;
|
|
||||||
|
|
||||||
if (lv.base < 4) {
|
|
||||||
struct vector_info tmp;
|
|
||||||
tmp.base = allocate_vector(lv.wid);
|
|
||||||
tmp.wid = lv.wid;
|
|
||||||
if (tmp.base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of right shift (>>>).\n",
|
|
||||||
ivl_expr_file(expr), ivl_expr_lineno(expr),
|
|
||||||
lv.wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
|
||||||
tmp.base, lv.base, lv.wid);
|
|
||||||
lv = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ivl_expr_signed(expr))
|
|
||||||
opcode = "%shiftr/s";
|
|
||||||
else
|
|
||||||
opcode = "%shiftr";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Figure out the shift amount and load that into the index
|
|
||||||
register. The value may be a constant, or may need to be
|
|
||||||
evaluated at run time. */
|
|
||||||
eval_logic_into_integer(re,0);
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %s/i0 %u, %u;\n", opcode, lv.base, lv.wid);
|
|
||||||
|
|
||||||
if (lv.base >= 8)
|
|
||||||
save_expression_lookaside(lv.base, expr, lv.wid);
|
|
||||||
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vector_info draw_load_add_immediate(ivl_expr_t le,
|
static struct vector_info draw_load_add_immediate(ivl_expr_t le,
|
||||||
ivl_expr_t re,
|
ivl_expr_t re,
|
||||||
|
|
@ -1781,12 +1635,6 @@ static struct vector_info draw_binary_expr(ivl_expr_t expr,
|
||||||
rv = draw_binary_expr_arith(expr, wid);
|
rv = draw_binary_expr_arith(expr, wid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l': /* << */
|
|
||||||
case 'r': /* >> */
|
|
||||||
case 'R': /* >>> */
|
|
||||||
rv = draw_binary_expr_lrs(expr, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'o': /* || (logical or) */
|
case 'o': /* || (logical or) */
|
||||||
rv = draw_binary_expr_lor(expr, wid, stuff_ok_flag);
|
rv = draw_binary_expr_lor(expr, wid, stuff_ok_flag);
|
||||||
stuff_ok_used_flag = 1;
|
stuff_ok_used_flag = 1;
|
||||||
|
|
@ -1802,7 +1650,7 @@ static struct vector_info draw_binary_expr(ivl_expr_t expr,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "vvp.tgt error: unsupported binary (%c)\n",
|
fprintf(stderr, "vvp.tgt error: draw_binary_expr: unsupported binary (%c)\n",
|
||||||
ivl_expr_opcode(expr));
|
ivl_expr_opcode(expr));
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,10 @@ static void draw_binary_vec4_lrs(ivl_expr_t expr, int stuff_ok_flag)
|
||||||
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
||||||
break;
|
break;
|
||||||
case 'R': /* >>> */
|
case 'R': /* >>> */
|
||||||
fprintf(vvp_out, " %%shiftrs %u;\n", use_index_reg);
|
if (ivl_expr_signed(le))
|
||||||
|
fprintf(vvp_out, " %%shiftr/s %u;\n", use_index_reg);
|
||||||
|
else
|
||||||
|
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
|
||||||
|
|
@ -1168,29 +1168,6 @@ The index may be signed, and if less than 0, the beginning bits are
|
||||||
not assigned. Also, if the bits go beyond the end of the signal, those
|
not assigned. Also, if the bits go beyond the end of the signal, those
|
||||||
bits are not written anywhere.
|
bits are not written anywhere.
|
||||||
|
|
||||||
|
|
||||||
* %shiftl/i0 <bit>, <wid> (XXXX Old implementation)
|
|
||||||
|
|
||||||
This instruction shifts the vector left (towards more significant
|
|
||||||
bits) by the amount in index register 0. The <bit> is the address of
|
|
||||||
the LSB of the vector, and <wid> the width of the vector. The shift is
|
|
||||||
done in place. Zero values are shifted in.
|
|
||||||
|
|
||||||
For a negative shift the value is padded with 'bx.
|
|
||||||
|
|
||||||
* %shiftr/i0 <bit>, <wid> (XXXX Old implementation)
|
|
||||||
* %shiftr/s/i0 <bit>, <wid> (XXXX Old implementation)
|
|
||||||
|
|
||||||
This instruction shifts the vector right (towards the less significant
|
|
||||||
bits) by the amount in the index register 0. The <bit> is the address
|
|
||||||
of the LSB of the vector, and <wid> is the width of the vector. The
|
|
||||||
shift is done in place.
|
|
||||||
|
|
||||||
%shiftr/i0 is an unsigned down shift, so zeros are shifted into the
|
|
||||||
top bits. %shiftr/s/i0 is a signed shift, so the value is sign-extended.
|
|
||||||
|
|
||||||
For a negative shift %shiftr/i0 will pad the value with 'bx.
|
|
||||||
|
|
||||||
* %shiftl <idx>
|
* %shiftl <idx>
|
||||||
* %shiftr <idx>
|
* %shiftr <idx>
|
||||||
* %shiftr/s <idx>
|
* %shiftr/s <idx>
|
||||||
|
|
@ -1199,6 +1176,12 @@ These instructions shift the top value in the vec4 stack left (towards
|
||||||
MSB) or right, possibly signed. The <idx> is the address of the index
|
MSB) or right, possibly signed. The <idx> is the address of the index
|
||||||
register that contains the amount to shift.
|
register that contains the amount to shift.
|
||||||
|
|
||||||
|
The instruction also checks flag bit 4. If it is true, the result is
|
||||||
|
replaced with X instead of a shifted result. This is intended to
|
||||||
|
detect that the index contents were not valid.
|
||||||
|
|
||||||
|
For a negative shift, %shiftr will pad the vlaue with 'bx.
|
||||||
|
|
||||||
* %split/vec4 <wid>
|
* %split/vec4 <wid>
|
||||||
|
|
||||||
Pull the top vec4 vector from the stack and split it into two
|
Pull the top vec4 vector from the stack and split it into two
|
||||||
|
|
|
||||||
182
vvp/vthread.cc
182
vvp/vthread.cc
|
|
@ -5491,54 +5491,6 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
|
||||||
{
|
|
||||||
int base = cp->bit_idx[0];
|
|
||||||
int wid = cp->number;
|
|
||||||
int shift = thr->words[0].w_int;
|
|
||||||
|
|
||||||
assert(base >= 4);
|
|
||||||
thr_check_addr(thr, base+wid-1);
|
|
||||||
|
|
||||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
|
||||||
// The result is 'bx if the shift amount is undefined.
|
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
|
||||||
thr->bits4.set_vec(base, tmp);
|
|
||||||
|
|
||||||
} else if (shift >= wid) {
|
|
||||||
// Shift is so far that all value is shifted out. Write
|
|
||||||
// in a constant 0 result.
|
|
||||||
vvp_vector4_t tmp (wid, BIT4_0);
|
|
||||||
thr->bits4.set_vec(base, tmp);
|
|
||||||
|
|
||||||
} else if (shift > 0) {
|
|
||||||
vvp_vector4_t tmp (thr->bits4, base, wid-shift);
|
|
||||||
thr->bits4.set_vec(base+shift, tmp);
|
|
||||||
|
|
||||||
// Fill zeros on the bottom
|
|
||||||
vvp_vector4_t fil (shift, BIT4_0);
|
|
||||||
thr->bits4.set_vec(base, fil);
|
|
||||||
|
|
||||||
} else if (shift <= -wid) {
|
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
|
||||||
thr->bits4.set_vec(base, tmp);
|
|
||||||
|
|
||||||
} else if (shift < 0) {
|
|
||||||
// For a negative shift we pad with 'bx.
|
|
||||||
int idx;
|
|
||||||
for (idx = 0 ; (idx-shift) < wid ; idx += 1) {
|
|
||||||
unsigned src = base + idx - shift;
|
|
||||||
unsigned dst = base + idx;
|
|
||||||
thr_put_bit(thr, dst, thr_get_bit(thr, src));
|
|
||||||
}
|
|
||||||
for ( ; idx < wid ; idx += 1)
|
|
||||||
thr_put_bit(thr, base+idx, BIT4_X);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* %shiftl <idx>
|
* %shiftl <idx>
|
||||||
*/
|
*/
|
||||||
|
|
@ -5581,61 +5533,6 @@ bool of_SHIFTL(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* This is an unsigned right shift:
|
|
||||||
*
|
|
||||||
* %shiftr/i0 <bit>, <wid>
|
|
||||||
*
|
|
||||||
* The vector at address <bit> with width <wid> is shifted right a
|
|
||||||
* number of bits stored in index/word register 0.
|
|
||||||
*/
|
|
||||||
bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
|
|
||||||
{
|
|
||||||
int base = cp->bit_idx[0];
|
|
||||||
int wid = cp->number;
|
|
||||||
int shift = thr->words[0].w_int;
|
|
||||||
|
|
||||||
assert(base >= 4);
|
|
||||||
thr_check_addr(thr, base+wid-1);
|
|
||||||
|
|
||||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
|
||||||
// The result is 'bx if the shift amount is undefined.
|
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
|
||||||
thr->bits4.set_vec(base, tmp);
|
|
||||||
|
|
||||||
} else if (shift > wid) {
|
|
||||||
// Shift so far that the entire vector is shifted out.
|
|
||||||
vvp_vector4_t tmp (wid, BIT4_0);
|
|
||||||
thr->bits4.set_vec(base, tmp);
|
|
||||||
|
|
||||||
} else if (shift > 0) {
|
|
||||||
// The mov method should handle overlapped source/dest
|
|
||||||
thr->bits4.mov(base, base+shift, wid-shift);
|
|
||||||
|
|
||||||
vvp_vector4_t tmp (shift, BIT4_0);
|
|
||||||
thr->bits4.set_vec(base+wid-shift, tmp);
|
|
||||||
|
|
||||||
} else if (shift < -wid) {
|
|
||||||
// Negative shift is so far that all the value is shifted out.
|
|
||||||
// Write in a constant 'bx result.
|
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
|
||||||
thr->bits4.set_vec(base, tmp);
|
|
||||||
|
|
||||||
} else if (shift < 0) {
|
|
||||||
|
|
||||||
// For a negative shift we pad with 'bx.
|
|
||||||
vvp_vector4_t tmp (thr->bits4, base, wid+shift);
|
|
||||||
thr->bits4.set_vec(base-shift, tmp);
|
|
||||||
|
|
||||||
vvp_vector4_t fil (-shift, BIT4_X);
|
|
||||||
thr->bits4.set_vec(base, fil);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* %shiftr <idx>
|
* %shiftr <idx>
|
||||||
* This is an unsigned right shift. The <idx> is a number that selects
|
* This is an unsigned right shift. The <idx> is a number that selects
|
||||||
|
|
@ -5678,53 +5575,42 @@ bool of_SHIFTR(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
/*
|
||||||
bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
|
* %shiftr/s <wid>
|
||||||
{
|
*/
|
||||||
int base = cp->bit_idx[0];
|
|
||||||
int wid = cp->number;
|
|
||||||
int shift = thr->words[0].w_int;
|
|
||||||
vvp_bit4_t sign = thr_get_bit(thr, base+wid-1);
|
|
||||||
|
|
||||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
|
||||||
// The result is 'bx if the shift amount is undefined.
|
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
|
||||||
thr->bits4.set_vec(base, tmp);
|
|
||||||
} else if (shift >= wid) {
|
|
||||||
for (int idx = 0 ; idx < wid ; idx += 1)
|
|
||||||
thr_put_bit(thr, base+idx, sign);
|
|
||||||
|
|
||||||
} else if (shift > 0) {
|
|
||||||
for (int idx = 0 ; idx < (wid-shift) ; idx += 1) {
|
|
||||||
unsigned src = base + idx + shift;
|
|
||||||
unsigned dst = base + idx;
|
|
||||||
thr_put_bit(thr, dst, thr_get_bit(thr, src));
|
|
||||||
}
|
|
||||||
for (int idx = (wid-shift) ; idx < wid ; idx += 1)
|
|
||||||
thr_put_bit(thr, base+idx, sign);
|
|
||||||
|
|
||||||
} else if (shift < -wid) {
|
|
||||||
// Negative shift is so far that all the value is
|
|
||||||
// shifted out. Write in a constant 'bx result.
|
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
|
||||||
thr->bits4.set_vec(base, tmp);
|
|
||||||
|
|
||||||
} else if (shift < 0) {
|
|
||||||
|
|
||||||
// For a negative shift we pad with 'bx.
|
|
||||||
vvp_vector4_t tmp (thr->bits4, base, wid+shift);
|
|
||||||
thr->bits4.set_vec(base-shift, tmp);
|
|
||||||
|
|
||||||
vvp_vector4_t fil (-shift, BIT4_X);
|
|
||||||
thr->bits4.set_vec(base, fil);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool of_SHIFTR_S(vthread_t thr, vvp_code_t cp)
|
bool of_SHIFTR_S(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "XXXX of_SHIFTR_S not implemented\n");
|
int use_index = cp->number;
|
||||||
|
int shift = thr->words[use_index].w_int;
|
||||||
|
|
||||||
|
vvp_vector4_t val = thr->pop_vec4();
|
||||||
|
int wid = val.size();
|
||||||
|
|
||||||
|
vvp_bit4_t sign_bit = val.value(val.size()-1);
|
||||||
|
|
||||||
|
if (thr->flags[4] == BIT4_1) {
|
||||||
|
val = vvp_vector4_t(wid, BIT4_X);
|
||||||
|
|
||||||
|
} else if (shift > wid) {
|
||||||
|
val = vvp_vector4_t(wid, sign_bit);
|
||||||
|
|
||||||
|
} else if (shift > 0) {
|
||||||
|
val.mov(0, shift, wid-shift);
|
||||||
|
|
||||||
|
vvp_vector4_t tmp (shift, sign_bit);
|
||||||
|
val.set_vec(wid-shift, tmp);
|
||||||
|
|
||||||
|
} else if (shift < -wid) {
|
||||||
|
val = vvp_vector4_t(wid, BIT4_X);
|
||||||
|
|
||||||
|
} else if (shift < 0) {
|
||||||
|
int use_shift = -shift;
|
||||||
|
val.mov(use_shift, 0, wid-use_shift);
|
||||||
|
vvp_vector4_t tmp(use_shift, BIT4_X);
|
||||||
|
val.set_vec(0, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
thr->push_vec4(val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue