Fix problems in rshift code.

This patch fixes the following problems in the right shift code.

The >>> result is only signed if the l-arg is also signed.

The r-arg is always unsigned.

Only sign extend the l-arg when the >>> operator is used.
This relates to an optimization for certain constant shifts.

Removed some obsoleted/outdated code.
(cherry picked from commit d7f272d14c)
This commit is contained in:
Cary R 2009-03-30 17:14:36 -07:00 committed by Stephen Williams
parent 710ad582ed
commit ceea5d568c
2 changed files with 12 additions and 32 deletions

View File

@ -643,13 +643,13 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
}
if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
long shift = rpc->value().as_long();
unsigned long shift = rpc->value().as_ulong();
// Special case: The shift is the size of the entire
// left operand, and the shift is unsigned. Elaborate as
// a constant-0.
if ((op_=='r' || (lp->has_sign()==false))
&& shift >= (long)lp->expr_width()) {
if ((op_=='r' || (lp->has_sign()==false)) &&
shift >= lp->expr_width()) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
@ -666,7 +666,11 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
// Special case: the shift is the size of the entire
// left operand, and the shift is signed. Elaborate as a
// replication of the top bit of the left expression.
if (shift >= (long)lp->expr_width()) {
//
// The above test assures us that op_ == 'R' && the left
// argument is signed when the shift is greater than the
// expression width.
if (shift >= lp->expr_width()) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
@ -685,34 +689,10 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
return tmp;
}
// Special case: shift is negative (so do a left shift)
// and is greater than the output width. Replace the
// expression with a constant-0.
if (shift < 0 && (0-shift) >= use_wid) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Value signed-right-shifted " << shift
<< " beyond width of " << use_wid
<< "." << endl;
tmp = make_const_0(use_wid);
tmp->set_line(*this);
return tmp;
}
ivl_assert(*this, shift >= 0);
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Value signed-right-shifted " << shift
<< " beyond width of " << lp->expr_width()
<< ". shift=" << shift
<< ", expr_wid=" << expr_wid
<< ", expr=" << *lp << endl;
// If this is lossless, then pad the left expression
// enough to cover the right shift.
if (expr_wid == -2 && use_wid+shift > (long)lp->expr_width()) {
if (expr_wid == -2 && use_wid+shift > lp->expr_width()) {
lp->cast_signed(lp->has_sign() && op_=='R');
lp = pad_to_width(lp, use_wid + shift, *this);
}

View File

@ -602,7 +602,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
const bool right_flag = op_ == 'r' || op_ == 'R';
const bool signed_flag = op_ == 'R';
const bool signed_flag = has_sign();
/* Detect the special case where the shift amount is
constant. Evaluate the shift amount, and simply reconnect