/* tc-m68hc11.c -- Assembler code for the Motorola 68HC11 & 68HC12.
- Copyright (C) 1999, 2000, 2001 Free Software Foundation.
+ Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
Written by Stephane Carrez (stcarrez@worldnet.fr)
This file is part of GAS, the GNU Assembler.
/* This macro has no side-effects. */
#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+#define RELAX_STATE(s) ((s) >> 2)
+#define RELAX_LENGTH(s) ((s) & 3)
#define IS_OPCODE(C1,C2) (((C1) & 0x0FF) == ((C2) & 0x0FF))
{"fdb", cons, 2},
{"fcc", stringer, 1},
{"rmb", s_space, 0},
+
+ /* Dwarf2 support for Gcc. */
{"file", dwarf2_directive_file, 0},
{"loc", dwarf2_directive_loc, 0},
+ /* Motorola ALIS. */
+ {"xrefb", s_ignore, 0}, /* Same as xref */
+
{0, 0, 0}
};
\f
return 0;
}
+/* Listing header selected according to cpu. */
+const char *
+m68hc11_listing_header ()
+{
+ if (current_architecture & cpu6811)
+ return "M68HC11 GAS ";
+ else
+ return "M68HC12 GAS ";
+}
+
void
md_show_usage (stream)
FILE *stream;
get_default_target ();
switch (c)
{
- /* -S means keep external to 2 bits offset rather than 16 bits one. */
+ /* -S means keep external to 2 bit offset rather than 16 bit one. */
case OPTION_SHORT_BRANCHS:
case 'S':
flag_fixed_branchs = 1;
if (mode & M6812_AUTO_INC_DEC)
return (num != 0 && num <= 8 && num >= -8);
- /* The 68HC12 supports 5, 9 and 16-bits offsets. */
+ /* The 68HC12 supports 5, 9 and 16-bit offsets. */
if (mode & (M6812_INDEXED_IND | M6812_INDEXED | M6812_OP_IDX))
mode = M6811_OP_IND16;
}
}
-/* Put a 2 bytes expression described by 'oper'. If this expression contains
+/* Put a 2 byte expression described by 'oper'. If this expression contains
unresolved symbols, generate a 16-bit fixup. */
static void
fixup16 (oper, mode, opmode)
int jmp_mode;
{
unsigned char code;
- int insn_size;
char *f;
unsigned long n;
assert (operands[0].reg1 == REG_NONE && operands[0].reg2 == REG_NONE);
code = opcode->opcode;
- insn_size = 1;
n = operands[0].exp.X_add_number;
int jmp_mode;
{
unsigned char code;
- int insn_size;
char *f;
unsigned long n;
assert (operands[0].reg1 != REG_NONE);
code = opcode->opcode & 0x0FF;
- insn_size = 1;
f = m68hc11_new_insn (1);
number_to_chars_bigendian (f, code, 1);
{
int i;
char *f;
- int insn_size = 1;
long format;
int move_insn = 0;
number_to_chars_bigendian (f, page_code, 1);
f++;
- insn_size = 2;
}
else
f = m68hc11_new_insn (1);
move_insn = 1;
if (format & M6812_OP_IDX)
{
- insn_size += build_indexed_byte (&operands[0], format, 1);
+ build_indexed_byte (&operands[0], format, 1);
i = 1;
format &= ~M6812_OP_IDX;
}
if (format & M6812_OP_IDX_P2)
{
- insn_size += build_indexed_byte (&operands[1], format, 1);
+ build_indexed_byte (&operands[1], format, 1);
i = 0;
format &= ~M6812_OP_IDX_P2;
}
if (format & (M6811_OP_DIRECT | M6811_OP_IMM8))
{
- insn_size++;
fixup8 (&operands[i].exp,
format & (M6811_OP_DIRECT | M6811_OP_IMM8 | M6812_OP_TRAP_ID),
operands[i].mode);
}
else if (format & (M6811_OP_IMM16 | M6811_OP_IND16))
{
- insn_size += 2;
fixup16 (&operands[i].exp, format & (M6811_OP_IMM16 | M6811_OP_IND16),
operands[i].mode);
i++;
if ((format & M6811_OP_IY) && (operands[0].reg1 != REG_Y))
as_bad (_("Invalid indexed register, expecting register Y."));
- insn_size++;
fixup8 (&operands[0].exp, M6811_OP_IX, operands[0].mode);
i = 1;
}
else if (format &
(M6812_OP_IDX | M6812_OP_IDX_2 | M6812_OP_IDX_1 | M6812_OP_D_IDX))
{
- insn_size += build_indexed_byte (&operands[i], format, move_insn);
+ build_indexed_byte (&operands[i], format, move_insn);
i++;
}
else if (format & M6812_OP_REG && current_architecture & cpu6812)
{
- insn_size += build_reg_mode (&operands[i], format);
+ build_reg_mode (&operands[i], format);
i++;
}
if (format & M6811_OP_BITMASK)
{
- insn_size++;
fixup8 (&operands[i].exp, M6811_OP_BITMASK, operands[i].mode);
i++;
}
if (format & M6811_OP_JUMP_REL)
{
- insn_size++;
fixup8 (&operands[i].exp, M6811_OP_JUMP_REL, operands[i].mode);
- i++;
}
else if (format & M6812_OP_IND16_P2)
{
- insn_size += 2;
fixup16 (&operands[1].exp, M6811_OP_IND16, operands[1].mode);
}
}
}
/* Identify a possible instruction alias. There are some on the
- 68HC12 to emulate a fiew 68HC11 instructions. */
+ 68HC12 to emulate a few 68HC11 instructions. */
if (opc == NULL && (current_architecture & cpu6812))
{
int i;
buffer_address += fragP->fr_fix;
/* The displacement of the address, from current location. */
- value = fragP->fr_symbol ? S_GET_VALUE (fragP->fr_symbol) : 0;
+ value = S_GET_VALUE (fragP->fr_symbol);
disp = (value + fragP->fr_offset) - object_address;
- disp += symbol_get_frag (fragP->fr_symbol)->fr_address;
switch (fragP->fr_subtype)
{
fragS *fragP;
asection *segment;
{
- int old_fr_fix;
- char *buffer_address = fragP->fr_fix + fragP->fr_literal;
+ if (RELAX_LENGTH (fragP->fr_subtype) == STATE_UNDF)
+ {
+ if (S_GET_SEGMENT (fragP->fr_symbol) != segment
+ || !relaxable_symbol (fragP->fr_symbol))
+ {
+ /* Non-relaxable cases. */
+ int old_fr_fix;
+ char *buffer_address;
- old_fr_fix = fragP->fr_fix;
+ old_fr_fix = fragP->fr_fix;
+ buffer_address = fragP->fr_fix + fragP->fr_literal;
- switch (fragP->fr_subtype)
- {
- case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF):
+ switch (RELAX_STATE (fragP->fr_subtype))
+ {
+ case STATE_PC_RELATIVE:
+
+ /* This relax is only for bsr and bra. */
+ assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
+ || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
+ || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));
+
+ if (flag_fixed_branchs)
+ as_bad_where (fragP->fr_file, fragP->fr_line,
+ _("bra or bsr with undefined symbol."));
+
+ /* The symbol is undefined or in a separate section.
+ Turn bra into a jmp and bsr into a jsr. The insn
+ becomes 3 bytes long (instead of 2). A fixup is
+ necessary for the unresolved symbol address. */
+ fragP->fr_opcode[0] = convert_branch (fragP->fr_opcode[0]);
+
+ fix_new (fragP, fragP->fr_fix - 1, 2, fragP->fr_symbol,
+ fragP->fr_offset, 0, BFD_RELOC_16);
+ fragP->fr_fix++;
+ break;
- /* This relax is only for bsr and bra. */
- assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
- || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
- || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));
+ case STATE_CONDITIONAL_BRANCH:
+ assert (current_architecture & cpu6811);
- /* A relaxable case. */
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment
- && relaxable_symbol (fragP->fr_symbol))
- {
- fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
- }
- else
- {
- if (flag_fixed_branchs)
- as_bad_where (fragP->fr_file, fragP->fr_line,
- _("bra or bsr with undefined symbol."));
+ fragP->fr_opcode[0] ^= 1; /* Reverse sense of branch. */
+ fragP->fr_opcode[1] = 3; /* Skip next jmp insn (3 bytes). */
- /* The symbol is undefined or in a separate section. Turn bra into a
- jmp and bsr into a jsr. The insn becomes 3 bytes long (instead of
- 2). A fixup is necessary for the unresolved symbol address. */
+ /* Don't use fr_opcode[2] because this may be
+ in a different frag. */
+ buffer_address[0] = M6811_JMP;
- fragP->fr_opcode[0] = convert_branch (fragP->fr_opcode[0]);
+ fragP->fr_fix++;
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 0, BFD_RELOC_16);
+ fragP->fr_fix += 2;
+ break;
- fragP->fr_fix++;
- fix_new (fragP, old_fr_fix - 1, 2, fragP->fr_symbol,
- fragP->fr_offset, 0, BFD_RELOC_16);
- frag_wane (fragP);
- }
- break;
+ case STATE_INDEXED_OFFSET:
+ assert (current_architecture & cpu6812);
- case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF):
- assert (current_architecture & cpu6811);
+ /* Switch the indexed operation to 16-bit mode. */
+ fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3;
+ fragP->fr_opcode[0] |= 0xe2;
+ fragP->fr_fix++;
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 0, BFD_RELOC_16);
+ fragP->fr_fix++;
+ break;
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment
- && relaxable_symbol (fragP->fr_symbol))
- {
- fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH,
- STATE_BYTE);
- }
- else
- {
- fragP->fr_opcode[0] ^= 1; /* Reverse sense of branch. */
- fragP->fr_opcode[1] = 3; /* Skip next jmp insn (3 bytes). */
+ case STATE_XBCC_BRANCH:
+ assert (current_architecture & cpu6812);
+
+ fragP->fr_opcode[0] ^= 0x20; /* Reverse sense of branch. */
+ fragP->fr_opcode[1] = 3; /* Skip next jmp insn (3 bytes). */
+
+ /* Don't use fr_opcode[2] because this may be
+ in a different frag. */
+ buffer_address[0] = M6812_JMP;
+
+ fragP->fr_fix++;
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 0, BFD_RELOC_16);
+ fragP->fr_fix += 2;
+ break;
+
+ case STATE_CONDITIONAL_BRANCH_6812:
+ assert (current_architecture & cpu6812);
- /* Don't use fr_opcode[2] because this may be
- in a different frag. */
- buffer_address[0] = M6811_JMP;
+ /* Translate into a lbcc branch. */
+ fragP->fr_opcode[1] = fragP->fr_opcode[0];
+ fragP->fr_opcode[0] = M6811_OPCODE_PAGE2;
- fragP->fr_fix++;
- fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
- fragP->fr_offset, 0, BFD_RELOC_16);
- fragP->fr_fix += 2;
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 0, BFD_RELOC_16_PCREL);
+ fragP->fr_fix += 2;
+ break;
+
+ default:
+ as_fatal (_("Subtype %d is not recognized."), fragP->fr_subtype);
+ }
frag_wane (fragP);
- }
- break;
- case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF):
- assert (current_architecture & cpu6812);
+ /* Return the growth in the fixed part of the frag. */
+ return fragP->fr_fix - old_fr_fix;
+ }
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment
- && relaxable_symbol (fragP->fr_symbol))
+ /* Relaxable cases. */
+ switch (RELAX_STATE (fragP->fr_subtype))
{
+ case STATE_PC_RELATIVE:
+ /* This relax is only for bsr and bra. */
+ assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
+ || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
+ || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));
+
+ fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
+ break;
+
+ case STATE_CONDITIONAL_BRANCH:
+ assert (current_architecture & cpu6811);
+
+ fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH,
+ STATE_BYTE);
+ break;
+
+ case STATE_INDEXED_OFFSET:
+ assert (current_architecture & cpu6812);
+
fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_OFFSET,
STATE_BITS5);
- }
- else
- {
- /* Switch the indexed operation to 16-bit mode. */
- fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3;
- fragP->fr_opcode[0] |= 0xe2;
- fragP->fr_fix++;
- fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
- fragP->fr_offset, 0, BFD_RELOC_16);
- fragP->fr_fix++;
- frag_wane (fragP);
- }
- break;
+ break;
- case ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_UNDF):
- assert (current_architecture & cpu6812);
+ case STATE_XBCC_BRANCH:
+ assert (current_architecture & cpu6812);
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment
- && relaxable_symbol (fragP->fr_symbol))
- {
fragP->fr_subtype = ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_BYTE);
- }
- else
- {
- fragP->fr_opcode[0] ^= 0x20; /* Reverse sense of branch. */
- fragP->fr_opcode[1] = 3; /* Skip next jmp insn (3 bytes). */
-
- /* Don't use fr_opcode[2] because this may be
- in a different frag. */
- buffer_address[0] = M6812_JMP;
-
- fragP->fr_fix++;
- fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
- fragP->fr_offset, 0, BFD_RELOC_16);
- fragP->fr_fix += 2;
- frag_wane (fragP);
- }
- break;
+ break;
- case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_UNDF):
- assert (current_architecture & cpu6812);
+ case STATE_CONDITIONAL_BRANCH_6812:
+ assert (current_architecture & cpu6812);
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment
- && relaxable_symbol (fragP->fr_symbol))
- {
fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812,
STATE_BYTE);
+ break;
}
- else
- {
- /* Translate into a lbcc branch. */
- fragP->fr_opcode[1] = fragP->fr_opcode[0];
- fragP->fr_opcode[0] = M6811_OPCODE_PAGE2;
-
- fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
- fragP->fr_offset, 0, BFD_RELOC_16_PCREL);
- fragP->fr_fix += 2;
- frag_wane (fragP);
- }
- break;
-
- default:
- as_fatal (_("Subtype %d is not recognized."), fragP->fr_subtype);
}
- return (fragP->fr_fix - old_fr_fix);
+ if (fragP->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
+ as_fatal (_("Subtype %d is not recognized."), fragP->fr_subtype);
+
+ /* Return the size of the variable part of the frag. */
+ return md_relax_table[fragP->fr_subtype].rlx_length;
}
int
return 0;
}
-
-int
-m68hc11_cleanup ()
-{
- return 1;
-}