Tidy up decoding of shift based addressing modes.
Add extra tests for these addressing modes
This commit is contained in:
parent
e52ef561b8
commit
8cb8bcbabb
5 changed files with 213 additions and 93 deletions
|
@ -1,3 +1,20 @@
|
|||
2000-08-16 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* config/tc-arm.c (struct asm_shift): Delete.
|
||||
(shift[]): Delete.
|
||||
(enum asm_shift_index): New.
|
||||
(struct asm_shift_properties): New.
|
||||
(struct asm_shift_name): New.
|
||||
(shift_properties[]); New.
|
||||
(shift_names[]); New.
|
||||
|
||||
(decode_shift): Use new structures.
|
||||
Issue a warning is "ROR #0" is used.
|
||||
Issue a warning if "ASR #0" or "LSR #0" is used.
|
||||
|
||||
(md_begin): Initialise arm_shift_hsh table from new
|
||||
asm_shift_name array.
|
||||
|
||||
2000-08-16 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/tc-sparc.c: Kill all warnings.
|
||||
|
|
|
@ -166,28 +166,54 @@ struct arm_it
|
|||
|
||||
struct arm_it inst;
|
||||
|
||||
struct asm_shift
|
||||
enum asm_shift_index
|
||||
{
|
||||
CONST char * template;
|
||||
unsigned long value;
|
||||
SHIFT_LSL = 0,
|
||||
SHIFT_LSR,
|
||||
SHIFT_ASR,
|
||||
SHIFT_ROR,
|
||||
SHIFT_RRX
|
||||
};
|
||||
|
||||
static CONST struct asm_shift shift[] =
|
||||
struct asm_shift_properties
|
||||
{
|
||||
{"asl", 0},
|
||||
{"lsl", 0},
|
||||
{"lsr", 0x00000020},
|
||||
{"asr", 0x00000040},
|
||||
{"ror", 0x00000060},
|
||||
{"rrx", 0x00000060},
|
||||
{"ASL", 0},
|
||||
{"LSL", 0},
|
||||
{"LSR", 0x00000020},
|
||||
{"ASR", 0x00000040},
|
||||
{"ROR", 0x00000060},
|
||||
{"RRX", 0x00000060}
|
||||
enum asm_shift_index index;
|
||||
unsigned long bit_field;
|
||||
unsigned int allows_0 : 1;
|
||||
unsigned int allows_32 : 1;
|
||||
};
|
||||
|
||||
static const struct asm_shift_properties shift_properties [] =
|
||||
{
|
||||
{ SHIFT_LSL, 0, 1, 0},
|
||||
{ SHIFT_LSR, 0x20, 0, 1},
|
||||
{ SHIFT_ASR, 0x40, 0, 1},
|
||||
{ SHIFT_ROR, 0x60, 0, 0},
|
||||
{ SHIFT_RRX, 0x60, 0, 0}
|
||||
};
|
||||
|
||||
struct asm_shift_name
|
||||
{
|
||||
const char * name;
|
||||
const struct asm_shift_properties * properties;
|
||||
};
|
||||
|
||||
static const struct asm_shift_name shift_names [] =
|
||||
{
|
||||
{ "asl", shift_properties + SHIFT_LSL },
|
||||
{ "lsl", shift_properties + SHIFT_LSL },
|
||||
{ "lsr", shift_properties + SHIFT_LSR },
|
||||
{ "asr", shift_properties + SHIFT_ASR },
|
||||
{ "ror", shift_properties + SHIFT_ROR },
|
||||
{ "rrx", shift_properties + SHIFT_RRX },
|
||||
{ "ASL", shift_properties + SHIFT_LSL },
|
||||
{ "LSL", shift_properties + SHIFT_LSL },
|
||||
{ "LSR", shift_properties + SHIFT_LSR },
|
||||
{ "ASR", shift_properties + SHIFT_ASR },
|
||||
{ "ROR", shift_properties + SHIFT_ROR },
|
||||
{ "RRX", shift_properties + SHIFT_RRX }
|
||||
};
|
||||
|
||||
#define NO_SHIFT_RESTRICT 1
|
||||
#define SHIFT_RESTRICT 0
|
||||
|
||||
|
@ -2505,7 +2531,7 @@ decode_shift (str, unrestrict)
|
|||
char ** str;
|
||||
int unrestrict;
|
||||
{
|
||||
struct asm_shift * shft;
|
||||
struct asm_shift_name * shift;
|
||||
char * p;
|
||||
char c;
|
||||
|
||||
|
@ -2522,83 +2548,87 @@ decode_shift (str, unrestrict)
|
|||
|
||||
c = * p;
|
||||
* p = '\0';
|
||||
shft = (struct asm_shift *) hash_find (arm_shift_hsh, * str);
|
||||
shift = (struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
|
||||
* p = c;
|
||||
if (shft)
|
||||
|
||||
if (shift == NULL)
|
||||
{
|
||||
if ( ! strncmp (* str, "rrx", 3)
|
||||
|| ! strncmp (* str, "RRX", 3))
|
||||
{
|
||||
* str = p;
|
||||
inst.instruction |= shft->value;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
skip_whitespace (p);
|
||||
|
||||
if (unrestrict && reg_required_here (& p, 8) != FAIL)
|
||||
{
|
||||
inst.instruction |= shft->value | SHIFT_BY_REG;
|
||||
* str = p;
|
||||
return SUCCESS;
|
||||
}
|
||||
else if (is_immediate_prefix (* p))
|
||||
{
|
||||
inst.error = NULL;
|
||||
p ++;
|
||||
|
||||
if (my_get_expression (& inst.reloc.exp, & p))
|
||||
return FAIL;
|
||||
|
||||
/* Validate some simple #expressions. */
|
||||
if (inst.reloc.exp.X_op == O_constant)
|
||||
{
|
||||
unsigned num = inst.reloc.exp.X_add_number;
|
||||
|
||||
/* Reject operations greater than 32, or lsl #32. */
|
||||
if (num > 32 || (num == 32 && shft->value == 0))
|
||||
{
|
||||
inst.error = _("Invalid immediate shift");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/* Shifts of zero should be converted to lsl
|
||||
(which is zero). */
|
||||
if (num == 0)
|
||||
{
|
||||
* str = p;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Shifts of 32 are encoded as 0, for those shifts that
|
||||
support it. */
|
||||
if (num == 32)
|
||||
num = 0;
|
||||
|
||||
inst.instruction |= (num << 7) | shft->value;
|
||||
* str = p;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
|
||||
inst.reloc.pc_rel = 0;
|
||||
inst.instruction |= shft->value;
|
||||
|
||||
* str = p;
|
||||
return SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
inst.error = (unrestrict
|
||||
? _("shift requires register or #expression")
|
||||
: _("shift requires #expression"));
|
||||
* str = p;
|
||||
return FAIL;
|
||||
}
|
||||
inst.error = _("Shift expression expected");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
inst.error = _("Shift expression expected");
|
||||
return FAIL;
|
||||
assert (shift->properties->index == shift_properties[shift->properties->index].index);
|
||||
|
||||
if (shift->properties->index == SHIFT_RRX)
|
||||
{
|
||||
* str = p;
|
||||
inst.instruction |= shift->properties->bit_field;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
skip_whitespace (p);
|
||||
|
||||
if (unrestrict && reg_required_here (& p, 8) != FAIL)
|
||||
{
|
||||
inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
|
||||
* str = p;
|
||||
return SUCCESS;
|
||||
}
|
||||
else if (! is_immediate_prefix (* p))
|
||||
{
|
||||
inst.error = (unrestrict
|
||||
? _("shift requires register or #expression")
|
||||
: _("shift requires #expression"));
|
||||
* str = p;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
inst.error = NULL;
|
||||
p ++;
|
||||
|
||||
if (my_get_expression (& inst.reloc.exp, & p))
|
||||
return FAIL;
|
||||
|
||||
/* Validate some simple #expressions. */
|
||||
if (inst.reloc.exp.X_op == O_constant)
|
||||
{
|
||||
unsigned num = inst.reloc.exp.X_add_number;
|
||||
|
||||
/* Reject operations greater than 32. */
|
||||
if (num > 32
|
||||
/* Reject a shift of 0 unless the mode allows it. */
|
||||
|| (num == 0 && shift->properties->allows_0 == 0)
|
||||
/* Reject a shift of 32 unless the mode allows it. */
|
||||
|| (num == 32 && shift->properties->allows_32 == 0)
|
||||
)
|
||||
{
|
||||
/* As a special case we allow ROR #0, but we issue a message
|
||||
reminding the programmer that this is actually an RRX. */
|
||||
if (num == 0 && shift->properties->index == SHIFT_ROR)
|
||||
as_tsktsk (_("ROR #0 is actually RRX"));
|
||||
else
|
||||
{
|
||||
inst.error = _("Invalid immediate shift");
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shifts of 32 are encoded as 0, for those shifts that
|
||||
support it. */
|
||||
if (num == 32)
|
||||
num = 0;
|
||||
|
||||
inst.instruction |= (num << 7) | shift->properties->bit_field;
|
||||
}
|
||||
else
|
||||
{
|
||||
inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
|
||||
inst.reloc.pc_rel = 0;
|
||||
inst.instruction |= shift->properties->bit_field;
|
||||
}
|
||||
|
||||
* str = p;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Do those data_ops which can take a negative immediate constant
|
||||
|
@ -5240,8 +5270,8 @@ md_begin ()
|
|||
hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
|
||||
for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
|
||||
hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
|
||||
for (i = 0; i < sizeof (shift) / sizeof (struct asm_shift); i++)
|
||||
hash_insert (arm_shift_hsh, shift[i].template, (PTR) (shift + i));
|
||||
for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
|
||||
hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
|
||||
for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
|
||||
hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
|
||||
|
||||
|
@ -7388,7 +7418,7 @@ arm_parse_reloc ()
|
|||
}
|
||||
reloc_map[] =
|
||||
{
|
||||
#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
|
||||
#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
|
||||
MAP ("(got)", BFD_RELOC_ARM_GOT32),
|
||||
MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
|
||||
/* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2000-08-16 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* gas/arm/inst.s: Add tests for edge cases of shift based
|
||||
addressing modes.
|
||||
|
||||
* gas/arm/inst.d: Add expected results for new tests.
|
||||
|
||||
2000-07-20 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
* gas/all/gas.exp: Don't run floating-point tests on CRIS.
|
||||
|
|
|
@ -167,3 +167,35 @@ Disassembly of section .text:
|
|||
[ ]*268:.*_wibble.*
|
||||
0000026c <[^>]*> dafffffe ? ble 0000026c <[^>]*>
|
||||
[ ]*26c:.*testerfunc.*
|
||||
00000270 <[^>]*> e1a01102 ? mov r1, r2, lsl #2
|
||||
00000274 <[^>]*> e1a01002 ? mov r1, r2
|
||||
00000278 <[^>]*> e1a01f82 ? mov r1, r2, lsl #31
|
||||
0000027c <[^>]*> e1a01312 ? mov r1, r2, lsl r3
|
||||
00000280 <[^>]*> e1a01122 ? mov r1, r2, lsr #2
|
||||
00000284 <[^>]*> e1a01fa2 ? mov r1, r2, lsr #31
|
||||
00000288 <[^>]*> e1a01022 ? mov r1, r2, lsr #32
|
||||
0000028c <[^>]*> e1a01332 ? mov r1, r2, lsr r3
|
||||
00000290 <[^>]*> e1a01142 ? mov r1, r2, asr #2
|
||||
00000294 <[^>]*> e1a01fc2 ? mov r1, r2, asr #31
|
||||
00000298 <[^>]*> e1a01042 ? mov r1, r2, asr #32
|
||||
0000029c <[^>]*> e1a01352 ? mov r1, r2, asr r3
|
||||
000002a0 <[^>]*> e1a01162 ? mov r1, r2, ror #2
|
||||
000002a4 <[^>]*> e1a01fe2 ? mov r1, r2, ror #31
|
||||
000002a8 <[^>]*> e1a01372 ? mov r1, r2, ror r3
|
||||
000002ac <[^>]*> e1a01062 ? mov r1, r2, rrx
|
||||
000002b0 <[^>]*> e1a01102 ? mov r1, r2, lsl #2
|
||||
000002b4 <[^>]*> e1a01002 ? mov r1, r2
|
||||
000002b8 <[^>]*> e1a01f82 ? mov r1, r2, lsl #31
|
||||
000002bc <[^>]*> e1a01312 ? mov r1, r2, lsl r3
|
||||
000002c0 <[^>]*> e1a01122 ? mov r1, r2, lsr #2
|
||||
000002c4 <[^>]*> e1a01fa2 ? mov r1, r2, lsr #31
|
||||
000002c8 <[^>]*> e1a01022 ? mov r1, r2, lsr #32
|
||||
000002cc <[^>]*> e1a01332 ? mov r1, r2, lsr r3
|
||||
000002d0 <[^>]*> e1a01142 ? mov r1, r2, asr #2
|
||||
000002d4 <[^>]*> e1a01fc2 ? mov r1, r2, asr #31
|
||||
000002d8 <[^>]*> e1a01042 ? mov r1, r2, asr #32
|
||||
000002dc <[^>]*> e1a01352 ? mov r1, r2, asr r3
|
||||
000002e0 <[^>]*> e1a01162 ? mov r1, r2, ror #2
|
||||
000002e4 <[^>]*> e1a01fe2 ? mov r1, r2, ror #31
|
||||
000002e8 <[^>]*> e1a01372 ? mov r1, r2, ror r3
|
||||
000002ec <[^>]*> e1a01062 ? mov r1, r2, rrx
|
||||
|
|
|
@ -187,3 +187,37 @@ bar:
|
|||
blpl hohum
|
||||
b _wibble
|
||||
ble testerfunc
|
||||
|
||||
mov r1, r2, lsl #2
|
||||
mov r1, r2, lsl #0
|
||||
mov r1, r2, lsl #31
|
||||
mov r1, r2, lsl r3
|
||||
mov r1, r2, lsr #2
|
||||
mov r1, r2, lsr #31
|
||||
mov r1, r2, lsr #32
|
||||
mov r1, r2, lsr r3
|
||||
mov r1, r2, asr #2
|
||||
mov r1, r2, asr #31
|
||||
mov r1, r2, asr #32
|
||||
mov r1, r2, asr r3
|
||||
mov r1, r2, ror #2
|
||||
mov r1, r2, ror #31
|
||||
mov r1, r2, ror r3
|
||||
mov r1, r2, rrx
|
||||
mov r1, r2, LSL #2
|
||||
mov r1, r2, LSL #0
|
||||
mov r1, r2, LSL #31
|
||||
mov r1, r2, LSL r3
|
||||
mov r1, r2, LSR #2
|
||||
mov r1, r2, LSR #31
|
||||
mov r1, r2, LSR #32
|
||||
mov r1, r2, LSR r3
|
||||
mov r1, r2, ASR #2
|
||||
mov r1, r2, ASR #31
|
||||
mov r1, r2, ASR #32
|
||||
mov r1, r2, ASR r3
|
||||
mov r1, r2, ROR #2
|
||||
mov r1, r2, ROR #31
|
||||
mov r1, r2, ROR r3
|
||||
mov r1, r2, RRX
|
||||
|
Loading…
Reference in a new issue