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:
parent
710ad582ed
commit
ceea5d568c
40
elab_expr.cc
40
elab_expr.cc
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -602,7 +602,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue