diff options
author | Nick Clifton <nickc@redhat.com> | 2005-10-12 10:56:46 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2005-10-12 10:56:46 +0000 |
commit | dc191a8f00d6dccb76ec917ec286b59d6876b010 (patch) | |
tree | 1444c76a892e3f247c69ce82a6d628b5a7fe8211 /gas/config/tc-avr.c | |
parent | 3ed30f54fcf7b4a58b2874b56e10cb945ca4d299 (diff) | |
download | gdb-dc191a8f00d6dccb76ec917ec286b59d6876b010.zip gdb-dc191a8f00d6dccb76ec917ec286b59d6876b010.tar.gz gdb-dc191a8f00d6dccb76ec917ec286b59d6876b010.tar.bz2 |
* config/tc-avr.c: Convert to ISO C90 format. Fix formatting and generally
tidy up the code.
* config/tc-avr.h: Likewise.
Diffstat (limited to 'gas/config/tc-avr.c')
-rw-r--r-- | gas/config/tc-avr.c | 538 |
1 files changed, 251 insertions, 287 deletions
diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c index 3516001..74cc6c3 100644 --- a/gas/config/tc-avr.c +++ b/gas/config/tc-avr.c @@ -25,14 +25,15 @@ #include "as.h" #include "safe-ctype.h" #include "subsegs.h" +#include "libiberty.h" struct avr_opcodes_s { - char *name; - char *constraints; - int insn_size; /* In words. */ - int isa; - unsigned int bin_opcode; + char * name; + char * constraints; + int insn_size; /* In words. */ + int isa; + unsigned int bin_opcode; }; #define AVR_INSN(NAME, CONSTR, OPCODE, SIZE, ISA, BIN) \ @@ -121,22 +122,23 @@ static struct mcu_type_s mcu_types[] = }; /* Current MCU type. */ -static struct mcu_type_s default_mcu = {"avr2", AVR_ISA_2xxx,bfd_mach_avr2}; -static struct mcu_type_s *avr_mcu = &default_mcu; +static struct mcu_type_s default_mcu = {"avr2", AVR_ISA_2xxx,bfd_mach_avr2}; +static struct mcu_type_s * avr_mcu = & default_mcu; /* AVR target-specific switches. */ struct avr_opt_s { - int all_opcodes; /* -mall-opcodes: accept all known AVR opcodes */ - int no_skip_bug; /* -mno-skip-bug: no warnings for skipping 2-word insns */ - int no_wrap; /* -mno-wrap: reject rjmp/rcall with 8K wrap-around */ + int all_opcodes; /* -mall-opcodes: accept all known AVR opcodes. */ + int no_skip_bug; /* -mno-skip-bug: no warnings for skipping 2-word insns. */ + int no_wrap; /* -mno-wrap: reject rjmp/rcall with 8K wrap-around. */ }; static struct avr_opt_s avr_opt = { 0, 0, 0 }; const char EXP_CHARS[] = "eE"; const char FLT_CHARS[] = "dD"; -static void avr_set_arch (int dummy); + +static void avr_set_arch (int); /* The target specific pseudo-ops which we support. */ const pseudo_typeS md_pseudo_table[] = @@ -147,27 +149,17 @@ const pseudo_typeS md_pseudo_table[] = #define LDI_IMMEDIATE(x) (((x) & 0xf) | (((x) << 4) & 0xf00)) -static void show_mcu_list PARAMS ((FILE *)); -static char *skip_space PARAMS ((char *)); -static char *extract_word PARAMS ((char *, char *, int)); -static unsigned int avr_operand PARAMS ((struct avr_opcodes_s *, - int, char *, char **)); -static unsigned int avr_operands PARAMS ((struct avr_opcodes_s *, char **)); -static unsigned int avr_get_constant PARAMS ((char *, int)); -static char *parse_exp PARAMS ((char *, expressionS *)); -static bfd_reloc_code_real_type avr_ldi_expression PARAMS ((expressionS *)); - -#define EXP_MOD_NAME(i) exp_mod[i].name -#define EXP_MOD_RELOC(i) exp_mod[i].reloc -#define EXP_MOD_NEG_RELOC(i) exp_mod[i].neg_reloc -#define HAVE_PM_P(i) exp_mod[i].have_pm +#define EXP_MOD_NAME(i) exp_mod[i].name +#define EXP_MOD_RELOC(i) exp_mod[i].reloc +#define EXP_MOD_NEG_RELOC(i) exp_mod[i].neg_reloc +#define HAVE_PM_P(i) exp_mod[i].have_pm struct exp_mod_s { - char *name; - bfd_reloc_code_real_type reloc; - bfd_reloc_code_real_type neg_reloc; - int have_pm; + char * name; + bfd_reloc_code_real_type reloc; + bfd_reloc_code_real_type neg_reloc; + int have_pm; }; static struct exp_mod_s exp_mod[] = @@ -189,9 +181,12 @@ static struct hash_control *avr_hash; static struct hash_control *avr_mod_hash; #define OPTION_MMCU 'm' -#define OPTION_ALL_OPCODES (OPTION_MD_BASE + 1) -#define OPTION_NO_SKIP_BUG (OPTION_MD_BASE + 2) -#define OPTION_NO_WRAP (OPTION_MD_BASE + 3) +enum options +{ + OPTION_ALL_OPCODES = OPTION_MD_BASE + 1, + OPTION_NO_SKIP_BUG, + OPTION_NO_WRAP +}; struct option md_longopts[] = { @@ -207,8 +202,7 @@ size_t md_longopts_size = sizeof (md_longopts); /* Display nicely formatted list of known MCU names. */ static void -show_mcu_list (stream) - FILE *stream; +show_mcu_list (FILE *stream) { int i, x; @@ -234,8 +228,7 @@ show_mcu_list (stream) } static inline char * -skip_space (s) - char *s; +skip_space (char *s) { while (*s == ' ' || *s == '\t') ++s; @@ -268,17 +261,15 @@ extract_word (char *from, char *to, int limit) } int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp ATTRIBUTE_UNUSED; - asection *seg ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, + asection *seg ATTRIBUTE_UNUSED) { abort (); return 0; } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _("AVR options:\n" @@ -300,21 +291,17 @@ md_show_usage (stream) } static void -avr_set_arch (dummy) - int dummy ATTRIBUTE_UNUSED; +avr_set_arch (int dummy ATTRIBUTE_UNUSED) { - char *str; + char str[20]; - str = (char *) alloca (20); input_line_pointer = extract_word (input_line_pointer, str, 20); md_parse_option (OPTION_MMCU, str); bfd_set_arch_mach (stdoutput, TARGET_ARCH, avr_mcu->mach); } int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, char *arg) { switch (c) { @@ -367,10 +354,9 @@ md_parse_option (c, arg) } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { - return 0; + return NULL; } /* Turn a string in input_line_pointer into a floating point constant @@ -379,10 +365,7 @@ md_undefined_symbol (name) returned, or NULL on OK. */ char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[4]; @@ -419,19 +402,19 @@ md_atof (type, litP, sizeP) } void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - fragS *fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + fragS *fragP ATTRIBUTE_UNUSED) { abort (); } void -md_begin () +md_begin (void) { unsigned int i; struct avr_opcodes_s *opcode; + avr_hash = hash_new (); /* Insert unique names into hash table. This hash table then provides a @@ -442,7 +425,7 @@ md_begin () avr_mod_hash = hash_new (); - for (i = 0; i < sizeof (exp_mod) / sizeof (exp_mod[0]); ++i) + for (i = 0; i < ARRAY_SIZE (exp_mod); ++i) hash_insert (avr_mod_hash, EXP_MOD_NAME (i), (void *) (i + 10)); bfd_set_arch_mach (stdoutput, TARGET_ARCH, avr_mcu->mach); @@ -452,14 +435,13 @@ md_begin () If result greater than MAX then error. */ static unsigned int -avr_get_constant (str, max) - char *str; - int max; +avr_get_constant (char *str, int max) { expressionS ex; + str = skip_space (str); input_line_pointer = str; - expression (&ex); + expression (& ex); if (ex.X_op != O_constant) as_bad (_("constant value required")); @@ -470,105 +452,124 @@ avr_get_constant (str, max) return ex.X_add_number; } -/* Parse instruction operands. - Return binary opcode. */ +/* Parse for ldd/std offset. */ -static unsigned int -avr_operands (opcode, line) - struct avr_opcodes_s *opcode; - char **line; +static void +avr_offset_expression (expressionS *exp) { - char *op = opcode->constraints; - unsigned int bin = opcode->bin_opcode; - char *frag = frag_more (opcode->insn_size * 2); - char *str = *line; - int where = frag - frag_now->fr_literal; - static unsigned int prev = 0; /* Previous opcode. */ + char *str = input_line_pointer; + char *tmp; + char op[8]; - /* Opcode have operands. */ - if (*op) + 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) { - unsigned int reg1 = 0; - unsigned int reg2 = 0; - int reg1_present = 0; - int reg2_present = 0; + int x = exp->X_add_number; + + if (x < -255 || x > 255) + as_warn (_("constant out of 8-bit range: %d"), x); + } +} - /* Parse first operand. */ - if (REGISTER_P (*op)) - reg1_present = 1; - reg1 = avr_operand (opcode, where, op, &str); - ++op; +/* Parse ordinary expression. */ - /* Parse second operand. */ - if (*op) - { - if (*op == ',') - ++op; +static char * +parse_exp (char *s, expressionS *op) +{ + input_line_pointer = s; + expression (op); + if (op->X_op == O_absent) + as_bad (_("missing operand")); + return input_line_pointer; +} - if (*op == '=') - { - reg2 = reg1; - reg2_present = 1; - } - else - { - if (REGISTER_P (*op)) - reg2_present = 1; +/* Parse special expressions (needed for LDI command): + xx8 (address) + xx8 (-address) + pm_xx8 (address) + pm_xx8 (-address) + where xx is: hh, hi, lo. */ - str = skip_space (str); - if (*str++ != ',') - as_bad (_("`,' required")); - str = skip_space (str); +static bfd_reloc_code_real_type +avr_ldi_expression (expressionS *exp) +{ + char *str = input_line_pointer; + char *tmp; + char op[8]; + int mod; + tmp = str; - reg2 = avr_operand (opcode, where, op, &str); + str = extract_word (str, op, sizeof (op)); - } + if (op[0]) + { + mod = (int) hash_find (avr_mod_hash, op); - if (reg1_present && reg2_present) - reg2 = (reg2 & 0xf) | ((reg2 << 5) & 0x200); - else if (reg2_present) - reg2 <<= 4; - } - if (reg1_present) - reg1 <<= 4; - bin |= reg1 | reg2; - } + if (mod) + { + int closes = 0; - /* Detect undefined combinations (like ld r31,Z+). */ - if (!avr_opt.all_opcodes && AVR_UNDEF_P (bin)) - as_warn (_("undefined combination of operands")); + mod -= 10; + str = skip_space (str); - if (opcode->insn_size == 2) - { - /* Warn if the previous opcode was cpse/sbic/sbis/sbrc/sbrs - (AVR core bug, fixed in the newer devices). */ + if (*str == '(') + { + int neg_p = 0; - if (!(avr_opt.no_skip_bug || - (avr_mcu->isa & (AVR_ISA_MUL | AVR_ISA_MOVW))) - && AVR_SKIP_P (prev)) - as_warn (_("skipping two-word instruction")); + ++str; - bfd_putl32 ((bfd_vma) bin, frag); - } - else - bfd_putl16 ((bfd_vma) bin, frag); + if (strncmp ("pm(", str, 3) == 0 + || strncmp ("-(pm(", str, 5) == 0) + { + if (HAVE_PM_P (mod)) + { + ++mod; + ++closes; + } + else + as_bad (_("illegal expression")); - prev = bin; - *line = str; - return bin; -} + if (*str == '-') + { + neg_p = 1; + ++closes; + str += 5; + } + else + str += 3; + } -/* Parse for ldd/std offset */ + if (*str == '-' && *(str + 1) == '(') + { + neg_p ^= 1; + ++closes; + str += 2; + } -static void -avr_offset_expression (expressionS *exp) -{ - char *str = input_line_pointer; - char *tmp; - char op[8]; + input_line_pointer = str; + expression (exp); - tmp = str; - str = extract_word (str, op, sizeof (op)); + do + { + if (*input_line_pointer != ')') + { + as_bad (_("`)' required")); + break; + } + input_line_pointer++; + } + while (closes--); + + return neg_p ? EXP_MOD_NEG_RELOC (mod) : EXP_MOD_RELOC (mod); + } + } + } input_line_pointer = tmp; expression (exp); @@ -577,21 +578,22 @@ avr_offset_expression (expressionS *exp) 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); } + + return BFD_RELOC_AVR_LDI; } /* Parse one instruction operand. Return operand bitmask. Also fixups can be generated. */ static unsigned int -avr_operand (opcode, where, op, line) - struct avr_opcodes_s *opcode; - int where; - char *op; - char **line; +avr_operand (struct avr_opcodes_s *opcode, + int where, + char *op, + char **line) { expressionS op_expr; unsigned int op_mask = 0; @@ -828,13 +830,95 @@ avr_operand (opcode, where, op, line) return op_mask; } +/* Parse instruction operands. + Return binary opcode. */ + +static unsigned int +avr_operands (struct avr_opcodes_s *opcode, char **line) +{ + char *op = opcode->constraints; + unsigned int bin = opcode->bin_opcode; + char *frag = frag_more (opcode->insn_size * 2); + char *str = *line; + int where = frag - frag_now->fr_literal; + static unsigned int prev = 0; /* Previous opcode. */ + + /* Opcode have operands. */ + if (*op) + { + unsigned int reg1 = 0; + unsigned int reg2 = 0; + int reg1_present = 0; + int reg2_present = 0; + + /* Parse first operand. */ + if (REGISTER_P (*op)) + reg1_present = 1; + reg1 = avr_operand (opcode, where, op, &str); + ++op; + + /* Parse second operand. */ + if (*op) + { + if (*op == ',') + ++op; + + if (*op == '=') + { + reg2 = reg1; + reg2_present = 1; + } + else + { + if (REGISTER_P (*op)) + reg2_present = 1; + + str = skip_space (str); + if (*str++ != ',') + as_bad (_("`,' required")); + str = skip_space (str); + + reg2 = avr_operand (opcode, where, op, &str); + } + + if (reg1_present && reg2_present) + reg2 = (reg2 & 0xf) | ((reg2 << 5) & 0x200); + else if (reg2_present) + reg2 <<= 4; + } + if (reg1_present) + reg1 <<= 4; + bin |= reg1 | reg2; + } + + /* Detect undefined combinations (like ld r31,Z+). */ + if (!avr_opt.all_opcodes && AVR_UNDEF_P (bin)) + as_warn (_("undefined combination of operands")); + + if (opcode->insn_size == 2) + { + /* Warn if the previous opcode was cpse/sbic/sbis/sbrc/sbrs + (AVR core bug, fixed in the newer devices). */ + if (!(avr_opt.no_skip_bug || + (avr_mcu->isa & (AVR_ISA_MUL | AVR_ISA_MOVW))) + && AVR_SKIP_P (prev)) + as_warn (_("skipping two-word instruction")); + + bfd_putl32 ((bfd_vma) bin, frag); + } + else + bfd_putl16 ((bfd_vma) bin, frag); + + prev = bin; + *line = str; + return bin; +} + /* GAS will call this function for each section at the end of the assembly, to permit the CPU backend to adjust the alignment of a section. */ valueT -md_section_align (seg, addr) - asection *seg; - valueT addr; +md_section_align (asection *seg, valueT addr) { int align = bfd_get_section_alignment (stdoutput, seg); return ((addr + (1 << align) - 1) & (-1 << align)); @@ -847,9 +931,7 @@ md_section_align (seg, addr) macro would return the length of an instruction. */ long -md_pcrel_from_section (fixp, sec) - fixS *fixp; - segT sec; +md_pcrel_from_section (fixS *fixp, segT sec) { if (fixp->fx_addsy != (symbolS *) NULL && (!S_IS_DEFINED (fixp->fx_addsy) @@ -863,10 +945,7 @@ md_pcrel_from_section (fixp, sec) value in the object file. */ void -md_apply_fix (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg; +md_apply_fix (fixS *fixP, valueT * valP, segT seg) { unsigned char *where; unsigned long insn; @@ -1095,15 +1174,14 @@ md_apply_fix (fixP, valP, seg) then it is done here. */ arelent * -tc_gen_reloc (seg, fixp) - asection *seg ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, + fixS *fixp) { arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc = xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; @@ -1126,8 +1204,7 @@ tc_gen_reloc (seg, fixp) } void -md_assemble (str) - char *str; +md_assemble (char *str) { struct avr_opcodes_s *opcode; char op[11]; @@ -1158,6 +1235,7 @@ md_assemble (str) but that is wrong. Our caller assumes we don't change it. */ { char *t = input_line_pointer; + avr_operands (opcode, &str); if (*skip_space (str)) as_bad (_("garbage at end of line")); @@ -1165,117 +1243,6 @@ md_assemble (str) } } -/* Parse ordinary expression. */ - -static char * -parse_exp (s, op) - char *s; - expressionS *op; -{ - input_line_pointer = s; - expression (op); - if (op->X_op == O_absent) - as_bad (_("missing operand")); - return input_line_pointer; -} - -/* Parse special expressions (needed for LDI command): - xx8 (address) - xx8 (-address) - pm_xx8 (address) - pm_xx8 (-address) - where xx is: hh, hi, lo. */ - -static bfd_reloc_code_real_type -avr_ldi_expression (exp) - expressionS *exp; -{ - char *str = input_line_pointer; - char *tmp; - char op[8]; - int mod; - tmp = str; - - str = extract_word (str, op, sizeof (op)); - - if (op[0]) - { - mod = (int) hash_find (avr_mod_hash, op); - - if (mod) - { - int closes = 0; - - mod -= 10; - str = skip_space (str); - - if (*str == '(') - { - int neg_p = 0; - - ++str; - - if (strncmp ("pm(", str, 3) == 0 - || strncmp ("-(pm(", str, 5) == 0) - { - if (HAVE_PM_P (mod)) - { - ++mod; - ++closes; - } - else - as_bad (_("illegal expression")); - - if (*str == '-') - { - neg_p = 1; - ++closes; - str += 5; - } - else - str += 3; - } - - if (*str == '-' && *(str + 1) == '(') - { - neg_p ^= 1; - ++closes; - str += 2; - } - - input_line_pointer = str; - expression (exp); - - do - { - if (*input_line_pointer != ')') - { - as_bad (_("`)' required")); - break; - } - input_line_pointer++; - } - while (closes--); - - return neg_p ? EXP_MOD_NEG_RELOC (mod) : EXP_MOD_RELOC (mod); - } - } - } - - 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); - } - - return BFD_RELOC_AVR_LDI; -} - /* Flag to pass `pm' mode between `avr_parse_cons_expression' and `avr_cons_fix_new'. */ static int exp_mod_pm = 0; @@ -1285,9 +1252,7 @@ static int exp_mod_pm = 0; Relocation: BFD_RELOC_AVR_16_PM. */ void -avr_parse_cons_expression (exp, nbytes) - expressionS *exp; - int nbytes; +avr_parse_cons_expression (expressionS *exp, int nbytes) { char *tmp; @@ -1329,11 +1294,10 @@ avr_parse_cons_expression (exp, nbytes) } void -avr_cons_fix_new (frag, where, nbytes, exp) - fragS *frag; - int where; - int nbytes; - expressionS *exp; +avr_cons_fix_new (fragS *frag, + int where, + int nbytes, + expressionS *exp) { if (exp_mod_pm == 0) { |