diff options
author | Nick Clifton <nickc@redhat.com> | 2004-12-22 14:25:42 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2004-12-22 14:25:42 +0000 |
commit | 750bce0ee10ab816e29d8f01733ad000466181fb (patch) | |
tree | 7b299de8a67aa64196ee9cbda3b524f9a4a89270 /gas/config | |
parent | 76a56260628e949cd60b00f8035a53cbadca61ad (diff) | |
download | gdb-750bce0ee10ab816e29d8f01733ad000466181fb.zip gdb-750bce0ee10ab816e29d8f01733ad000466181fb.tar.gz gdb-750bce0ee10ab816e29d8f01733ad000466181fb.tar.bz2 |
Add support for the new R_AVR_LDI, R_AVR_6 and R_AVR_6_ADIW relocs for the
LDI, ADIW/SBIW and LDD/STD instructions.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-avr.c | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c index 31bb780..c0c2e3b 100644 --- a/gas/config/tc-avr.c +++ b/gas/config/tc-avr.c @@ -1,6 +1,6 @@ /* tc-avr.c -- Assembler code for the ATMEL AVR - Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. Contributed by Denis Chertykov <denisc@overta.ru> This file is part of GAS, the GNU Assembler. @@ -557,6 +557,31 @@ avr_operands (opcode, line) return bin; } +/* Parse for ldd/std offset */ + +static void +avr_offset_expression (expressionS *exp) +{ + char *str = input_line_pointer; + char *tmp; + char op[8]; + + tmp = str; + str = extract_word (str, op, sizeof (op)); + + input_line_pointer = tmp; + expression (exp); + + /* Warn about expressions that fail to use lo8 (). */ + if (exp->X_op == O_constant) + { + int x = exp->X_add_number; + + if (x < -255 || x > 255) + as_warn (_("constant out of 8-bit range: %d"), x); + } +} + /* Parse one instruction operand. Return operand bitmask. Also fixups can be generated. */ @@ -695,10 +720,11 @@ avr_operand (opcode, where, op, line) str = skip_space (str); if (*str++ == '+') { - unsigned int x; - x = avr_get_constant (str, 63); + input_line_pointer = str; + avr_offset_expression (& op_expr); str = input_line_pointer; - op_mask |= (x & 7) | ((x & (3 << 3)) << 7) | ((x & (1 << 5)) << 8); + fix_new_exp (frag_now, where, 3, + &op_expr, FALSE, BFD_RELOC_AVR_6); } } break; @@ -750,13 +776,11 @@ avr_operand (opcode, where, op, line) break; case 'K': - { - unsigned int x; - - x = avr_get_constant (str, 63); - str = input_line_pointer; - op_mask |= (x & 0xf) | ((x & 0x30) << 2); - } + input_line_pointer = str; + avr_offset_expression (& op_expr); + str = input_line_pointer; + fix_new_exp (frag_now, where, 3, + & op_expr, FALSE, BFD_RELOC_AVR_6_ADIW); break; case 'S': @@ -936,6 +960,27 @@ md_apply_fix3 (fixP, valP, seg) bfd_putl16 ((bfd_vma) (value >> 1), where); break; + case BFD_RELOC_AVR_LDI: + if (value > 255) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("operand out of range: %ld"), value); + bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where); + break; + + case BFD_RELOC_AVR_6: + if ((value > 63) || (value < 0)) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("operand out of range: %ld"), value); + bfd_putl16 ((bfd_vma) insn | ((value & 7) | ((value & (3 << 3)) << 7) | ((value & (1 << 5)) << 8)), where); + break; + + case BFD_RELOC_AVR_6_ADIW: + if ((value > 63) || (value < 0)) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("operand out of range: %ld"), value); + bfd_putl16 ((bfd_vma) insn | (value & 0xf) | ((value & 0x30) << 2), where); + break; + case BFD_RELOC_AVR_LO8_LDI: bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where); break; @@ -1227,10 +1272,8 @@ avr_ldi_expression (exp) if (x < -255 || x > 255) as_warn (_("constant out of 8-bit range: %d"), x); } - else - as_warn (_("expression possibly out of 8-bit range")); - return BFD_RELOC_AVR_LO8_LDI; + return BFD_RELOC_AVR_LDI; } /* Flag to pass `pm' mode between `avr_parse_cons_expression' and |