2000-05-25 Alexandre Oliva <aoliva@cygnus.com>

* config/tc-mn10300.c (mn10300_insert_operand): Negate negative
accumulator's shift.
2000-05-08  Alexandre Oliva  <aoliva@cygnus.com>
* config/tc-mn10300.c (md_relax_table, md_convert_frag,
md_assemble, md_estimate_size_before_relax): Handle fbCC.
2000-04-20  Alexandre Oliva  <aoliva@cygnus.com>
* config/tc-mn10300.c (HAVE_AM33): Redefine in terms of
HAVE_AM33_2.
2000-04-03  Alexandre Oliva  <aoliva@cygnus.com>
* config/tc-mn10300.c (md_pseudo_table): Use AM33_2 constant.
(HAVE_AM33): Match AM33_2 too.
(HAVE_AM33_2): New macro.
(md_assemble): Use it.  Match 2.0 registers only if HAVE_AM33_2.
2000-04-01  Alexandre Oliva  <aoliva@cygnus.com>
* config/tc-mn10300.c (md_pseudo_table): Added `am33_2'.
(float_registers, double_registers): New variables.
(float_register_name, double_register_name): New functions.
(md_assemble): Recognize FP registers.  Implement FMT_D3.
(mn10300_insert_operand): Support FP registers.
This commit is contained in:
Alexandre Oliva 2003-07-10 02:50:00 +00:00
parent e1f834a331
commit e7b715256e
2 changed files with 440 additions and 1 deletions

View file

@ -1,3 +1,26 @@
2003-07-09 Alexandre Oliva <aoliva@redhat.com>
2000-05-25 Alexandre Oliva <aoliva@cygnus.com>
* config/tc-mn10300.c (mn10300_insert_operand): Negate negative
accumulator's shift.
2000-05-08 Alexandre Oliva <aoliva@cygnus.com>
* config/tc-mn10300.c (md_relax_table, md_convert_frag,
md_assemble, md_estimate_size_before_relax): Handle fbCC.
2000-04-20 Alexandre Oliva <aoliva@cygnus.com>
* config/tc-mn10300.c (HAVE_AM33): Redefine in terms of
HAVE_AM33_2.
2000-04-03 Alexandre Oliva <aoliva@cygnus.com>
* config/tc-mn10300.c (md_pseudo_table): Use AM33_2 constant.
(HAVE_AM33): Match AM33_2 too.
(HAVE_AM33_2): New macro.
(md_assemble): Use it. Match 2.0 registers only if HAVE_AM33_2.
2000-04-01 Alexandre Oliva <aoliva@cygnus.com>
* config/tc-mn10300.c (md_pseudo_table): Added `am33_2'.
(float_registers, double_registers): New variables.
(float_register_name, double_register_name): New functions.
(md_assemble): Recognize FP registers. Implement FMT_D3.
(mn10300_insert_operand): Support FP registers.
2003-07-08 Chris Demetriou <cgd@broadcom.com>
* config/tc-mips.c (mips_validate_fix): Do not warn about branch

View file

@ -78,6 +78,11 @@ const relax_typeS md_relax_table[] = {
{0x7fff, -0x8000, 3, 12},
{0x7fffffff, -0x80000000, 5, 0},
/* fbCC relaxing */
{0x7f, -0x80, 3, 14},
{0x7fff, -0x8000, 6, 15},
{0x7fffffff, -0x80000000, 8, 0},
};
/* Local functions. */
@ -127,11 +132,13 @@ const pseudo_typeS md_pseudo_table[] =
{
{ "am30", set_arch_mach, AM30 },
{ "am33", set_arch_mach, AM33 },
{ "am33_2", (void (*) PARAMS ((int))) set_arch_mach, AM33_2 },
{ "mn10300", set_arch_mach, MN103 },
{NULL, 0, 0}
};
#define HAVE_AM33 (current_machine == AM33)
#define HAVE_AM33_2 (current_machine == AM33_2)
#define HAVE_AM33 (current_machine == AM33 || HAVE_AM33_2)
#define HAVE_AM30 (current_machine == AM30)
/* Opcode hash table. */
@ -251,6 +258,69 @@ static const struct reg_name other_registers[] =
#define OTHER_REG_NAME_CNT \
(sizeof (other_registers) / sizeof (struct reg_name))
static const struct reg_name float_registers[] =
{
{ "fs0", 0 },
{ "fs1", 1 },
{ "fs10", 10 },
{ "fs11", 11 },
{ "fs12", 12 },
{ "fs13", 13 },
{ "fs14", 14 },
{ "fs15", 15 },
{ "fs16", 16 },
{ "fs17", 17 },
{ "fs18", 18 },
{ "fs19", 19 },
{ "fs2", 2 },
{ "fs20", 20 },
{ "fs21", 21 },
{ "fs22", 22 },
{ "fs23", 23 },
{ "fs24", 24 },
{ "fs25", 25 },
{ "fs26", 26 },
{ "fs27", 27 },
{ "fs28", 28 },
{ "fs29", 29 },
{ "fs3", 3 },
{ "fs30", 30 },
{ "fs31", 31 },
{ "fs4", 4 },
{ "fs5", 5 },
{ "fs6", 6 },
{ "fs7", 7 },
{ "fs8", 8 },
{ "fs9", 9 },
};
#define FLOAT_REG_NAME_CNT \
(sizeof (float_registers) / sizeof (struct reg_name))
static const struct reg_name double_registers[] =
{
{ "fd0", 0 },
{ "fd10", 10 },
{ "fd12", 12 },
{ "fd14", 14 },
{ "fd16", 16 },
{ "fd18", 18 },
{ "fd2", 2 },
{ "fd20", 20 },
{ "fd22", 22 },
{ "fd24", 24 },
{ "fd26", 26 },
{ "fd28", 28 },
{ "fd30", 30 },
{ "fd4", 4 },
{ "fd6", 6 },
{ "fd8", 8 },
};
#define DOUBLE_REG_NAME_CNT \
(sizeof (double_registers) / sizeof (struct reg_name))
/* reg_name_search does a binary search of the given register table
to see if "name" is a valid regiter name. Returns the register
number from the array on success, or -1 on failure. */
@ -518,6 +588,101 @@ other_register_name (expressionP)
return FALSE;
}
static bfd_boolean double_register_name PARAMS ((expressionS *));
static bfd_boolean float_register_name PARAMS ((expressionS *));
/* Summary of float_register_name:
in: Input_line_pointer points to 1st char of operand.
out: A expressionS.
The operand may have been a register: in this case, X_op == O_register,
X_add_number is set to the register number, and truth is returned.
Input_line_pointer->(next non-blank) char after operand, or is in
its original state. */
static bfd_boolean
float_register_name (expressionP)
expressionS *expressionP;
{
int reg_number;
char *name;
char *start;
char c;
/* Find the spelling of the operand. */
start = name = input_line_pointer;
c = get_symbol_end ();
reg_number = reg_name_search (float_registers, FLOAT_REG_NAME_CNT, name);
/* Put back the delimiting char. */
* input_line_pointer = c;
/* Look to see if it's in the register table. */
if (reg_number >= 0)
{
expressionP->X_op = O_register;
expressionP->X_add_number = reg_number;
/* Make the rest nice. */
expressionP->X_add_symbol = NULL;
expressionP->X_op_symbol = NULL;
return TRUE;
}
/* Reset the line as if we had not done anything. */
input_line_pointer = start;
return FALSE;
}
/* Summary of double_register_name:
in: Input_line_pointer points to 1st char of operand.
out: A expressionS.
The operand may have been a register: in this case, X_op == O_register,
X_add_number is set to the register number, and truth is returned.
Input_line_pointer->(next non-blank) char after operand, or is in
its original state. */
static bfd_boolean
double_register_name (expressionP)
expressionS *expressionP;
{
int reg_number;
char *name;
char *start;
char c;
/* Find the spelling of the operand. */
start = name = input_line_pointer;
c = get_symbol_end ();
reg_number = reg_name_search (double_registers, DOUBLE_REG_NAME_CNT, name);
/* Put back the delimiting char. */
* input_line_pointer = c;
/* Look to see if it's in the register table. */
if (reg_number >= 0)
{
expressionP->X_op = O_register;
expressionP->X_add_number = reg_number;
/* Make the rest nice. */
expressionP->X_add_symbol = NULL;
expressionP->X_op_symbol = NULL;
return TRUE;
}
/* Reset the line as if we had not done anything. */
input_line_pointer = start;
return FALSE;
}
void
md_show_usage (stream)
FILE *stream;
@ -865,6 +1030,151 @@ md_convert_frag (abfd, sec, fragP)
fragP->fr_var = 0;
fragP->fr_fix += 5;
}
else if (fragP->fr_subtype == 13)
{
fix_new (fragP, fragP->fr_fix + 2, 1, fragP->fr_symbol,
fragP->fr_offset + 2, 1, BFD_RELOC_8_PCREL);
fragP->fr_var = 0;
fragP->fr_fix += 3;
}
else if (fragP->fr_subtype == 14)
{
/* Reverse the condition of the first branch. */
int offset = fragP->fr_fix;
int opcode = fragP->fr_literal[offset + 1] & 0xff;
switch (opcode)
{
case 0xd0:
opcode = 0xd1;
break;
case 0xd1:
opcode = 0xd0;
break;
case 0xd2:
opcode = 0xdc;
break;
case 0xd3:
opcode = 0xdb;
break;
case 0xd4:
opcode = 0xda;
break;
case 0xd5:
opcode = 0xd9;
break;
case 0xd6:
opcode = 0xd8;
break;
case 0xd7:
opcode = 0xdd;
break;
case 0xd8:
opcode = 0xd6;
break;
case 0xd9:
opcode = 0xd5;
break;
case 0xda:
opcode = 0xd4;
break;
case 0xdb:
opcode = 0xd3;
break;
case 0xdc:
opcode = 0xd2;
break;
case 0xdd:
opcode = 0xd7;
break;
default:
abort ();
}
fragP->fr_literal[offset + 1] = opcode;
/* Create a fixup for the reversed conditional branch. */
sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
fix_new (fragP, fragP->fr_fix + 2, 1,
symbol_new (buf, sec, 0, fragP->fr_next),
fragP->fr_offset + 2, 1, BFD_RELOC_8_PCREL);
/* Now create the unconditional branch + fixup to the
final target. */
fragP->fr_literal[offset + 3] = 0xcc;
fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
fragP->fr_offset + 1, 1, BFD_RELOC_16_PCREL);
fragP->fr_var = 0;
fragP->fr_fix += 6;
}
else if (fragP->fr_subtype == 15)
{
/* Reverse the condition of the first branch. */
int offset = fragP->fr_fix;
int opcode = fragP->fr_literal[offset + 1] & 0xff;
switch (opcode)
{
case 0xd0:
opcode = 0xd1;
break;
case 0xd1:
opcode = 0xd0;
break;
case 0xd2:
opcode = 0xdc;
break;
case 0xd3:
opcode = 0xdb;
break;
case 0xd4:
opcode = 0xda;
break;
case 0xd5:
opcode = 0xd9;
break;
case 0xd6:
opcode = 0xd8;
break;
case 0xd7:
opcode = 0xdd;
break;
case 0xd8:
opcode = 0xd6;
break;
case 0xd9:
opcode = 0xd5;
break;
case 0xda:
opcode = 0xd4;
break;
case 0xdb:
opcode = 0xd3;
break;
case 0xdc:
opcode = 0xd2;
break;
case 0xdd:
opcode = 0xd7;
break;
default:
abort ();
}
fragP->fr_literal[offset + 1] = opcode;
/* Create a fixup for the reversed conditional branch. */
sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
fix_new (fragP, fragP->fr_fix + 2, 1,
symbol_new (buf, sec, 0, fragP->fr_next),
fragP->fr_offset + 2, 1, BFD_RELOC_8_PCREL);
/* Now create the unconditional branch + fixup to the
final target. */
fragP->fr_literal[offset + 3] = 0xdc;
fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
fragP->fr_offset + 1, 1, BFD_RELOC_32_PCREL);
fragP->fr_var = 0;
fragP->fr_fix += 8;
}
else
abort ();
}
@ -965,6 +1275,7 @@ md_assemble (str)
/* If the instruction is not available on the current machine
then it can not possibly match. */
if (opcode->machine
&& !(opcode->machine == AM33_2 && HAVE_AM33_2)
&& !(opcode->machine == AM33 && HAVE_AM33)
&& !(opcode->machine == AM30 && HAVE_AM30))
goto error;
@ -1059,6 +1370,39 @@ md_assemble (str)
goto error;
}
}
else if (operand->flags & MN10300_OPERAND_FSREG)
{
if (!float_register_name (&ex))
{
input_line_pointer = hold;
str = hold;
goto error;
}
}
else if (operand->flags & MN10300_OPERAND_FDREG)
{
if (!double_register_name (&ex))
{
input_line_pointer = hold;
str = hold;
goto error;
}
}
else if (operand->flags & MN10300_OPERAND_FPCR)
{
char *start = input_line_pointer;
char c = get_symbol_end ();
if (strcasecmp (start, "fpcr") != 0)
{
*input_line_pointer = c;
input_line_pointer = hold;
str = hold;
goto error;
}
*input_line_pointer = c;
goto keep_going;
}
else if (operand->flags & MN10300_OPERAND_USP)
{
char *start = input_line_pointer;
@ -1298,6 +1642,18 @@ md_assemble (str)
str = hold;
goto error;
}
else if (HAVE_AM33_2 && float_register_name (&ex))
{
input_line_pointer = hold;
str = hold;
goto error;
}
else if (HAVE_AM33_2 && double_register_name (&ex))
{
input_line_pointer = hold;
str = hold;
goto error;
}
else if (*str == ')' || *str == '(')
{
input_line_pointer = hold;
@ -1324,6 +1680,8 @@ md_assemble (str)
mask = MN10300_OPERAND_DREG | MN10300_OPERAND_AREG;
if (HAVE_AM33)
mask |= MN10300_OPERAND_RREG | MN10300_OPERAND_XRREG;
if (HAVE_AM33_2)
mask |= MN10300_OPERAND_FSREG | MN10300_OPERAND_FDREG;
if ((operand->flags & mask) == 0)
{
input_line_pointer = hold;
@ -1491,6 +1849,9 @@ keep_going:
if (opcode->format == FMT_D2)
size = 4;
if (opcode->format == FMT_D3)
size = 5;
if (opcode->format == FMT_D4)
size = 6;
@ -1529,6 +1890,8 @@ keep_going:
/* jmp */
else if (size == 3 && opcode->opcode == 0xcc0000)
type = 10;
else if (size == 3 && (opcode->opcode & 0xfff000) == 0xf8d000)
type = 13;
/* bCC (uncommon cases) */
else
type = 3;
@ -1635,6 +1998,12 @@ keep_going:
is really two 8bit immediates. */
number_to_chars_bigendian (f, insn, 4);
}
else if (opcode->format == FMT_D3)
{
number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
number_to_chars_bigendian (f + 4, extension & 0xff, 1);
}
else if (opcode->format == FMT_D4)
{
unsigned long temp = ((insn & 0xffff) << 16) | (extension & 0xffff);
@ -1897,6 +2266,8 @@ md_estimate_size_before_relax (fragp, seg)
|| seg != S_GET_SEGMENT (fragp->fr_symbol)))
fragp->fr_subtype = 12;
if (fragp->fr_subtype == 13)
return 3;
if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
abort ();
@ -2075,6 +2446,51 @@ mn10300_insert_operand (insnp, extensionp, operand, val, file, line, shift)
*extensionp |= ((val & ((1 << (24 - operand->bits)) - 1))
<< operand->shift);
}
else if ((operand->flags & (MN10300_OPERAND_FSREG | MN10300_OPERAND_FDREG)))
{
/* See devo/opcodes/m10300-opc.c just before #define FSM0 for an
explanation of these variables. Note that FMT-implied shifts
are not taken into account for FP registers. */
unsigned long mask_low, mask_high;
int shl_low, shr_high, shl_high;
switch (operand->bits)
{
case 5:
/* Handle regular FP registers. */
if (operand->shift >= 0)
{
/* This is an `m' register. */
shl_low = operand->shift;
shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
}
else
{
/* This is an `n' register. */
shl_low = -operand->shift;
shl_high = shl_low / 4;
}
mask_low = 0x0f;
mask_high = 0x10;
shr_high = 4;
break;
case 3:
/* Handle accumulators. */
shl_low = -operand->shift;
shl_high = 0;
mask_low = 0x03;
mask_high = 0x04;
shr_high = 2;
break;
default:
abort ();
}
*insnp |= ((((val & mask_high) >> shr_high) << shl_high)
| ((val & mask_low) << shl_low));
}
else if ((operand->flags & MN10300_OPERAND_EXTENDED) == 0)
{
*insnp |= (((long) val & ((1 << operand->bits) - 1))