/* tc-m68k.c -- Assemble for the m68k family
- Copyright (C) 1987, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
02111-1307, USA. */
#include <ctype.h>
-#define NO_RELOC 0
#include "as.h"
#include "obstack.h"
#include "subsegs.h"
/* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful */
-#if defined (OBJ_ELF) || defined (TE_DELTA)
-CONST char comment_chars[] = "|#";
+#if (defined (OBJ_ELF) && ! defined (TE_PSOS) && ! defined (TE_LINUX)) || defined (TE_DELTA)
+const char comment_chars[] = "|#";
#else
-CONST char comment_chars[] = "|";
+const char comment_chars[] = "|";
#endif
/* This array holds the chars that only start a comment at the beginning of
first line of the input file. This is because the compiler outputs
#NO_APP at the beginning of its output. */
/* Also note that comments like this one will always work. */
-CONST char line_comment_chars[] = "#";
+const char line_comment_chars[] = "#";
-CONST char line_separator_chars[] = "";
+const char line_separator_chars[] = "";
/* Chars that can be used to separate mant from exp in floating point nums */
CONST char EXP_CHARS[] = "eE";
/* Are we trying to generate PIC code? If so, absolute references
ought to be made into linkage table references or pc-relative
- references. */
+ references. Not implemented. For ELF there are other means
+ to denote pic relocations. */
int flag_want_pic;
static int flag_short_refs; /* -l option */
int flag_reg_prefix_optional;
#endif
+/* Whether --register-prefix-optional was used on the command line. */
+static int reg_prefix_optional_seen;
+
/* The floating point coprocessor to use by default. */
static enum m68k_register m68k_float_copnum = COP1;
significance of some values (in the branch instruction, for
example). */
int pcrel_fix;
+#ifdef OBJ_ELF
+ /* Whether this expression needs special pic relocation, and if
+ so, which. */
+ enum pic_relocation pic_reloc;
+#endif
}
reloc[5]; /* Five is enough??? */
};
the_ins.reloc[the_ins.nrel].exp = exp->exp;
the_ins.reloc[the_ins.nrel].wid = width;
the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
+#ifdef OBJ_ELF
+ the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
+#endif
the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
}
struct m68k_cpu {
unsigned long arch;
const char *name;
+ int alias;
};
static const struct m68k_cpu archs[] = {
- { m68000, "68000" },
- { m68010, "68010" },
- { m68020, "68020" },
- { m68030, "68030" },
- { m68040, "68040" },
- { m68060, "68060" },
- { cpu32, "cpu32" },
- { m68881, "68881" },
- { m68851, "68851" },
+ { m68000, "68000", 0 },
+ { m68010, "68010", 0 },
+ { m68020, "68020", 0 },
+ { m68030, "68030", 0 },
+ { m68040, "68040", 0 },
+ { m68060, "68060", 0 },
+ { cpu32, "cpu32", 0 },
+ { m68881, "68881", 0 },
+ { m68851, "68851", 0 },
/* Aliases (effectively, so far as gas is concerned) for the above
cpus. */
- { m68020, "68k" },
- { m68000, "68302" },
- { m68000, "68008" },
- { m68000, "68ec000" },
- { m68000, "68hc000" },
- { m68000, "68hc001" },
- { m68020, "68ec020" },
- { m68030, "68ec030" },
- { m68040, "68ec040" },
- { cpu32, "68330" },
- { cpu32, "68331" },
- { cpu32, "68332" },
- { cpu32, "68333" },
- { cpu32, "68340" },
- { cpu32, "68360" },
- { m68881, "68882" },
+ { m68020, "68k", 1 },
+ { m68000, "68302", 1 },
+ { m68000, "68008", 1 },
+ { m68000, "68ec000", 1 },
+ { m68000, "68hc000", 1 },
+ { m68000, "68hc001", 1 },
+ { m68020, "68ec020", 1 },
+ { m68030, "68ec030", 1 },
+ { m68040, "68ec040", 1 },
+ { cpu32, "68330", 1 },
+ { cpu32, "68331", 1 },
+ { cpu32, "68332", 1 },
+ { cpu32, "68333", 1 },
+ { cpu32, "68340", 1 },
+ { cpu32, "68360", 1 },
+ { m68881, "68882", 1 },
};
static const int n_archs = sizeof (archs) / sizeof (archs[0]);
function to call to execute this pseudo-op
Integer arg to pass to the function
*/
-CONST pseudo_typeS md_pseudo_table[] =
+const pseudo_typeS md_pseudo_table[] =
{
{"data1", s_data1, 0},
{"data2", s_data2, 0},
{"even", s_even, 0},
{"skip", s_space, 0},
{"proc", s_proc, 0},
-#ifdef TE_SUN3
+#if defined (TE_SUN3) || defined (OBJ_ELF)
{"align", s_align_bytes, 0},
#endif
#ifdef OBJ_ELF
{"swbeg", s_ignore, 0},
#endif
+ {"extend", float_cons, 'x'},
+ {"ldouble", float_cons, 'x'},
/* The following pseudo-ops are supported for MRI compatibility. */
{"chip", s_chip, 0},
{"dsb", s_space, 1},
{"xdef", s_globl, 0},
+#ifdef OBJ_ELF
+ {"align", s_align_bytes, 0},
+#else
{"align", s_align_ptwo, 0},
+#endif
#ifdef M68KCOFF
{"sect", obj_coff_section, 0},
{"section", obj_coff_section, 0},
#define isuword(x) ((x)>=0 && (x)<=65535)
#define isbyte(x) ((x)>= -255 && (x)<=255)
-#define isword(x) ((x)>=-32768 && (x)<=65535)
+#define isword(x) ((x)>=-65536 && (x)<=65535)
#define islong(x) (1)
extern char *input_line_pointer;
tc_coff_fix2rtype (fixP)
fixS *fixP;
{
+ if (fixP->fx_tcbit && fixP->fx_size == 4)
+ return R_RELLONG_NEG;
#ifdef NO_PCREL_RELOCS
know (fixP->fx_pcrel == 0);
return (fixP->fx_size == 1 ? R_RELBYTE
#endif
+#ifdef OBJ_ELF
+
+/* Compute the relocation code for a fixup of SIZE bytes, using pc
+ relative relocation if PCREL is non-zero. PIC says whether a special
+ pic relocation was requested. */
+
+static bfd_reloc_code_real_type get_reloc_code
+ PARAMS ((int, int, enum pic_relocation));
+
+static bfd_reloc_code_real_type
+get_reloc_code (size, pcrel, pic)
+ int size;
+ int pcrel;
+ enum pic_relocation pic;
+{
+ switch (pic)
+ {
+ case pic_got_pcrel:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_GOT_PCREL;
+ case 2:
+ return BFD_RELOC_16_GOT_PCREL;
+ case 4:
+ return BFD_RELOC_32_GOT_PCREL;
+ }
+ break;
+
+ case pic_got_off:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_GOTOFF;
+ case 2:
+ return BFD_RELOC_16_GOTOFF;
+ case 4:
+ return BFD_RELOC_32_GOTOFF;
+ }
+ break;
+
+ case pic_plt_pcrel:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PLT_PCREL;
+ case 2:
+ return BFD_RELOC_16_PLT_PCREL;
+ case 4:
+ return BFD_RELOC_32_PLT_PCREL;
+ }
+ break;
+
+ case pic_plt_off:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PLTOFF;
+ case 2:
+ return BFD_RELOC_16_PLTOFF;
+ case 4:
+ return BFD_RELOC_32_PLTOFF;
+ }
+ break;
+
+ case pic_none:
+ if (pcrel)
+ {
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PCREL;
+ case 2:
+ return BFD_RELOC_16_PCREL;
+ case 4:
+ return BFD_RELOC_32_PCREL;
+ }
+ }
+ else
+ {
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8;
+ case 2:
+ return BFD_RELOC_16;
+ case 4:
+ return BFD_RELOC_32;
+ }
+ }
+ }
+
+ as_bad ("Can not do %d byte %s%srelocation", size,
+ pcrel ? "pc-relative " : "",
+ pic == pic_none ? "" : "pic ");
+ return BFD_RELOC_NONE;
+}
+
+/* Here we decide which fixups can be adjusted to make them relative
+ to the beginning of the section instead of the symbol. Basically
+ we need to make sure that the dynamic relocations are done
+ correctly, so in some cases we force the original symbol to be
+ used. */
+int
+tc_m68k_fix_adjustable (fixP)
+ fixS *fixP;
+{
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERNAL (fixP->fx_addsy))
+ return 0;
+
+ /* adjust_reloc_syms doesn't know about the GOT */
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8_GOT_PCREL:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_8_GOTOFF:
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_32_GOTOFF:
+ case BFD_RELOC_8_PLT_PCREL:
+ case BFD_RELOC_16_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+ case BFD_RELOC_8_PLTOFF:
+ case BFD_RELOC_16_PLTOFF:
+ case BFD_RELOC_32_PLTOFF:
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
+#else /* !OBJ_ELF */
+
+#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
+
+#endif /* OBJ_ELF */
+
#ifdef BFD_ASSEMBLER
arelent *
arelent *reloc;
bfd_reloc_code_real_type code;
-#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
- switch (F (fixp->fx_size, fixp->fx_pcrel))
+ if (fixp->fx_tcbit)
+ abort ();
+
+ if (fixp->fx_r_type != BFD_RELOC_NONE)
+ code = fixp->fx_r_type;
+ else
{
+#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
+ switch (F (fixp->fx_size, fixp->fx_pcrel))
+ {
#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
- MAP (1, 0, BFD_RELOC_8);
- MAP (2, 0, BFD_RELOC_16);
- MAP (4, 0, BFD_RELOC_32);
- MAP (1, 1, BFD_RELOC_8_PCREL);
- MAP (2, 1, BFD_RELOC_16_PCREL);
- MAP (4, 1, BFD_RELOC_32_PCREL);
- default:
- abort ();
+ MAP (1, 0, BFD_RELOC_8);
+ MAP (2, 0, BFD_RELOC_16);
+ MAP (4, 0, BFD_RELOC_32);
+ MAP (1, 1, BFD_RELOC_8_PCREL);
+ MAP (2, 1, BFD_RELOC_16_PCREL);
+ MAP (4, 1, BFD_RELOC_32_PCREL);
+ default:
+ abort ();
+ }
}
+#undef F
+#undef MAP
reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
assert (reloc != 0);
reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+#ifndef OBJ_ELF
if (fixp->fx_pcrel)
reloc->addend = fixp->fx_addnumber;
else
reloc->addend = 0;
+#else
+ if (!fixp->fx_pcrel)
+ reloc->addend = fixp->fx_addnumber;
+ else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+ reloc->addend = (section->vma
+ + (fixp->fx_pcrel_adjust == 64
+ ? -1 : fixp->fx_pcrel_adjust)
+ + fixp->fx_addnumber
+ + md_pcrel_from (fixp));
+ else
+ reloc->addend = (fixp->fx_offset
+ + (fixp->fx_pcrel_adjust == 64
+ ? -1 : fixp->fx_pcrel_adjust));
+#endif
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
assert (reloc->howto != 0);
&& (opP->disp.exp.X_op != O_constant
|| ! isword (opP->disp.exp.X_add_number)))
losing++;
+ else if (s[1] == 'W'
+ && ! isvar (&opP->disp)
+ && (opP->disp.exp.X_op != O_constant
+ || ! issword (opP->disp.exp.X_add_number)))
+ losing++;
break;
case '^':
if (opP->mode == CONTROL
|| opP->mode == FPREG
|| opP->mode == REGLST
+ || opP->mode == IMMED
|| (opP->mode != ABSL
- && opP->mode != IMMED
&& (opP->reg == PC
|| opP->reg == ZPC)))
losing++;
|| opP->mode == AREG
|| opP->mode == REGLST)
losing++;
+ /* We should accept immediate operands, but they
+ supposedly have to be quad word, and we don't
+ handle that. I would like to see what a Motorola
+ assembler does before doing something here. */
+ if (opP->mode == IMMED)
+ losing++;
break;
case 'f':
losing++;
break;
- case 'P':
+ case '0':
+ if (opP->mode != CONTROL || opP->reg != TC)
+ losing++;
+ break;
+
+ case '1':
+ if (opP->mode != CONTROL || opP->reg != AC)
+ losing++;
+ break;
+
+ case '2':
if (opP->mode != CONTROL
- || (opP->reg != TC
- && opP->reg != CAL
+ || (opP->reg != CAL
&& opP->reg != VAL
- && opP->reg != SCC
- && opP->reg != AC))
+ && opP->reg != SCC))
losing++;
break;
for (idx = 0; idx < sizeof (archs) / sizeof (archs[0]);
idx++)
{
- if (archs[idx].arch & ok_arch)
+ if ((archs[idx].arch & ok_arch)
+ && ! archs[idx].alias)
{
if (got_one)
{
addword (nextword);
baseo = 0;
break;
+ case 'W':
+ if (!issword (nextword))
+ opP->error = "operand out of range";
+ addword (nextword);
+ baseo = 0;
+ break;
case 'l':
addword (nextword >> 16);
addword (nextword);
&& cpu_of_arch (current_architecture) >= m68020)
|| opP->disp.size == SIZE_LONG)))
{
+ if (cpu_of_arch (current_architecture) < m68020)
+ opP->error =
+ "displacement too large for this architecture; needs 68020 or higher";
if (opP->reg == PC)
tmpreg = 0x3B; /* 7.3 */
else
{
if (opP->reg == PC)
{
-#if 0
- addword (0x0170);
- add_fix ('l', &opP->disp, 1, 2);
- addword (0), addword (0);
-#else
- add_frag (adds (&opP->disp),
- offs (&opP->disp),
- TAB (PCLEA, SZ_UNDEF));
+ if (opP->disp.size == SIZE_LONG
+#ifdef OBJ_ELF
+ /* If the displacement needs pic
+ relocation it cannot be relaxed. */
+ || opP->disp.pic_reloc != pic_none
#endif
- break;
+ )
+ {
+ addword (0x0170);
+ add_fix ('l', &opP->disp, 1, 2);
+ }
+ else
+ {
+ add_frag (adds (&opP->disp),
+ offs (&opP->disp),
+ TAB (PCLEA, SZ_UNDEF));
+ break;
+ }
}
else
{
else if (siz1 == SIZE_UNSPEC
&& opP->reg == PC
&& isvar (&opP->disp)
- && subs (&opP->disp) == NULL)
+ && subs (&opP->disp) == NULL
+#ifdef OBJ_ELF
+ /* If the displacement needs pic
+ relocation it cannot be relaxed. */
+ && opP->disp.pic_reloc == pic_none
+#endif
+ )
{
nextword += baseo & 0xff;
addword (nextword);
if (isvar (&opP->disp)
&& !subs (&opP->disp)
&& adds (&opP->disp)
+#ifdef OBJ_ELF
+ /* If the displacement needs pic relocation it
+ cannot be relaxed. */
+ && opP->disp.pic_reloc == pic_none
+#endif
&& S_GET_SEGMENT (adds (&opP->disp)) == now_seg
&& cpu_of_arch (current_architecture) >= m68020
&& !flag_long_jumps
opP->error = "out of range";
insop (tmpreg, opcode);
if (isvar (&opP->disp))
- the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
+ the_ins.reloc[the_ins.nrel - 1].n =
+ (opcode->m_codenum) * 2 + 1;
break;
case 'w':
if (!isword (tmpreg))
if (isvar (&opP->disp))
the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
break;
+ case 'W':
+ if (!issword (tmpreg))
+ opP->error = "out of range";
+ insop (tmpreg, opcode);
+ if (isvar (&opP->disp))
+ the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
+ break;
case 'l':
/* Because of the way insop works, we put these two out
backwards. */
if (subs (&opP->disp)) /* We can't relax it */
goto long_branch;
+#ifdef OBJ_ELF
+ /* If the displacement needs pic relocation it cannot be
+ relaxed. */
+ if (opP->disp.pic_reloc != pic_none)
+ goto long_branch;
+#endif
+
/* This could either be a symbol, or an absolute
address. No matter, the frag hacking will finger it
out. Not quite: it can't switch from BRANCH to
install_operand (s[1], tmpreg);
break;
- case 'P':
+ case '0':
+ case '1':
+ case '2':
switch (opP->reg)
{
case TC:
break;
case 'b':
case 'w':
+ case 'W':
case 'l':
break;
case 'e':
n,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (n, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
return;
wid,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
(void) frag_var (rs_machine_dependent, 10, 0,
wid,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
}
#endif
init_regtable ();
+
+#ifdef OBJ_ELF
+ record_alignment (text_section, 2);
+ record_alignment (data_section, 2);
+ record_alignment (bss_section, 2);
+#endif
}
void
md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0;
}
+/* This is called if we go in or out of MRI mode because of the .mri
+ pseudo-op. */
+
+void
+m68k_mri_mode_change (on)
+ int on;
+{
+ if (on)
+ {
+ if (! flag_reg_prefix_optional)
+ {
+ flag_reg_prefix_optional = 1;
+#ifdef REGISTER_PREFIX
+ init_regtable ();
+#endif
+ }
+ m68k_abspcadd = 1;
+ m68k_rel32 = 0;
+ }
+ else
+ {
+ if (! reg_prefix_optional_seen)
+ {
+#ifdef REGISTER_PREFIX_OPTIONAL
+ flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
+#else
+ flag_reg_prefix_optional = 0;
+#endif
+#ifdef REGISTER_PREFIX
+ init_regtable ();
+#endif
+ }
+ m68k_abspcadd = 0;
+ m68k_rel32 = 1;
+ }
+}
+
/* Equal to MAX_PRECISION in atof-ieee.c */
#define MAX_LITTLENUMS 6
else
val &= 0x7fffffff;
+#ifdef OBJ_ELF
+ if (fixP->fx_addsy)
+ {
+ memset (buf, 0, fixP->fx_size);
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc */
+ return;
+ }
+#endif
+
switch (fixP->fx_size)
{
/* The cast to offsetT below are necessary to make code correct for
BAD_CASE (fixP->fx_size);
}
+ /* Fix up a negative reloc. */
+ if (fixP->fx_addsy == NULL && fixP->fx_subsy != NULL)
+ {
+ fixP->fx_addsy = fixP->fx_subsy;
+ fixP->fx_subsy = NULL;
+ fixP->fx_tcbit = 1;
+ }
+
/* For non-pc-relative values, it's conceivable we might get something
like "0xff" for a byte field. So extend the upper part of the range
to accept such numbers. We arbitrarily disallow "-0xff" or "0xff+0xff",
{
case TAB (BCC68000, BYTE):
case TAB (ABRANCH, BYTE):
- /* We can't do a short jump to the next instruction,
- so we force word mode. */
- if (fragP->fr_symbol && S_GET_VALUE (fragP->fr_symbol) == 0 &&
- fragP->fr_symbol->sy_frag == fragP->fr_next)
+ /* We can't do a short jump to the next instruction, so in that
+ case we force word mode. At this point S_GET_VALUE should
+ return the offset of the symbol within its frag. If the
+ symbol is at the start of a frag, and it is the next frag
+ with any data in it (usually this is just the next frag, but
+ assembler listings may introduce empty frags), we must use
+ word mode. */
+ if (fragP->fr_symbol && S_GET_VALUE (fragP->fr_symbol) == 0)
{
- fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
- fragP->fr_var += 2;
+ fragS *l;
+
+ for (l = fragP->fr_next;
+ l != fragP->fr_symbol->sy_frag;
+ l = l->fr_next)
+ if (l->fr_fix + l->fr_var != 0)
+ break;
+ if (l == fragP->fr_symbol->sy_frag)
+ {
+ fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
+ fragP->fr_var += 2;
+ }
}
break;
default:
s_chip (ignore)
int ignore;
{
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
mri_chip ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
demand_empty_rest_of_line ();
}
int c;
struct m68k_op rop;
unsigned long mask;
+ char *stop = NULL;
+ char stopc;
if (line_label == NULL)
{
return;
}
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
SKIP_WHITESPACE ();
s = input_line_pointer;
S_SET_VALUE (line_label, mask);
line_label->sy_frag = &zero_address_frag;
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
demand_empty_rest_of_line ();
}
static void pop_mri_control PARAMS ((void));
static int parse_mri_condition PARAMS ((int *));
static int parse_mri_control_operand
- PARAMS ((int *, const char **, const char **, const char **, const char **));
+ PARAMS ((int *, char **, char **, char **, char **));
static int swap_mri_condition PARAMS ((int));
static int reverse_mri_condition PARAMS ((int));
static void build_mri_control_operand
- PARAMS ((int, int, const char *, const char *, const char *, const char *,
- const char *, const char *, int));
+ PARAMS ((int, int, char *, char *, char *, char *, const char *,
+ const char *, int));
static void parse_mri_control_expression
PARAMS ((char *, int, const char *, const char *, int));
static int
parse_mri_control_operand (pcc, leftstart, leftstop, rightstart, rightstop)
int *pcc;
- const char **leftstart;
- const char **leftstop;
- const char **rightstart;
- const char **rightstop;
+ char **leftstart;
+ char **leftstop;
+ char **rightstart;
+ char **rightstop;
{
char *s;
rightstop, truelab, falselab, extent)
int qual;
int cc;
- const char *leftstart;
- const char *leftstop;
- const char *rightstart;
- const char *rightstop;
+ char *leftstart;
+ char *leftstop;
+ char *rightstart;
+ char *rightstop;
const char *truelab;
const char *falselab;
int extent;
char *buf;
char *s;
- /* The 68k can't do a general comparision with an immediate operand
- on the right hand side. */
- if (rightstart != NULL && *rightstart == '#')
+ if (leftstart != NULL)
{
- const char *temp;
-
- cc = swap_mri_condition (cc);
- temp = leftstart;
- leftstart = rightstart;
- rightstart = temp;
- temp = leftstop;
- leftstop = rightstop;
- rightstop = temp;
+ struct m68k_op leftop, rightop;
+ char c;
+
+ /* Swap the compare operands, if necessary, to produce a legal
+ m68k compare instruction. Comparing a register operand with
+ a non-register operand requires the register to be on the
+ right (cmp, cmpa). Comparing an immediate value with
+ anything requires the immediate value to be on the left
+ (cmpi). */
+
+ c = *leftstop;
+ *leftstop = '\0';
+ (void) m68k_ip_op (leftstart, &leftop);
+ *leftstop = c;
+
+ c = *rightstop;
+ *rightstop = '\0';
+ (void) m68k_ip_op (rightstart, &rightop);
+ *rightstop = c;
+
+ if (rightop.mode == IMMED
+ || ((leftop.mode == DREG || leftop.mode == AREG)
+ && (rightop.mode != DREG && rightop.mode != AREG)))
+ {
+ char *temp;
+
+ cc = swap_mri_condition (cc);
+ temp = leftstart;
+ leftstart = rightstart;
+ rightstart = temp;
+ temp = leftstop;
+ leftstop = rightstop;
+ rightstop = temp;
+ }
}
if (truelab == NULL)
{
int c;
int cc;
- const char *leftstart;
- const char *leftstop;
- const char *rightstart;
- const char *rightstop;
+ char *leftstart;
+ char *leftstop;
+ char *rightstart;
+ char *rightstop;
c = *stop;
*stop = '\0';
/* A structured control directive must end with THEN with an
optional qualifier. */
s = input_line_pointer;
- while (! is_end_of_line[(unsigned char) *s])
+ while (! is_end_of_line[(unsigned char) *s]
+ && (! flag_mri || *s != '*'))
++s;
--s;
while (s > input_line_pointer && (*s == ' ' || *s == '\t'))
else
input_line_pointer = s + 1;
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
colon (mri_control_stack->next);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
pop_mri_control ();
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
md_assemble (buf);
free (buf);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
md_assemble (buf);
free (buf);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
*s = '\0';
n->incr = buf;
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
pop_mri_control ();
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
n = push_mri_control (mri_repeat);
colon (n->top);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
demand_empty_rest_of_line ();
}
input_line_pointer = s;
+ pop_mri_control ();
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
struct mri_control_info *n;
s = input_line_pointer;
- while (! is_end_of_line[(unsigned char) *s])
+ while (! is_end_of_line[(unsigned char) *s]
+ && (! flag_mri || *s != '*'))
s++;
--s;
while (*s == ' ' || *s == '\t')
if (*input_line_pointer == '.')
input_line_pointer += 2;
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
pop_mri_control ();
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
\f
case OPTION_REGISTER_PREFIX_OPTIONAL:
flag_reg_prefix_optional = 1;
+ reg_prefix_optional_seen = 1;
break;
- case 'Q':
+ /* -V: SVR4 argument to print version ID. */
case 'V':
+ print_version_id ();
+ break;
+
+ /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+ should be emitted or not. FIXME: Not implemented. */
+ case 'Q':
break;
default: