This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
Re: [Fwd: bfd Patch for -relax on sh-hms]
- To: Joern Rennecke <amylaar at cygnus dot co dot uk>
- Subject: Re: [Fwd: bfd Patch for -relax on sh-hms]
- From: Dave Brolley <brolley at redhat dot com>
- Date: Thu, 03 Feb 2000 14:31:28 -0500
- CC: amylaar at redhat dot com, rth at redhat dot com, ian at zembu dot com, binutils at sourceware dot cygnus dot com
- Organization: Red Hat
- References: <200002031709.RAA30989@phal.cygnus.co.uk>
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. */