2
0
mirror of https://frontier.innolan.net/github/amigaos-cross-toolchain6.git synced 2024-10-19 10:29:55 +00:00
Files
amigaos-cross-toolchain6/patches/binutils-2.9.1/gas/config/tc-m68k.c.diff
Krystian Bacławski da2d7bde0e Update patches.
2012-08-04 13:01:59 +02:00

758 lines
24 KiB
Diff

--- binutils-2.9.1/gas/config/tc-m68k.c 1998-05-01 17:44:43.000000000 +0200
+++ binutils-2.9.1/gas/config/tc-m68k.c 2012-08-04 12:43:35.000000000 +0200
@@ -27,6 +27,12 @@
#include "opcode/m68k.h"
#include "m68k-parse.h"
+/* FIXME: delete this #define as soon as the code that references
+ N_TEXT is changed */
+#ifdef BFD_ASSEMBLER
+#define N_TEXT 4
+#endif
+
/* This string holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful. The macro
tc_comment_chars points to this. We use this, rather than the
@@ -70,6 +76,7 @@
static int flag_short_refs; /* -l option */
static int flag_long_jumps; /* -S option */
+static int flag_small_code; /* -sc option */
#ifdef REGISTER_PREFIX_OPTIONAL
int flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
@@ -156,6 +163,9 @@
/* Mode AINDX (apc-relative) using PC, with variable target, might fit
in 16 or 8 bits. */
#define PCINDEX 7
+/* AmigaOS relocations */
+#define ABSREL 8
+#define IMMREL 9
struct m68k_incant
{
@@ -243,6 +253,7 @@
so, which. */
enum pic_relocation pic_reloc;
#endif
+ char baserel;
}
reloc[5]; /* Five is enough??? */
};
@@ -268,7 +279,7 @@
/* Static functions. */
static void insop PARAMS ((int, const struct m68k_incant *));
-static void add_fix PARAMS ((int, struct m68k_exp *, int, int));
+static void add_fix PARAMS ((int, struct m68k_exp *, int, int, int));
static void add_frag PARAMS ((symbolS *, offsetT, int));
/* Like addword, but goes BEFORE general operands */
@@ -291,11 +302,12 @@
/* The numo+1 kludge is so we can hit the low order byte of the prev word.
Blecch. */
static void
-add_fix (width, exp, pc_rel, pc_fix)
+add_fix (width, exp, pc_rel, pc_fix, base_rel)
int width;
struct m68k_exp *exp;
int pc_rel;
int pc_fix;
+ int base_rel;
{
the_ins.reloc[the_ins.nrel].n = ((width == 'B' || width == '3')
? (the_ins.numo*2-1)
@@ -308,7 +320,8 @@
#ifdef OBJ_ELF
the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
#endif
- the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
+ the_ins.reloc[the_ins.nrel].pcrel = pc_rel;
+ the_ins.reloc[the_ins.nrel++].baserel = base_rel;
}
/* Cause an extra frag to be generated here, inserting up to 10 bytes
@@ -425,6 +438,15 @@
/* BCC68000 is for patching in an extra jmp instruction for long offsets
on the 68000. The 68000 doesn't support long branches with branchs */
+/* ABSREL (nice name;-)) is used in small-code, it might be
+ * implemented base-relative (a4), pc-relative, or base-rel with an extra
+ * add instruction to add the base-register
+ *
+ * IMMREL is the analogous mode for immediate addressing of variables. This
+ * one can lead into situations, where a replacement is not possible:
+ * addl #foo,a0
+ * can't be made pc-relative, if foo is in the text segment */
+
/* This table desribes how you change sizes for the various types of variable
size expressions. This version only supports two kinds. */
@@ -479,6 +501,17 @@
{32765, -32770, 2, TAB (PCINDEX, LONG)},
{0, 0, 4, 0},
{1, 1, 0, 0},
+
+ {127, -128, 0, 0},
+ {32767, -32768, 2, TAB(ABSREL,LONG)},
+ {0, 0, 6, 0},
+ {1, 1, 0, 0},
+
+ {127, -128, 0, 0},
+ {32767, -32768, 2, TAB(IMMREL,LONG)},
+ {0, 0, 6, 0},
+ {1, 1, 0, 0},
+
};
/* These are the machine dependent pseudo-ops. These are included so
@@ -500,12 +533,14 @@
{"even", s_even, 0},
{"skip", s_space, 0},
{"proc", s_proc, 0},
+#ifndef __amigaos__
#if defined (TE_SUN3) || defined (OBJ_ELF)
{"align", s_align_bytes, 0},
#endif
#ifdef OBJ_ELF
{"swbeg", s_ignore, 0},
#endif
+#endif
{"extend", float_cons, 'x'},
{"ldouble", float_cons, 'x'},
@@ -1820,7 +1855,20 @@
else
nextword = get_num (&opP->disp, 0);
if (isvar (&opP->disp))
- add_fix (s[1], &opP->disp, 0, 0);
+ {
+/* This doesn't work when the symbol is N_UNDF! So we ignore this for the moment.
+
+ if (flag_small_code)
+ {
+ add_frag (adds(&opP->disp),
+ offs(&opP->disp),
+ TAB(IMMREL, SZ_UNDEF));
+ break;
+ }
+ else
+*/
+ add_fix(s[1], &opP->disp, 0, 0, opP->disp.baserel);
+ }
switch (s[1])
{
case 'b':
@@ -1980,7 +2028,7 @@
)
{
addword (0x0170);
- add_fix ('l', &opP->disp, 1, 2);
+ add_fix ('l', &opP->disp, 1, 2, opP->disp.baserel);
}
else
{
@@ -1993,7 +2041,7 @@
else
{
addword (0x0170);
- add_fix ('l', &opP->disp, 0, 0);
+ add_fix ('l', &opP->disp, 0, 0, opP->disp.baserel);
}
}
else
@@ -2011,10 +2059,10 @@
{
if (opP->reg == PC)
{
- add_fix ('w', &opP->disp, 1, 0);
+ add_fix ('w', &opP->disp, 1, 0, opP->disp.baserel);
}
else
- add_fix ('w', &opP->disp, 0, 0);
+ add_fix ('w', &opP->disp, 0, 0, opP->disp.baserel);
}
}
addword (nextword);
@@ -2119,9 +2167,9 @@
fit (possible on m68000) let the
fixup processing complain later. */
if (opP->reg == PC)
- add_fix ('B', &opP->disp, 1, 1);
+ add_fix ('B', &opP->disp, 1, 1, 0); /* FIXME? -fnf */
else
- add_fix ('B', &opP->disp, 0, 0);
+ add_fix ('B', &opP->disp, 0, 0, 0); /* FIXME? -fnf */
}
else if (siz1 != SIZE_BYTE)
{
@@ -2251,9 +2299,9 @@
if (siz1 != SIZE_UNSPEC && isvar (&opP->disp))
{
if (opP->reg == PC || opP->reg == ZPC)
- add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 1, 2);
+ add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 1, 2, opP->disp.baserel);
else
- add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 0, 0);
+ add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 0, 0, opP->disp.baserel);
}
if (siz1 == SIZE_LONG)
addword (baseo >> 16);
@@ -2261,7 +2309,7 @@
addword (baseo);
if (siz2 != SIZE_UNSPEC && isvar (&opP->odisp))
- add_fix (siz2 == SIZE_LONG ? 'l' : 'w', &opP->odisp, 0, 0);
+ add_fix (siz2 == SIZE_LONG ? 'l' : 'w', &opP->odisp, 0, 0, opP->disp.baserel);
if (siz2 == SIZE_LONG)
addword (outro >> 16);
if (siz2 != SIZE_UNSPEC)
@@ -2293,7 +2341,7 @@
&& opP->disp.pic_reloc == pic_none
#endif
&& S_GET_SEGMENT (adds (&opP->disp)) == now_seg
- && HAVE_LONG_BRANCH(current_architecture)
+ && (HAVE_LONG_BRANCH(current_architecture) || flag_small_code)
&& !flag_long_jumps
&& !strchr ("~%&$?", s[0]))
{
@@ -2305,8 +2353,20 @@
}
/* Fall through into long */
case SIZE_LONG:
+#if 0
+ /* This doesn't work when the symbol is N_UNDF! We ignore this for now. */
+
+ if (flag_small_code)
+ {
+ tmpreg=0x3A; /* 7.2 */
+ add_frag (adds(&opP->disp),
+ offs(&opP->disp),
+ TAB(ABSREL, SZ_UNDEF));
+ break;
+ }
+#endif
if (isvar (&opP->disp))
- add_fix ('l', &opP->disp, 0, 0);
+ add_fix ('l', &opP->disp, 0, 0, opP->disp.baserel);
tmpreg = 0x39;/* 7.1 mode */
addword (nextword >> 16);
@@ -2318,7 +2378,7 @@
/* Fall through. */
case SIZE_WORD: /* Word */
if (isvar (&opP->disp))
- add_fix ('w', &opP->disp, 0, 0);
+ add_fix ('w', &opP->disp, 0, 0, opP->disp.baserel);
tmpreg = 0x38;/* 7.0 mode */
addword (nextword);
@@ -2354,7 +2414,7 @@
}
tmpreg = get_num (&opP->disp, tmpreg);
if (isvar (&opP->disp))
- add_fix (s[1], &opP->disp, 0, 0);
+ add_fix (s[1], &opP->disp, 0, 0, opP->disp.baserel);
switch (s[1])
{
case 'b': /* Danger: These do no check for
@@ -2423,10 +2483,10 @@
which is a char, and may therefore be unsigned. We
want to pass -1, but we pass 64 instead, and convert
back in md_pcrel_from. */
- add_fix ('B', &opP->disp, 1, 64);
+ add_fix ('B', &opP->disp, 1, 64, opP->disp.baserel);
break;
case 'W':
- add_fix ('w', &opP->disp, 1, 0);
+ add_fix ('w', &opP->disp, 1, 0, opP->disp.baserel);
addword (0);
break;
case 'L':
@@ -2434,7 +2494,7 @@
if (!HAVE_LONG_BRANCH(current_architecture))
as_warn ("Can't use long branches on 68000/68010/5200");
the_ins.opcode[the_ins.numo - 1] |= 0xff;
- add_fix ('l', &opP->disp, 1, 0);
+ add_fix ('l', &opP->disp, 1, 0, opP->disp.baserel);
addword (0);
addword (0);
break;
@@ -2479,19 +2539,19 @@
break;
}
#endif
- add_fix ('w', &opP->disp, 1, 0);
+ add_fix ('w', &opP->disp, 1, 0, opP->disp.baserel);
}
addword (0);
break;
case 'C': /* Fixed size LONG coproc branches */
- add_fix ('l', &opP->disp, 1, 0);
+ add_fix ('l', &opP->disp, 1, 0, opP->disp.baserel);
addword (0);
addword (0);
break;
case 'c': /* Var size Coprocesssor branches */
if (subs (&opP->disp))
{
- add_fix ('l', &opP->disp, 1, 0);
+ add_fix ('l', &opP->disp, 1, 0, opP->disp.baserel);
add_frag ((symbolS *) 0, (offsetT) 0, TAB (FBRANCH, LONG));
}
else if (adds (&opP->disp))
@@ -2502,7 +2562,7 @@
/* add_frag ((symbolS *) 0, offs (&opP->disp),
TAB(FBRANCH,SHORT)); */
the_ins.opcode[the_ins.numo - 1] |= 0x40;
- add_fix ('l', &opP->disp, 1, 0);
+ add_fix ('l', &opP->disp, 1, 0, opP->disp.baserel);
addword (0);
addword (0);
}
@@ -2856,7 +2916,7 @@
break;
case '_': /* used only for move16 absolute 32-bit address */
if (isvar (&opP->disp))
- add_fix ('l', &opP->disp, 0, 0);
+ add_fix ('l', &opP->disp, 0, 0, opP->disp.baserel);
tmpreg = get_num (&opP->disp, 80);
addword (tmpreg >> 16);
addword (tmpreg & 0xFFFF);
@@ -3162,8 +3222,8 @@
{ "a3", ADDR3 },
{ "a4", ADDR4 },
{ "a5", ADDR5 },
+ { "fp", ADDR5 },
{ "a6", ADDR6 },
- { "fp", ADDR6 },
{ "a7", ADDR7 },
{ "sp", ADDR7 },
{ "ssp", ADDR7 },
@@ -3439,7 +3499,8 @@
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
get_reloc_code (n, the_ins.reloc[m].pcrel,
- the_ins.reloc[m].pic_reloc));
+ the_ins.reloc[m].pic_reloc),
+ the_ins.reloc[m].baserel);
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
if (the_ins.reloc[m].wid == 'B')
fixP->fx_signed = 1;
@@ -3486,7 +3547,8 @@
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
get_reloc_code (wid, the_ins.reloc[m].pcrel,
- the_ins.reloc[m].pic_reloc));
+ the_ins.reloc[m].pic_reloc),
+ the_ins.reloc[m].baserel);
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
(void) frag_var (rs_machine_dependent, 10, 0,
@@ -3523,7 +3585,8 @@
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
get_reloc_code (wid, the_ins.reloc[m].pcrel,
- the_ins.reloc[m].pic_reloc));
+ the_ins.reloc[m].pic_reloc),
+ the_ins.reloc[m].baserel);
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
}
@@ -4146,7 +4209,11 @@
case TAB (ABRANCH, LONG):
if (!HAVE_LONG_BRANCH(current_architecture))
{
- if (fragP->fr_opcode[0] == 0x61)
+ if (flag_small_code)
+ {
+ as_bad("Long branch in small code model, not supported.");
+ }
+ else if (fragP->fr_opcode[0] == 0x61)
/* BSR */
{
fragP->fr_opcode[0] = 0x4E;
@@ -4158,7 +4225,7 @@
fragP->fr_symbol,
fragP->fr_offset,
0,
- NO_RELOC);
+ NO_RELOC, 0);
fragP->fr_fix += 4;
ext = 0;
@@ -4169,7 +4236,7 @@
fragP->fr_opcode[0] = 0x4E;
fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG offset */
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
- fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_offset, 0, NO_RELOC, 0);
fragP->fr_fix += 4;
ext = 0;
}
@@ -4197,7 +4264,7 @@
*buffer_address++ = (char) 0xf9;
fragP->fr_fix += 2; /* account for jmp instruction */
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
- fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_offset, 0, NO_RELOC, 0);
fragP->fr_fix += 4;
ext = 0;
break;
@@ -4214,7 +4281,7 @@
fragP->fr_fix += 6; /* account for bra/jmp instructions */
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
- fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_offset, 0, NO_RELOC, 0);
fragP->fr_fix += 4;
ext = 0;
break;
@@ -4233,8 +4300,10 @@
/* The thing to do here is force it to ABSOLUTE LONG, since
PCREL is really trying to shorten an ABSOLUTE address anyway */
/* JF FOO This code has not been tested */
+ if (flag_small_code)
+ as_bad ("Trying to force a pcrel thing into absolute mode while in small code mode");
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset,
- 0, NO_RELOC);
+ 0, NO_RELOC, 0);
if ((fragP->fr_opcode[1] & 0x3F) != 0x3A)
as_bad ("Internal error (long PC-relative operand) for insn 0x%04x at 0x%lx",
(unsigned) fragP->fr_opcode[0],
@@ -4246,14 +4315,14 @@
break;
case TAB (PCLEA, SHORT):
fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
- fragP->fr_offset, 1, NO_RELOC);
+ fragP->fr_offset, 1, NO_RELOC, 0);
fragP->fr_opcode[1] &= ~0x3F;
fragP->fr_opcode[1] |= 0x3A; /* 072 - mode 7.2 */
ext = 2;
break;
case TAB (PCLEA, LONG):
fixP = fix_new (fragP, (int) (fragP->fr_fix) + 2, 4, fragP->fr_symbol,
- fragP->fr_offset, 1, NO_RELOC);
+ fragP->fr_offset, 1, NO_RELOC, 0);
fixP->fx_pcrel_adjust = 2;
/* Already set to mode 7.3; this indicates: PC indirect with
suppressed index, 32-bit displacement. */
@@ -4283,7 +4352,7 @@
buffer_address[-1] = 0x20;
fixP = fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
fragP->fr_offset, (fragP->fr_opcode[1] & 077) == 073,
- NO_RELOC);
+ NO_RELOC, 0);
fixP->fx_pcrel_adjust = 2;
ext = 2;
break;
@@ -4291,13 +4360,89 @@
disp += 2;
fixP = fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
fragP->fr_offset, (fragP->fr_opcode[1] & 077) == 073,
- NO_RELOC);
+ NO_RELOC, 0);
fixP->fx_pcrel_adjust = 2;
assert (fragP->fr_fix >= 2);
buffer_address[-2] |= 0x1;
buffer_address[-1] = 0x30;
ext = 4;
break;
+ case TAB(ABSREL,BYTE):
+ as_bad ("ABSREL_BYTE: how the ** does this look ?? \n");
+ break;
+ case TAB(ABSREL,SHORT):
+ subseg_change (text_section, 0);
+ ext = 2;
+ fragP->fr_opcode[1] &= ~0x3f;
+ if ((S_GET_TYPE (fragP->fr_symbol)) == N_TEXT)
+ {
+ /* so this is really a pc-relative address */
+ fragP->fr_opcode[1] |= 0x3a;
+ fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol, fragP->fr_offset+2, 1, NO_RELOC, 0);
+ break;
+ }
+ /* in that case we have to generate base-relative code
+ * (note: if we're in N_UNDF, this could as well be pc-relative, but the linker
+ * will have to do the final patch in that case) */
+ fragP->fr_opcode[1] |= 0x2c; /* (a4) */
+ fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol,fragP->fr_offset, 0, NO_RELOC, 1);
+ break;
+ case TAB(ABSREL,LONG):
+ as_bad ("ABSREL_LONG: sorry, not supported.\n");
+ break;
+
+ case TAB(IMMREL,BYTE):
+ as_bad ("IMMREL_BYTE: how the ** does this look ?? \n");
+ break;
+ case TAB(IMMREL,SHORT):
+ subseg_change (text_section, 0);
+ ext = 0;
+ if ((S_GET_TYPE (fragP->fr_symbol)) == N_TEXT)
+ {
+ /* we can only fix operations on data registers, not on <ea> */
+ if ((fragP->fr_opcode[1] & 0x38) != 0)
+ {
+ /* use the normal reloc32, sigh... */
+ fix_new (fragP,(int)(fragP->fr_fix),4,fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC, 0);
+ fragP->fr_fix += 4;
+ break;
+ }
+
+ /* so this is really a pc-relative address
+ * What we have to do now is a VERY UGLY AND BIG KLUDGE. Basically do the
+ * following thing:
+ * turn
+ * addl #foo,d0 (foo is N_TEXT)
+ * into
+ * pea foo(pc)
+ * addl (sp)+,d0
+ */
+ *buffer_address++ = fragP->fr_opcode[0]; /* save the original command */
+ *buffer_address++ = fragP->fr_opcode[1];
+ fragP->fr_opcode[0] = 0x48; /* PEA */
+ fragP->fr_opcode[1] = 0x7a;
+ fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol, fragP->fr_offset+2, 1, NO_RELOC, 0);
+
+ *buffer_address++ = 0x9f; /* sp@+ */
+ fragP->fr_fix += 4; /* two byte fix, two byte code extension */
+ break;
+ }
+ /* in that case we have to generate base-relative code
+ * (note: if we're in N_UNDF, this could as well be pc-relative, but the linker
+ * will have to do the final patch in that case) */
+
+ /* analogous (more or less;-)) to above, the following conversion is done
+ * turn
+ * addl #bar,d0 (bar is N_DATA)
+ * into
+ * addl #<bar>,d0 where <bar> is a baserel-reloc
+ * addl a4,d0
+ */
+
+ fix_new(fragP,(int)(fragP->fr_fix), 4,fragP->fr_symbol,fragP->fr_offset, 0, NO_RELOC, 1);
+ *buffer_address++ = 0xd0;
+ *buffer_address++ = 0x8c;
+ break;
}
if (ext)
@@ -4355,26 +4500,68 @@
fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
break;
}
- else if ((fragP->fr_symbol == 0) || !HAVE_LONG_BRANCH(current_architecture))
+ else if ((fragP->fr_symbol == 0) || !HAVE_LONG_BRANCH(current_architecture) || !flag_small_code)
{
/* On 68000, or for absolute value, switch to abs long */
/* FIXME, we should check abs val, pick short or long */
- if (fragP->fr_opcode[0] == 0x61)
+ if (fragP->fr_opcode[0] == 0x61)
{
- fragP->fr_opcode[0] = 0x4E;
- fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */
- fix_new (fragP, fragP->fr_fix, 4,
- fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC);
- fragP->fr_fix += 4;
+ if (flag_small_code)
+ {
+ /* leave the BSR, no need to change
+ * it into a JSR (PC,..) */
+ subseg_change(text_section, 0);
+ fix_new(fragP, fragP->fr_fix, 2,
+ fragP->fr_symbol, fragP->fr_offset, 1, NO_RELOC, 0);
+ fragP->fr_fix+=2;
+ fragP->fr_opcode[1]=0x00;
+ }
+ else if (flag_short_refs)
+ {
+ subseg_change(text_section, 0);
+ fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol,
+ fragP->fr_offset + 2, 0, NO_RELOC, 0);
+ fragP->fr_fix+=2;
+ fragP->fr_opcode[1]=0x00;
+ }
+ else
+ {
+ fragP->fr_opcode[0] = 0x4E;
+ fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */
+ subseg_change (text_section, 0);
+ fix_new (fragP, fragP->fr_fix, 4,
+ fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC, 0);
+ fragP->fr_fix += 4;
+ }
frag_wane (fragP);
}
else if (fragP->fr_opcode[0] == 0x60)
{
- fragP->fr_opcode[0] = 0x4E;
- fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG offset */
- fix_new (fragP, fragP->fr_fix, 4,
- fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC);
- fragP->fr_fix += 4;
+ if (flag_small_code)
+ {
+ subseg_change(text_section, 0);
+ fix_new(fragP, fragP->fr_fix, 2,
+ fragP->fr_symbol, fragP->fr_offset, 1, NO_RELOC, 0);
+ fragP->fr_fix+=2;
+ }
+ else if (flag_short_refs)
+ {
+ fragP->fr_opcode[0]= 0x4E;
+ fragP->fr_opcode[1]= 0xF8; /* JMP with ABSL WORD offset */
+ subseg_change(text_section, 0);
+ fix_new(fragP, fragP->fr_fix, 2,
+ fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC, 0);
+ fragP->fr_fix+=2;
+ }
+ else
+ {
+ fragP->fr_opcode[0] = 0x4E;
+ fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG offset */
+ subseg_change (text_section, 0);
+ fix_new (fragP, fragP->fr_fix, 4,
+ fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC, 0);
+ fragP->fr_fix += 4;
+ }
frag_wane (fragP);
}
else
@@ -4385,7 +4572,7 @@
else
{ /* Symbol is still undefined. Make it simple */
fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
- fragP->fr_offset, 1, NO_RELOC);
+ fragP->fr_offset, 1, NO_RELOC, 0);
fragP->fr_fix += 4;
fragP->fr_opcode[1] = (char) 0xff;
frag_wane (fragP);
@@ -4405,7 +4592,7 @@
else
{
fix_new (fragP, (int) fragP->fr_fix, 4, fragP->fr_symbol,
- fragP->fr_offset, 1, NO_RELOC);
+ fragP->fr_offset, 1, NO_RELOC, 0);
fragP->fr_fix += 4;
fragP->fr_opcode[1] |= 0x40; /* Turn on LONG bit */
frag_wane (fragP);
@@ -4450,7 +4637,7 @@
buffer_address[1] = (char) 0xf8;
fragP->fr_fix += 2; /* account for jmp instruction */
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
- fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_offset, 0, NO_RELOC, 0);
fragP->fr_fix += 2;
}
else
@@ -4461,7 +4648,7 @@
buffer_address[1] = (char) 0xf9;
fragP->fr_fix += 2; /* account for jmp instruction */
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
- fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_offset, 0, NO_RELOC, 0);
fragP->fr_fix += 4;
}
frag_wane (fragP);
@@ -4491,7 +4678,7 @@
buffer_address[5] = (char) 0xf8;
fragP->fr_fix += 6; /* account for bra/jmp instruction */
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
- fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_offset, 0, NO_RELOC, 0);
fragP->fr_fix += 2;
}
else
@@ -4502,7 +4689,7 @@
buffer_address[5] = (char) 0xf9;
fragP->fr_fix += 6; /* account for bra/jmp instruction */
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
- fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_offset, 0, NO_RELOC, 0);
fragP->fr_fix += 4;
}
@@ -4542,6 +4729,16 @@
}
break;
+ case TAB(ABSREL,SZ_UNDEF):
+ if ((S_GET_SEGMENT (fragP->fr_symbol)) == segment || flag_short_refs || flag_small_code) {
+ fragP->fr_subtype = TAB(ABSREL, SHORT);
+ fragP->fr_var += 2;
+ } else {
+ fragP->fr_subtype = TAB(ABSREL, LONG);
+ fragP->fr_var += 6;
+ }
+ break;
+
default:
break;
}
@@ -4604,7 +4801,7 @@
the_bytes[5] = (ri->r_symbolnum >> 8) & 0x0ff;
the_bytes[6] = ri->r_symbolnum & 0x0ff;
the_bytes[7] = (((ri->r_pcrel << 7) & 0x80) | ((ri->r_length << 5) & 0x60) |
- ((ri->r_extern << 4) & 0x10));
+ ((ri->r_extern << 4) & 0x10) | ((ri->r_baserel << 3) & 0x08));
}
#endif /* comment */
@@ -4638,7 +4835,7 @@
where[5] = (r_symbolnum >> 8) & 0x0ff;
where[6] = r_symbolnum & 0x0ff;
where[7] = (((fixP->fx_pcrel << 7) & 0x80) | ((nbytes_r_length[fixP->fx_size] << 5) & 0x60) |
- (((!S_IS_DEFINED (fixP->fx_addsy)) << 4) & 0x10));
+ (((!S_IS_DEFINED (fixP->fx_addsy)) << 4) & 0x10) | ((fixP->tc_fix_data << 3) & 0x08));
}
#endif
@@ -4678,7 +4875,7 @@
md_number_to_chars (ptr, (valueT) 0x4EF9, 2);
md_number_to_chars (ptr + 2, (valueT) offset, 4);
fix_new (frag, (ptr + 2) - frag->fr_literal, 4, to_symbol, (offsetT) 0,
- 0, NO_RELOC);
+ 0, NO_RELOC, 0);
}
else
{
@@ -6549,7 +6746,7 @@
#ifdef OBJ_ELF
CONST char *md_shortopts = "lSA:m:kQ:V";
#else
-CONST char *md_shortopts = "lSA:m:k";
+CONST char *md_shortopts = "SA:m:s:k";
#endif
struct option md_longopts[] = {
@@ -6589,6 +6786,13 @@
flag_long_jumps = 1;
break;
+ case 's':
+ if (!strcmp(arg, "c") || !strcmp(arg, "mallcode"))
+ flag_small_code = 1;
+ else
+ return 0;
+ break;
+
case 'A':
if (*arg == 'm')
arg++;
@@ -6731,7 +6935,6 @@
{
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\n\
| -mcpu32 | -m5200\n\
@@ -6745,6 +6948,7 @@
[default yes for 68020 and up]\n\
-pic, -k generate position independent code\n\
-S turn jbsr into jsr\n\
+-smallcode, -sc small code model\n\
--register-prefix-optional\n\
recognize register names without prefix character\n\
--bitwise-or do not treat `|' as a comment character\n");