+Wed Apr 5 22:04:20 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * reloc.c (_bfd_relocate_contents): Add BFD_RELOC_SH_LOOP_START and
+ BFD_RELOC_SH_LOOP_END.
+ * elf32-sh.c (sh_elf_howto_tab): Change special_func to
+ sh_elf_ignore_reloc for all entries that sh_elf_reloc used to ignore.
+ Add entries for R_SH_LOOP_START and R_SH_LOOP_END.
+ (sh_elf_reloc_loop): New function.
+ (sh_elf_reloc): No need to test for always-to-be-ignored relocs
+ any more.
+ (sh_rel): Add entries for BFD_RELOC_SH_LOOP_{START,END}.
+ (sh_elf_relocate_section): Handle BFD_RELOC_SH_LOOP_{START,END}.
+ * bfd-in2.h, libbfd.h: Regenerate.
+
2000-04-04 Alan Modra <alan@linuxcare.com.au>
* po/bfd.pot: Regenerate.
BFD_RELOC_SH_CODE,
BFD_RELOC_SH_DATA,
BFD_RELOC_SH_LABEL,
+ BFD_RELOC_SH_LOOP_START,
+ BFD_RELOC_SH_LOOP_END,
/* Thumb 23-, 12- and 9-bit pc-relative branches. The lowest bit must
be zero and is not stored in the instruction. */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ sh_elf_ignore_reloc, /* special_function */
"R_SH_NONE", /* name */
false, /* partial_inplace */
0, /* src_mask */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ sh_elf_ignore_reloc, /* special_function */
"R_SH_REL32", /* name */
false, /* partial_inplace */
0, /* src_mask */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ sh_elf_ignore_reloc, /* special_function */
"R_SH_DIR8WPN", /* name */
true, /* partial_inplace */
0xff, /* src_mask */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ sh_elf_ignore_reloc, /* special_function */
"R_SH_DIR8WPL", /* name */
true, /* partial_inplace */
0xff, /* src_mask */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ sh_elf_ignore_reloc, /* special_function */
"R_SH_DIR8WPZ", /* name */
true, /* partial_inplace */
0xff, /* src_mask */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ sh_elf_ignore_reloc, /* special_function */
"R_SH_DIR8BP", /* name */
false, /* partial_inplace */
0, /* src_mask */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ sh_elf_ignore_reloc, /* special_function */
"R_SH_DIR8W", /* name */
false, /* partial_inplace */
0, /* src_mask */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ sh_elf_ignore_reloc, /* special_function */
"R_SH_DIR8L", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
+ /* 8 bit PC relative divided by 2 - but specified in a very odd way. */
+ HOWTO (R_SH_LOOP_START, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ sh_elf_ignore_reloc, /* special_function */
+ "R_SH_LOOP_START", /* name */
+ true, /* partial_inplace */
+ 0xff, /* src_mask */
+ 0xff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* 8 bit PC relative divided by 2 - but specified in a very odd way. */
+ HOWTO (R_SH_LOOP_END, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ sh_elf_ignore_reloc, /* special_function */
+ "R_SH_LOOP_END", /* name */
+ true, /* partial_inplace */
+ 0xff, /* src_mask */
+ 0xff, /* dst_mask */
+ true), /* pcrel_offset */
+
};
-/* This function is used for normal relocs. This is like the COFF
+static bfd_reloc_status_type
+sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr,
+ symbol_section, start, end)
+ int r_type;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ bfd_vma addr;
+ asection *symbol_section;
+ bfd_vma start, end;
+{
+ static bfd_vma last_addr;
+ asection *last_symbol_section;
+ bfd_byte *free_contents = NULL;
+ bfd_byte *start_ptr, *ptr, *last_ptr;
+ int diff, cum_diff;
+ bfd_signed_vma x;
+ int insn;
+
+ /* Sanity check the address. */
+ if (addr > input_section->_raw_size)
+ return bfd_reloc_outofrange;
+
+ /* We require the start and end relocations to be processed consecutively -
+ although we allow then to be processed forwards or backwards. */
+ if (! last_addr)
+ {
+ last_addr = addr;
+ last_symbol_section = symbol_section;
+ return bfd_reloc_ok;
+ }
+ if (last_addr != addr)
+ abort ();
+ last_addr = 0;
+
+ if (! symbol_section || last_symbol_section != symbol_section || end < start)
+ return bfd_reloc_outofrange;
+
+ /* Get the symbol_section contents. */
+ if (symbol_section != input_section)
+ {
+ if (elf_section_data (symbol_section)->this_hdr.contents != NULL)
+ contents = elf_section_data (symbol_section)->this_hdr.contents;
+ else
+ {
+ free_contents = contents
+ = (bfd_byte *) bfd_malloc (symbol_section->_raw_size);
+ if (contents == NULL)
+ return bfd_reloc_outofrange;
+ if (! bfd_get_section_contents (input_bfd, symbol_section, contents,
+ (file_ptr) 0,
+ symbol_section->_raw_size))
+ {
+ free (contents);
+ return bfd_reloc_outofrange;
+ }
+ }
+ }
+#define IS_PPI(PTR) ((bfd_get_16 (input_bfd, (PTR)) & 0xfc00) == 0xf800)
+ start_ptr = contents + start;
+ for (cum_diff = -6, ptr = contents + end; cum_diff < 0 && ptr > start_ptr;)
+ {
+ for (last_ptr = ptr, ptr -= 4; ptr >= start_ptr && IS_PPI (ptr);)
+ ptr -= 2;
+ ptr += 2;
+ diff = last_ptr - ptr >> 1;
+ cum_diff += diff & 1;
+ cum_diff += diff;
+ }
+ /* Calculate the start / end values to load into rs / re minus four -
+ so that will cancel out the four we would otherwise have to add to
+ addr to get the value to subtract in order to get relative addressing. */
+ if (cum_diff >= 0)
+ {
+ start -= 4;
+ end = (ptr + cum_diff * 2) - contents;
+ }
+ else
+ {
+ bfd_vma start0 = start - 4;
+
+ while (start0 >= 0 && IS_PPI (contents + start0))
+ start0 -= 2;
+ start0 = start - 2 - ((start - start0) & 2);
+ start = start0 - cum_diff - 2;
+ end = start0;
+ }
+
+ if (free_contents)
+ free (free_contents);
+
+ insn = bfd_get_16 (input_bfd, contents + addr);
+
+ x = (insn & 0x200 ? end : start) - addr;
+ if (input_section != symbol_section)
+ x += ((symbol_section->output_section->vma + symbol_section->output_offset)
+ - (input_section->output_section->vma
+ + input_section->output_offset));
+ x >>= 1;
+ if (x < -128 || x > 127)
+ return bfd_reloc_overflow;
+
+ x = insn & ~0xff | x & 0xff;
+ bfd_put_16 (input_bfd, x, contents + addr);
+
+ return bfd_reloc_ok;
+}
+
+/* This function is used for normal relocs. This used to be like the COFF
function, and is almost certainly incorrect for other ELF targets. */
static bfd_reloc_status_type
/* Almost all relocs have to do with relaxing. If any work must be
done for them, it has been done in sh_relax_section. */
- if (r_type != R_SH_DIR32
- && (r_type != R_SH_IND12W
- || (symbol_in->flags & BSF_LOCAL) != 0))
+ if (r_type == R_SH_IND12W && (symbol_in->flags & BSF_LOCAL) != 0)
return bfd_reloc_ok;
if (symbol_in != NULL
{ BFD_RELOC_SH_LABEL, R_SH_LABEL },
{ BFD_RELOC_VTABLE_INHERIT, R_SH_GNU_VTINHERIT },
{ BFD_RELOC_VTABLE_ENTRY, R_SH_GNU_VTENTRY },
+ { BFD_RELOC_SH_LOOP_START, R_SH_LOOP_START },
+ { BFD_RELOC_SH_LOOP_END, R_SH_LOOP_END },
};
/* Given a BFD reloc code, return the howto structure for the
/* Many of the relocs are only used for relaxing, and are
handled entirely by the relaxation code. */
- if (r_type > (int) R_SH_LAST_INVALID_RELOC)
+ if (r_type > (int) R_SH_LAST_INVALID_RELOC
+ && r_type < (int) R_SH_LOOP_START)
continue;
if (r_type < 0
- || r_type >= (int) R_SH_FIRST_INVALID_RELOC)
+ || (r_type >= (int) R_SH_FIRST_INVALID_RELOC
+ && r_type <= (int) R_SH_LAST_INVALID_RELOC))
{
bfd_set_error (bfd_error_bad_value);
return false;
/* FIXME: This is certainly incorrect. However, it is how the
COFF linker works. */
if (r_type != (int) R_SH_DIR32
- && r_type != (int) R_SH_IND12W)
+ && r_type != (int) R_SH_IND12W
+ && r_type != (int) R_SH_LOOP_START
+ && r_type != (int) R_SH_LOOP_END)
continue;
howto = sh_elf_howto_table + r_type;
{
case (int)R_SH_DIR32:
addend = rel->r_addend;
+ /* Fall through. */
+ default:
+ /* COFF relocs don't use the addend. The addend is used for
+ R_SH_DIR32 to be compatible with other compilers. */
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ relocation, addend);
break;
+ case R_SH_LOOP_START:
+ {
+ static bfd_vma start, end;
+
+ start = (relocation + rel->r_addend
+ - (sec->output_section->vma + sec->output_offset));
+ r = sh_elf_reloc_loop (r_type, input_bfd, input_section, contents,
+ rel->r_offset, sec, start, end);
+ break;
+ case R_SH_LOOP_END:
+ end = (relocation + rel->r_addend
+ - (sec->output_section->vma + sec->output_offset));
+ r = sh_elf_reloc_loop (r_type, input_bfd, input_section, contents,
+ rel->r_offset, sec, start, end);
+ break;
+ }
}
- /* COFF relocs don't use the addend. The addend is used for R_SH_DIR32
- to be compatible with other compilers. */
- r = _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents, rel->r_offset,
- relocation, addend);
-
if (r != bfd_reloc_ok)
{
switch (r)
"BFD_RELOC_SH_CODE",
"BFD_RELOC_SH_DATA",
"BFD_RELOC_SH_LABEL",
+ "BFD_RELOC_SH_LOOP_START",
+ "BFD_RELOC_SH_LOOP_END",
"BFD_RELOC_THUMB_PCREL_BRANCH9",
"BFD_RELOC_THUMB_PCREL_BRANCH12",
"BFD_RELOC_THUMB_PCREL_BRANCH23",
BFD_RELOC_SH_DATA
ENUMX
BFD_RELOC_SH_LABEL
+ENUMX
+ BFD_RELOC_SH_LOOP_START
+ENUMX
+ BFD_RELOC_SH_LOOP_END
ENUMDOC
Hitachi SH relocs. Not all of these appear in object files.
+Wed Apr 5 22:07:19 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * config/tc-sh.c (immediate): Delete.
+ (sh_operand_info): Add immediate member.
+ (parse_reg): Use A_PC for pc.
+ (parse_exp): Add second argument 'op'. All callers changed.
+ (parse_at): Expect pc to be coded as A_PC.
+ Use immediate field in *op.
+ (insert): Add fourth argument 'op'. All callers changed.
+ (build_relax): Add second argument 'op'. All callers changed.
+ (insert_loop_bounds): New function.
+ (build_Mytes): Remove DISP_4.
+ Split IMM_[48]{,BY[24]} into IMM[01]_[48]{,BY[24]}. Add REPEAT.
+ (assemble_ppi): Use immediate field in *operand.
+ (sh_force_relocation): Handle BFD_RELOC_SH_LOOP_{START,END}.
+ (md_apply_fix): Likewise.
+ (tc_gen_reloc): Likewise. Check for a pcrel BFD_RELOC_SH_LABEL.
+
Wed Apr 5 06:35:45 2000 Alexandre Oliva <oliva@lsd.ic.unicamp.br>
* config/tc-sparc.c (sparc_ip): Avoid string pasting.
static int reg_efg;
static int reg_b;
-static expressionS immediate; /* absolute expression */
-
typedef struct
{
sh_arg_type type;
int reg;
+ expressionS immediate;
}
-
sh_operand_info;
#define IDENT_CHAR(c) (isalnum (c) || (c) == '_')
}
if (src[0] == 'p' && src[1] == 'c' && ! IDENT_CHAR ((unsigned char) src[2]))
{
- *mode = A_DISP_PC;
+ /* Don't use A_DISP_PC here - that would accept stuff like 'mova pc,r0'
+ and use an uninitialized immediate. */
+ *mode = A_PC;
return 2;
}
if (src[0] == 'g' && src[1] == 'b' && src[2] == 'r'
static
char *
-parse_exp (s)
+parse_exp (s, op)
char *s;
+ sh_operand_info *op;
{
char *save;
char *new;
save = input_line_pointer;
input_line_pointer = s;
- expression (&immediate);
- if (immediate.X_op == O_absent)
+ expression (&op->immediate);
+ if (op->immediate.X_op == O_absent)
as_bad (_("missing operand"));
new = input_line_pointer;
input_line_pointer = save;
else
{
/* Must be an @(disp,.. thing) */
- src = parse_exp (src);
+ src = parse_exp (src, op);
if (src[0] == ',')
src++;
/* Now can be rn, gbr or pc */
{
op->type = A_DISP_GBR;
}
- else if (mode == A_DISP_PC)
+ else if (mode == A_PC)
{
/* Turn a plain @(4,pc) into @(.+4,pc) */
- if (immediate.X_op == O_constant) {
- immediate.X_add_symbol = dot();
- immediate.X_op = O_symbol;
+ if (op->immediate.X_op == O_constant) {
+ op->immediate.X_add_symbol = dot();
+ op->immediate.X_op = O_symbol;
}
op->type = A_DISP_PC;
}
if (src[0] == '#')
{
src++;
- *ptr = parse_exp (src);
+ *ptr = parse_exp (src, op);
op->type = A_IMM;
return;
}
else
{
/* Not a reg, the only thing left is a displacement */
- *ptr = parse_exp (src);
+ *ptr = parse_exp (src, op);
op->type = A_DISP_PC;
return;
}
static void
-insert (where, how, pcrel)
+insert (where, how, pcrel, op)
char *where;
int how;
int pcrel;
+ sh_operand_info *op;
{
fix_new_exp (frag_now,
where - frag_now->fr_literal,
2,
- &immediate,
+ &op->immediate,
pcrel,
how);
}
static void
-build_relax (opcode)
+build_relax (opcode, op)
sh_opcode_info *opcode;
+ sh_operand_info *op;
{
int high_byte = target_big_endian ? 0 : 1;
char *p;
md_relax_table[C (what, COND32)].rlx_length,
md_relax_table[C (what, COND8)].rlx_length,
C (what, 0),
- immediate.X_add_symbol,
- immediate.X_add_number,
+ op->immediate.X_add_symbol,
+ op->immediate.X_add_number,
0);
p[high_byte] = (opcode->nibbles[0] << 4) | (opcode->nibbles[1]);
}
md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length,
md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length,
C (UNCOND_JUMP, 0),
- immediate.X_add_symbol,
- immediate.X_add_number,
+ op->immediate.X_add_symbol,
+ op->immediate.X_add_number,
0);
p[high_byte] = (opcode->nibbles[0] << 4);
}
}
+/* insert ldrs & ldre with fancy relocations that relaxation can recognize. */
+static char *
+insert_loop_bounds (output, operand)
+ char *output;
+ sh_operand_info *operand;
+{
+ char *name;
+ symbolS *end_sym;
+
+ /* Since the low byte of the opcode will be overwritten by the reloc, we
+ can just stash the high byte into both bytes and ignore endianness. */
+ output[0] = 0x8c;
+ output[1] = 0x8c;
+ insert (output, BFD_RELOC_SH_LOOP_START, 1, operand);
+ insert (output, BFD_RELOC_SH_LOOP_END, 1, operand + 1);
+
+ if (sh_relax)
+ {
+ static int count = 0;
+
+ /* If the last loop insn is a two-byte-insn, it is in danger of being
+ swapped with the insn after it. To prevent this, create a new
+ symbol - complete with SH_LABEL reloc - after the last loop insn.
+ If the last loop insn is four bytes long, the symbol will be
+ right in the middle, but four byte insns are not swapped anyways. */
+ /* A REPEAT takes 6 bytes. The SH has a 32 bit address space.
+ Hence a 9 digit number should be enough to count all REPEATs. */
+ name = alloca (11);
+ sprintf (name, "_R%x", count++ & 0x3fffffff);
+ end_sym = symbol_new (name, undefined_section, 0, &zero_address_frag);
+ /* Make this a local symbol. */
+#ifdef OBJ_COFF
+ SF_SET_LOCAL (end_sym);
+#endif /* OBJ_COFF */
+ symbol_table_insert (end_sym);
+ end_sym->sy_value = operand[1].immediate;
+ end_sym->sy_value.X_add_number += 2;
+ fix_new (frag_now, frag_now_fix (), 2, end_sym, 0, 1, BFD_RELOC_SH_LABEL);
+ }
+
+ output = frag_more (2);
+ output[0] = 0x8e;
+ output[1] = 0x8e;
+ insert (output, BFD_RELOC_SH_LOOP_START, 1, operand);
+ insert (output, BFD_RELOC_SH_LOOP_END, 1, operand + 1);
+
+ return frag_more (2);
+}
+
/* Now we know what sort of opcodes it is, lets build the bytes -
*/
static void
case REG_B:
nbuf[index] = reg_b | 0x08;
break;
- case DISP_4:
- insert (output + low_byte, BFD_RELOC_SH_IMM4, 0);
+ case IMM0_4BY4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0, operand);
+ break;
+ case IMM0_4BY2:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4BY2, 0, operand);
+ break;
+ case IMM0_4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4, 0, operand);
+ break;
+ case IMM1_4BY4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0, operand + 1);
+ break;
+ case IMM1_4BY2:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4BY2, 0, operand + 1);
break;
- case IMM_4BY4:
- insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0);
+ case IMM1_4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4, 0, operand + 1);
break;
- case IMM_4BY2:
- insert (output + low_byte, BFD_RELOC_SH_IMM4BY2, 0);
+ case IMM0_8BY4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8BY4, 0, operand);
break;
- case IMM_4:
- insert (output + low_byte, BFD_RELOC_SH_IMM4, 0);
+ case IMM0_8BY2:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8BY2, 0, operand);
break;
- case IMM_8BY4:
- insert (output + low_byte, BFD_RELOC_SH_IMM8BY4, 0);
+ case IMM0_8:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8, 0, operand);
break;
- case IMM_8BY2:
- insert (output + low_byte, BFD_RELOC_SH_IMM8BY2, 0);
+ case IMM1_8BY4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8BY4, 0, operand + 1);
break;
- case IMM_8:
- insert (output + low_byte, BFD_RELOC_SH_IMM8, 0);
+ case IMM1_8BY2:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8BY2, 0, operand + 1);
+ break;
+ case IMM1_8:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8, 0, operand + 1);
break;
case PCRELIMM_8BY4:
- insert (output, BFD_RELOC_SH_PCRELIMM8BY4, 1);
+ insert (output, BFD_RELOC_SH_PCRELIMM8BY4, 1, operand);
break;
case PCRELIMM_8BY2:
- insert (output, BFD_RELOC_SH_PCRELIMM8BY2, 1);
+ insert (output, BFD_RELOC_SH_PCRELIMM8BY2, 1, operand);
+ break;
+ case REPEAT:
+ output = insert_loop_bounds (output, operand);
+ nbuf[index] = opcode->nibbles[3];
+ operand += 2;
break;
default:
printf (_("failed for %d\n"), i);
break;
case PSH:
- if (immediate.X_op != O_constant)
+ if (operand[0].immediate.X_op != O_constant)
as_bad (_("dsp immediate shift value not constant"));
field_b = ((opcode->nibbles[2] << 12)
- | (immediate.X_add_number & 127) << 4
+ | (operand[0].immediate.X_add_number & 127) << 4
| reg_n);
break;
case PPI3:
if (opcode->arg[0] == A_BDISP12
|| opcode->arg[0] == A_BDISP8)
{
- parse_exp (op_end + 1);
- build_relax (opcode);
+ parse_exp (op_end + 1, &operand[0]);
+ build_relax (opcode, &operand[0]);
}
else
{
{
if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
- || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY
+ || fix->fx_r_type == BFD_RELOC_SH_LOOP_START
+ || fix->fx_r_type == BFD_RELOC_SH_LOOP_END)
return 1;
if (! sh_relax)
/* Nothing to do here. */
break;
+ case BFD_RELOC_SH_LOOP_START:
+ case BFD_RELOC_SH_LOOP_END:
+
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_VTABLE_ENTRY:
fixP->fx_done = 0;
else if (r_type == BFD_RELOC_VTABLE_INHERIT
|| r_type == BFD_RELOC_VTABLE_ENTRY)
rel->addend = fixp->fx_offset;
+ else if (r_type == BFD_RELOC_SH_LOOP_START
+ || r_type == BFD_RELOC_SH_LOOP_END)
+ rel->addend = fixp->fx_offset;
+ else if (r_type == BFD_RELOC_SH_LABEL && fixp->fx_pcrel)
+ {
+ rel->addend = 0;
+ rel->address = rel->addend = fixp->fx_offset;
+ }
else if (fixp->fx_pcrel)
rel->addend = fixp->fx_addnumber;
else
+Wed Apr 5 22:08:41 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * sh.h (R_SH_LOOP_START, R_SH_LOOP_END): Define.
+
2000-03-15 Kazu Hirata <kazu@hxi.com>
* internal.h: Fix a typo in the comment for R_MOVL2.
#define R_SH_LABEL 32 /* label */
/* NB: R_SH_SWITCH8 is 33 */
+
+#define R_SH_LOOP_START 34
+#define R_SH_LOOP_END 35
+Wed Apr 5 22:08:59 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * sh.h (R_SH_LOOP_START, R_SH_LOOP_END): New RELOC_NUMBERs.
+
2000-03-27 Denis Chertykov <denisc@overta.ru>
* avr.h: New file. AVR ELF support for BFD.
/* SH ELF support for BFD.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2000 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
RELOC_NUMBER (R_SH_SWITCH8, 33)
RELOC_NUMBER (R_SH_GNU_VTINHERIT, 34)
RELOC_NUMBER (R_SH_GNU_VTENTRY, 35)
+ RELOC_NUMBER (R_SH_LOOP_START, 36)
+ RELOC_NUMBER (R_SH_LOOP_END, 37)
EMPTY_RELOC (R_SH_max)
END_RELOC_NUMBERS
+Wed Apr 5 22:05:40 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * sh-opc.h (sh_nibble_type): Remove DISP_8 and DISP_4.
+ Split IMM_[48]{,BY[24]} into IMM[01]_[48]{,BY[24]}. Add REPEAT.
+ (sh_arg_type): Add A_PC.
+ (sh_table): Update entries using immediates. Add repeat.
+ * sh-dis.c (print_insn_shx): Remove DISP_8 and DISP_4.
+ Split IMM_[48]{,BY[24]} into IMM[01]_[48]{,BY[24]}. Add REPEAT.
+
2000-04-04 Alan Modra <alan@linuxcare.com.au>
* po/opcodes.pot: Regenerate.
/* Disassemble SH instructions.
- Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94, 95, 96, 97, 1998, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
imm |= ~0xfff;
imm = imm * 2 + 4;
goto ok;
- case IMM_4:
+ case IMM0_4:
+ case IMM1_4:
imm = nibs[3];
goto ok;
- case IMM_4BY2:
+ case IMM0_4BY2:
+ case IMM1_4BY2:
imm = nibs[3] <<1;
goto ok;
- case IMM_4BY4:
+ case IMM0_4BY4:
+ case IMM1_4BY4:
imm = nibs[3] <<2;
goto ok;
- case IMM_8:
+ case IMM0_8:
+ case IMM1_8:
imm = (nibs[2] << 4) | nibs[3];
goto ok;
case PCRELIMM_8BY2:
imm = ((nibs[2] << 4) | nibs[3]) <<2;
relmask = ~ (bfd_vma) 3;
goto ok;
- case IMM_8BY2:
+ case IMM0_8BY2:
+ case IMM1_8BY2:
imm = ((nibs[2] << 4) | nibs[3]) <<1;
goto ok;
- case IMM_8BY4:
+ case IMM0_8BY4:
+ case IMM1_8BY4:
imm = ((nibs[2] << 4) | nibs[3]) <<2;
goto ok;
- case DISP_8:
- imm = (nibs[2] << 4) | (nibs[3]);
- goto ok;
- case DISP_4:
- imm = nibs[3];
- goto ok;
case REG_N:
rn = nibs[n];
break;
rn |= (rn & 2) << 1;
break;
case PPI:
+ case REPEAT:
goto fail;
default:
abort();
/* Definitions for SH opcodes.
- Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94, 95, 96, 97, 1999, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
REG_B,
BRANCH_12,
BRANCH_8,
- DISP_8,
- DISP_4,
- IMM_4,
- IMM_4BY2,
- IMM_4BY4,
+ IMM0_4,
+ IMM0_4BY2,
+ IMM0_4BY4,
+ IMM1_4,
+ IMM1_4BY2,
+ IMM1_4BY4,
PCRELIMM_8BY2,
PCRELIMM_8BY4,
- IMM_8,
- IMM_8BY2,
- IMM_8BY4,
+ IMM0_8,
+ IMM0_8BY2,
+ IMM0_8BY4,
+ IMM1_8,
+ IMM1_8BY2,
+ IMM1_8BY4,
PPI,
NOPX,
NOPY,
PMUL,
PPI3,
PDC,
- PPIC
+ PPIC,
+ REPEAT
} sh_nibble_type;
typedef enum {
A_DEC_M,
A_DEC_N,
A_DISP_GBR,
+ A_PC,
A_DISP_PC,
A_DISP_REG_M,
A_DISP_REG_N,
sh_opcode_info sh_table[] = {
-/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM_8}, arch_sh1_up},
+/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh1_up},
/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh1_up},
/* 0011nnnnmmmm1111 addv <REG_M>,<REG_N>*/{"addv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_F}, arch_sh1_up},
-/* 11001001i8*1.... and #<imm>,R0 */{"and",{A_IMM,A_R0},{HEX_C,HEX_9,IMM_8}, arch_sh1_up},
+/* 11001001i8*1.... and #<imm>,R0 */{"and",{A_IMM,A_R0},{HEX_C,HEX_9,IMM0_8}, arch_sh1_up},
/* 0010nnnnmmmm1001 and <REG_M>,<REG_N> */{"and",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_9}, arch_sh1_up},
-/* 11001101i8*1.... and.b #<imm>,@(R0,GBR)*/{"and.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_D,IMM_8}, arch_sh1_up},
+/* 11001101i8*1.... and.b #<imm>,@(R0,GBR)*/{"and.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_D,IMM0_8}, arch_sh1_up},
/* 1010i12......... bra <bdisp12> */{"bra",{A_BDISP12},{HEX_A,BRANCH_12}, arch_sh1_up},
/* 0000000000001000 clrt */{"clrt",{0},{HEX_0,HEX_0,HEX_0,HEX_8}, arch_sh1_up},
-/* 10001000i8*1.... cmp/eq #<imm>,R0 */{"cmp/eq",{A_IMM,A_R0},{HEX_8,HEX_8,IMM_8}, arch_sh1_up},
+/* 10001000i8*1.... cmp/eq #<imm>,R0 */{"cmp/eq",{A_IMM,A_R0},{HEX_8,HEX_8,IMM0_8}, arch_sh1_up},
/* 0011nnnnmmmm0000 cmp/eq <REG_M>,<REG_N>*/{"cmp/eq",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_0}, arch_sh1_up},
/* 0100nnnnmmmm1111 mac.w @<REG_M>+,@<REG_N>+*/{"mac.w",{A_INC_M,A_INC_N},{HEX_4,REG_N,REG_M,HEX_F}, arch_sh1_up},
-/* 1110nnnni8*1.... mov #<imm>,<REG_N> */{"mov",{A_IMM,A_REG_N},{HEX_E,REG_N,IMM_8}, arch_sh1_up},
+/* 1110nnnni8*1.... mov #<imm>,<REG_N> */{"mov",{A_IMM,A_REG_N},{HEX_E,REG_N,IMM0_8}, arch_sh1_up},
/* 0110nnnnmmmm0011 mov <REG_M>,<REG_N> */{"mov",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_3}, arch_sh1_up},
/* 0010nnnnmmmm0000 mov.b <REG_M>,@<REG_N>*/{"mov.b",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_0}, arch_sh1_up},
-/* 10000100mmmmi4*1 mov.b @(<disp>,<REG_M>),R0*/{"mov.b",{A_DISP_REG_M,A_R0},{HEX_8,HEX_4,REG_M,IMM_4}, arch_sh1_up},
+/* 10000100mmmmi4*1 mov.b @(<disp>,<REG_M>),R0*/{"mov.b",{A_DISP_REG_M,A_R0},{HEX_8,HEX_4,REG_M,IMM0_4}, arch_sh1_up},
-/* 11000100i8*1.... mov.b @(<disp>,GBR),R0*/{"mov.b",{A_DISP_GBR,A_R0},{HEX_C,HEX_4,IMM_8}, arch_sh1_up},
+/* 11000100i8*1.... mov.b @(<disp>,GBR),R0*/{"mov.b",{A_DISP_GBR,A_R0},{HEX_C,HEX_4,IMM0_8}, arch_sh1_up},
/* 0000nnnnmmmm1100 mov.b @(R0,<REG_M>),<REG_N>*/{"mov.b",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_C}, arch_sh1_up},
/* 0110nnnnmmmm0000 mov.b @<REG_M>,<REG_N>*/{"mov.b",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_0}, arch_sh1_up},
-/* 10000000mmmmi4*1 mov.b R0,@(<disp>,<REG_M>)*/{"mov.b",{A_R0,A_DISP_REG_M},{HEX_8,HEX_0,REG_M,IMM_4}, arch_sh1_up},
+/* 10000000mmmmi4*1 mov.b R0,@(<disp>,<REG_M>)*/{"mov.b",{A_R0,A_DISP_REG_M},{HEX_8,HEX_0,REG_M,IMM1_4}, arch_sh1_up},
-/* 11000000i8*1.... mov.b R0,@(<disp>,GBR)*/{"mov.b",{A_R0,A_DISP_GBR},{HEX_C,HEX_0,IMM_8}, arch_sh1_up},
+/* 11000000i8*1.... mov.b R0,@(<disp>,GBR)*/{"mov.b",{A_R0,A_DISP_GBR},{HEX_C,HEX_0,IMM1_8}, arch_sh1_up},
-/* 0001nnnnmmmmi4*4 mov.l <REG_M>,@(<disp>,<REG_N>)*/{"mov.l",{ A_REG_M,A_DISP_REG_N},{HEX_1,REG_N,REG_M,IMM_4BY4}, arch_sh1_up},
+/* 0001nnnnmmmmi4*4 mov.l <REG_M>,@(<disp>,<REG_N>)*/{"mov.l",{ A_REG_M,A_DISP_REG_N},{HEX_1,REG_N,REG_M,IMM1_4BY4}, arch_sh1_up},
/* 0000nnnnmmmm0110 mov.l <REG_M>,@(R0,<REG_N>)*/{"mov.l",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_6}, arch_sh1_up},
/* 0010nnnnmmmm0010 mov.l <REG_M>,@<REG_N>*/{"mov.l",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_2}, arch_sh1_up},
-/* 0101nnnnmmmmi4*4 mov.l @(<disp>,<REG_M>),<REG_N>*/{"mov.l",{A_DISP_REG_M,A_REG_N},{HEX_5,REG_N,REG_M,IMM_4BY4}, arch_sh1_up},
+/* 0101nnnnmmmmi4*4 mov.l @(<disp>,<REG_M>),<REG_N>*/{"mov.l",{A_DISP_REG_M,A_REG_N},{HEX_5,REG_N,REG_M,IMM0_4BY4}, arch_sh1_up},
-/* 11000110i8*4.... mov.l @(<disp>,GBR),R0*/{"mov.l",{A_DISP_GBR,A_R0},{HEX_C,HEX_6,IMM_8BY4}, arch_sh1_up},
+/* 11000110i8*4.... mov.l @(<disp>,GBR),R0*/{"mov.l",{A_DISP_GBR,A_R0},{HEX_C,HEX_6,IMM0_8BY4}, arch_sh1_up},
/* 1101nnnni8p4.... mov.l @(<disp>,PC),<REG_N>*/{"mov.l",{A_DISP_PC,A_REG_N},{HEX_D,REG_N,PCRELIMM_8BY4}, arch_sh1_up},
/* 0110nnnnmmmm0010 mov.l @<REG_M>,<REG_N>*/{"mov.l",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_2}, arch_sh1_up},
-/* 11000010i8*4.... mov.l R0,@(<disp>,GBR)*/{"mov.l",{A_R0,A_DISP_GBR},{HEX_C,HEX_2,IMM_8BY4}, arch_sh1_up},
+/* 11000010i8*4.... mov.l R0,@(<disp>,GBR)*/{"mov.l",{A_R0,A_DISP_GBR},{HEX_C,HEX_2,IMM1_8BY4}, arch_sh1_up},
/* 0000nnnnmmmm0101 mov.w <REG_M>,@(R0,<REG_N>)*/{"mov.w",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_5}, arch_sh1_up},
/* 0010nnnnmmmm0001 mov.w <REG_M>,@<REG_N>*/{"mov.w",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_1}, arch_sh1_up},
-/* 10000101mmmmi4*2 mov.w @(<disp>,<REG_M>),R0*/{"mov.w",{A_DISP_REG_M,A_R0},{HEX_8,HEX_5,REG_M,IMM_4BY2}, arch_sh1_up},
+/* 10000101mmmmi4*2 mov.w @(<disp>,<REG_M>),R0*/{"mov.w",{A_DISP_REG_M,A_R0},{HEX_8,HEX_5,REG_M,IMM0_4BY2}, arch_sh1_up},
-/* 11000101i8*2.... mov.w @(<disp>,GBR),R0*/{"mov.w",{A_DISP_GBR,A_R0},{HEX_C,HEX_5,IMM_8BY2}, arch_sh1_up},
+/* 11000101i8*2.... mov.w @(<disp>,GBR),R0*/{"mov.w",{A_DISP_GBR,A_R0},{HEX_C,HEX_5,IMM0_8BY2}, arch_sh1_up},
/* 1001nnnni8p2.... mov.w @(<disp>,PC),<REG_N>*/{"mov.w",{A_DISP_PC,A_REG_N},{HEX_9,REG_N,PCRELIMM_8BY2}, arch_sh1_up},
/* 0110nnnnmmmm0001 mov.w @<REG_M>,<REG_N>*/{"mov.w",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_1}, arch_sh1_up},
-/* 10000001mmmmi4*2 mov.w R0,@(<disp>,<REG_M>)*/{"mov.w",{A_R0,A_DISP_REG_M},{HEX_8,HEX_1,REG_M,IMM_4BY2}, arch_sh1_up},
+/* 10000001mmmmi4*2 mov.w R0,@(<disp>,<REG_M>)*/{"mov.w",{A_R0,A_DISP_REG_M},{HEX_8,HEX_1,REG_M,IMM1_4BY2}, arch_sh1_up},
-/* 11000001i8*2.... mov.w R0,@(<disp>,GBR)*/{"mov.w",{A_R0,A_DISP_GBR},{HEX_C,HEX_1,IMM_8BY2}, arch_sh1_up},
+/* 11000001i8*2.... mov.w R0,@(<disp>,GBR)*/{"mov.w",{A_R0,A_DISP_GBR},{HEX_C,HEX_1,IMM0_8BY2}, arch_sh1_up},
/* 11000111i8p4.... mova @(<disp>,PC),R0*/{"mova",{A_DISP_PC,A_R0},{HEX_C,HEX_7,PCRELIMM_8BY4}, arch_sh1_up},
/* 0000nnnn11000011 movca.l R0,@<REG_N> */{"movca.l",{A_R0,A_IND_N},{HEX_0,REG_N,HEX_C,HEX_3}, arch_sh4_up},
/* 0000nnnn10110011 ocbwb @<REG_N> */{"ocbwb",{A_IND_N},{HEX_0,REG_N,HEX_B,HEX_3}, arch_sh4_up},
-/* 11001011i8*1.... or #<imm>,R0 */{"or",{A_IMM,A_R0},{HEX_C,HEX_B,IMM_8}, arch_sh1_up},
+/* 11001011i8*1.... or #<imm>,R0 */{"or",{A_IMM,A_R0},{HEX_C,HEX_B,IMM0_8}, arch_sh1_up},
/* 0010nnnnmmmm1011 or <REG_M>,<REG_N> */{"or",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_B}, arch_sh1_up},
-/* 11001111i8*1.... or.b #<imm>,@(R0,GBR)*/{"or.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_F,IMM_8}, arch_sh1_up},
+/* 11001111i8*1.... or.b #<imm>,@(R0,GBR)*/{"or.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_F,IMM0_8}, arch_sh1_up},
/* 0000nnnn10000011 pref @<REG_N> */{"pref",{A_IND_N},{HEX_0,REG_N,HEX_8,HEX_3}, arch_sh4_up},
/* 0100nnnn00010100 setrc <REG_N> */{"setrc",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_4}, arch_sh_dsp_up},
-/* 10000010i8*1.... setrc #<imm> */{"setrc",{A_IMM},{HEX_8,HEX_2,IMM_8}, arch_sh_dsp_up},
+/* 10000010i8*1.... setrc #<imm> */{"setrc",{A_IMM},{HEX_8,HEX_2,IMM0_8}, arch_sh_dsp_up},
+
+/* repeat start end <REG_N> */{"repeat",{A_DISP_PC,A_DISP_PC,A_REG_N},{REPEAT,REG_N,HEX_1,HEX_4}, arch_sh_dsp_up},
+
+/* repeat start end #<imm> */{"repeat",{A_DISP_PC,A_DISP_PC,A_IMM},{REPEAT,HEX_2,IMM0_8,HEX_8}, arch_sh_dsp_up},
/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh3_up},
/* 0100nnnn00011011 tas.b @<REG_N> */{"tas.b",{A_IND_N},{HEX_4,REG_N,HEX_1,HEX_B}, arch_sh1_up},
-/* 11000011i8*1.... trapa #<imm> */{"trapa",{A_IMM},{HEX_C,HEX_3,IMM_8}, arch_sh1_up},
+/* 11000011i8*1.... trapa #<imm> */{"trapa",{A_IMM},{HEX_C,HEX_3,IMM0_8}, arch_sh1_up},
-/* 11001000i8*1.... tst #<imm>,R0 */{"tst",{A_IMM,A_R0},{HEX_C,HEX_8,IMM_8}, arch_sh1_up},
+/* 11001000i8*1.... tst #<imm>,R0 */{"tst",{A_IMM,A_R0},{HEX_C,HEX_8,IMM0_8}, arch_sh1_up},
/* 0010nnnnmmmm1000 tst <REG_M>,<REG_N> */{"tst",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_8}, arch_sh1_up},
-/* 11001100i8*1.... tst.b #<imm>,@(R0,GBR)*/{"tst.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_C,IMM_8}, arch_sh1_up},
+/* 11001100i8*1.... tst.b #<imm>,@(R0,GBR)*/{"tst.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_C,IMM0_8}, arch_sh1_up},
-/* 11001010i8*1.... xor #<imm>,R0 */{"xor",{A_IMM,A_R0},{HEX_C,HEX_A,IMM_8}, arch_sh1_up},
+/* 11001010i8*1.... xor #<imm>,R0 */{"xor",{A_IMM,A_R0},{HEX_C,HEX_A,IMM0_8}, arch_sh1_up},
/* 0010nnnnmmmm1010 xor <REG_M>,<REG_N> */{"xor",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_A}, arch_sh1_up},
-/* 11001110i8*1.... xor.b #<imm>,@(R0,GBR)*/{"xor.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_E,IMM_8}, arch_sh1_up},
+/* 11001110i8*1.... xor.b #<imm>,@(R0,GBR)*/{"xor.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_E,IMM0_8}, arch_sh1_up},
/* 0010nnnnmmmm1101 xtrct <REG_M>,<REG_N>*/{"xtrct",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_D}, arch_sh1_up},