opcodes/cgen: Rework calculation of shift when inserting fields
The calculation of the shift amount, used to insert fields into the instruction buffer, is not correct when the following conditions are all true: - CGEN_INT_INSN_P is defined, and true. - CGEN_INSN_LSB0_P is true - Total instruction length is greater than the length of a single instruction word (the instruction is made of multiple words) - The word offset is non-zero (the field is outside the first word) When the above conditions are all true, the calculated shift fails to take account of the total instruction length. After this commit the calculation of the shift amount is split into two parts, first we calculate the shift required to get to BIT0 of the word in which the field lives, then we calculate the shift required to place the field within the instruction word. The change in this commit only effects the CGEN_INT_INSN_P defined true case, but changes the code for both CGEN_INSN_LSB0_P true, and false. In the case of CGEN_INSN_LSB0_P being false, the code used to say: shift = total_length - (word_offset + start + length); Now it says: shift_to_word = total_length - (word_offset + word_length); shift_within_word = word_length - start - length; shift = shift_to_word + shift_within_word; From which we can see that in all cases the computed shift value should be unchanged. In the case of CGEN_INSN_LSB0_P being true, the code used to say: shift = (word_offset + start + 1) - length; Now it says: shift_to_word = total_length - (word_offset + word_length); shift_within_word = start + 1 - length; shift = shift_to_word + shift_within_word; In the case where 'total_length == word_length' AND 'word_offset == 0' (which indicates an instruction of a single word), we see that the computed shift value will be unchanged. However, when the total_length and word_length are different, and the word_offset is non-zero then the computed shift value will be different (and correct). opcodes/ChangeLog: * cgen-ibld.in (insert_normal): Rework calculation of shift. * epiphany-ibld.c: Regenerate. * fr30-ibld.c: Regenerate. * frv-ibld.c: Regenerate. * ip2k-ibld.c: Regenerate. * iq2000-ibld.c: Regenerate. * lm32-ibld.c: Regenerate. * m32c-ibld.c: Regenerate. * m32r-ibld.c: Regenerate. * mep-ibld.c: Regenerate. * mt-ibld.c: Regenerate. * or1k-ibld.c: Regenerate. * xc16x-ibld.c: Regenerate. * xstormy16-ibld.c: Regenerate.
This commit is contained in:
parent
0f99255d74
commit
a143b0045c
15 changed files with 157 additions and 42 deletions
|
@ -1,3 +1,20 @@
|
||||||
|
2016-02-02 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||||
|
|
||||||
|
* cgen-ibld.in (insert_normal): Rework calculation of shift.
|
||||||
|
* epiphany-ibld.c: Regenerate.
|
||||||
|
* fr30-ibld.c: Regenerate.
|
||||||
|
* frv-ibld.c: Regenerate.
|
||||||
|
* ip2k-ibld.c: Regenerate.
|
||||||
|
* iq2000-ibld.c: Regenerate.
|
||||||
|
* lm32-ibld.c: Regenerate.
|
||||||
|
* m32c-ibld.c: Regenerate.
|
||||||
|
* m32r-ibld.c: Regenerate.
|
||||||
|
* mep-ibld.c: Regenerate.
|
||||||
|
* mt-ibld.c: Regenerate.
|
||||||
|
* or1k-ibld.c: Regenerate.
|
||||||
|
* xc16x-ibld.c: Regenerate.
|
||||||
|
* xstormy16-ibld.c: Regenerate.
|
||||||
|
|
||||||
2016-02-02 Andrew Burgess <andrew.burgess@embecosm.com>
|
2016-02-02 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||||
|
|
||||||
* epiphany-dis.c: Regenerated from latest cpu files.
|
* epiphany-dis.c: Regenerated from latest cpu files.
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
|
||||||
#if CGEN_INT_INSN_P
|
#if CGEN_INT_INSN_P
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift;
|
int shift_within_word, shift_to_word, shift;
|
||||||
|
|
||||||
|
/* How to shift the value to BIT0 of the word. */
|
||||||
|
shift_to_word = total_length - (word_offset + word_length);
|
||||||
|
|
||||||
|
/* How to shift the value to the field within the word. */
|
||||||
if (CGEN_INSN_LSB0_P)
|
if (CGEN_INSN_LSB0_P)
|
||||||
shift = (word_offset + start + 1) - length;
|
shift_within_word = start + 1 - length;
|
||||||
else
|
else
|
||||||
shift = total_length - (word_offset + start + length);
|
shift_within_word = word_length - start - length;
|
||||||
|
|
||||||
|
/* The total SHIFT, then mask in the value. */
|
||||||
|
shift = shift_to_word + shift_within_word;
|
||||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue