aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-avr.c
diff options
context:
space:
mode:
authorBarney Stratford <barney_stratford@fastmail.fm>2014-07-01 10:20:17 +0100
committerNick Clifton <nickc@redhat.com>2014-07-01 10:20:17 +0100
commitf36e88862f94c15a88fa27df7af906ad75a42e7f (patch)
tree9add52ee9bff834949cac235d41b733efd326d4e /gas/config/tc-avr.c
parentba8e7d1e24bc53269b5814c99a321783dab3812a (diff)
downloadgdb-f36e88862f94c15a88fa27df7af906ad75a42e7f.zip
gdb-f36e88862f94c15a88fa27df7af906ad75a42e7f.tar.gz
gdb-f36e88862f94c15a88fa27df7af906ad75a42e7f.tar.bz2
Add support for the AVR Tiny series of microcontrollers.
* archures.c: add avrtiny architecture for avr target. * bfd-in2.h: Regenerate. * cpu-avr.c (arch_info_struct): add avrtiny arch info. * elf32-avr.c (elf_avr_howto_table): new relocation R_AVR_LDS_STS_16 added for 16 bit LDS/STS instruction of avrtiny arch. (avr_reloc_map): reloc R_AVR_LDS_STS_16 is mapped to BFD_RELOC_AVR_LDS_STS_16. (bfd_elf_avr_final_write_processing): select machine number avrtiny arch. (elf32_avr_object_p): set machine number for avrtiny arch. * libbfd.h: Regenerate. * reloc.c: Add documentation for BFD_RELOC_AVR_LDS_STS_16 reloc. * config/tc-avr.c (mcu_types): Add avrtiny arch. Add avrtiny arch devices attiny4, attiny5, attiny9, attiny10, attiny20 and attiny40. (md_show_usage): Add avrtiny arch in usage message. (avr_operand): validate and issue error for invalid register for avrtiny. add new reloc exp for 16 bit lds/sts instruction. (md_apply_fix): check 16 bit lds/sts operand for out of range and encode. (md_assemble): check ISA for arch and issue diagnostic. * include/elf/avr.h (E_AVR_MACH_AVRTINY): define avrtiny machine number. (R_AVR_LDS_STS_16): define 16 bit lds/sts reloc number. * include/opcode/avr.h (AVR_ISA_TINY): define avrtiny specific ISA. (AVR_ISA_2xxxa): define ISA without LPM. (AVR_ISA_AVRTINY): define avrtiny arch ISA. Add doc for contraint used in 16 bit lds/sts. Adjust ISA group for icall, ijmp, pop and push. Add 16 bit lds/sts encoding and update 32 bit lds/sts constraints. * opcodes/avr-dis.c (avr_operand): Handle constraint j for 16 bit lds/sts. (print_insn_avr): do not select opcode if insn ISA is avrtiny and machine is not avrtiny. * Makefile.am (ALL_EMULATION_SOURCES): add avrtiny emulation source. (eavrtiny.c): add rules for avrtiny emulation source. * Makefile.in: Regenerate. * configure.tgt: Add avrtiny to avr target emulations. * scripttempl/avrtiny.sc: New file. linker script template for avrtiny arch. * emulparams/avrtiny.sh: New file. emulation parameters for avrtiny arch.
Diffstat (limited to 'gas/config/tc-avr.c')
-rw-r--r--gas/config/tc-avr.c107
1 files changed, 79 insertions, 28 deletions
diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c
index e4bc59c..9ed7de8 100644
--- a/gas/config/tc-avr.c
+++ b/gas/config/tc-avr.c
@@ -89,6 +89,7 @@ static struct mcu_type_s mcu_types[] =
{"avrxmega5", AVR_ISA_XMEGA, bfd_mach_avrxmega5},
{"avrxmega6", AVR_ISA_XMEGA, bfd_mach_avrxmega6},
{"avrxmega7", AVR_ISA_XMEGA, bfd_mach_avrxmega7},
+ {"avrtiny", AVR_ISA_AVRTINY, bfd_mach_avrtiny},
{"at90s1200", AVR_ISA_1200, bfd_mach_avr1},
{"attiny11", AVR_ISA_AVR1, bfd_mach_avr1},
{"attiny12", AVR_ISA_AVR1, bfd_mach_avr1},
@@ -323,6 +324,12 @@ static struct mcu_type_s mcu_types[] =
{"atxmega128a1", AVR_ISA_XMEGA, bfd_mach_avrxmega7},
{"atxmega128a1u", AVR_ISA_XMEGAU, bfd_mach_avrxmega7},
{"atxmega128a4u", AVR_ISA_XMEGAU, bfd_mach_avrxmega7},
+ {"attiny4", AVR_ISA_AVRTINY, bfd_mach_avrtiny},
+ {"attiny5", AVR_ISA_AVRTINY, bfd_mach_avrtiny},
+ {"attiny9", AVR_ISA_AVRTINY, bfd_mach_avrtiny},
+ {"attiny10", AVR_ISA_AVRTINY, bfd_mach_avrtiny},
+ {"attiny20", AVR_ISA_AVRTINY, bfd_mach_avrtiny},
+ {"attiny40", AVR_ISA_AVRTINY, bfd_mach_avrtiny},
{NULL, 0, 0}
};
@@ -513,7 +520,7 @@ md_show_usage (FILE *stream)
" avrxmega5 - XMEGA, > 64K, <= 128K FLASH, > 64K RAM\n"
" avrxmega6 - XMEGA, > 128K, <= 256K FLASH, <= 64K RAM\n"
" avrxmega7 - XMEGA, > 128K, <= 256K FLASH, > 64K RAM\n"
- " or immediate microcontroller name.\n"));
+ " avrtiny - AVR Tiny core with 16 gp registers\n"));
fprintf (stream,
_(" -mall-opcodes accept all AVR opcodes, even if not supported by MCU\n"
" -mno-skip-bug disable warnings for skipping two-word instructions\n"
@@ -855,29 +862,41 @@ avr_operand (struct avr_opcodes_s *opcode,
case 'a':
case 'v':
if (*str == 'r' || *str == 'R')
- {
- char r_name[20];
+ {
+ 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';
- }
- }
+ 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;
- }
+ {
+ op_mask = avr_get_constant (str, 31);
+ str = input_line_pointer;
+ }
+
+ if (avr_mcu->mach == bfd_mach_avrtiny)
+ {
+ if (op_mask < 16 || op_mask > 31)
+ {
+ as_bad (_("register name or number from 16 to 31 required"));
+ break;
+ }
+ }
+ else if (op_mask > 31)
+ {
+ as_bad (_("register name or number from 0 to 31 required"));
+ break;
+ }
- if (op_mask <= 31)
- {
switch (*op)
{
case 'a':
@@ -905,9 +924,6 @@ avr_operand (struct avr_opcodes_s *opcode,
break;
}
break;
- }
- as_bad (_("register name or number from 0 to 31 required"));
- break;
case 'e':
{
@@ -1014,6 +1030,12 @@ avr_operand (struct avr_opcodes_s *opcode,
&op_expr, FALSE, BFD_RELOC_16);
break;
+ case 'j':
+ str = parse_exp (str, &op_expr);
+ fix_new_exp (frag_now, where, opcode->insn_size * 2,
+ &op_expr, FALSE, BFD_RELOC_AVR_LDS_STS_16);
+ break;
+
case 'M':
{
bfd_reloc_code_real_type r_type;
@@ -1415,11 +1437,21 @@ md_apply_fix (fixS *fixP, valueT * valP, segT seg)
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where);
break;
+ case BFD_RELOC_AVR_LDS_STS_16:
+ if ((value < 0x40) || (value > 0xBF))
+ as_warn_where (fixP->fx_file, fixP->fx_line,
+ _("operand out of range: 0x%lx"),
+ (unsigned long)value);
+ insn |= ((value & 0xF) | ((value & 0x30) << 5) | ((value & 0x40) << 2));
+ bfd_putl16 ((bfd_vma) insn, 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);
+ bfd_putl16 ((bfd_vma) insn | ((value & 7) | ((value & (3 << 3)) << 7)
+ | ((value & (1 << 5)) << 8)), where);
break;
case BFD_RELOC_AVR_6_ADIW:
@@ -1594,6 +1626,28 @@ md_assemble (char *str)
opcode = (struct avr_opcodes_s *) hash_find (avr_hash, op);
+ if (opcode && !avr_opt.all_opcodes)
+ {
+ /* Check if the instruction's ISA bit is ON in the ISA bits of the part
+ specified by the user. If not look for other instructions
+ specifications with same mnemonic who's ISA bits matches.
+
+ This requires include/opcode/avr.h to have the instructions with
+ same mnenomic to be specified in sequence. */
+
+ while ((opcode->isa & avr_mcu->isa) != opcode->isa)
+ {
+ opcode++;
+
+ if (opcode->name && strcmp(op, opcode->name))
+ {
+ as_bad (_("illegal opcode %s for mcu %s"),
+ opcode->name, avr_mcu->name);
+ return;
+ }
+ }
+ }
+
if (opcode == NULL)
{
as_bad (_("unknown opcode `%s'"), op);
@@ -1606,9 +1660,6 @@ md_assemble (char *str)
if (*str && *opcode->constraints == '?')
++opcode;
- if (!avr_opt.all_opcodes && (opcode->isa & avr_mcu->isa) != opcode->isa)
- as_bad (_("illegal opcode %s for mcu %s"), opcode->name, avr_mcu->name);
-
dwarf2_emit_insn (0);
/* We used to set input_line_pointer to the result of get_operands,