/* tc-m68k.c -- Assemble for the m68k family
Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001
+ 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-#include <ctype.h>
#include "as.h"
+#include "safe-ctype.h"
#include "obstack.h"
#include "subsegs.h"
#include "dwarf2dbg.h"
+#include "dw2gencfi.h"
#include "opcode/m68k.h"
#include "m68k-parse.h"
const char line_separator_chars[] = ";";
/* Chars that can be used to separate mant from exp in floating point nums */
-CONST char EXP_CHARS[] = "eE";
+const char EXP_CHARS[] = "eE";
/* Chars that mean this number is a floating point constant, as
in "0f12.456" or "0d1.2345e12". */
-CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
changed in read.c . Ideally it shouldn't have to know about it at all,
const struct m68k_incant *opcode;
{
int z;
- for(z=the_ins.numo;z>opcode->m_codenum;--z)
- the_ins.opcode[z]=the_ins.opcode[z-1];
- for(z=0;z<the_ins.nrel;z++)
- the_ins.reloc[z].n+=2;
+ for (z = the_ins.numo; z > opcode->m_codenum; --z)
+ the_ins.opcode[z] = the_ins.opcode[z - 1];
+ for (z = 0; z < the_ins.nrel; z++)
+ the_ins.reloc[z].n += 2;
for (z = 0; z < the_ins.nfrag; z++)
the_ins.fragb[z].fragoff++;
- the_ins.opcode[opcode->m_codenum]=w;
+ the_ins.opcode[opcode->m_codenum] = w;
the_ins.numo++;
}
offsetT off;
int type;
{
- the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;
- the_ins.fragb[the_ins.nfrag].fadd=add;
- the_ins.fragb[the_ins.nfrag].foff=off;
- the_ins.fragb[the_ins.nfrag++].fragty=type;
+ the_ins.fragb[the_ins.nfrag].fragoff = the_ins.numo;
+ the_ins.fragb[the_ins.nfrag].fadd = add;
+ the_ins.fragb[the_ins.nfrag].foff = off;
+ the_ins.fragb[the_ins.nfrag++].fragty = type;
}
#define isvar(ex) \
static void s_mri_until PARAMS ((int));
static void s_mri_while PARAMS ((int));
static void s_mri_endw PARAMS ((int));
-static void md_apply_fix_2 PARAMS ((fixS *, offsetT));
static void md_convert_frag_1 PARAMS ((fragS *));
static int current_architecture;
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
- */
+
+ Please check tc-m68k.h:md_prepare_relax_scan if changing this table. */
relax_typeS md_relax_table[] =
{
{ 127, -128, 0, TAB (BRANCHBWL, SHORT) },
{"extend", float_cons, 'x'},
{"ldouble", float_cons, 'x'},
-#ifdef OBJ_ELF
- /* Dwarf2 support for Gcc. */
- {"file", dwarf2_directive_file, 0},
- {"loc", dwarf2_directive_loc, 0},
-#endif
-
/* The following pseudo-ops are supported for MRI compatibility. */
{"chip", s_chip, 0},
{"comline", s_space, 1},
extern void obj_coff_section PARAMS ((int));
#endif
-CONST pseudo_typeS mote_pseudo_table[] =
+const pseudo_typeS mote_pseudo_table[] =
{
{"dcl", cons, 4},
extern char *input_line_pointer;
-static char mklower_table[256];
-#define mklower(c) (mklower_table[(unsigned char) (c)])
static char notend_table[256];
static char alt_notend_table[256];
#define notend(s) \
tc_m68k_fix_adjustable (fixP)
fixS *fixP;
{
- /* Prevent all adjustments to global symbols. */
- if (! relaxable_symbol (fixP->fx_addsy))
- return 0;
-
/* adjust_reloc_syms doesn't know about the GOT */
switch (fixP->fx_r_type)
{
arelent *
tc_gen_reloc (section, fixp)
- asection *section;
+ asection *section ATTRIBUTE_UNUSED;
fixS *fixp;
{
arelent *reloc;
default:
losing++;
}
- break;
+ break;
case 'n':
switch (opP->mode)
default:
losing++;
}
- break;
+ break;
case 'o':
switch (opP->mode)
default:
losing++;
}
- break;
+ break;
case 'p':
switch (opP->mode)
break;
case DISP:
if (opP->reg == PC || opP->reg == ZPC)
- losing++;
+ losing++;
break;
default:
losing++;
}
- break;
+ break;
case 'q':
switch (opP->mode)
break;
case DISP:
if (opP->reg == PC || opP->reg == ZPC)
- losing++;
+ losing++;
break;
default:
losing++;
break;
}
- break;
+ break;
case 'v':
switch (opP->mode)
break;
case DISP:
if (opP->reg == PC || opP->reg == ZPC)
- losing++;
+ losing++;
break;
default:
losing++;
the frag obstack to make all the bytes
contiguous. */
frag_grow (14);
- nextword += baseo & 0xff;
- addword (nextword);
- add_frag (adds (&opP->disp), offs (&opP->disp),
- TAB (PCINDEX, SZ_UNDEF));
+ nextword += baseo & 0xff;
+ addword (nextword);
+ add_frag (adds (&opP->disp), offs (&opP->disp),
+ TAB (PCINDEX, SZ_UNDEF));
break;
- }
+ }
}
}
else
if (adds (&opP->disp) == 0)
{
if (the_ins.opcode[0] == 0x6000) /* jbra */
- the_ins.opcode[0] = 0x4EF1;
+ the_ins.opcode[0] = 0x4EF9;
else if (the_ins.opcode[0] == 0x6100) /* jbsr */
- the_ins.opcode[0] = 0x4EB1;
+ the_ins.opcode[0] = 0x4EB9;
else /* jCC */
{
the_ins.opcode[0] ^= 0x0100;
the_ins.opcode[0] |= 0x0006;
- addword (0x4EF1);
+ addword (0x4EF9);
}
add_fix ('l', &opP->disp, 0, 0);
addword (0);
&zero_address_frag));
for (i = 0; regname[i]; i++)
- buf[i] = islower (regname[i]) ? toupper (regname[i]) : regname[i];
+ buf[i] = TOUPPER (regname[i]);
buf[i] = '\0';
symbol_table_insert (symbol_new (buf, reg_section, regnum,
my lord ghod hath spoken, so we do it this way. Excuse the ugly var
names. */
- register const struct m68k_opcode *ins;
- register struct m68k_incant *hack, *slak;
- register const char *retval = 0; /* empty string, or error msg text */
- register int i;
- register char c;
+ const struct m68k_opcode *ins;
+ struct m68k_incant *hack, *slak;
+ const char *retval = 0; /* empty string, or error msg text */
+ int i;
if (flag_mri)
{
}
}
- for (i = 0; i < (int) sizeof (mklower_table); i++)
- mklower_table[i] = (isupper (c = (char) i)) ? tolower (c) : c;
-
for (i = 0; i < (int) sizeof (notend_table); i++)
{
notend_table[i] = 0;
/* Note which set of "movec" control registers is available. */
switch (cpu_of_arch (current_architecture))
{
+ case 0:
+ as_warn (_("architecture not yet selected: defaulting to 68020"));
+ control_regs = m68020_control_regs;
+ break;
+
case m68000:
control_regs = m68000_control_regs;
break;
number_to_chars_bigendian (buf, val, n);
}
-static void
-md_apply_fix_2 (fixP, val)
+void
+md_apply_fix3 (fixP, valP, seg)
fixS *fixP;
- offsetT val;
+ valueT *valP;
+ segT seg ATTRIBUTE_UNUSED;
{
+ offsetT val = *valP;
addressT upper_limit;
offsetT lower_limit;
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+ fixP->fx_done = 1;
+
#ifdef OBJ_ELF
if (fixP->fx_addsy)
{
switch (fixP->fx_size)
{
- /* The cast to offsetT below are necessary to make code correct for
- machines where ints are smaller than offsetT */
+ /* The cast to offsetT below are necessary to make code
+ correct for machines where ints are smaller than offsetT. */
case 1:
*buf++ = val;
upper_limit = 0x7f;
as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid byte branch offset"));
}
-#ifdef BFD_ASSEMBLER
-int
-md_apply_fix (fixP, valp)
- fixS *fixP;
- valueT *valp;
-{
- md_apply_fix_2 (fixP, (addressT) *valp);
- return 1;
-}
-#else
-void md_apply_fix (fixP, val)
- fixS *fixP;
- long val;
-{
- md_apply_fix_2 (fixP, (addressT) val);
-}
-#endif
-
/* *fragP has been relaxed to its final size, and now needs to have
the bytes inside it modified to conform to the new size There is UGLY
MAGIC here. ..
{
fragS *l;
- for (l = fragP->fr_next; l != sym_frag; l = l->fr_next)
+ for (l = fragP->fr_next; l && l != sym_frag; l = l->fr_next)
if (l->fr_fix != 0)
break;
if (l == sym_frag)
* Out: GNU LD relocation length code: 0, 1, or 2.
*/
- static CONST unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
+ static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
long r_symbolnum;
know (fixP->fx_addsy != NULL);
#endif /* OBJ_AOUT or OBJ_BOUT */
#ifndef WORKING_DOT_WORD
-CONST int md_short_jump_size = 4;
-CONST int md_long_jump_size = 6;
+const int md_short_jump_size = 4;
+const int md_long_jump_size = 6;
void
md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
if (on)
listing |= LISTING_SYMBOLS;
else
- listing &=~ LISTING_SYMBOLS;
+ listing &= ~LISTING_SYMBOLS;
}
/* Handle the MRI REG pseudo-op. */
SKIP_WHITESPACE ();
s = input_line_pointer;
- while (isalnum ((unsigned char) *input_line_pointer)
+ while (ISALNUM (*input_line_pointer)
#ifdef REGISTER_PREFIX
|| *input_line_pointer == REGISTER_PREFIX
#endif
/* md_assemble expects the opcode to be in lower case. */
for (s = str; *s != ' ' && *s != '\0'; s++)
- {
- if (isupper ((unsigned char) *s))
- *s = tolower ((unsigned char) *s);
- }
+ *s = TOLOWER (*s);
md_assemble (str);
}
++input_line_pointer;
SKIP_WHITESPACE ();
- if (isupper (c1))
- c1 = tolower (c1);
- if (isupper (c2))
- c2 = tolower (c2);
+ c1 = TOLOWER (c1);
+ c2 = TOLOWER (c2);
*pcc = (c1 << 8) | c2;
/* We must make sure we don't misinterpret AND/OR at the end of labels!
if d0 <eq> #FOOAND and d1 <ne> #BAROR then
^^^ ^^ */
- if ( ( s == input_line_pointer
- || *(s-1) == ' '
- || *(s-1) == '\t')
- && ( ( strncasecmp (s, "AND", 3) == 0
- && (s[3] == '.' || ! is_part_of_name (s[3])))
- || ( strncasecmp (s, "OR", 2) == 0
- && (s[2] == '.' || ! is_part_of_name (s[2])))))
- break;
+ if ((s == input_line_pointer
+ || *(s-1) == ' '
+ || *(s-1) == '\t')
+ && ((strncasecmp (s, "AND", 3) == 0
+ && (s[3] == '.' || ! is_part_of_name (s[3])))
+ || (strncasecmp (s, "OR", 2) == 0
+ && (s[2] == '.' || ! is_part_of_name (s[2])))))
+ break;
}
*rightstart = input_line_pointer;
temp = leftstop;
leftstop = rightstop;
rightstop = temp;
- } else {
+ }
+ else
+ {
cc = swap_mri_condition (cc);
}
}
*s++ = 'm';
*s++ = 'p';
if (qual != '\0')
- *s++ = tolower(qual);
+ *s++ = TOLOWER (qual);
*s++ = ' ';
memcpy (s, leftstart, leftstop - leftstart);
s += leftstop - leftstart;
*s++ = cc >> 8;
*s++ = cc & 0xff;
if (extent != '\0')
- *s++ = tolower(extent);
+ *s++ = TOLOWER (extent);
*s++ = ' ';
strcpy (s, truelab);
mri_assemble (buf);
mri_control_stack->else_seen = 1;
buf = (char *) xmalloc (20 + strlen (mri_control_stack->bottom));
- q[0] = tolower(qual);
+ q[0] = TOLOWER (qual);
q[1] = '\0';
sprintf (buf, "bra%s %s", q, mri_control_stack->bottom);
mri_assemble (buf);
}
buf = (char *) xmalloc (20 + strlen (n->bottom));
- ex[0] = tolower(extent);
+ ex[0] = TOLOWER (extent);
ex[1] = '\0';
sprintf (buf, "bra%s %s", ex, n->bottom);
mri_assemble (buf);
}
buf = (char *) xmalloc (20 + strlen (n->next));
- ex[0] = tolower(extent);
+ ex[0] = TOLOWER (extent);
ex[1] = '\0';
sprintf (buf, "bra%s %s", ex, n->next);
mri_assemble (buf);
*s++ = 'v';
*s++ = 'e';
if (qual != '\0')
- *s++ = tolower(qual);
+ *s++ = TOLOWER (qual);
*s++ = ' ';
memcpy (s, initstart, initstop - initstart);
s += initstop - initstart;
*s++ = 'm';
*s++ = 'p';
if (qual != '\0')
- *s++ = tolower(qual);
+ *s++ = TOLOWER (qual);
*s++ = ' ';
memcpy (s, endstart, endstop - endstart);
s += endstop - endstart;
mri_assemble (buf);
/* bcc bottom */
- ex[0] = tolower(extent);
+ ex[0] = TOLOWER (extent);
ex[1] = '\0';
if (up)
sprintf (buf, "blt%s %s", ex, n->bottom);
strcpy (s, "sub");
s += 3;
if (qual != '\0')
- *s++ = tolower(qual);
+ *s++ = TOLOWER (qual);
*s++ = ' ';
memcpy (s, bystart, bystop - bystart);
s += bystop - bystart;
This is important when assembling:
while d0 <ne> 12(a0,d0*2) do
while d0 <ne> #CONST*20 do */
- while ( ! ( is_end_of_line[(unsigned char) *s]
- || ( flag_mri
- && *s == '*'
- && ( s == input_line_pointer
- || *(s-1) == ' '
- || *(s-1) == '\t'))))
+ while (! (is_end_of_line[(unsigned char) *s]
+ || (flag_mri
+ && *s == '*'
+ && (s == input_line_pointer
+ || *(s-1) == ' '
+ || *(s-1) == '\t'))))
s++;
--s;
while (*s == ' ' || *s == '\t')
*/
#ifdef OBJ_ELF
-CONST char *md_shortopts = "lSA:m:kQ:V";
+const char *md_shortopts = "lSA:m:kQ:V";
#else
-CONST char *md_shortopts = "lSA:m:k";
+const char *md_shortopts = "lSA:m:k";
#endif
struct option md_longopts[] = {
case 'A':
if (*arg == 'm')
- arg++;
+ arg++;
/* intentional fall-through */
case 'm':
md_show_usage (stream)
FILE *stream;
{
+ const char *default_cpu = TARGET_CPU;
+ int i;
+ unsigned int default_arch;
+
+ /* Get the canonical name for the default target CPU. */
+ if (*default_cpu == 'm')
+ default_cpu++;
+ for (i = 0; i < n_archs; i++)
+ {
+ if (strcasecmp (default_cpu, archs[i].name) == 0)
+ {
+ default_arch = archs[i].arch;
+ for (i = 0; i < n_archs; i++)
+ {
+ if (archs[i].arch == default_arch
+ && !archs[i].alias)
+ {
+ default_cpu = archs[i].name;
+ break;
+ }
+ }
+ }
+ }
+
fprintf (stream, _("\
680X0 options:\n\
-l use 1 word for refs to undefined symbols [default 2]\n\
-m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040 | -m68060 |\n\
-m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -m68360 | -mcpu32 |\n\
-m5200 | -m5202 | -m5204 | -m5206 | -m5206e | -m5307 | -m5407\n\
- specify variant of 680X0 architecture [default 68020]\n\
+ specify variant of 680X0 architecture [default %s]\n\
-m68881 | -m68882 | -mno-68881 | -mno-68882\n\
target has/lacks floating-point coprocessor\n\
- [default yes for 68020, 68030, and cpu32]\n"));
+ [default yes for 68020, 68030, and cpu32]\n"),
+ default_cpu);
fprintf (stream, _("\
-m68851 | -mno-68851\n\
target has/lacks memory-management unit coprocessor\n\
#endif
#endif
#ifdef OBJ_ELF
-void m68k_elf_final_processing()
+void
+m68k_elf_final_processing ()
{
- /* Set file-specific flags if this is a cpu32 processor */
- if (cpu_of_arch (current_architecture) & cpu32)
- elf_elfheader (stdoutput)->e_flags |= EF_CPU32;
+ /* Set file-specific flags if this is a cpu32 processor */
+ if (cpu_of_arch (current_architecture) & cpu32)
+ elf_elfheader (stdoutput)->e_flags |= EF_CPU32;
+ else if ((cpu_of_arch (current_architecture) & m68000up)
+ && !(cpu_of_arch (current_architecture) & m68020up))
+ elf_elfheader (stdoutput)->e_flags |= EF_M68000;
}
#endif
+
+int
+tc_m68k_regname_to_dw2regnum (const char *regname)
+{
+ unsigned int regnum;
+ static const char *const regnames[] =
+ {
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7",
+ "pc"
+ };
+
+ for (regnum = 0; regnum < ARRAY_SIZE (regnames); regnum++)
+ if (strcmp (regname, regnames[regnum]) == 0)
+ return regnum;
+
+ return -1;
+}
+
+void
+tc_m68k_frame_initial_instructions (void)
+{
+ static int sp_regno = -1;
+
+ if (sp_regno < 0)
+ sp_regno = tc_m68k_regname_to_dw2regnum ("sp");
+
+ cfi_add_CFA_def_cfa (sp_regno, -DWARF2_CIE_DATA_ALIGNMENT);
+ cfi_add_CFA_offset (DWARF2_DEFAULT_RETURN_COLUMN, DWARF2_CIE_DATA_ALIGNMENT);
+}