/* tc-m68hc11.c -- Assembler code for the Motorola 68HC11 & 68HC12.
- Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Written by Stephane Carrez (stcarrez@nerim.fr)
This file is part of GAS, the GNU Assembler.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "as.h"
#include "safe-ctype.h"
jmp L
Setting the flag forbidds this. */
-static short flag_fixed_branchs = 0;
+static short flag_fixed_branches = 0;
/* Force to use long jumps (absolute) instead of relative branches. */
static short flag_force_long_jumps = 0;
struct option md_longopts[] = {
#define OPTION_FORCE_LONG_BRANCH (OPTION_MD_BASE)
- {"force-long-branchs", no_argument, NULL, OPTION_FORCE_LONG_BRANCH},
+ {"force-long-branches", no_argument, NULL, OPTION_FORCE_LONG_BRANCH},
+ {"force-long-branchs", no_argument, NULL, OPTION_FORCE_LONG_BRANCH}, /* Misspelt version kept for backwards compatibility. */
-#define OPTION_SHORT_BRANCHS (OPTION_MD_BASE + 1)
- {"short-branchs", no_argument, NULL, OPTION_SHORT_BRANCHS},
+#define OPTION_SHORT_BRANCHES (OPTION_MD_BASE + 1)
+ {"short-branches", no_argument, NULL, OPTION_SHORT_BRANCHES},
+ {"short-branchs", no_argument, NULL, OPTION_SHORT_BRANCHES}, /* Misspelt version kept for backwards compatibility. */
#define OPTION_STRICT_DIRECT_MODE (OPTION_MD_BASE + 2)
{"strict-direct-mode", no_argument, NULL, OPTION_STRICT_DIRECT_MODE},
-mlong use 32-bit int ABI\n\
-mshort-double use 32-bit double ABI\n\
-mlong-double use 64-bit double ABI (default)\n\
- --force-long-branchs always turn relative branchs into absolute ones\n\
- -S,--short-branchs do not turn relative branchs into absolute ones\n\
+ --force-long-branches always turn relative branches into absolute ones\n\
+ -S,--short-branches do not turn relative branches into absolute ones\n\
when the offset is out of range\n\
--strict-direct-mode do not turn the direct mode into extended mode\n\
when the instruction does not support direct mode\n\
switch (c)
{
/* -S means keep external to 2 bit offset rather than 16 bit one. */
- case OPTION_SHORT_BRANCHS:
+ case OPTION_SHORT_BRANCHES:
case 'S':
- flag_fixed_branchs = 1;
+ flag_fixed_branches = 1;
break;
case OPTION_FORCE_LONG_BRANCH:
fixS *fixp;
/* Now create a 24-bit fixup. */
- fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
+ fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 3,
oper, FALSE, BFD_RELOC_M68HC11_24);
number_to_chars_bigendian (f, 0, 3);
}
if ((jmp_mode == 0 && flag_force_long_jumps)
|| (operands[0].exp.X_op == O_constant
&& (!check_range (n, opcode->format) &&
- (jmp_mode == 1 || flag_fixed_branchs == 0))))
+ (jmp_mode == 1 || flag_fixed_branches == 0))))
{
frag = frag_now;
where = frag_now_fix ();
- fix_new (frag_now, frag_now_fix (), 1,
+ fix_new (frag_now, frag_now_fix (), 0,
&abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
if (code == M6811_BSR || code == M6811_BRA || code == M6812_BSR)
frag = frag_now;
where = frag_now_fix ();
- fix_new (frag_now, frag_now_fix (), 1,
+ fix_new (frag_now, frag_now_fix (), 0,
&abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
f = m68hc11_new_insn (2);
frag = frag_now;
where = frag_now_fix ();
- fix_new (frag_now, frag_now_fix (), 1,
+ fix_new (frag_now, frag_now_fix (), 0,
&abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
/* Branch offset must fit in 8-bits, don't do some relax. */
- if (jmp_mode == 0 && flag_fixed_branchs)
+ if (jmp_mode == 0 && flag_fixed_branches)
{
opcode = m68hc11_new_insn (1);
number_to_chars_bigendian (opcode, code, 1);
if ((jmp_mode == 0 && flag_force_long_jumps)
|| (operands[1].exp.X_op == O_constant
&& (!check_range (n, M6812_OP_IBCC_MARKER) &&
- (jmp_mode == 1 || flag_fixed_branchs == 0))))
+ (jmp_mode == 1 || flag_fixed_branches == 0))))
{
f = frag_more (2);
code ^= 0x20;
else
{
/* Branch offset must fit in 8-bits, don't do some relax. */
- if (jmp_mode == 0 && flag_fixed_branchs)
+ if (jmp_mode == 0 && flag_fixed_branches)
{
fixup8 (&operands[0].exp, M6811_OP_JUMP_REL, M6811_OP_JUMP_REL);
}
sym = make_expr_symbol (&op->exp);
off = 0;
}
- frag_var (rs_machine_dependent, 2, 2,
- ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF),
- sym, off, f);
+ /* movb/movw cannot be relaxed. */
+ if (move_insn)
+ {
+ byte <<= 6;
+ number_to_chars_bigendian (f, byte, 1);
+ fix_new (frag_now, f - frag_now->fr_literal, 1,
+ sym, off, 0, BFD_RELOC_M68HC12_5B);
+ return 1;
+ }
+ else
+ {
+ number_to_chars_bigendian (f, byte, 1);
+ frag_var (rs_machine_dependent, 2, 2,
+ ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF),
+ sym, off, f);
+ }
}
else
{
f = frag_more (1);
- number_to_chars_bigendian (f, byte, 1);
- frag_var (rs_machine_dependent, 2, 2,
- ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_UNDF),
- op->exp.X_add_symbol,
- op->exp.X_add_number, f);
+ /* movb/movw cannot be relaxed. */
+ if (move_insn)
+ {
+ byte <<= 6;
+ number_to_chars_bigendian (f, byte, 1);
+ fix_new (frag_now, f - frag_now->fr_literal, 1,
+ op->exp.X_add_symbol, op->exp.X_add_number, 0, BFD_RELOC_M68HC12_5B);
+ return 1;
+ }
+ else
+ {
+ number_to_chars_bigendian (f, byte, 1);
+ frag_var (rs_machine_dependent, 2, 2,
+ ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_UNDF),
+ op->exp.X_add_symbol,
+ op->exp.X_add_number, f);
+ }
}
return 3;
}
format = opcode->format;
if (format & M6811_OP_BRANCH)
- fix_new (frag_now, frag_now_fix (), 1,
+ fix_new (frag_now, frag_now_fix (), 0,
&abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
if (format & OP_EXTENDED)
struct m68hc11_opcode_def *opc;
struct m68hc11_opcode *opcode;
- unsigned char *op_start, *save;
- unsigned char *op_end;
+ unsigned char *op_start, *op_end;
+ char *save;
char name[20];
int nlen = 0;
operand operands[M6811_MAX_OPERANDS];
- int nb_operands;
+ int nb_operands = 0;
int branch_optimize = 0;
int alias_id = -1;
/* Find the opcode end and get the opcode in 'name'. The opcode is forced
lower case (the opcode table only has lower case op-codes). */
- for (op_start = op_end = (unsigned char *) (str);
+ for (op_start = op_end = (unsigned char *) str;
*op_end && nlen < 20 && !is_end_of_line[*op_end] && *op_end != ' ';
op_end++)
{
opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash, name);
/* If it's not recognized, look for 'jbsr' and 'jbxx'. These are
- pseudo insns for relative branch. For these branchs, we always
- optimize them (turned into absolute branchs) even if --short-branchs
+ pseudo insns for relative branch. For these branches, we always
+ optimize them (turned into absolute branches) even if --short-branches
is given. */
if (opc == NULL && name[0] == 'j' && name[1] == 'b')
{
return;
}
save = input_line_pointer;
- input_line_pointer = op_end;
+ input_line_pointer = (char *) op_end;
if (opc)
{
return;
}
- fix_new_exp (frag_now, frag_now_fix (), 2, &ex, 1,
+ fix_new_exp (frag_now, frag_now_fix (), 0, &ex, 1,
BFD_RELOC_M68HC11_RL_GROUP);
demand_empty_rest_of_line ();
|| IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
|| IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));
- if (flag_fixed_branchs)
+ if (flag_fixed_branches)
as_bad_where (fragP->fr_file, fragP->fr_line,
_("bra or bsr with undefined symbol."));
}
void
-md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
char *where;
long value = * valP;
case BFD_RELOC_M68HC11_LO8:
case BFD_RELOC_8:
case BFD_RELOC_M68HC11_PAGE:
-#if 0
- bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
-#endif
((bfd_byte *) where)[0] = (bfd_byte) value;
break;
case BFD_RELOC_8_PCREL:
-#if 0
- bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
-#endif
((bfd_byte *) where)[0] = (bfd_byte) value;
if (value < -128 || value > 127)
where[0] = where[0] | (value & 0x07);
break;
+ case BFD_RELOC_M68HC12_5B:
+ if (value < -16 || value > 15)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Offset out of 5-bit range for movw/movb insn: %ld"),
+ value);
+ if (value >= 0)
+ where[0] |= value;
+ else
+ where[0] |= (0x10 | (16 + value));
+ break;
+
case BFD_RELOC_M68HC11_RL_JUMP:
case BFD_RELOC_M68HC11_RL_GROUP:
case BFD_RELOC_VTABLE_INHERIT: