X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-m68k.c;h=cd70be1207d2784772dfb3335761e60977009330;hb=fd58f4b10e95fade6653c2ff2d42c58e37f6921d;hp=3cb8121ca7f02a0ad755b0d5d85b47fdae81fba6;hpb=f00f5ecd1dfe466c1a25dd50032f4f1f6d72b9f6;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index 3cb8121ca7..cd70be1207 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -1,5 +1,5 @@ /* 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. @@ -19,7 +19,6 @@ 02111-1307, USA. */ #include -#define NO_RELOC 0 #include "as.h" #include "obstack.h" #include "subsegs.h" @@ -29,10 +28,10 @@ /* 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 @@ -42,9 +41,9 @@ CONST char comment_chars[] = "|"; 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"; @@ -62,7 +61,8 @@ const int md_reloc_size = 8; /* Size of relocation record */ /* 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 */ @@ -74,6 +74,9 @@ int flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL; 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; @@ -199,6 +202,11 @@ struct m68k_it 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??? */ }; @@ -252,6 +260,9 @@ add_fix (width, exp, pc_rel, pc_fix) 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; } @@ -315,36 +326,37 @@ static int current_architecture; 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]); @@ -419,7 +431,7 @@ relax_typeS md_relax_table[] = 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}, @@ -427,12 +439,14 @@ CONST pseudo_typeS md_pseudo_table[] = {"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}, @@ -497,7 +511,11 @@ CONST pseudo_typeS mote_pseudo_table[] = {"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}, @@ -511,7 +529,7 @@ CONST pseudo_typeS mote_pseudo_table[] = #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; @@ -562,6 +580,8 @@ short 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 @@ -580,6 +600,145 @@ tc_coff_fix2rtype (fixP) #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 * @@ -590,28 +749,53 @@ tc_gen_reloc (section, fixp) 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); @@ -830,6 +1014,11 @@ m68k_ip (instring) && (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 '^': @@ -854,8 +1043,8 @@ m68k_ip (instring) 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++; @@ -1222,6 +1411,12 @@ m68k_ip (instring) || 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': @@ -1230,13 +1425,21 @@ m68k_ip (instring) 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; @@ -1336,7 +1539,8 @@ m68k_ip (instring) 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) { @@ -1416,6 +1620,12 @@ m68k_ip (instring) 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); @@ -1533,6 +1743,9 @@ m68k_ip (instring) && 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 @@ -1541,16 +1754,24 @@ m68k_ip (instring) { 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 { @@ -1696,7 +1917,13 @@ m68k_ip (instring) 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); @@ -1832,6 +2059,11 @@ m68k_ip (instring) 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 @@ -1901,7 +2133,8 @@ m68k_ip (instring) 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)) @@ -1910,6 +2143,13 @@ m68k_ip (instring) 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. */ @@ -1964,6 +2204,13 @@ m68k_ip (instring) 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 @@ -2253,7 +2500,9 @@ m68k_ip (instring) install_operand (s[1], tmpreg); break; - case 'P': + case '0': + case '1': + case '2': switch (opP->reg) { case TC: @@ -2489,6 +2738,7 @@ install_operand (mode, val) break; case 'b': case 'w': + case 'W': case 'l': break; case 'e': @@ -2894,7 +3144,8 @@ md_assemble (str) 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; @@ -2938,7 +3189,8 @@ md_assemble (str) 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, @@ -2974,7 +3226,8 @@ md_assemble (str) 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; } } @@ -3141,6 +3394,12 @@ md_begin () #endif init_regtable (); + +#ifdef OBJ_ELF + record_alignment (text_section, 2); + record_alignment (data_section, 2); + record_alignment (bss_section, 2); +#endif } void @@ -3236,6 +3495,43 @@ m68k_init_after_args () 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 @@ -3327,6 +3623,15 @@ md_apply_fix_2 (fixP, val) 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 @@ -3354,6 +3659,14 @@ md_apply_fix_2 (fixP, val) 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", @@ -3849,13 +4162,27 @@ md_estimate_size_before_relax (fragP, segment) { 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: @@ -4219,7 +4546,14 @@ static void 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 (); } @@ -4480,6 +4814,8 @@ s_reg (ignore) int c; struct m68k_op rop; unsigned long mask; + char *stop = NULL; + char stopc; if (line_label == NULL) { @@ -4488,6 +4824,9 @@ s_reg (ignore) return; } + if (flag_mri) + stop = mri_comment_field (&stopc); + SKIP_WHITESPACE (); s = input_line_pointer; @@ -4542,6 +4881,9 @@ s_reg (ignore) 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 (); } @@ -4680,12 +5022,12 @@ static struct mri_control_info *push_mri_control 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)); @@ -4781,10 +5123,10 @@ parse_mri_condition (pcc) 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; @@ -4908,10 +5250,10 @@ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart, 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; @@ -4919,19 +5261,42 @@ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart, 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) @@ -4992,10 +5357,10 @@ parse_mri_control_expression (stop, qual, truelab, falselab, extent) { 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'; @@ -5103,7 +5468,8 @@ s_mri_if (qual) /* 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')) @@ -5154,6 +5520,12 @@ s_mri_if (qual) 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 (); } @@ -5210,6 +5582,12 @@ s_mri_else (qual) 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 (); } @@ -5236,6 +5614,12 @@ s_mri_endi (ignore) pop_mri_control (); + if (flag_mri) + { + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + } + demand_empty_rest_of_line (); } @@ -5269,6 +5653,12 @@ s_mri_break (extent) 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 (); } @@ -5302,6 +5692,12 @@ s_mri_next (extent) 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 (); } @@ -5529,6 +5925,12 @@ s_mri_for (qual) *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 (); } @@ -5559,6 +5961,12 @@ s_mri_endf (ignore) pop_mri_control (); + if (flag_mri) + { + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + } + demand_empty_rest_of_line (); } @@ -5572,6 +5980,11 @@ s_mri_repeat (ignore) 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 (); } @@ -5603,6 +6016,14 @@ s_mri_until (qual) 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 (); } @@ -5617,7 +6038,8 @@ s_mri_while (qual) 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') @@ -5644,6 +6066,12 @@ s_mri_while (qual) 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 (); } @@ -5672,6 +6100,12 @@ s_mri_endw (ignore) pop_mri_control (); + if (flag_mri) + { + while (! is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + } + demand_empty_rest_of_line (); } @@ -5813,10 +6247,17 @@ md_parse_option (c, arg) 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: