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:
Cary R 2009-08-25 09:55:27 -07:00 committed by Stephen Williams
parent d108221fef
commit ecb00017cb
2 changed files with 47 additions and 12 deletions

View File

@ -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

View File

@ -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;
}