diff -u -r binutils-2.10-orig/gas/config/tc-m68k.c binutils-2.10/gas/config/tc-m68k.c --- binutils-2.10-orig/gas/config/tc-m68k.c Thu May 10 07:58:09 2001 +++ binutils-2.10/gas/config/tc-m68k.c Thu May 10 08:57:56 2001 @@ -72,6 +72,12 @@ to denote pic relocations. */ int flag_want_pic; +/* This option disables the conversion of short PC relative branches into + longer absolute branches. This allows for generation of PIC code which + can utilise the jbsr, jbra pseudo op codes (which saves about 5% code + size in our environment) */ +static int m68k_relative_branches; + static int flag_short_refs; /* -l option */ static int flag_long_jumps; /* -S option */ @@ -634,11 +640,15 @@ */ if (opcode[0] == 0x60 && opcode[1] == 0xff) /* BRA -> JMP */ { + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative branch to absolute jump")); opcode[0] = 0x4e; opcode[1] = 0xf9; } else if (opcode[0] == 0x61 && opcode[1] == 0xff) /* BSR -> JSR */ { + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative BSR to absolute JSR")); opcode[0] = 0x4e; opcode[1] = 0xb9; } @@ -4322,6 +4332,8 @@ if (fragP->fr_opcode[0] == 0x61) /* BSR */ { + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative BSR to absolute JSR")); fragP->fr_opcode[0] = 0x4E; fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */ @@ -4339,6 +4351,8 @@ /* BRA */ else if (fragP->fr_opcode[0] == 0x60) { + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative branch to absolute jump")); 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, @@ -4361,6 +4375,8 @@ } break; case TAB (BCC68000, LONG): + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative conditional branch to absolute jump")); /* only Bcc 68000 instructions can come here */ /* change bcc into b!cc/jmp absl long */ fragP->fr_opcode[0] ^= 0x01; /* invert bcc */ @@ -4381,6 +4397,8 @@ /* only DBcc 68000 instructions can come here */ /* change dbcc into dbcc/jmp absl long */ /* JF: these used to be fr_opcode[2-7], but that's wrong */ + if (m68k_relative_branches) + as_fatal(_("Tried to convert DBcc to absolute jump")); *buffer_address++ = 0x00; /* branch offset = 4 */ *buffer_address++ = 0x04; *buffer_address++ = 0x60; /* put in bra pc+6 */ @@ -4546,6 +4564,8 @@ /* FIXME, we should check abs val, pick short or long */ if (fragP->fr_opcode[0] == 0x61) { + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative BSR to absolute JSR")); fragP->fr_opcode[0] = 0x4E; fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */ fix_new (fragP, fragP->fr_fix, 4, @@ -4555,6 +4575,8 @@ } else if (fragP->fr_opcode[0] == 0x60) { + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative branch to absolute jump")); fragP->fr_opcode[0] = 0x4E; fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG offset */ fix_new (fragP, fragP->fr_fix, 4, @@ -4639,6 +4661,8 @@ } else { + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative conditional branch to absolute jump")); /* change bcc into b!cc/jmp absl long */ fragP->fr_opcode[0] ^= 0x01; /* invert bcc */ fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */ @@ -4675,6 +4699,8 @@ } else { + if (m68k_relative_branches) + as_fatal(_("Tried to convert DBcc to absolute jump")); /* change dbcc into dbcc/jmp absl long */ /* JF: these used to be fr_opcode[2-4], which is wrong. */ buffer_address[0] = 0x00; /* branch offset = 4 */ @@ -4860,6 +4886,8 @@ if (!HAVE_LONG_BRANCH(current_architecture)) { + if (m68k_relative_branches) + as_fatal(_("Tried to convert PC relative branch to absolute jump")); offset = to_addr - S_GET_VALUE (to_symbol); md_number_to_chars (ptr, (valueT) 0x4EF9, 2); md_number_to_chars (ptr + 2, (valueT) offset, 4); @@ -6773,6 +6801,8 @@ {"disp-size-default-16", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_16}, #define OPTION_DISP_SIZE_DEFAULT_32 (OPTION_MD_BASE + 6) {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32}, +#define OPTION_RELATIVE_BRANCHES (OPTION_MD_BASE + 7) + {"relative-branches", no_argument, NULL, OPTION_RELATIVE_BRANCHES}, {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof(md_longopts); @@ -6923,6 +6953,10 @@ m68k_rel32_from_cmdline = 1; break; + case OPTION_RELATIVE_BRANCHES: + m68k_relative_branches = 1; + break; + default: return 0; } @@ -6957,7 +6991,9 @@ --base-size-default-16 base reg without size is 16 bits\n\ --base-size-default-32 base reg without size is 32 bits (default)\n\ --disp-size-default-16 displacement with unknown size is 16 bits\n\ ---disp-size-default-32 displacement with unknown size is 32 bits (default)\n")); +--disp-size-default-32 displacement with unknown size is 32 bits (default)\n\ +--relative-branches do not turn short relative branches into long\n\ + absolute one\n")); } #ifdef TEST2