summaryrefslogtreecommitdiff
path: root/gas/config/tc-crx.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2012-02-27 06:37:38 +0000
committerAlan Modra <amodra@bigpond.net.au>2012-02-27 06:37:38 +0000
commit8efcb44b891d0bcc97f47212f203c879e7712ba6 (patch)
tree3a9df73b94b6b0606d62ba0bc33a2e3aae5ddc49 /gas/config/tc-crx.c
parent5f68d9bce47a17a53d1a4c8f96da9c6eb4817670 (diff)
downloadbinutils-redhat-8efcb44b891d0bcc97f47212f203c879e7712ba6.tar.gz
gas/
* config/tc-crx.c: Include bfd_stdint.h. (getconstant): Remove irrelevant comment. Don't fail due to sign-extension of int mask. (check_range): Rewrite using unsigned arithmetic throughout. opcodes/ * crx-dis.c (print_arg): Mask constant to 32 bits. * crx-opc.c (cst4_map): Use int array. include/opcode/ * crx.h (cst4_map): Update declaration.
Diffstat (limited to 'gas/config/tc-crx.c')
-rw-r--r--gas/config/tc-crx.c52
1 files changed, 28 insertions, 24 deletions
diff --git a/gas/config/tc-crx.c b/gas/config/tc-crx.c
index b347d8b828..775781bf3f 100644
--- a/gas/config/tc-crx.c
+++ b/gas/config/tc-crx.c
@@ -1,5 +1,5 @@
/* tc-crx.c -- Assembler code for the CRX CPU core.
- Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012
Free Software Foundation, Inc.
Contributed by Tomer Levi, NSC, Israel.
@@ -24,6 +24,7 @@
MA 02110-1301, USA. */
#include "as.h"
+#include "bfd_stdint.h"
#include "safe-ctype.h"
#include "dwarf2dbg.h"
#include "opcode/crx.h"
@@ -1173,9 +1174,7 @@ getreg_image (reg r)
static long
getconstant (long x, int nbits)
{
- /* The following expression avoids overflow if
- 'nbits' is the number of bits in 'bfd_vma'. */
- return (x & ((((1 << (nbits - 1)) - 1) << 1) | 1));
+ return x & ((((1U << (nbits - 1)) - 1) << 1) | 1);
}
/* Print a constant value to 'output_opcode':
@@ -1326,17 +1325,14 @@ get_number_of_operands (void)
static op_err
check_range (long *num, int bits, int unsigned flags, int update)
{
- long min, max;
+ uint32_t max;
int retval = OP_LEGAL;
int bin;
- long upper_64kb = 0xFFFF0000;
- long value = *num;
+ uint32_t upper_64kb = 0xffff0000;
+ uint32_t value = *num;
- /* For hosts witah longs bigger than 32-bits make sure that the top
- bits of a 32-bit negative value read in by the parser are set,
- so that the correct comparisons are made. */
- if (value & 0x80000000)
- value |= (-1L << 31);
+ /* Trim all values to 32 bits. uint32_t can be more than 32 bits. */
+ value &= 0xffffffff;
/* Verify operand value is even. */
if (flags & OP_EVEN)
@@ -1360,7 +1356,12 @@ check_range (long *num, int bits, int unsigned flags, int update)
if (flags & OP_SHIFT)
{
+ /* All OP_SHIFT args are also OP_SIGNED, so we want to keep the
+ sign. However, right shift of a signed type with a negative
+ value is implementation defined. See ISO C 6.5.7. So we use
+ an unsigned type and sign extend afterwards. */
value >>= 1;
+ value = ((value ^ 0x40000000) - 0x40000000) & 0xffffffff;
if (update)
*num = value;
}
@@ -1382,13 +1383,14 @@ check_range (long *num, int bits, int unsigned flags, int update)
{
int is_dispu4 = 0;
- int mul = (instruction->flags & DISPUB4) ? 1
- : (instruction->flags & DISPUW4) ? 2
- : (instruction->flags & DISPUD4) ? 4 : 0;
+ uint32_t mul = (instruction->flags & DISPUB4 ? 1
+ : instruction->flags & DISPUW4 ? 2
+ : instruction->flags & DISPUD4 ? 4
+ : 0);
for (bin = 0; bin < cst4_maps; bin++)
{
- if (value == (mul * bin))
+ if (value == mul * bin)
{
is_dispu4 = 1;
if (update)
@@ -1405,7 +1407,7 @@ check_range (long *num, int bits, int unsigned flags, int update)
for (bin = 0; bin < cst4_maps; bin++)
{
- if (value == cst4_map[bin])
+ if (value == ((uint32_t) cst4_map[bin] & 0xffffffff))
{
is_cst4 = 1;
if (update)
@@ -1418,17 +1420,19 @@ check_range (long *num, int bits, int unsigned flags, int update)
}
else if (flags & OP_SIGNED)
{
- max = (1 << (bits - 1)) - 1;
- min = - (1 << (bits - 1));
- if ((value > max) || (value < min))
+ max = 1;
+ max = max << (bits - 1);
+ value += max;
+ max = ((max - 1) << 1) | 1;
+ if (value > max)
retval = OP_OUT_OF_RANGE;
}
else if (flags & OP_UNSIGNED)
{
- max = ((((1 << (bits - 1)) - 1) << 1) | 1);
- min = 0;
- if (((unsigned long) value > (unsigned long) max)
- || ((unsigned long) value < (unsigned long) min))
+ max = 1;
+ max = max << (bits - 1);
+ max = ((max - 1) << 1) | 1;
+ if (value > max)
retval = OP_OUT_OF_RANGE;
}
return retval;