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)) { 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 // Special case: The shift is the size of the entire
// left operand, and the shift is unsigned. Elaborate as // left operand, and the shift is unsigned. Elaborate as
// a constant-0. // a constant-0.
if ((op_=='r' || (lp->has_sign()==false)) if ((op_=='r' || (lp->has_sign()==false)) &&
&& shift >= (long)lp->expr_width()) { shift >= lp->expr_width()) {
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: " 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 // Special case: the shift is the size of the entire
// left operand, and the shift is signed. Elaborate as a // left operand, and the shift is signed. Elaborate as a
// replication of the top bit of the left expression. // 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) if (debug_elaborate)
cerr << get_fileline() << ": debug: " cerr << get_fileline() << ": debug: "
@ -685,34 +689,10 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
return tmp; 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 // If this is lossless, then pad the left expression
// enough to cover the right shift. // 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); lp = pad_to_width(lp, use_wid + shift, *this);
} }

View File

@ -601,8 +601,8 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
return 0; return 0;
} }
const bool right_flag = op_ == 'r' || op_ == 'R'; 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 /* Detect the special case where the shift amount is
constant. Evaluate the shift amount, and simply reconnect constant. Evaluate the shift amount, and simply reconnect