{"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},
{"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}
};
" 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"
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':
break;
}
break;
- }
- as_bad (_("register name or number from 0 to 31 required"));
- break;
case 'e':
{
&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;
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:
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);
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,