/* tc-m68hc11.c -- Assembler code for the Motorola 68HC11 & 68HC12.
- Copyright (C) 1999, 2000 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.
#include "opcode/m68hc11.h"
#include "dwarf2dbg.h"
-struct dwarf2_line_info debug_line;
-
const char comment_chars[] = ";!";
const char line_comment_chars[] = "#*";
const char line_separator_chars[] = "";
/* 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))
size expressions. This version only supports two kinds. */
/* The fields are:
- How far Forward this mode will reach:
- How far Backward this mode will reach:
- How many bytes this mode will add to the size of the frag
- Which mode to go to if the offset won't fit in this one */
+ How far Forward this mode will reach.
+ How far Backward this mode will reach.
+ How many bytes this mode will add to the size of the frag.
+ Which mode to go to if the offset won't fit in this one. */
relax_typeS md_relax_table[] = {
- {1, 1, 0, 0}, /* First entries aren't used */
- {1, 1, 0, 0}, /* For no good reason except */
- {1, 1, 0, 0}, /* that the VAX doesn't either */
+ {1, 1, 0, 0}, /* First entries aren't used. */
+ {1, 1, 0, 0}, /* For no good reason except. */
+ {1, 1, 0, 0}, /* that the VAX doesn't either. */
{1, 1, 0, 0},
/* Relax for bcc <L>.
/* Relax for indexed offset: 5-bits, 9-bits, 16-bits. */
{(15), (-16), 0, ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9)},
{(255), (-256), 1, ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16)},
- {0, 0, 1, 0},
+ {0, 0, 2, 0},
{1, 1, 0, 0},
/* Relax for dbeq/ibeq/tbeq r,<L>:
};
/* 68HC11 and 68HC12 registers. They are numbered according to the 68HC12. */
-typedef enum register_id
-{
+typedef enum register_id {
REG_NONE = -1,
REG_A = 0,
REG_B = 1,
REG_PC = 8
} register_id;
-typedef struct operand
-{
+typedef struct operand {
expressionS exp;
register_id reg1;
register_id reg2;
int mode;
} operand;
-struct m68hc11_opcode_def
-{
+struct m68hc11_opcode_def {
long format;
int min_operands;
int max_operands;
static struct m68hc11_opcode_def *m68hc11_opcode_defs = 0;
static int m68hc11_nb_opcode_defs = 0;
-typedef struct alias
-{
+typedef struct alias {
const char *name;
const char *alias;
-}
-alias;
+} alias;
static alias alias_opcodes[] = {
{"cpd", "cmpd"},
{0, 0}
};
-/* local functions */
-static register_id reg_name_search PARAMS ((char *name));
-static register_id register_name PARAMS (());
-static int check_range PARAMS ((long num, int mode));
-
+/* Local functions. */
+static register_id reg_name_search PARAMS ((char *));
+static register_id register_name PARAMS ((void));
+static int check_range PARAMS ((long, int));
static void print_opcode_list PARAMS ((void));
-
static void get_default_target PARAMS ((void));
-static void print_insn_format PARAMS ((char *name));
-static int get_operand PARAMS ((operand * op, int first, long opmode));
-static void fixup8 PARAMS ((expressionS * oper, int mode, int opmode));
-static void fixup16 PARAMS ((expressionS * oper, int mode, int opmode));
+static void print_insn_format PARAMS ((char *));
+static int get_operand PARAMS ((operand *, int, long));
+static void fixup8 PARAMS ((expressionS *, int, int));
+static void fixup16 PARAMS ((expressionS *, int, int));
static struct m68hc11_opcode *find_opcode
-PARAMS (
- (struct m68hc11_opcode_def * opc, operand operands[],
- int *nb_operands));
+ PARAMS ((struct m68hc11_opcode_def *, operand *, int *));
static void build_jump_insn
-PARAMS (
- (struct m68hc11_opcode * opcode, operand operands[], int nb_operands,
- int optimize));
-
-static void build_insn PARAMS ((struct m68hc11_opcode * opcode,
- operand operands[], int nb_operands));
+ PARAMS ((struct m68hc11_opcode *, operand *, int, int));
+static void build_insn
+ PARAMS ((struct m68hc11_opcode *, operand *, int));
/* Controls whether relative branches can be turned into long branches.
When the relative offset is too large, the insn are changed:
jmp L
dbcc -> db!cc +3
jmp L
-
+
Setting the flag forbidds this. */
static short flag_fixed_branchs = 0;
{"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
/* Options and initialization. */
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)
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;
return 0;
}
-/* Equal to MAX_PRECISION in atof-ieee.c */
+/* Equal to MAX_PRECISION in atof-ieee.c. */
#define MAX_LITTLENUMS 6
/* Turn a string in input_line_pointer into a floating point constant
of type TYPE, and store the appropriate bytes in *LITP. The number
of LITTLENUMS emitted is stored in *SIZEP. An error message is
returned, or NULL on OK. */
-
char *
md_atof (type, litP, sizeP)
char type;
return ((addr + (1 << align) - 1) & (-1 << align));
}
-
static int
cmp_opcode (op1, op2)
struct m68hc11_opcode *op1;
m68hc11_init_after_args ()
{
}
-
\f
/* Builtin help. */
int example = flag_print_opcodes == 2;
if (example)
- {
- printf (_("# Example of `%s' instructions\n\t.sect .text\n_start:\n"),
- default_cpu);
- }
+ printf (_("# Example of `%s' instructions\n\t.sect .text\n_start:\n"),
+ default_cpu);
opcodes = m68hc11_sorted_opcodes;
printf ("\n");
}
-
/* Print the instruction format. This operation is called when some
instruction is not correct. Instruction format is printed as an
error message. */
}
while (strcmp (opcode->name, name) == 0);
}
-
\f
/* Analysis of 68HC11 and 68HC12 operands. */
return p;
}
-/* register_name() checks the string at input_line_pointer
+/* Check the string at input_line_pointer
to see if it is a valid register name. */
static register_id
register_name ()
if (c)
*p++ = 0;
- /* look to see if it's in the register table. */
+ /* Look to see if it's in the register table. */
reg_number = reg_name_search (input_line_pointer);
if (reg_number != REG_NONE)
{
return reg_number;
}
-/* get_operands parses a string of operands and returns
- an array of expressions.
+/* Parse a string of operands and return an array of expressions.
Operand mode[0] mode[1] exp[0] exp[1]
#n M6811_OP_IMM16 - O_*
n,r+ M6812_POST_INC " "
A,r B,r D,r M6811_OP_REG M6812_OP_REG O_register O_register
[D,r] M6811_OP_IDX_2 M6812_OP_REG O_register O_register
- [n,r] M6811_OP_IDX_1 M6812_OP_REG O_constant O_register
-
-*/
-
+ [n,r] M6811_OP_IDX_1 M6812_OP_REG O_constant O_register */
static int
get_operand (oper, which, opmode)
operand *oper;
if (!(opmode & (M6811_OP_IMM8 | M6811_OP_IMM16 | M6811_OP_BITMASK)))
{
as_bad (_("Immediate operand is not allowed for operand %d."),
- which);
+ which);
return -1;
}
if (*p == ',')
{
+ int possible_mode = M6811_OP_NONE;
+ char *old_input_line;
p++;
/* 68HC12 pre increment or decrement. */
{
if (*p == '-')
{
- mode = M6812_PRE_DEC;
+ possible_mode = M6812_PRE_DEC;
p++;
- if (current_architecture & cpu6811)
- as_bad (_("Pre-decrement mode is not valid for 68HC11"));
}
else if (*p == '+')
{
- mode = M6812_PRE_INC;
+ possible_mode = M6812_PRE_INC;
p++;
- if (current_architecture & cpu6811)
- as_bad (_("Pre-increment mode is not valid for 68HC11"));
}
p = skip_whites (p);
}
+ old_input_line = input_line_pointer;
input_line_pointer = p;
reg = register_name ();
- /* Backtrack... */
+ /* Backtrack if we have a valid constant expression and
+ it does not correspond to the offset of the 68HC12 indexed
+ addressing mode (as in N,x). */
+ if (reg == REG_NONE && mode == M6811_OP_NONE
+ && possible_mode != M6811_OP_NONE)
+ {
+ oper->mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;
+ input_line_pointer = skip_whites (old_input_line);
+ return 1;
+ }
+
+ if (possible_mode != M6811_OP_NONE)
+ mode = possible_mode;
+
+ if ((current_architecture & cpu6811)
+ && possible_mode != M6811_OP_NONE)
+ as_bad (_("Pre-increment mode is not valid for 68HC11"));
+ /* Backtrack. */
if (which == 0 && opmode & M6812_OP_IDX_P2
&& reg != REG_X && reg != REG_Y
&& reg != REG_PC && reg != REG_SP)
/* If the mode is not known until now, this is either a label
or an indirect address. */
if (mode == M6811_OP_NONE)
- {
- mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;
- }
+ mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;
p = input_line_pointer;
while (*p == ' ' || *p == '\t')
{
/* Auto increment and decrement are ok for [-8..8] without 0. */
if (mode & M6812_AUTO_INC_DEC)
- {
- return (num != 0 && num <= 8 && num >= -8);
- }
+ 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;
- }
+ mode = M6811_OP_IND16;
if (mode & M6812_OP_JUMP_REL16)
mode = M6811_OP_IND16;
return 0;
}
}
-
\f
/* Gas fixup generation. */
}
}
-/* 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)
if (!check_range (oper->X_add_number, mode))
{
as_bad (_("Operand out of 16-bit range: `%ld'."),
- oper->X_add_number);
+ oper->X_add_number);
}
number_to_chars_bigendian (f, oper->X_add_number & 0x0FFFF, 2);
}
as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);
}
}
-
\f
/* 68HC11 and 68HC12 code generation. */
/* Start a new insn that contains at least 'size' bytes. Record the
line information of that insn in the dwarf2 debug sections. */
-static char*
+static char *
m68hc11_new_insn (size)
int size;
{
- char* f;
+ char *f;
f = frag_more (size);
- /* Emit line number information in dwarf2 debug sections. */
- if (debug_type == DEBUG_DWARF2)
- {
- bfd_vma addr;
-
- dwarf2_where (&debug_line);
- addr = frag_now->fr_address + frag_now_fix () - size;
- dwarf2_gen_line_info (addr, &debug_line);
- }
+ dwarf2_emit_insn (size);
+
return f;
}
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;
opcode = m68hc11_new_insn (2);
number_to_chars_bigendian (opcode, code, 1);
number_to_chars_bigendian (opcode + 1, 0, 1);
- frag_var (rs_machine_dependent, 1, 1,
+ frag_var (rs_machine_dependent, 2, 1,
ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF),
operands[0].exp.X_add_symbol, (offsetT) n, opcode);
}
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);
if (!check_range (val, mode))
{
as_bad (_("Increment/decrement value is out of range: `%ld'."),
- val);
+ val);
}
if (mode & (M6812_POST_INC | M6812_PRE_INC))
byte |= (val - 1) & 0x07;
if (move_insn && !(val >= -16 && val <= 15))
{
- as_bad (_("Offset out of 5-bit range for movw/movb insn."));
+ as_bad (_("Offset out of 5-bit range for movw/movb insn: %ld."),
+ val);
return -1;
}
return 3;
}
}
- f = frag_more (1);
- number_to_chars_bigendian (f, byte, 1);
- /*
- fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
- &op->exp, false, BFD_RELOC_16); */
- frag_var (rs_machine_dependent, 2, 2,
- ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF),
- op->exp.X_add_symbol, val, f);
+ if (op->reg1 != REG_PC)
+ {
+ byte = (byte << 3) | 0xe2;
+ f = frag_more (1);
+ number_to_chars_bigendian (f, byte, 1);
+
+ f = frag_more (2);
+ fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
+ &op->exp, false, BFD_RELOC_16);
+ number_to_chars_bigendian (f, 0, 2);
+ }
+ else
+ {
+ f = frag_more (1);
+ number_to_chars_bigendian (f, byte, 1);
+ frag_var (rs_machine_dependent, 2, 2,
+ ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF),
+ op->exp.X_add_symbol,
+ op->exp.X_add_number, f);
+ }
return 3;
}
{
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);
}
}
-
\f
/* Opcode identification and operand analysis. */
}
if (mode & M6812_OP_REG)
{
- if (i == 0 && format & M6812_OP_REG
- && operands[i].reg2 == REG_NONE)
+ if (i == 0
+ && (format & M6812_OP_REG)
+ && (operands[i].reg2 == REG_NONE))
continue;
- if (i == 0 && format & M6812_OP_REG
- && format & M6812_OP_REG_2 && operands[i].reg2 != REG_NONE)
- {
- continue;
- }
- if (i == 0 && format & M6812_OP_D_IDX)
+ if (i == 0
+ && (format & M6812_OP_REG)
+ && (format & M6812_OP_REG_2)
+ && (operands[i].reg2 != REG_NONE))
+ continue;
+ if (i == 0
+ && (format & M6812_OP_IDX)
+ && (operands[i].reg2 != REG_NONE))
+ continue;
+ if (i == 0
+ && (format & M6812_OP_D_IDX))
continue;
- if (i == 0 && (format & M6812_OP_IDX)
+ if (i == 0
+ && (format & M6812_OP_IDX)
&& (format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)))
continue;
- if (i == 1 && format & M6812_OP_IDX_P2)
+ if (i == 1
+ && (format & M6812_OP_IDX_P2))
continue;
break;
}
return opcode;
}
-
/* Find the real opcode and its associated operands. We use a progressive
approach here. On entry, 'opc' points to the first opcode in the
table that matches the opcode name in the source line. We try to
result = get_operand (&operands[i], i, opc->format);
if (result <= 0)
- {
- return 0;
- }
+ return 0;
/* Special case where the bitmask of the bclr/brclr
instructions is not introduced by #.
{
opcode = find (opc, operands, i);
if (opcode)
- {
- return opcode;
- }
+ return opcode;
}
if (*input_line_pointer == ',')
input_line_pointer++;
}
+
return 0;
}
#define M6812_XBCC_MARKER (M6812_OP_TBCC_MARKER \
| M6812_OP_DBCC_MARKER \
| M6812_OP_IBCC_MARKER)
-
\f
/* Gas line assembler entry point. */
int branch_optimize = 0;
int alias_id = -1;
- /* Drop leading whitespace */
+ /* Drop leading whitespace. */
while (*str == ' ')
str++;
}
/* 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;
if (alias_id >= 0)
{
char *f = m68hc11_new_insn (m68hc12_alias[alias_id].size);
-
+
number_to_chars_bigendian (f, m68hc12_alias[alias_id].code1, 1);
if (m68hc12_alias[alias_id].size > 1)
number_to_chars_bigendian (f + 1, m68hc12_alias[alias_id].code2, 1);
else
build_insn (opcode, operands, nb_operands);
}
-
\f
/* Relocation, relaxation and frag conversions. */
-
long
md_pcrel_from_section (fixp, sec)
fixS *fixp;
int adjust;
if (fixp->fx_addsy != (symbolS *) NULL
&& (!S_IS_DEFINED (fixp->fx_addsy)
- || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
+ || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
return 0;
adjust = fixp->fx_pcrel_adjust;
fragS *fragP;
{
fixS *fixp;
+ long value;
long disp;
char *buffer_address = fragP->fr_literal;
buffer_address += fragP->fr_fix;
/* The displacement of the address, from current location. */
- disp = fragP->fr_symbol ? S_GET_VALUE (fragP->fr_symbol) : 0;
- disp = (disp + fragP->fr_offset) - object_address;
- disp += symbol_get_frag (fragP->fr_symbol)->fr_address;
+ value = S_GET_VALUE (fragP->fr_symbol);
+ disp = (value + fragP->fr_offset) - object_address;
switch (fragP->fr_subtype)
{
case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):
/* Invert branch. */
fragP->fr_opcode[0] ^= 1;
- fragP->fr_opcode[1] = 3; /* Branch offset */
+ fragP->fr_opcode[1] = 3; /* Branch offset. */
buffer_address[0] = M6811_JMP;
fix_new (fragP, fragP->fr_fix + 1, 2,
fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
break;
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5):
- fragP->fr_opcode[0] = fragP->fr_opcode[0] << 5;
- fragP->fr_opcode[0] |= disp & 0x1f;
+ fragP->fr_opcode[0] = fragP->fr_opcode[0] << 6;
+ if ((fragP->fr_opcode[0] & 0x0ff) == 0x0c0)
+ fragP->fr_opcode[0] |= disp & 0x1f;
+ else
+ fragP->fr_opcode[0] |= value & 0x1f;
break;
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9):
fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
fragP->fr_opcode[0] |= 0xE0;
- fix_new (fragP, fragP->fr_fix + 1, 1,
+ fix_new (fragP, fragP->fr_fix, 1,
fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_8);
fragP->fr_fix += 1;
break;
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16):
fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
- fragP->fr_opcode[0] |= 0xE2;
- fix_new (fragP, fragP->fr_fix, 2,
- fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
- fragP->fr_fix += 1;
+ fragP->fr_opcode[0] |= 0xe2;
+ if ((fragP->fr_opcode[0] & 0x0ff) == 0x0fa)
+ {
+ fixp = fix_new (fragP, fragP->fr_fix, 2,
+ fragP->fr_symbol, fragP->fr_offset,
+ 1, BFD_RELOC_16_PCREL);
+ fixp->fx_pcrel_adjust = 2;
+ }
+ else
+ {
+ fix_new (fragP, fragP->fr_fix, 2,
+ fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
+ }
+ fragP->fr_fix += 2;
break;
case ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_BYTE):
}
}
+/* On an ELF system, we can't relax a weak symbol. The weak symbol
+ can be overridden at final link time by a non weak symbol. We can
+ relax externally visible symbol because there is no shared library
+ and such symbol can't be overridden (unless they are weak). */
+static int
+relaxable_symbol (symbol)
+ symbolS *symbol;
+{
+ return ! S_IS_WEAK (symbol);
+}
+
/* Force truly undefined symbols to their maximum size, and generally set up
the frag list to be relaxed. */
int
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)
- {
- 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)
- {
- 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 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. */
- if ((fragP->fr_opcode[1] & 0x21) == 0x20)
- fragP->fr_opcode[1] = (fragP->fr_opcode[1] >> 3) | 0xc0 | 0x02;
-
- 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_XBCC_BRANCH, STATE_UNDF):
- assert (current_architecture & cpu6812);
+ case STATE_XBCC_BRANCH:
+ assert (current_architecture & cpu6812);
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
- {
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)
- {
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
case BFD_RELOC_M68HC11_HI8:
value = value >> 8;
- /* Fall through */
+ /* Fall through. */
case BFD_RELOC_M68HC11_LO8:
case BFD_RELOC_8:
- /*bfd_putb8 ((bfd_vma) value, (unsigned char *) where); */
+#if 0
+ bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
+#endif
((bfd_byte *) where)[0] = (bfd_byte) value;
break;
case BFD_RELOC_8_PCREL:
- /*bfd_putb8 ((bfd_vma) value, (unsigned char *) where); */
+#if 0
+ bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
+#endif
((bfd_byte *) where)[0] = (bfd_byte) value;
if (value < -128 || value > 127)
as_fatal (_("Line %d: unknown relocation type: 0x%x."),
fixp->fx_line, fixp->fx_r_type);
}
- return 0;
-}
-int
-m68hc11_cleanup ()
-{
- return 1;
-}
-
-void
-m68hc11_end_of_source ()
-{
- segT saved_seg;
- subsegT saved_subseg;
- segT debug_info;
- char* p;
- long total_size = 0;
-
- if (debug_type != DEBUG_DWARF2)
- return;
-
- dwarf2_finish ();
-
- saved_seg = now_seg;
- saved_subseg = now_subseg;
-
- debug_info = subseg_new (".debug_info", 0);
- bfd_set_section_flags (stdoutput, debug_info, SEC_READONLY);
- subseg_set (debug_info, 0);
- p = frag_more (10);
- total_size = 12;
-
-# define STUFF(val,size) md_number_to_chars (p, val, size); p += size;
- STUFF (total_size, 4); /* Length of compilation unit. */
- STUFF (2, 2); /* Dwarf version */
- STUFF (0, 4);
- STUFF (2, 1); /* Pointer size */
- STUFF (1, 1); /* Compile unit */
- STUFF (0, 4);
-
- now_subseg = saved_subseg;
- now_seg = saved_seg;
+ return 0;
}