Fix some large/negative immediate value compiler bugs.
Fix how immediate values are checked and allow a large negative value to be returned from get_number_immediate().
This commit is contained in:
parent
d508960a9e
commit
7969a58eeb
|
|
@ -49,53 +49,76 @@ int number_is_unknown(ivl_expr_t ex)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function returns TRUE if the number can be represented in a
|
* This function returns TRUE if the number can be represented as a
|
||||||
* 16bit immediate value. This amounts to looking for non-zero bits
|
* lim_wid immediate value. This amounts to verifying that any upper
|
||||||
* above bitX. The maximum size of the immediate may vary, so use
|
* bits are the same. For a negative value we do not support the most
|
||||||
* lim_wid at the width limit to use.
|
* negative twos-complement value since it can not be negated. This
|
||||||
|
* code generator always emits positive values, hence the negation
|
||||||
|
* requirement.
|
||||||
*/
|
*/
|
||||||
int number_is_immediate(ivl_expr_t ex, unsigned lim_wid, int negative_ok_flag)
|
int number_is_immediate(ivl_expr_t ex, unsigned lim_wid, int negative_ok_flag)
|
||||||
{
|
{
|
||||||
const char*bits;
|
const char *bits;
|
||||||
unsigned nbits = ivl_expr_width(ex);
|
unsigned nbits = ivl_expr_width(ex);
|
||||||
char pad_bit = '0';
|
char pad_bit = '0';
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
|
|
||||||
|
/* We can only convert numbers to an immediate value. */
|
||||||
if (ivl_expr_type(ex) != IVL_EX_NUMBER
|
if (ivl_expr_type(ex) != IVL_EX_NUMBER
|
||||||
&& ivl_expr_type(ex) != IVL_EX_ULONG
|
&& ivl_expr_type(ex) != IVL_EX_ULONG
|
||||||
&& ivl_expr_type(ex) != IVL_EX_DELAY)
|
&& ivl_expr_type(ex) != IVL_EX_DELAY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* If a negative value is OK, then we really have one less
|
||||||
|
* significant bit because of the sign bit. */
|
||||||
|
if (negative_ok_flag) lim_wid -= 1;
|
||||||
|
|
||||||
|
/* This is an unsigned value so it can not have the -2**N problem. */
|
||||||
if (ivl_expr_type(ex) == IVL_EX_ULONG) {
|
if (ivl_expr_type(ex) == IVL_EX_ULONG) {
|
||||||
long imm;
|
unsigned long imm;
|
||||||
if (lim_wid >= 8*sizeof(long)) return 1;
|
if (lim_wid >= 8*sizeof(unsigned long)) return 1;
|
||||||
/* At this point we know that lim_wid is smaller than a long. */
|
/* At this point we know that lim_wid is smaller than an
|
||||||
imm = labs(ivl_expr_uvalue(ex));
|
* unsigned long variable. */
|
||||||
if (imm < (1L<<lim_wid)) return 1;
|
imm = ivl_expr_uvalue(ex);
|
||||||
|
if (imm < (1UL << lim_wid)) return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is an unsigned value so it can not have the -2**N problem. */
|
||||||
if (ivl_expr_type(ex) == IVL_EX_DELAY) {
|
if (ivl_expr_type(ex) == IVL_EX_DELAY) {
|
||||||
|
uint64_t imm;
|
||||||
if (lim_wid >= 8*sizeof(uint64_t)) return 1;
|
if (lim_wid >= 8*sizeof(uint64_t)) return 1;
|
||||||
/* For now we only support this as a 64 bit value. */
|
/* At this point we know that lim_wid is smaller than a
|
||||||
|
* uint64_t variable. */
|
||||||
|
imm = ivl_expr_delay_val(ex);
|
||||||
|
if (imm < ((uint64_t)1 << lim_wid)) return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bits = ivl_expr_bits(ex);
|
bits = ivl_expr_bits(ex);
|
||||||
|
|
||||||
if (ivl_expr_signed(ex) && bits[nbits-1]=='1')
|
if (ivl_expr_signed(ex) && bits[nbits-1]=='1') pad_bit = '1';
|
||||||
pad_bit = '1';
|
|
||||||
|
|
||||||
if (pad_bit == '1' && !negative_ok_flag)
|
if (pad_bit == '1' && !negative_ok_flag) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (idx = lim_wid ; idx < nbits ; idx += 1)
|
for (idx = lim_wid ; idx < nbits ; idx += 1)
|
||||||
if (bits[idx] != pad_bit)
|
if (bits[idx] != pad_bit) return 0;
|
||||||
|
|
||||||
|
/* If we have a negative number make sure it is not too big. */
|
||||||
|
if (pad_bit == '1') {
|
||||||
|
for (idx = 0; idx < lim_wid; idx += 1)
|
||||||
|
if (bits[idx] == '1') return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can return positive or negative values. You must verify that the
|
||||||
|
* number is not unknown (number_is_unknown) and is small enough
|
||||||
|
* (number_is_immediate).
|
||||||
|
*/
|
||||||
long get_number_immediate(ivl_expr_t ex)
|
long get_number_immediate(ivl_expr_t ex)
|
||||||
{
|
{
|
||||||
long imm = 0;
|
long imm = 0;
|
||||||
|
|
@ -109,18 +132,19 @@ long get_number_immediate(ivl_expr_t ex)
|
||||||
case IVL_EX_NUMBER: {
|
case IVL_EX_NUMBER: {
|
||||||
const char*bits = ivl_expr_bits(ex);
|
const char*bits = ivl_expr_bits(ex);
|
||||||
unsigned nbits = ivl_expr_width(ex);
|
unsigned nbits = ivl_expr_width(ex);
|
||||||
|
/* We can not copy more bits than fit into a long. */
|
||||||
|
if (nbits > 8*sizeof(long)) nbits = 8*sizeof(long);
|
||||||
for (idx = 0 ; idx < nbits ; idx += 1) switch (bits[idx]){
|
for (idx = 0 ; idx < nbits ; idx += 1) switch (bits[idx]){
|
||||||
case '0':
|
case '0':
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
assert(idx < IMM_WID);
|
|
||||||
imm |= 1L << idx;
|
imm |= 1L << idx;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if (ivl_expr_signed(ex) && bits[nbits-1]=='1' && nbits < IMM_WID)
|
if (ivl_expr_signed(ex) && bits[nbits-1]=='1' &&
|
||||||
imm |= -1L << nbits;
|
nbits < 8*sizeof(long)) imm |= -1L << nbits;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue