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
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
* %ix/add <idx>, <low> <high>
|
||||
* %ix/sub <idx>, <low> <high>
|
||||
* %ix/mul <idx>, <low> <high>
|
||||
* %ix/add <idx>, <low>, <high>
|
||||
* %ix/sub <idx>, <low>, <high>
|
||||
* %ix/mul <idx>, <low>, <high>
|
||||
|
||||
These instructions add, subtract, or multiply the selected index
|
||||
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
|
||||
done in place. Zero values are shifted in.
|
||||
|
||||
For a negative shift the value is padded with 'bx.
|
||||
|
||||
* %shiftr/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
|
||||
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>
|
||||
|
||||
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 width = cp->number;
|
||||
|
||||
unsigned long v = 0;
|
||||
uint64_t v = 0;
|
||||
bool unknown_flag = false;
|
||||
|
||||
vvp_bit4_t vv = BIT4_0;
|
||||
|
|
@ -2654,7 +2654,7 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
|
|||
break;
|
||||
}
|
||||
|
||||
v |= (unsigned long) vv << i;
|
||||
v |= (uint64_t) vv << i;
|
||||
|
||||
if (base >= 4)
|
||||
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. */
|
||||
if (!unknown_flag) {
|
||||
unsigned long pad = vv;
|
||||
uint64_t pad = vv;
|
||||
for (unsigned i = width ; i < 8*sizeof(v) ; i += 1) {
|
||||
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 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);
|
||||
|
|
@ -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.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
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
|
||||
// in a constant 0 result.
|
||||
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
|
||||
vvp_vector4_t fil (shift, BIT4_0);
|
||||
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;
|
||||
}
|
||||
|
|
@ -4244,12 +4256,16 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
unsigned base = cp->bit_idx[0];
|
||||
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) {
|
||||
// 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 > 0) {
|
||||
unsigned idx;
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue