Line 1... |
Line 1... |
/* tc-crx.c -- Assembler code for the CRX CPU core.
|
/* 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.
|
Free Software Foundation, Inc.
|
|
|
Contributed by Tomer Levi, NSC, Israel.
|
Contributed by Tomer Levi, NSC, Israel.
|
Originally written for GAS 2.12 by Tomer Levi, NSC, Israel.
|
Originally written for GAS 2.12 by Tomer Levi, NSC, Israel.
|
Updates, BFDizing, GNUifying and ELF support by Tomer Levi.
|
Updates, BFDizing, GNUifying and ELF support by Tomer Levi.
|
Line 22... |
Line 22... |
along with GAS; see the file COPYING. If not, write to the
|
along with GAS; see the file COPYING. If not, write to the
|
Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
|
Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
|
MA 02110-1301, USA. */
|
MA 02110-1301, USA. */
|
|
|
#include "as.h"
|
#include "as.h"
|
|
#include "bfd_stdint.h"
|
#include "safe-ctype.h"
|
#include "safe-ctype.h"
|
#include "dwarf2dbg.h"
|
#include "dwarf2dbg.h"
|
#include "opcode/crx.h"
|
#include "opcode/crx.h"
|
#include "elf/crx.h"
|
#include "elf/crx.h"
|
|
|
Line 1171... |
Line 1172... |
/* Routine used to represent integer X using NBITS bits. */
|
/* Routine used to represent integer X using NBITS bits. */
|
|
|
static long
|
static long
|
getconstant (long x, int nbits)
|
getconstant (long x, int nbits)
|
{
|
{
|
/* The following expression avoids overflow if
|
return x & ((((1U << (nbits - 1)) - 1) << 1) | 1);
|
'nbits' is the number of bits in 'bfd_vma'. */
|
|
return (x & ((((1 << (nbits - 1)) - 1) << 1) | 1));
|
|
}
|
}
|
|
|
/* Print a constant value to 'output_opcode':
|
/* Print a constant value to 'output_opcode':
|
ARG holds the operand's type and value.
|
ARG holds the operand's type and value.
|
SHIFT represents the location of the operand to be print into.
|
SHIFT represents the location of the operand to be print into.
|
Line 1324... |
Line 1323... |
Return OP_LEGAL upon success, actual error type upon failure. */
|
Return OP_LEGAL upon success, actual error type upon failure. */
|
|
|
static op_err
|
static op_err
|
check_range (long *num, int bits, int unsigned flags, int update)
|
check_range (long *num, int bits, int unsigned flags, int update)
|
{
|
{
|
long min, max;
|
uint32_t max;
|
int retval = OP_LEGAL;
|
int retval = OP_LEGAL;
|
int bin;
|
int bin;
|
long upper_64kb = 0xFFFF0000;
|
uint32_t upper_64kb = 0xffff0000;
|
long value = *num;
|
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);
|
|
|
|
/* Verify operand value is even. */
|
/* Verify operand value is even. */
|
if (flags & OP_EVEN)
|
if (flags & OP_EVEN)
|
{
|
{
|
if (value % 2)
|
if (value % 2)
|
Line 1358... |
Line 1351... |
return OP_NOT_UPPER_64KB;
|
return OP_NOT_UPPER_64KB;
|
}
|
}
|
|
|
if (flags & OP_SHIFT)
|
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 >>= 1;
|
|
value = (value ^ 0x40000000) - 0x40000000;
|
if (update)
|
if (update)
|
*num = value;
|
*num = value;
|
}
|
}
|
else if (flags & OP_SHIFT_DEC)
|
else if (flags & OP_SHIFT_DEC)
|
{
|
{
|
Line 1380... |
Line 1378... |
|
|
if (flags & OP_DISPU4)
|
if (flags & OP_DISPU4)
|
{
|
{
|
int is_dispu4 = 0;
|
int is_dispu4 = 0;
|
|
|
int mul = (instruction->flags & DISPUB4) ? 1
|
uint32_t mul = (instruction->flags & DISPUB4 ? 1
|
: (instruction->flags & DISPUW4) ? 2
|
: instruction->flags & DISPUW4 ? 2
|
: (instruction->flags & DISPUD4) ? 4 : 0;
|
: instruction->flags & DISPUD4 ? 4
|
|
: 0);
|
|
|
for (bin = 0; bin < cst4_maps; bin++)
|
for (bin = 0; bin < cst4_maps; bin++)
|
{
|
{
|
if (value == (mul * bin))
|
if (value == mul * bin)
|
{
|
{
|
is_dispu4 = 1;
|
is_dispu4 = 1;
|
if (update)
|
if (update)
|
*num = bin;
|
*num = bin;
|
break;
|
break;
|
Line 1403... |
Line 1402... |
{
|
{
|
int is_cst4 = 0;
|
int is_cst4 = 0;
|
|
|
for (bin = 0; bin < cst4_maps; bin++)
|
for (bin = 0; bin < cst4_maps; bin++)
|
{
|
{
|
if (value == cst4_map[bin])
|
if (value == (uint32_t) cst4_map[bin])
|
{
|
{
|
is_cst4 = 1;
|
is_cst4 = 1;
|
if (update)
|
if (update)
|
*num = bin;
|
*num = bin;
|
break;
|
break;
|
Line 1416... |
Line 1415... |
if (!is_cst4)
|
if (!is_cst4)
|
retval = OP_ILLEGAL_CST4;
|
retval = OP_ILLEGAL_CST4;
|
}
|
}
|
else if (flags & OP_SIGNED)
|
else if (flags & OP_SIGNED)
|
{
|
{
|
max = (1 << (bits - 1)) - 1;
|
max = 1;
|
min = - (1 << (bits - 1));
|
max = max << (bits - 1);
|
if ((value > max) || (value < min))
|
value += max;
|
|
max = ((max - 1) << 1) | 1;
|
|
if (value > max)
|
retval = OP_OUT_OF_RANGE;
|
retval = OP_OUT_OF_RANGE;
|
}
|
}
|
else if (flags & OP_UNSIGNED)
|
else if (flags & OP_UNSIGNED)
|
{
|
{
|
max = ((((1 << (bits - 1)) - 1) << 1) | 1);
|
max = 1;
|
min = 0;
|
max = max << (bits - 1);
|
if (((unsigned long) value > (unsigned long) max)
|
max = ((max - 1) << 1) | 1;
|
|| ((unsigned long) value < (unsigned long) min))
|
if (value > max)
|
retval = OP_OUT_OF_RANGE;
|
retval = OP_OUT_OF_RANGE;
|
}
|
}
|
return retval;
|
return retval;
|
}
|
}
|
|
|