/* tc-sh.c -- Assemble code for the Renesas / SuperH SH
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
return FALSE;
}
-#endif /* OBJ_ELF */
/* Optimize a difference of symbols which have rs_align_test frag if
possible. */
int
sh_optimize_expr (expressionS *l, operatorT op, expressionS *r)
{
-#ifdef OBJ_ELF
bfd_vma frag_off;
if (op == O_subtract
l->X_add_symbol = 0;
return 1;
}
-#endif /* OBJ_ELF */
return 0;
}
+#endif /* OBJ_ELF */
\f
/* This function is called once, at assembler startup time. This should
set up all the tables, etc that the MD part of the assembler needs. */
parse_exp (char *s, sh_operand_info *op)
{
char *save;
- char *new;
+ char *new_pointer;
save = input_line_pointer;
input_line_pointer = s;
|| sh_PIC_related_p (op->immediate.X_op_symbol))
as_bad (_("misplaced PIC operand"));
#endif
- new = input_line_pointer;
+ new_pointer = input_line_pointer;
input_line_pointer = save;
- return new;
+ return new_pointer;
}
/* The many forms of operand:
static unsigned int
build_Mytes (sh_opcode_info *opcode, sh_operand_info *operand)
{
- int index;
+ int indx;
char nbuf[8];
char *output;
unsigned int size = 2;
else
output = frag_more (2);
- for (index = 0; index < max_index; index++)
+ for (indx = 0; indx < max_index; indx++)
{
- sh_nibble_type i = opcode->nibbles[index];
+ sh_nibble_type i = opcode->nibbles[indx];
if (i < 16)
{
- nbuf[index] = i;
+ nbuf[indx] = i;
}
else
{
{
case REG_N:
case REG_N_D:
- nbuf[index] = reg_n;
+ nbuf[indx] = reg_n;
break;
case REG_M:
- nbuf[index] = reg_m;
+ nbuf[indx] = reg_m;
break;
case SDT_REG_N:
if (reg_n < 2 || reg_n > 5)
as_bad (_("Invalid register: 'r%d'"), reg_n);
- nbuf[index] = (reg_n & 3) | 4;
+ nbuf[indx] = (reg_n & 3) | 4;
break;
case REG_NM:
- nbuf[index] = reg_n | (reg_m >> 2);
+ nbuf[indx] = reg_n | (reg_m >> 2);
break;
case REG_B:
- nbuf[index] = reg_b | 0x08;
+ nbuf[indx] = reg_b | 0x08;
break;
case REG_N_B01:
- nbuf[index] = reg_n | 0x01;
+ nbuf[indx] = reg_n | 0x01;
break;
case IMM0_3s:
- nbuf[index] |= 0x08;
+ nbuf[indx] |= 0x08;
case IMM0_3c:
insert (output + low_byte, BFD_RELOC_SH_IMM3, 0, operand);
break;
case IMM0_3Us:
- nbuf[index] |= 0x80;
+ nbuf[indx] |= 0x80;
case IMM0_3Uc:
insert (output + low_byte, BFD_RELOC_SH_IMM3U, 0, operand);
break;
break;
case REPEAT:
output = insert_loop_bounds (output, operand);
- nbuf[index] = opcode->nibbles[3];
+ nbuf[indx] = opcode->nibbles[3];
operand += 2;
break;
default:
}
/* Various routines to kill one day. */
-/* 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 (int type, char *litP, int *sizeP)
{
- int prec;
- LITTLENUM_TYPE words[4];
- char *t;
- int i;
-
- switch (type)
- {
- case 'f':
- prec = 2;
- break;
-
- case 'd':
- prec = 4;
- break;
-
- default:
- *sizeP = 0;
- return _("bad call to md_atof");
- }
-
- t = atof_ieee (input_line_pointer, type, words);
- if (t)
- input_line_pointer = t;
-
- *sizeP = prec * 2;
-
- if (! target_big_endian)
- {
- for (i = prec - 1; i >= 0; i--)
- {
- md_number_to_chars (litP, (valueT) words[i], 2);
- litP += 2;
- }
- }
- else
- {
- for (i = 0; i < prec; i++)
- {
- md_number_to_chars (litP, (valueT) words[i], 2);
- litP += 2;
- }
- }
-
- return NULL;
+ return ieee_md_atof (type, litP, sizeP, target_big_endian);
}
/* Handle the .uses pseudo-op. This pseudo-op is used just before a
OPTION_NO_EXPAND,
OPTION_PT32,
#endif
+ OPTION_H_TICK_HEX,
OPTION_DUMMY /* Not used. This is just here to make it easy to add and subtract options from this enum. */
};
{"no-expand", no_argument, NULL, OPTION_NO_EXPAND},
{"expand-pt32", no_argument, NULL, OPTION_PT32},
#endif /* HAVE_SH64 */
+ { "h-tick-hex", no_argument, NULL, OPTION_H_TICK_HEX },
{NULL, no_argument, NULL, 0}
};
}
if (!preset_target_arch)
- as_bad ("Invalid argument to --isa option: %s", arg);
+ as_bad (_("Invalid argument to --isa option: %s"), arg);
}
break;
sh64_abi = sh64_abi_64;
}
else
- as_bad ("Invalid argument to --abi option: %s", arg);
+ as_bad (_("Invalid argument to --abi option: %s"), arg);
break;
case OPTION_NO_MIX:
break;
#endif /* HAVE_SH64 */
+ case OPTION_H_TICK_HEX:
+ enable_h_tick_hex = 1;
+ break;
+
default:
return 0;
}
else if (frag->fr_type == rs_align_test)
{
if (bytes != 0)
- as_warn_where (frag->fr_file, frag->fr_line, _("misaligned data"));
+ as_bad_where (frag->fr_file, frag->fr_line, _("misaligned data"));
}
if (sh_relax
break;
case BFD_RELOC_SH_PCRELIMM8BY4:
+ /* If we are dealing with a known destination ... */
+ if ((fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
+ && (fixP->fx_subsy == NULL || S_IS_DEFINED (fixP->fx_addsy)))
+ {
+ /* Don't silently move the destination due to misalignment.
+ The absolute address is the fragment base plus the offset into
+ the fragment plus the pc relative offset to the label. */
+ if ((fixP->fx_frag->fr_address + fixP->fx_where + val) & 3)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("offset to unaligned destination"));
+
+ /* The displacement cannot be zero or backward even if aligned.
+ Allow -2 because val has already been adjusted somewhere. */
+ if (val < -2)
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("negative offset"));
+ }
+
/* The lower two bits of the PC are cleared before the
displacement is added in. We can assume that the destination
is on a 4 byte boundary. If this instruction is also on a 4
val = ((val >> shift)
| ((long) -1 & ~ ((long) -1 >> shift)));
}
+
+ /* Extend sign for 64-bit host. */
+ val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
if (max != 0 && (val < min || val > max))
as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
else if (max != 0)
bfd_get_reloc_code_name (r_type));
/* Set howto to a garbage value so that we can keep going. */
rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
- assert (rel->howto != NULL);
+ gas_assert (rel->howto != NULL);
}
#ifdef OBJ_ELF
else if (rel->howto->type == R_SH_IND12W)