From a1867a27d076940e9ff463cacd4912c4749cf33b Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 26 May 2007 14:49:39 +0000 Subject: [PATCH] * 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. --- gas/ChangeLog | 9 ++++++ gas/config/tc-ppc.c | 70 ++++++++++++++++++++++++--------------------- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 8b471d5dc21..95dfaa44dea 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2007-05-26 Alan Modra + + * 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 * config/tc-arm.c (T2_SUBS_PC_LR): Define. diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 96f165c2b43..b07306e677d 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -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; - - 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); + { + long tmp = min; + min = -max; + max = -tmp; + } + + 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) { -- 2.30.2