diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c index 8f6d0ec..6e6f0d0 100644 --- a/gas/config/tc-avr.c +++ b/gas/config/tc-avr.c @@ -862,28 +862,40 @@ avr_operand (struct avr_opcodes_s *opcode, case 'r': case 'a': case 'v': - if (*str == 'r' || *str == 'R') - { - char r_name[20]; - - str = extract_word (str, r_name, sizeof (r_name)); - op_mask = 0xff; - if (ISDIGIT (r_name[1])) - { - if (r_name[2] == '\0') - op_mask = r_name[1] - '0'; - else if (r_name[1] != '0' - && ISDIGIT (r_name[2]) - && r_name[3] == '\0') - op_mask = (r_name[1] - '0') * 10 + r_name[2] - '0'; - } - } - else - { - op_mask = avr_get_constant (str, 31); - str = input_line_pointer; - } - + { + char * old_str = str; + char *lower; + char r_name[20]; + + str = extract_word (str, r_name, sizeof (r_name)); + for (lower = r_name; *lower; ++lower) + { + if (*lower >= 'A' && *lower <= 'Z') + *lower += 'a' - 'A'; + } + if (r_name[0] == 'r' && ISDIGIT (r_name[1]) && r_name[2] == 0) + /* Single-digit register number, ie r0-r9 */ + op_mask = r_name[1] - '0'; + else if (r_name[0] == 'r' && ISDIGIT (r_name[1]) && + ISDIGIT (r_name[2]) && r_name[3] == 0) + /* Double-digit register number, ie r10 - r32 */ + op_mask = (r_name[1] - '0') * 10 + r_name[2] - '0'; + else if (r_name[0] >= 'x' && r_name[0] <= 'z' && + (r_name[1] == 'l' || r_name[1] == 'h') && r_name[2] == 0) + /* registers r26-r31 referred to by name, ie xl, xh, yl, yh, zl, zh */ + op_mask = (r_name[0] - 'x') * 2 + (r_name[1] == 'h') + 26; + else if ((*op == 'v' || *op == 'w') && + r_name[0] >= 'x' && r_name[0] <= 'z' && r_name[1] == 0) + /* For the movw and addiw instructions, refer to registers x, y and z by name */ + op_mask = (r_name[0] - 'x') * 2 + 26; + else + { + /* Numeric or symbolic constant register number */ + op_mask = avr_get_constant (old_str, 31); + str = input_line_pointer; + } + } + if (avr_mcu->isa & AVR_ISA_FEW_REGS) { if (op_mask < 16 || op_mask >= 32)