This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [Fwd: bfd Patch for -relax on sh-hms]


OK,

Below are Joern's comments and attached is an updated patch which
incorporates those comments. Once again, someone please commit
this if it's OK and let me know.

Thanks,
Dave

Joern Rennecke wrote:
> 
> >         * (sh_insn_sets_reg, sh_insn_sets_freg): New prototypes.
> 
> sh_insn_uses_or_sets_reg and sh_insn_uses_or_sets_freg should also get
> prototypes.
> 
> >         * (sh_insn_uses_regs, sh_insn_uses_freg): Use new macros.
> 
> It's called sh_insn_uses_reg.
> 
> > !   if ((f1 & (SETSSP | USESSP)) &&
> > !       (f2 & (SETSSP | USESSP)))
> >       return true;
> 
> This returns a conflict if there are just two uses - that is wrong.
> Moreover, the formatting is wrong.
> That should be something like:
> 
>   if (((f1 | f2) & SETSSP)
>       && (f1 & (SETSSP | USESSP))
>       && (f2 & (SETSSP | USESSP)))
Wed Jan  5 13:18:04 PST 2000  Toshiyasu Morita (toshi.morita@sega.com)

        * coff-sh.c (USES1_REG, USES2_REG, SETS1_REG, SETS2_REG,
        USESF1_REG, USESF2_REG, SETSF1_REG, SETSF2_REG): New macros.
        * (sh_insn_sets_reg, sh_insn_sets_freg): New prototypes.
        * (sh_insn_sets_reg, sh_insn_uses_or_sets_reg, sh_insns_sets_freg,
        sh_insns_uses_or_sets_freg): New functions.
        * (sh_insn_uses_reg, sh_insn_uses_freg): Use new macros.
        * (sh_insns_conflict): Use new functions and new macros to 
        detect conflicts when two instructions both set same integer registers,
        both set same fp register, and both set special register.

Index: coff-sh.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/coff-sh.c,v
retrieving revision 1.6
diff -c -r1.6 coff-sh.c
*** coff-sh.c	1999/09/07 04:28:27	1.6
--- coff-sh.c	2000/02/03 19:27:04
***************
*** 1384,1393 ****
--- 1384,1395 ----
  /* This instruction uses the value in the register in the field at
     mask 0x0f00 of the instruction.  */
  #define USES1 (0x10)
+ #define USES1_REG(x) ((x & 0x0f00) >> 8)
  
  /* This instruction uses the value in the register in the field at
     mask 0x00f0 of the instruction.  */
  #define USES2 (0x20)
+ #define USES2_REG(x) ((x & 0x00f0) >> 4)
  
  /* This instruction uses the value in register 0.  */
  #define USESR0 (0x40)
***************
*** 1395,1404 ****
--- 1397,1408 ----
  /* This instruction sets the value in the register in the field at
     mask 0x0f00 of the instruction.  */
  #define SETS1 (0x80)
+ #define SETS1_REG(x) ((x & 0x0f00) >> 8)
  
  /* This instruction sets the value in the register in the field at
     mask 0x00f0 of the instruction.  */
  #define SETS2 (0x100)
+ #define SETS2_REG(x) ((x & 0x00f0) >> 4)
  
  /* This instruction sets register 0.  */
  #define SETSR0 (0x200)
***************
*** 1412,1421 ****
--- 1416,1427 ----
  /* This instruction uses the floating point register in the field at
     mask 0x0f00 of the instruction.  */
  #define USESF1 (0x1000)
+ #define USESF1_REG(x) ((x & 0x0f00) >> 8)
  
  /* This instruction uses the floating point register in the field at
     mask 0x00f0 of the instruction.  */
  #define USESF2 (0x2000)
+ #define USESF2_REG(x) ((x & 0x00f0) >> 4)
  
  /* This instruction uses floating point register 0.  */
  #define USESF0 (0x4000)
***************
*** 1423,1433 ****
--- 1429,1448 ----
  /* This instruction sets the floating point register in the field at
     mask 0x0f00 of the instruction.  */
  #define SETSF1 (0x8000)
+ #define SETSF1_REG(x) ((x & 0x0f00) >> 8)
  
  static boolean sh_insn_uses_reg
    PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
+ static boolean sh_insn_sets_reg
+   PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
+ static boolean sh_insn_uses_or_sets_reg
+   PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
  static boolean sh_insn_uses_freg
    PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
+ static boolean sh_insn_sets_freg
+   PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
+ static boolean sh_insn_uses_or_sets_freg
+   PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
  static boolean sh_insns_conflict
    PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
  	   const struct sh_opcode *));
***************
*** 1860,1865 ****
--- 1875,1894 ----
    return NULL;  
  }
  
+ /* See whether an instruction uses or sets a general purpose register */
+ 
+ static boolean
+ sh_insn_uses_or_sets_reg (insn, op, reg)
+      unsigned int insn;
+      const struct sh_opcode *op;
+      unsigned int reg;
+ {
+   if (sh_insn_uses_reg (insn, op, reg))
+     return true;
+ 
+   return sh_insn_sets_reg (insn, op, reg);
+ }
+ 
  /* See whether an instruction uses a general purpose register.  */
  
  static boolean
***************
*** 1873,1882 ****
    f = op->flags;
  
    if ((f & USES1) != 0
!       && ((insn & 0x0f00) >> 8) == reg)
      return true;
    if ((f & USES2) != 0
!       && ((insn & 0x00f0) >> 4) == reg)
      return true;
    if ((f & USESR0) != 0
        && reg == 0)
--- 1902,1911 ----
    f = op->flags;
  
    if ((f & USES1) != 0
!       && USES1_REG (insn) == reg)
      return true;
    if ((f & USES2) != 0
!       && USES2_REG (insn) == reg)
      return true;
    if ((f & USESR0) != 0
        && reg == 0)
***************
*** 1884,1889 ****
--- 1913,1956 ----
  
    return false;
  }
+ /* See whether an instruction sets a general purpose register.  */
+ 
+ static boolean
+ sh_insn_sets_reg (insn, op, reg)
+      unsigned int insn;
+      const struct sh_opcode *op;
+      unsigned int reg;
+ {
+   unsigned int f;
+ 
+   f = op->flags;
+ 
+   if ((f & SETS1) != 0
+       && SETS1_REG (insn) == reg)
+     return true;
+   if ((f & SETS2) != 0
+       && SETS2_REG (insn) == reg)
+     return true;
+   if ((f & SETSR0) != 0
+       && reg == 0)
+     return true;
+ 
+   return false;
+ }
+ 
+ /* See whether an instruction uses or sets a floating point register */
+ 
+ static boolean
+ sh_insn_uses_or_sets_freg (insn, op, reg)
+      unsigned int insn;
+      const struct sh_opcode *op;
+      unsigned int reg;
+ {
+   if (sh_insn_uses_freg (insn, op, reg))
+     return true;
+ 
+   return sh_insn_sets_freg (insn, op, reg);
+ }
  
  /* See whether an instruction uses a floating point register.  */
  
***************
*** 1907,1916 ****
       bit of the register number.  */
       
    if ((f & USESF1) != 0
!       && ((insn & 0x0e00) >> 8) == (freg & 0xe))
      return true;
    if ((f & USESF2) != 0
!       && ((insn & 0x00e0) >> 4) == (freg & 0xe))
      return true;
    if ((f & USESF0) != 0
        && freg == 0)
--- 1974,1983 ----
       bit of the register number.  */
       
    if ((f & USESF1) != 0
!       && (USESF1_REG (insn) & 0xe) == (freg & 0xe))
      return true;
    if ((f & USESF2) != 0
!       && (USESF2_REG (insn) & 0xe) == (freg & 0xe))
      return true;
    if ((f & USESF0) != 0
        && freg == 0)
***************
*** 1919,1924 ****
--- 1986,2019 ----
    return false;
  }
  
+ /* See whether an instruction sets a floating point register.  */
+ 
+ static boolean
+ sh_insn_sets_freg (insn, op, freg)
+      unsigned int insn;
+      const struct sh_opcode *op;
+      unsigned int freg;
+ {
+   unsigned int f;
+ 
+   f = op->flags;
+ 
+   /* We can't tell if this is a double-precision insn, so just play safe
+      and assume that it might be.  So not only have we test FREG against
+      itself, but also even FREG against FREG+1 - if the using insn uses
+      just the low part of a double precision value - but also an odd
+      FREG against FREG-1 -  if the setting insn sets just the low part
+      of a double precision value.
+      So what this all boils down to is that we have to ignore the lowest
+      bit of the register number.  */
+      
+   if ((f & SETSF1) != 0
+       && (SETSF1_REG (insn) & 0xe) == (freg & 0xe))
+     return true;
+ 
+   return false;
+ }
+ 
  /* See whether instructions I1 and I2 conflict, assuming I1 comes
     before I2.  OP1 and OP2 are the corresponding sh_opcode structures.
     This should return true if there is a conflict, or false if the
***************
*** 1946,1980 ****
        || (f2 & (BRANCH | DELAY)) != 0)
      return true;
  
!   if ((f1 & SETSSP) != 0 && (f2 & USESSP) != 0)
!     return true;
!   if ((f2 & SETSSP) != 0 && (f1 & USESSP) != 0)
      return true;
  
    if ((f1 & SETS1) != 0
!       && sh_insn_uses_reg (i2, op2, (i1 & 0x0f00) >> 8))
      return true;
    if ((f1 & SETS2) != 0
!       && sh_insn_uses_reg (i2, op2, (i1 & 0x00f0) >> 4))
      return true;
    if ((f1 & SETSR0) != 0
!       && sh_insn_uses_reg (i2, op2, 0))
      return true;
    if ((f1 & SETSF1) != 0
!       && sh_insn_uses_freg (i2, op2, (i1 & 0x0f00) >> 8))
      return true;
  
    if ((f2 & SETS1) != 0
!       && sh_insn_uses_reg (i1, op1, (i2 & 0x0f00) >> 8))
      return true;
    if ((f2 & SETS2) != 0
!       && sh_insn_uses_reg (i1, op1, (i2 & 0x00f0) >> 4))
      return true;
    if ((f2 & SETSR0) != 0
!       && sh_insn_uses_reg (i1, op1, 0))
      return true;
    if ((f2 & SETSF1) != 0
!       && sh_insn_uses_freg (i1, op1, (i2 & 0x0f00) >> 8))
      return true;
  
    /* The instructions do not conflict.  */
--- 2041,2075 ----
        || (f2 & (BRANCH | DELAY)) != 0)
      return true;
  
!   if (((f1 | f2) & SETSSP)
!       && (f1 & (SETSSP | USESSP))
!       && (f2 & (SETSSP | USESSP)))
      return true;
  
    if ((f1 & SETS1) != 0
!       && sh_insn_uses_or_sets_reg (i2, op2, SETS1_REG (i1)))
      return true;
    if ((f1 & SETS2) != 0
!       && sh_insn_uses_or_sets_reg (i2, op2, SETS2_REG (i1)))
      return true;
    if ((f1 & SETSR0) != 0
!       && sh_insn_uses_or_sets_reg (i2, op2, 0))
      return true;
    if ((f1 & SETSF1) != 0
!       && sh_insn_uses_or_sets_freg (i2, op2, SETSF1_REG (i1)))
      return true;
  
    if ((f2 & SETS1) != 0
!       && sh_insn_uses_or_sets_reg (i1, op1, SETS1_REG (i2)))
      return true;
    if ((f2 & SETS2) != 0
!       && sh_insn_uses_or_sets_reg (i1, op1, SETS2_REG (i2)))
      return true;
    if ((f2 & SETSR0) != 0
!       && sh_insn_uses_or_sets_reg (i1, op1, 0))
      return true;
    if ((f2 & SETSF1) != 0
!       && sh_insn_uses_or_sets_freg (i1, op1, SETSF1_REG (i2)))
      return true;
  
    /* The instructions do not conflict.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]