diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index cfd14cc98..1accf2c3c 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -1294,152 +1294,6 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t expr, 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, 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); break; - case 'l': /* << */ - case 'r': /* >> */ - case 'R': /* >>> */ - rv = draw_binary_expr_lrs(expr, wid); - break; - case 'o': /* || (logical or) */ rv = draw_binary_expr_lor(expr, wid, stuff_ok_flag); stuff_ok_used_flag = 1; @@ -1802,7 +1650,7 @@ static struct vector_info draw_binary_expr(ivl_expr_t expr, break; 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)); assert(0); } diff --git a/tgt-vvp/eval_vec4.c b/tgt-vvp/eval_vec4.c index 8572686cc..ee9ce19a1 100644 --- a/tgt-vvp/eval_vec4.c +++ b/tgt-vvp/eval_vec4.c @@ -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); break; 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; default: assert(0); diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index bb1dd3a43..3779dc1c7 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -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 bits are not written anywhere. - -* %shiftl/i0 , (XXXX Old implementation) - -This instruction shifts the vector left (towards more significant -bits) by the amount in index register 0. The is the address of -the LSB of the vector, and 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 , (XXXX Old implementation) -* %shiftr/s/i0 , (XXXX Old implementation) - -This instruction shifts the vector right (towards the less significant -bits) by the amount in the index register 0. The is the address -of the LSB of the vector, and 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 * %shiftr * %shiftr/s @@ -1199,6 +1176,12 @@ These instructions shift the top value in the vec4 stack left (towards MSB) or right, possibly signed. The is the address of the index 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 Pull the top vec4 vector from the stack and split it into two diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 4f62e3bfa..4c75ace45 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -5491,54 +5491,6 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp) 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 */ @@ -5581,61 +5533,6 @@ bool of_SHIFTL(vthread_t thr, vvp_code_t cp) return true; } - -#if 0 -/* - * This is an unsigned right shift: - * - * %shiftr/i0 , - * - * The vector at address with width 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 * This is an unsigned right shift. The is a number that selects @@ -5678,53 +5575,42 @@ bool of_SHIFTR(vthread_t thr, vvp_code_t cp) return true; } -#if 0 -bool of_SHIFTR_S_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; - 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 - +/* + * %shiftr/s + */ 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; }