mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 07:08:01 +08:00
Handle xxx@word + N. Treat it as xxx >> 2 + N.
This commit is contained in:
@ -35,7 +35,12 @@ const char FLT_CHARS[] = "dD";
|
|||||||
|
|
||||||
int Optimizing = 0;
|
int Optimizing = 0;
|
||||||
|
|
||||||
#define AT_WORD (-1)
|
#define AT_WORD_P(X) ((X)->X_op == O_right_shift \
|
||||||
|
&& (X)->X_op_symbol != NULL \
|
||||||
|
&& (X)->X_op_symbol->sy_value.X_op == O_constant \
|
||||||
|
&& (X)->X_op_symbol->sy_value.X_add_number == AT_WORD_RIGHT_SHIFT)
|
||||||
|
#define AT_WORD_RIGHT_SHIFT 2
|
||||||
|
|
||||||
|
|
||||||
/* fixups */
|
/* fixups */
|
||||||
#define MAX_INSN_FIXUPS (5)
|
#define MAX_INSN_FIXUPS (5)
|
||||||
@ -79,6 +84,8 @@ static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1
|
|||||||
int exec_type));
|
int exec_type));
|
||||||
|
|
||||||
struct option md_longopts[] = {
|
struct option md_longopts[] = {
|
||||||
|
#define OPTION_NOWARNSWAP (OPTION_MD_BASE)
|
||||||
|
{"nowarnswap", no_argument, NULL, OPTION_NOWARNSWAP},
|
||||||
{NULL, no_argument, NULL, 0}
|
{NULL, no_argument, NULL, 0}
|
||||||
};
|
};
|
||||||
size_t md_longopts_size = sizeof(md_longopts);
|
size_t md_longopts_size = sizeof(md_longopts);
|
||||||
@ -218,6 +225,9 @@ md_parse_option (c, arg)
|
|||||||
/* Optimize. Will attempt to parallelize operations */
|
/* Optimize. Will attempt to parallelize operations */
|
||||||
Optimizing = 1;
|
Optimizing = 1;
|
||||||
break;
|
break;
|
||||||
|
case OPTION_NOWARNSWAP:
|
||||||
|
flag_warn_suppress_instructionswap = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -425,18 +435,39 @@ get_operands (exp)
|
|||||||
expression (&exp[numops]);
|
expression (&exp[numops]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncasecmp (input_line_pointer, "@word", 5))
|
if (strncasecmp (input_line_pointer, "@word", 5) == 0)
|
||||||
{
|
{
|
||||||
|
input_line_pointer += 5;
|
||||||
if (exp[numops].X_op == O_register)
|
if (exp[numops].X_op == O_register)
|
||||||
{
|
{
|
||||||
/* if it looked like a register name but was followed by "@word" */
|
/* if it looked like a register name but was followed by
|
||||||
/* then it was really a symbol, so change it to one */
|
"@word" then it was really a symbol, so change it to
|
||||||
|
one */
|
||||||
exp[numops].X_op = O_symbol;
|
exp[numops].X_op = O_symbol;
|
||||||
exp[numops].X_add_symbol = symbol_find_or_make ((char *)exp[numops].X_op_symbol);
|
exp[numops].X_add_symbol = symbol_find_or_make ((char *)exp[numops].X_op_symbol);
|
||||||
}
|
}
|
||||||
exp[numops].X_op_symbol = (struct symbol *)-1;
|
|
||||||
exp[numops].X_add_number = AT_WORD;
|
/* check for identifier@word+constant */
|
||||||
input_line_pointer += 5;
|
if (*input_line_pointer == '-' || *input_line_pointer == '+')
|
||||||
|
{
|
||||||
|
char *orig_line = input_line_pointer;
|
||||||
|
expressionS new_exp;
|
||||||
|
expression (&new_exp);
|
||||||
|
exp[numops].X_add_number = new_exp.X_add_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert expr into a right shift by AT_WORD_RIGHT_SHIFT */
|
||||||
|
{
|
||||||
|
expressionS new_exp;
|
||||||
|
memset (&new_exp, 0, sizeof new_exp);
|
||||||
|
new_exp.X_add_number = AT_WORD_RIGHT_SHIFT;
|
||||||
|
new_exp.X_op = O_constant;
|
||||||
|
new_exp.X_unsigned = 1;
|
||||||
|
exp[numops].X_op_symbol = make_expr_symbol (&new_exp);
|
||||||
|
exp[numops].X_op = O_right_shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
know (AT_WORD_P (&exp[numops]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exp[numops].X_op == O_illegal)
|
if (exp[numops].X_op == O_illegal)
|
||||||
@ -533,12 +564,20 @@ build_insn (opcode, opers, insn)
|
|||||||
if (fixups->fc >= MAX_INSN_FIXUPS)
|
if (fixups->fc >= MAX_INSN_FIXUPS)
|
||||||
as_fatal ("too many fixups");
|
as_fatal ("too many fixups");
|
||||||
|
|
||||||
if (opers[i].X_op == O_symbol && number == AT_WORD &&
|
if (AT_WORD_P (&opers[i]))
|
||||||
opers[i].X_op_symbol == (struct symbol *)-1 )
|
|
||||||
{
|
{
|
||||||
number = opers[i].X_add_number = 0;
|
/* Reconize XXX>>1+N aka XXX@word+N as special (AT_WORD) */
|
||||||
fixups->fix[fixups->fc].reloc = BFD_RELOC_D10V_18;
|
fixups->fix[fixups->fc].reloc = BFD_RELOC_D10V_18;
|
||||||
} else
|
opers[i].X_op = O_symbol;
|
||||||
|
opers[i].X_op_symbol = NULL; /* Should free it */
|
||||||
|
/* number is left shifted by AT_WORD_RIGHT_SHIFT so
|
||||||
|
that, it is aligned with the symbol's value. Later,
|
||||||
|
BFD_RELOC_D10V_18 will right shift (symbol_value +
|
||||||
|
X_add_number). */
|
||||||
|
number <<= AT_WORD_RIGHT_SHIFT;
|
||||||
|
opers[i].X_add_number = number;
|
||||||
|
}
|
||||||
|
else
|
||||||
fixups->fix[fixups->fc].reloc =
|
fixups->fix[fixups->fc].reloc =
|
||||||
get_reloc((struct d10v_operand *)&d10v_operands[opcode->operands[i]]);
|
get_reloc((struct d10v_operand *)&d10v_operands[opcode->operands[i]]);
|
||||||
|
|
||||||
@ -718,7 +757,7 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
|
|||||||
{
|
{
|
||||||
if (opcode2->unit == IU)
|
if (opcode2->unit == IU)
|
||||||
as_fatal ("Two IU instructions may not be executed in parallel");
|
as_fatal ("Two IU instructions may not be executed in parallel");
|
||||||
if (flag_warn_instructionswap)
|
if (!flag_warn_suppress_instructionswap)
|
||||||
as_warn ("Swapping instruction order");
|
as_warn ("Swapping instruction order");
|
||||||
insn = FM00 | (insn2 << 15) | insn1;
|
insn = FM00 | (insn2 << 15) | insn1;
|
||||||
}
|
}
|
||||||
@ -726,7 +765,7 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
|
|||||||
{
|
{
|
||||||
if (opcode1->unit == MU)
|
if (opcode1->unit == MU)
|
||||||
as_fatal ("Two MU instructions may not be executed in parallel");
|
as_fatal ("Two MU instructions may not be executed in parallel");
|
||||||
if (flag_warn_instructionswap)
|
if (!flag_warn_suppress_instructionswap)
|
||||||
as_warn ("Swapping instruction order");
|
as_warn ("Swapping instruction order");
|
||||||
insn = FM00 | (insn2 << 15) | insn1;
|
insn = FM00 | (insn2 << 15) | insn1;
|
||||||
}
|
}
|
||||||
@ -1149,8 +1188,7 @@ find_opcode (opcode, myops)
|
|||||||
else
|
else
|
||||||
value = S_GET_VALUE(myops[opnum].X_add_symbol);
|
value = S_GET_VALUE(myops[opnum].X_add_symbol);
|
||||||
|
|
||||||
if (myops[opnum].X_add_number == AT_WORD &&
|
if (AT_WORD_P (&myops[opnum]))
|
||||||
myops[opnum].X_op_symbol == (struct symbol *)-1)
|
|
||||||
{
|
{
|
||||||
if (bits > 4)
|
if (bits > 4)
|
||||||
{
|
{
|
||||||
@ -1368,7 +1406,7 @@ md_apply_fix3 (fixp, valuep, seg)
|
|||||||
case BFD_RELOC_D10V_18_PCREL:
|
case BFD_RELOC_D10V_18_PCREL:
|
||||||
case BFD_RELOC_D10V_18:
|
case BFD_RELOC_D10V_18:
|
||||||
/* instruction addresses are always right-shifted by 2 */
|
/* instruction addresses are always right-shifted by 2 */
|
||||||
value >>= 2;
|
value >>= AT_WORD_RIGHT_SHIFT;
|
||||||
if (fixp->fx_size == 2)
|
if (fixp->fx_size == 2)
|
||||||
bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
|
bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user