* config/tc-m68hc11.c (md_begin): Take into account additional

page operand for call instruction.
	(print_opcode_format): Likewise.
	(check_range): Likewise for page range checking.
	(get_operand): Don't skip a possible comma in operands.
	(fixup8): Generate BFD_RELOC_M68HC11_PAGE reloc.
	(fixup16): Likwise with BFD_RELOC_M68HC11_LO16.
	(fixup24): New to handle call reloc.
	(build_insn): Handle missing page operand for call instruction.
	(find): Likewise.
	(md_apply_fix3): Take into account new relocs.
	(get_operand): Fix the mode for indexed indirect addressing.
	(build_indexed_byte): Fix post index byte for indexed indirect mode.
This commit is contained in:
Stephane Carrez 2002-08-13 21:38:15 +00:00
parent 9b701e4403
commit 7bfda7ebd0
2 changed files with 162 additions and 37 deletions

View File

@ -1,3 +1,19 @@
2002-08-13 Stephane Carrez <stcarrez@nerim.fr>
* config/tc-m68hc11.c (md_begin): Take into account additional
page operand for call instruction.
(print_opcode_format): Likewise.
(check_range): Likewise for page range checking.
(get_operand): Don't skip a possible comma in operands.
(fixup8): Generate BFD_RELOC_M68HC11_PAGE reloc.
(fixup16): Likwise with BFD_RELOC_M68HC11_LO16.
(fixup24): New to handle call reloc.
(build_insn): Handle missing page operand for call instruction.
(find): Likewise.
(md_apply_fix3): Take into account new relocs.
(get_operand): Fix the mode for indexed indirect addressing.
(build_indexed_byte): Fix post index byte for indexed indirect mode.
2002-08-12 Richard Sandiford <rsandifo@redhat.com>
* config/tc-mips.c (mips_ip): Don't work out the value of

View File

@ -1,6 +1,6 @@
/* tc-m68hc11.c -- Assembler code for the Motorola 68HC11 & 68HC12.
Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Stephane Carrez (stcarrez@worldnet.fr)
Written by Stephane Carrez (stcarrez@nerim.fr)
This file is part of GAS, the GNU Assembler.
@ -25,6 +25,7 @@
#include "subsegs.h"
#include "opcode/m68hc11.h"
#include "dwarf2dbg.h"
#include "elf/m68hc11.h"
const char comment_chars[] = ";!";
const char line_comment_chars[] = "#*";
@ -163,6 +164,7 @@ 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 void fixup24 PARAMS ((expressionS *, int, int));
static unsigned char convert_branch PARAMS ((unsigned char));
static char *m68hc11_new_insn PARAMS ((int));
static void build_dbranch_insn PARAMS ((struct m68hc11_opcode *,
@ -529,6 +531,10 @@ cmp_opcode (op1, op2)
return strcmp (op1->name, op2->name);
}
#define IS_CALL_SYMBOL(MODE) \
(((MODE) & (M6812_OP_PAGE|M6811_OP_IND16)) \
== ((M6812_OP_PAGE|M6811_OP_IND16)))
/* Initialize the assembler. Create the opcode hash table
(sorted on the names) with the M6811 opcode table
(from opcode library). */
@ -613,9 +619,15 @@ md_begin ()
expect++;
if (opcodes->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2))
expect++;
/* Special case for call instruction. */
if ((opcodes->format & M6812_OP_PAGE)
&& !(opcodes->format & M6811_OP_IND16))
expect++;
if (expect < opc->min_operands)
opc->min_operands = expect;
if (IS_CALL_SYMBOL (opcodes->format))
expect++;
if (expect > opc->max_operands)
opc->max_operands = expect;
}
@ -695,6 +707,15 @@ print_opcode_format (opcode, example)
p = &p[strlen (p)];
}
if (format & M6812_OP_PAGE)
{
if (example)
sprintf (p, ", %d", rand () & 0x0FF);
else
strcpy (p, ", <page>");
p = &p[strlen (p)];
}
if (format & M6811_OP_DIRECT)
{
if (example)
@ -900,19 +921,19 @@ register_name ()
/* 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_*
*<exp> M6811_OP_DIRECT - O_*
.{+-}<exp> M6811_OP_JUMP_REL - O_*
<exp> M6811_OP_IND16 - O_*
,r N,r M6812_OP_IDX M6812_OP_REG O_constant O_register
n,-r M6812_PRE_DEC M6812_OP_REG O_constant O_register
n,+r M6812_PRE_INC " "
n,r- M6812_POST_DEC " "
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 */
Operand mode[0] mode[1] exp[0] exp[1]
#n M6811_OP_IMM16 - O_*
*<exp> M6811_OP_DIRECT - O_*
.{+-}<exp> M6811_OP_JUMP_REL - O_*
<exp> M6811_OP_IND16 - O_*
,r N,r M6812_OP_IDX M6812_OP_REG O_constant O_register
n,-r M6812_PRE_DEC M6812_OP_REG O_constant O_register
n,+r M6812_PRE_INC " "
n,r- M6812_POST_DEC " "
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_D_IDX M6812_OP_REG O_register O_register
[n,r] M6811_OP_D_IDX_2 M6812_OP_REG O_constant O_register */
static int
get_operand (oper, which, opmode)
operand *oper;
@ -974,7 +995,7 @@ get_operand (oper, which, opmode)
as_bad (_("Indirect indexed addressing is not valid for 68HC11."));
p++;
mode = M6812_OP_IDX_2;
mode = M6812_OP_D_IDX;
p = skip_whites (p);
}
else if (*p == ',') /* Special handling of ,x and ,y. */
@ -996,7 +1017,7 @@ get_operand (oper, which, opmode)
}
input_line_pointer = p;
if (mode == M6811_OP_NONE || mode == M6812_OP_IDX_2)
if (mode == M6811_OP_NONE || mode == M6812_OP_D_IDX)
reg = register_name ();
else
reg = REG_NONE;
@ -1004,7 +1025,7 @@ get_operand (oper, which, opmode)
if (reg != REG_NONE)
{
p = skip_whites (input_line_pointer);
if (*p == ']' && mode == M6812_OP_IDX_2)
if (*p == ']' && mode == M6812_OP_D_IDX)
{
as_bad
(_("Missing second register or offset for indexed-indirect mode."));
@ -1015,7 +1036,7 @@ get_operand (oper, which, opmode)
oper->mode = mode | M6812_OP_REG;
if (*p != ',')
{
if (mode == M6812_OP_IDX_2)
if (mode == M6812_OP_D_IDX)
{
as_bad (_("Missing second register for indexed-indirect mode."));
return -1;
@ -1029,7 +1050,7 @@ get_operand (oper, which, opmode)
if (reg != REG_NONE)
{
p = skip_whites (input_line_pointer);
if (mode == M6812_OP_IDX_2)
if (mode == M6812_OP_D_IDX)
{
if (*p != ']')
{
@ -1037,6 +1058,7 @@ get_operand (oper, which, opmode)
return -1;
}
p++;
oper->mode = M6812_OP_D_IDX;
}
input_line_pointer = p;
@ -1089,7 +1111,7 @@ get_operand (oper, which, opmode)
p = input_line_pointer;
if (mode == M6811_OP_NONE || mode == M6811_OP_DIRECT
|| mode == M6812_OP_IDX_2)
|| mode == M6812_OP_D_IDX)
{
p = skip_whites (input_line_pointer);
@ -1097,6 +1119,8 @@ get_operand (oper, which, opmode)
{
int possible_mode = M6811_OP_NONE;
char *old_input_line;
old_input_line = p;
p++;
/* 68HC12 pre increment or decrement. */
@ -1114,7 +1138,6 @@ get_operand (oper, which, opmode)
}
p = skip_whites (p);
}
old_input_line = input_line_pointer;
input_line_pointer = p;
reg = register_name ();
@ -1150,7 +1173,7 @@ get_operand (oper, which, opmode)
as_bad (_("Wrong register in register indirect mode."));
return -1;
}
if (mode == M6812_OP_IDX_2)
if (mode == M6812_OP_D_IDX)
{
p = skip_whites (input_line_pointer);
if (*p++ != ']')
@ -1159,6 +1182,9 @@ get_operand (oper, which, opmode)
return -1;
}
input_line_pointer = p;
oper->reg1 = reg;
oper->mode = M6812_OP_D_IDX_2;
return 1;
}
if (reg != REG_NONE)
{
@ -1193,6 +1219,7 @@ get_operand (oper, which, opmode)
oper->mode = mode;
return 1;
}
input_line_pointer = old_input_line;
}
if (mode == M6812_OP_D_IDX_2)
@ -1236,6 +1263,7 @@ check_range (num, mode)
if (mode & M6812_OP_JUMP_REL16)
mode = M6811_OP_IND16;
mode &= ~M6811_OP_BRANCH;
switch (mode)
{
case M6811_OP_IX:
@ -1245,6 +1273,7 @@ check_range (num, mode)
case M6811_OP_BITMASK:
case M6811_OP_IMM8:
case M6812_OP_PAGE:
return (((num & 0xFFFFFF00) == 0) || ((num & 0xFFFFFF00) == 0xFFFFFF00))
? 1 : 0;
@ -1252,6 +1281,7 @@ check_range (num, mode)
return (num >= -128 && num <= 127) ? 1 : 0;
case M6811_OP_IND16:
case M6811_OP_IND16 | M6812_OP_PAGE:
case M6811_OP_IMM16:
return (((num & 0xFFFF0000) == 0) || ((num & 0xFFFF0000) == 0xFFFF0000))
? 1 : 0;
@ -1328,7 +1358,9 @@ fixup8 (oper, mode, opmode)
((opmode & M6811_OP_HIGH_ADDR)
? BFD_RELOC_M68HC11_HI8
: ((opmode & M6811_OP_LOW_ADDR)
? BFD_RELOC_M68HC11_LO8 : BFD_RELOC_8)));
? BFD_RELOC_M68HC11_LO8
: ((mode & M6812_OP_PAGE)
? BFD_RELOC_M68HC11_PAGE : BFD_RELOC_8))));
}
number_to_chars_bigendian (f, 0, 1);
}
@ -1368,7 +1400,9 @@ fixup16 (oper, mode, opmode)
oper,
(mode & M6812_OP_JUMP_REL16 ? true : false),
(mode & M6812_OP_JUMP_REL16
? BFD_RELOC_16_PCREL : BFD_RELOC_16));
? BFD_RELOC_16_PCREL
: (mode & M6812_OP_PAGE)
? BFD_RELOC_M68HC11_LO16 : BFD_RELOC_16));
number_to_chars_bigendian (f, 0, 2);
if (mode & M6812_OP_JUMP_REL16)
fixp->fx_pcrel_adjust = 2;
@ -1378,6 +1412,42 @@ fixup16 (oper, mode, opmode)
as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);
}
}
/* Put a 3 byte expression described by 'oper'. If this expression contains
unresolved symbols, generate a 24-bit fixup. */
static void
fixup24 (oper, mode, opmode)
expressionS *oper;
int mode;
int opmode ATTRIBUTE_UNUSED;
{
char *f;
f = frag_more (3);
if (oper->X_op == O_constant)
{
if (!check_range (oper->X_add_number, mode))
{
as_bad (_("Operand out of 16-bit range: `%ld'."),
oper->X_add_number);
}
number_to_chars_bigendian (f, oper->X_add_number & 0x0FFFFFF, 3);
}
else if (oper->X_op != O_register)
{
fixS *fixp;
/* Now create a 24-bit fixup. */
fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
oper, false, BFD_RELOC_M68HC11_24);
number_to_chars_bigendian (f, 0, 3);
}
else
{
as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);
}
}
/* 68HC11 and 68HC12 code generation. */
@ -1703,7 +1773,7 @@ build_indexed_byte (op, format, move_insn)
return 1;
}
if (mode & M6812_OP_IDX)
if (mode & (M6812_OP_IDX | M6812_OP_D_IDX_2))
{
switch (op->reg1)
{
@ -1741,7 +1811,7 @@ build_indexed_byte (op, format, move_insn)
return -1;
}
if (val >= -16 && val <= 15 && !(mode & M6812_OP_IDX_2))
if (val >= -16 && val <= 15 && !(mode & M6812_OP_D_IDX_2))
{
byte = byte << 6;
byte |= val & 0x1f;
@ -1749,7 +1819,7 @@ build_indexed_byte (op, format, move_insn)
number_to_chars_bigendian (f, byte, 1);
return 1;
}
else if (val >= -256 && val <= 255 && !(mode & M6812_OP_IDX_2))
else if (val >= -256 && val <= 255 && !(mode & M6812_OP_D_IDX_2))
{
byte = byte << 3;
byte |= 0xe0;
@ -1763,7 +1833,7 @@ build_indexed_byte (op, format, move_insn)
else
{
byte = byte << 3;
if (mode & M6812_OP_IDX_2)
if (mode & M6812_OP_D_IDX_2)
byte |= 0xe3;
else
byte |= 0xe2;
@ -1774,7 +1844,15 @@ build_indexed_byte (op, format, move_insn)
return 3;
}
}
if (op->reg1 != REG_PC)
if (mode & M6812_OP_D_IDX_2)
{
byte = (byte << 3) | 0xe3;
f = frag_more (1);
number_to_chars_bigendian (f, byte, 1);
fixup16 (&op->exp, 0, 0);
}
else if (op->reg1 != REG_PC)
{
byte = (byte << 3) | 0xe2;
f = frag_more (1);
@ -1797,9 +1875,9 @@ build_indexed_byte (op, format, move_insn)
return 3;
}
if (mode & M6812_OP_REG)
if (mode & (M6812_OP_REG | M6812_OP_D_IDX))
{
if (mode & M6812_OP_IDX_2)
if (mode & M6812_OP_D_IDX)
{
if (op->reg1 != REG_D)
as_bad (_("Expecting register D for indexed indirect mode."));
@ -1954,9 +2032,17 @@ build_insn (opcode, operands, nb_operands)
operands[i].mode);
i++;
}
else if (IS_CALL_SYMBOL (format) && nb_operands == 1)
{
format &= ~M6812_OP_PAGE;
fixup24 (&operands[i].exp, format & M6811_OP_IND16,
operands[i].mode);
i++;
}
else if (format & (M6811_OP_IMM16 | M6811_OP_IND16))
{
fixup16 (&operands[i].exp, format & (M6811_OP_IMM16 | M6811_OP_IND16),
fixup16 (&operands[i].exp,
format & (M6811_OP_IMM16 | M6811_OP_IND16 | M6812_OP_PAGE),
operands[i].mode);
i++;
}
@ -1971,7 +2057,8 @@ build_insn (opcode, operands, nb_operands)
i = 1;
}
else if (format &
(M6812_OP_IDX | M6812_OP_IDX_2 | M6812_OP_IDX_1 | M6812_OP_D_IDX))
(M6812_OP_IDX | M6812_OP_IDX_2 | M6812_OP_IDX_1
| M6812_OP_D_IDX | M6812_OP_D_IDX_2))
{
build_indexed_byte (&operands[i], format, move_insn);
i++;
@ -1994,6 +2081,10 @@ build_insn (opcode, operands, nb_operands)
{
fixup16 (&operands[1].exp, M6811_OP_IND16, operands[1].mode);
}
if (format & M6812_OP_PAGE)
{
fixup8 (&operands[i].exp, M6812_OP_PAGE, operands[i].mode);
}
}
/* Opcode identification and operand analysis. */
@ -2032,6 +2123,9 @@ find (opc, operands, nb_operands)
expect++;
if (opcode->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2))
expect++;
if ((opcode->format & M6812_OP_PAGE)
&& (!IS_CALL_SYMBOL (opcode->format) || nb_operands == 2))
expect++;
for (i = 0; expect == nb_operands && i < nb_operands; i++)
{
@ -2064,6 +2158,8 @@ find (opc, operands, nb_operands)
{
if (i == 0 && (format & M6811_OP_IND16) != 0)
continue;
if (i != 0 && (format & M6812_OP_PAGE) != 0)
continue;
if (i != 0 && (format & M6812_OP_IND16_P2) != 0)
continue;
if (i == 0 && (format & M6811_OP_BITMASK))
@ -2089,9 +2185,6 @@ find (opc, operands, nb_operands)
&& (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)
&& (format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)))
@ -2117,6 +2210,11 @@ find (opc, operands, nb_operands)
if (i == 1 && format & M6812_OP_IDX_P2)
continue;
}
if (mode & format & (M6812_OP_D_IDX | M6812_OP_D_IDX_2))
{
if (i == 0)
continue;
}
if (mode & M6812_AUTO_INC_DEC)
{
if (i == 0
@ -2204,7 +2302,10 @@ find_opcode (opc, operands, nb_operands)
if (i >= opc->min_operands)
{
opcode = find (opc, operands, i);
if (opcode)
if (opcode && !(opcode->format & M6812_OP_PAGE))
return opcode;
if (opcode && *input_line_pointer != ',')
return opcode;
}
@ -2779,8 +2880,15 @@ md_apply_fix3 (fixP, valP, seg)
bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
break;
case BFD_RELOC_24:
case BFD_RELOC_M68HC11_24:
bfd_putb16 ((bfd_vma) (value & 0x0ffff), (unsigned char *) where);
((bfd_byte*) where)[2] = ((value >> 16) & 0x0ff);
break;
case BFD_RELOC_16:
case BFD_RELOC_16_PCREL:
case BFD_RELOC_M68HC11_LO16:
bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
if (value < -65537 || value > 65535)
as_bad_where (fixP->fx_file, fixP->fx_line,
@ -2793,6 +2901,7 @@ md_apply_fix3 (fixP, valP, seg)
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