* config/tc-ppc.c (ppc_insert_operand): Truncate sign bits in

top 32 bits of 64 bit value if so doing results in passing
	range check.  Rewrite sign extension fudges similarly.  Enable
	fudges for powerpc64 too.  Report user value if range check
	fails rather than fudged value.  Negate PPC_OPERAND_NEGATIVE
	range rather than value, also to report user value on failure.
This commit is contained in:
Alan Modra 2007-05-26 14:49:39 +00:00
parent 602af7ef9e
commit a1867a27d0
2 changed files with 45 additions and 32 deletions

View File

@ -1,3 +1,12 @@
2007-05-26 Alan Modra <amodra@bigpond.net.au>
* config/tc-ppc.c (ppc_insert_operand): Truncate sign bits in
top 32 bits of 64 bit value if so doing results in passing
range check. Rewrite sign extension fudges similarly. Enable
fudges for powerpc64 too. Report user value if range check
fails rather than fudged value. Negate PPC_OPERAND_NEGATIVE
range rather than value, also to report user value on failure.
2007-03-25 Paul Brook <paul@codesourcery.com>
* config/tc-arm.c (T2_SUBS_PC_LR): Define.

View File

@ -86,9 +86,6 @@ static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
static bfd_boolean register_name PARAMS ((expressionS *));
static void ppc_set_cpu PARAMS ((void));
static unsigned long ppc_insert_operand
PARAMS ((unsigned long insn, const struct powerpc_operand *operand,
offsetT val, char *file, unsigned int line));
static void ppc_macro PARAMS ((char *str, const struct powerpc_macro *macro));
static void ppc_byte PARAMS ((int));
@ -1507,15 +1504,13 @@ ppc_cleanup ()
/* Insert an operand value into an instruction. */
static unsigned long
ppc_insert_operand (insn, operand, val, file, line)
unsigned long insn;
const struct powerpc_operand *operand;
offsetT val;
char *file;
unsigned int line;
ppc_insert_operand (unsigned long insn,
const struct powerpc_operand *operand,
offsetT val,
char *file,
unsigned int line)
{
long min, max, right;
offsetT test;
max = operand->bitm;
right = max & -max;
@ -1526,35 +1521,44 @@ ppc_insert_operand (insn, operand, val, file, line)
if ((operand->flags & PPC_OPERAND_SIGNOPT) == 0)
max = (max >> 1) & -right;
min = ~max & -right;
if (!ppc_obj64)
{
/* Some people write 32 bit hex constants with the sign
extension done by hand. This shouldn't really be
valid, but, to permit this code to assemble on a 64
bit host, we sign extend the 32 bit value. */
if (val > 0
&& (val & (offsetT) 0x80000000) != 0
&& (val & (offsetT) 0xffffffff) == val)
{
val -= 0x80000000;
val -= 0x80000000;
}
}
}
if ((operand->flags & PPC_OPERAND_PLUS1) != 0)
max++;
if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
test = - val;
else
test = val;
{
long tmp = min;
min = -max;
max = -tmp;
}
if ((min <= max && (test < (offsetT) min || test > (offsetT) max))
|| (test & (right - 1)) != 0)
as_bad_value_out_of_range (_("operand"),
test, (offsetT) min, (offsetT) max, file, line);
if (min <= max)
{
/* Some people write constants with the sign extension done by
hand but only up to 32 bits. This shouldn't really be valid,
but, to permit this code to assemble on a 64-bit host, we
sign extend the 32-bit value to 64 bits if so doing makes the
value valid. */
if (val > max
&& (offsetT) (val - 0x80000000 - 0x80000000) >= min
&& (offsetT) (val - 0x80000000 - 0x80000000) <= max
&& ((val - 0x80000000 - 0x80000000) & (right - 1)) == 0)
val = val - 0x80000000 - 0x80000000;
/* Similarly, people write expressions like ~(1<<15), and expect
this to be OK for a 32-bit unsigned value. */
else if (val < min
&& (offsetT) (val + 0x80000000 + 0x80000000) >= min
&& (offsetT) (val + 0x80000000 + 0x80000000) <= max
&& ((val + 0x80000000 + 0x80000000) & (right - 1)) == 0)
val = val + 0x80000000 + 0x80000000;
else if (val < min
|| val > max
|| (val & (right - 1)) != 0)
as_bad_value_out_of_range (_("operand"), val, min, max, file, line);
}
if (operand->insert)
{