From 8cb8bcbabb9d13b10a965bde4c72d38612e17464 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 16 Aug 2000 19:02:00 +0000 Subject: [PATCH] Tidy up decoding of shift based addressing modes. Add extra tests for these addressing modes --- gas/ChangeLog | 17 +++ gas/config/tc-arm.c | 206 ++++++++++++++++++++--------------- gas/testsuite/ChangeLog | 7 ++ gas/testsuite/gas/arm/inst.d | 32 ++++++ gas/testsuite/gas/arm/inst.s | 34 ++++++ 5 files changed, 208 insertions(+), 88 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 49bce914e97..f494672e58b 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,20 @@ +2000-08-16 Nick Clifton + + * 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 * config/tc-sparc.c: Kill all warnings. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 5ca0815288f..a2ae26f8c55 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -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 +}; + +struct asm_shift_properties +{ + enum asm_shift_index index; + unsigned long bit_field; + unsigned int allows_0 : 1; + unsigned int allows_32 : 1; }; -static CONST struct asm_shift shift[] = -{ - {"asl", 0}, - {"lsl", 0}, - {"lsr", 0x00000020}, - {"asr", 0x00000040}, - {"ror", 0x00000060}, - {"rrx", 0x00000060}, - {"ASL", 0}, - {"LSL", 0}, - {"LSR", 0x00000020}, - {"ASR", 0x00000040}, - {"ROR", 0x00000060}, - {"RRX", 0x00000060} +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; - } + inst.error = _("Shift expression expected"); + return FAIL; + } - skip_whitespace (p); + 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; + } - 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 ++; + skip_whitespace (p); - if (my_get_expression (& inst.reloc.exp, & p)) - return FAIL; + 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; - /* Validate some simple #expressions. */ - if (inst.reloc.exp.X_op == O_constant) + /* 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 { - 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.error = _("Invalid immediate shift"); + return FAIL; } - - 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; + /* 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)" diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index d815495219b..4cdeffbfca8 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2000-08-16 Nick Clifton + + * 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 * gas/all/gas.exp: Don't run floating-point tests on CRIS. diff --git a/gas/testsuite/gas/arm/inst.d b/gas/testsuite/gas/arm/inst.d index 041f65b788d..70fff23805c 100644 --- a/gas/testsuite/gas/arm/inst.d +++ b/gas/testsuite/gas/arm/inst.d @@ -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 diff --git a/gas/testsuite/gas/arm/inst.s b/gas/testsuite/gas/arm/inst.s index f76bac9e4b6..b162cfceca0 100644 --- a/gas/testsuite/gas/arm/inst.s +++ b/gas/testsuite/gas/arm/inst.s @@ -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 + \ No newline at end of file -- 2.30.2