Enhance %shiftr/i0 and $shiftl/i0 to work with negative shifts.
The %shiftr/i0 and %shiftl/i0 opcodes are used for some part selects and if we have a negative shift we want the value to be padded with 'bx. This patch enhances the two %shift/i0 opcodes to work with negative shifts and for negative shifts pad with 'bx instead of 'b0. It also fixes %ix/get/s to use a uint64_t instead of a unsigned long to avoid problems with sign extension on 32 bit machines.
This commit is contained in:
parent
d108221fef
commit
ecb00017cb
|
|
@ -417,7 +417,7 @@ These instructions are like the %ix/get instructions, except that they
|
||||||
read directly from a functor label instead of from thread bits. They
|
read directly from a functor label instead of from thread bits. They
|
||||||
set bit 4 just like %ix/get.
|
set bit 4 just like %ix/get.
|
||||||
|
|
||||||
* %ix/load <idx>, <low> <high>
|
* %ix/load <idx>, <low>, <high>
|
||||||
|
|
||||||
This instruction loads an immediate value into the addressed index
|
This instruction loads an immediate value into the addressed index
|
||||||
register. The index register holds signed 64 bit numeric values, so
|
register. The index register holds signed 64 bit numeric values, so
|
||||||
|
|
@ -428,9 +428,9 @@ vector. The values are unsigned decimal values and are combined as
|
||||||
<high> << 32 | <low> to produce the final value.
|
<high> << 32 | <low> to produce the final value.
|
||||||
|
|
||||||
|
|
||||||
* %ix/add <idx>, <low> <high>
|
* %ix/add <idx>, <low>, <high>
|
||||||
* %ix/sub <idx>, <low> <high>
|
* %ix/sub <idx>, <low>, <high>
|
||||||
* %ix/mul <idx>, <low> <high>
|
* %ix/mul <idx>, <low>, <high>
|
||||||
|
|
||||||
These instructions add, subtract, or multiply the selected index
|
These instructions add, subtract, or multiply the selected index
|
||||||
register by the immediate value. The 64 bit immediate value is built
|
register by the immediate value. The 64 bit immediate value is built
|
||||||
|
|
@ -758,6 +758,8 @@ 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
|
the LSB of the vector, and <wid> the width of the vector. The shift is
|
||||||
done in place. Zero values are shifted in.
|
done in place. Zero values are shifted in.
|
||||||
|
|
||||||
|
For a negative shift the value is padded with 'bx.
|
||||||
|
|
||||||
* %shiftr/i0 <bit>, <wid>
|
* %shiftr/i0 <bit>, <wid>
|
||||||
* %shiftr/s/i0 <bit>, <wid>
|
* %shiftr/s/i0 <bit>, <wid>
|
||||||
|
|
||||||
|
|
@ -769,6 +771,8 @@ shift is done in place.
|
||||||
%shiftr/i0 is an unsigned down shift, so zeros are shifted into the
|
%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.
|
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.
|
||||||
|
|
||||||
* %sub <bit-l>, <bit-r>, <wid>
|
* %sub <bit-l>, <bit-r>, <wid>
|
||||||
|
|
||||||
This instruction arithmetically subtracts the right vector out of the
|
This instruction arithmetically subtracts the right vector out of the
|
||||||
|
|
|
||||||
|
|
@ -2642,7 +2642,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
|
||||||
unsigned base = cp->bit_idx[1];
|
unsigned base = cp->bit_idx[1];
|
||||||
unsigned width = cp->number;
|
unsigned width = cp->number;
|
||||||
|
|
||||||
unsigned long v = 0;
|
uint64_t v = 0;
|
||||||
bool unknown_flag = false;
|
bool unknown_flag = false;
|
||||||
|
|
||||||
vvp_bit4_t vv = BIT4_0;
|
vvp_bit4_t vv = BIT4_0;
|
||||||
|
|
@ -2654,7 +2654,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
v |= (unsigned long) vv << i;
|
v |= (uint64_t) vv << i;
|
||||||
|
|
||||||
if (base >= 4)
|
if (base >= 4)
|
||||||
base += 1;
|
base += 1;
|
||||||
|
|
@ -2662,7 +2662,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
/* Sign-extend to fill the integer value. */
|
/* Sign-extend to fill the integer value. */
|
||||||
if (!unknown_flag) {
|
if (!unknown_flag) {
|
||||||
unsigned long pad = vv;
|
uint64_t pad = vv;
|
||||||
for (unsigned i = width ; i < 8*sizeof(v) ; i += 1) {
|
for (unsigned i = width ; i < 8*sizeof(v) ; i += 1) {
|
||||||
v |= pad << i;
|
v |= pad << i;
|
||||||
}
|
}
|
||||||
|
|
@ -4206,7 +4206,7 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
unsigned base = cp->bit_idx[0];
|
unsigned base = cp->bit_idx[0];
|
||||||
unsigned wid = cp->number;
|
unsigned wid = cp->number;
|
||||||
unsigned long shift = thr->words[0].w_int;
|
long shift = thr->words[0].w_int;
|
||||||
|
|
||||||
assert(base >= 4);
|
assert(base >= 4);
|
||||||
thr_check_addr(thr, base+wid-1);
|
thr_check_addr(thr, base+wid-1);
|
||||||
|
|
@ -4215,7 +4215,8 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
||||||
// The result is 'bx if the shift amount is undefined.
|
// The result is 'bx if the shift amount is undefined.
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
vvp_vector4_t tmp (wid, BIT4_X);
|
||||||
thr->bits4.set_vec(base, tmp);
|
thr->bits4.set_vec(base, tmp);
|
||||||
} else if (shift >= wid) {
|
|
||||||
|
} else if (shift >= (long)wid) {
|
||||||
// Shift is so far that all value is shifted out. Write
|
// Shift is so far that all value is shifted out. Write
|
||||||
// in a constant 0 result.
|
// in a constant 0 result.
|
||||||
vvp_vector4_t tmp (wid, BIT4_0);
|
vvp_vector4_t tmp (wid, BIT4_0);
|
||||||
|
|
@ -4228,6 +4229,17 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
||||||
// Fill zeros on the bottom
|
// Fill zeros on the bottom
|
||||||
vvp_vector4_t fil (shift, BIT4_0);
|
vvp_vector4_t fil (shift, BIT4_0);
|
||||||
thr->bits4.set_vec(base, fil);
|
thr->bits4.set_vec(base, fil);
|
||||||
|
|
||||||
|
} else if (shift < 0) {
|
||||||
|
// For a negative shift we pad with 'bx.
|
||||||
|
unsigned 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -4244,12 +4256,16 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
unsigned base = cp->bit_idx[0];
|
unsigned base = cp->bit_idx[0];
|
||||||
unsigned wid = cp->number;
|
unsigned wid = cp->number;
|
||||||
unsigned long shift = thr->words[0].w_int;
|
long shift = thr->words[0].w_int;
|
||||||
|
|
||||||
|
assert(base >= 4);
|
||||||
|
thr_check_addr(thr, base+wid-1);
|
||||||
|
|
||||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||||
// The result is 'bx if the shift amount is undefined.
|
// The result is 'bx if the shift amount is undefined.
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
vvp_vector4_t tmp (wid, BIT4_X);
|
||||||
thr->bits4.set_vec(base, tmp);
|
thr->bits4.set_vec(base, tmp);
|
||||||
|
|
||||||
} else if (shift > 0) {
|
} else if (shift > 0) {
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
for (idx = 0 ; (idx+shift) < wid ; idx += 1) {
|
for (idx = 0 ; (idx+shift) < wid ; idx += 1) {
|
||||||
|
|
@ -4259,6 +4275,21 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
|
||||||
}
|
}
|
||||||
for ( ; idx < wid ; idx += 1)
|
for ( ; idx < wid ; idx += 1)
|
||||||
thr_put_bit(thr, base+idx, BIT4_0);
|
thr_put_bit(thr, base+idx, BIT4_0);
|
||||||
|
|
||||||
|
} else if (shift < -(long)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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -4271,7 +4302,7 @@ bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
|
||||||
vvp_bit4_t sign = thr_get_bit(thr, base+wid-1);
|
vvp_bit4_t sign = thr_get_bit(thr, base+wid-1);
|
||||||
|
|
||||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||||
// The result is 'bx if the shift amount is undefined.
|
// The result is 'bx if the shift amount is undefined.
|
||||||
vvp_vector4_t tmp (wid, BIT4_X);
|
vvp_vector4_t tmp (wid, BIT4_X);
|
||||||
thr->bits4.set_vec(base, tmp);
|
thr->bits4.set_vec(base, tmp);
|
||||||
} else if (shift >= wid) {
|
} else if (shift >= wid) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue