sh-dsp REPEAT support:
authorJoern Rennecke <joern.rennecke@embecosm.com>
Wed, 5 Apr 2000 21:23:05 +0000 (21:23 +0000)
committerJoern Rennecke <joern.rennecke@embecosm.com>
Wed, 5 Apr 2000 21:23:05 +0000 (21:23 +0000)
opcodes:

        * 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.

gas:

        * 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.

include/coff:

        * sh.h (R_SH_LOOP_START, R_SH_LOOP_END): Define.

include/elf:

        * sh.h (R_SH_LOOP_START, R_SH_LOOP_END): New RELOC_NUMBERs.

bfd:

        * 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.

14 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf32-sh.c
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/config/tc-sh.c
include/coff/ChangeLog
include/coff/sh.h
include/elf/ChangeLog
include/elf/sh.h
opcodes/ChangeLog
opcodes/sh-dis.c
opcodes/sh-opc.h

index 2a8ec71..c7714f1 100644 (file)
@@ -1,3 +1,17 @@
+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.
index fa1c5b9..abbf203 100644 (file)
@@ -2086,6 +2086,8 @@ not stored in the instruction. */
   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. */
index ad60e07..6913fa4 100644 (file)
@@ -66,7 +66,7 @@ static reloc_howto_type sh_elf_howto_table[] =
         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 */
@@ -97,7 +97,7 @@ static reloc_howto_type sh_elf_howto_table[] =
         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 */
@@ -112,7 +112,7 @@ static reloc_howto_type sh_elf_howto_table[] =
         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 */
@@ -142,7 +142,7 @@ static reloc_howto_type sh_elf_howto_table[] =
         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 */
@@ -157,7 +157,7 @@ static reloc_howto_type sh_elf_howto_table[] =
         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 */
@@ -174,7 +174,7 @@ static reloc_howto_type sh_elf_howto_table[] =
         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 */
@@ -191,7 +191,7 @@ static reloc_howto_type sh_elf_howto_table[] =
         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 */
@@ -208,7 +208,7 @@ static reloc_howto_type sh_elf_howto_table[] =
         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 */
@@ -420,9 +420,147 @@ static reloc_howto_type sh_elf_howto_table[] =
          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
@@ -453,9 +591,7 @@ sh_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
 
   /* 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
@@ -549,6 +685,8 @@ static const struct elf_reloc_map sh_reloc_map[] =
   { 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
@@ -1734,11 +1872,13 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
       /* 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;
@@ -1747,7 +1887,9 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
       /* 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;
@@ -1803,15 +1945,32 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        {
        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)
index f9baf5a..774cfc3 100644 (file)
@@ -809,6 +809,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "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",
index a3318e6..3b1a00f 100644 (file)
@@ -2293,6 +2293,10 @@ ENUMX
   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.
 
index 9231d2f..7baad0d 100644 (file)
@@ -1,3 +1,21 @@
+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.
index 4003f5b..d468215 100644 (file)
@@ -244,14 +244,12 @@ static int reg_x, reg_y;
 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) == '_')
@@ -466,7 +464,9 @@ parse_reg (src, mode, reg)
     }
   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'
@@ -619,16 +619,17 @@ static symbolS *dot()
 
 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;
@@ -710,7 +711,7 @@ parse_at (src, op)
       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 */
@@ -725,12 +726,12 @@ parse_at (src, op)
                {
                  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;
                }
@@ -795,7 +796,7 @@ get_operand (ptr, op)
   if (src[0] == '#')
     {
       src++;
-      *ptr = parse_exp (src);
+      *ptr = parse_exp (src, op);
       op->type = A_IMM;
       return;
     }
@@ -815,7 +816,7 @@ get_operand (ptr, op)
   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;
     }
@@ -1177,22 +1178,24 @@ check (operand, low, high)
 
 
 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;
@@ -1204,8 +1207,8 @@ build_relax (opcode)
                    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]);
     }
@@ -1215,14 +1218,63 @@ build_relax (opcode)
                    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
@@ -1268,32 +1320,52 @@ build_Mytes (opcode, operand)
             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);
@@ -1457,10 +1529,10 @@ assemble_ppi (op_end, opcode)
          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:
@@ -1604,8 +1676,8 @@ md_assemble (str)
   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
     {
@@ -2407,7 +2479,9 @@ sh_force_relocation (fix)
 {
 
   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)
@@ -2643,6 +2717,9 @@ md_apply_fix (fixP, val)
       /* 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;
@@ -2993,6 +3070,14 @@ tc_gen_reloc (section, fixp)
   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
index 76b52c0..9630f40 100644 (file)
@@ -1,3 +1,7 @@
+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.
index f7271f2..2ea0d26 100644 (file)
@@ -305,3 +305,6 @@ struct external_reloc {
 #define R_SH_LABEL     32              /* label */
 
 /* NB: R_SH_SWITCH8 is 33 */
+
+#define R_SH_LOOP_START        34
+#define R_SH_LOOP_END  35
index e1f68c3..85ff853 100644 (file)
@@ -1,3 +1,7 @@
+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.
index faee509..2b132c1 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
 
@@ -76,6 +76,8 @@ START_RELOC_NUMBERS (elf_sh_reloc_type)
   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
 
index 401e1cf..aaf6a68 100644 (file)
@@ -1,3 +1,12 @@
+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.
index bef6518..3fc99dd 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -402,16 +402,20 @@ print_insn_shx (memaddr, info)
                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:
@@ -422,18 +426,14 @@ print_insn_shx (memaddr, info)
              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;
@@ -456,6 +456,7 @@ print_insn_shx (memaddr, info)
              rn |= (rn & 2) << 1;
              break;
            case PPI:
+           case REPEAT:
              goto fail;
            default:
              abort();
index 38bfbcd..f10ec43 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -39,16 +39,20 @@ typedef enum {
         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,
@@ -58,7 +62,8 @@ typedef enum {
        PMUL,
        PPI3,
        PDC,
-       PPIC
+       PPIC,
+       REPEAT
 } sh_nibble_type;
 
 typedef enum {
@@ -68,6 +73,7 @@ typedef enum {
        A_DEC_M,
        A_DEC_N,
        A_DISP_GBR,
+       A_PC,
        A_DISP_PC,
        A_DISP_REG_M,
        A_DISP_REG_N,
@@ -164,7 +170,7 @@ typedef struct {
 
 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},
 
@@ -172,11 +178,11 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -200,7 +206,7 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -328,7 +334,7 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -338,9 +344,9 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -348,11 +354,11 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -360,9 +366,9 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -372,7 +378,7 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -380,9 +386,9 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -392,9 +398,9 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
@@ -424,11 +430,11 @@ sh_opcode_info sh_table[] = {
 /* 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},
 
@@ -449,7 +455,11 @@ sh_opcode_info sh_table[] = {
 
 /* 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},
 
@@ -577,19 +587,19 @@ sh_opcode_info sh_table[] = {
 
 /* 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},