This is the mail archive of the binutils@sourceware.org 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]
Other format: [Raw text]

Coldfire fmovem fixes


This patch fixes three problems with the Coldfire fmovem(.d) instructions:

  (1) The disassembler doesn't recognise the instructions, even when a
      Coldfire architecture is selected.  The problem is that the masks
      in the opcodes table include the coprocessor ID field, and this
      field is determined by the format string; it isn't hardcoded into
      the opcode pattern itself.

  (2) The entries for "fmovem(d) list,addr" had the immediate form
      before the register form, so that the immediate form would be
      used in disassembly.  This isn't very user friendly, and isn't
      consistent with "fmovem(d) addr,list", so I swapped them.

  (3) Most importantly, the list formats in the fmovem entries used the
      wrong bit order.  They used "L" (fpX in bit X) instead of the
      correct "l" (fpX in bit 7 - X).  This meant that "fmovem" with
      an explicit register list would be assembled incorrectly.

Fixing (1) triggered a failure in the gas testsuite.  The Coldfire
fmovemd instructions come before the m68k fmoveml instructions -- as
they must, because the table is sorted -- and the disassembler would
therefore print the Coldfire instructions instead of the m68k ones if
no architecture was explicitly specified.

I think we should consistently prefer m68k insns or Coldfire insns
when no architecture has been specified.  To fix the gas testsuite
failure, this patch prefers m68k over Coldfire ones.  This shouldn't
affect Coldfire users because Coldfire objects should always be
explicitly marked as such.

I've added a testcase to mcf-fpu.[sd].  Tested on m68k-elf.
Also tested on binutils-csl-2_17-branch for a while now.
OK to install?

Richard


include/opcodes/
	* m68k.h (mcf_mask): Define.

opcodes/
	* m68k-opc.c (m68k_opcodes): Fix the masks of the Coldfire fmovemd
	and fmovem entries.  Put register list entries before immediate
	mask entries.  Use "l" rather than "L" in the fmovem entries.
	* m68k-dis.c (match_insn_m68k): Remove the PRIV argument and work it
	out from INFO.
	(m68k_scan_mask): New function, split out from...
	(print_insn_m68k): ...here.  If no architecture has been set,
	first try printing an m680x0 instruction, then try a Coldfire one.

gas/testsuite/
	* gas/m68k/mcf-fpu.s: Add fmovemd and fmovem instructions.
	* gas/m68k/mcf-fpu.d: Adjust accordingly.

Index: include/opcode/m68k.h
===================================================================
RCS file: /cvs/src/src/include/opcode/m68k.h,v
retrieving revision 1.12
diff -u -p -r1.12 m68k.h
--- include/opcode/m68k.h	28 Mar 2006 07:19:16 -0000	1.12
+++ include/opcode/m68k.h	22 May 2006 09:24:05 -0000
@@ -42,6 +42,7 @@
 #define mcfisa_aa 0x4000	/* ColdFire ISA_A+.  */
 #define mcfisa_b 0x8000		/* ColdFire ISA_B.  */
 #define mcfusp   0x10000	/* ColdFire USP instructions.  */
+#define mcf_mask 0x1f200
 
 /* Handy aliases.  */
 #define	m68040up   (m68040 | m68060)
Index: opcodes/m68k-opc.c
===================================================================
RCS file: /cvs/src/src/opcodes/m68k-opc.c,v
retrieving revision 1.17
diff -u -p -r1.17 m68k-opc.c
--- opcodes/m68k-opc.c	16 Jan 2006 16:23:30 -0000	1.17
+++ opcodes/m68k-opc.c	22 May 2006 09:24:06 -0000
@@ -913,10 +913,10 @@ const struct m68k_opcode m68k_opcodes[] 
 
 {"fmovecrx", 4,	two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7", mfloat },
 
-{"fmovemd", 4,	two(0xF000, 0xD000), two(0xFFC0, 0xFF00), "Iizsl3", cfloat },
-{"fmovemd", 4,	two(0xF000, 0xD000), two(0xFFC0, 0xFF00), "Iizs#3", cfloat },
-{"fmovemd", 4,	two(0xF000, 0xF000), two(0xFFC0, 0xFF00), "Ii#3ys", cfloat },
-{"fmovemd", 4,	two(0xF000, 0xF000), two(0xFFC0, 0xFF00), "Iil3ys", cfloat },
+{"fmovemd", 4,	two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Iizsl3", cfloat },
+{"fmovemd", 4,	two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Iizs#3", cfloat },
+{"fmovemd", 4,	two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Iil3ys", cfloat },
+{"fmovemd", 4,	two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Ii#3ys", cfloat },
 
 {"fmovemx", 4,	two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s", mfloat },
 {"fmovemx", 4,	two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s", mfloat },
@@ -938,10 +938,10 @@ const struct m68k_opcode m68k_opcodes[] 
    target is a single %fpiar.  */
 {"fmoveml", 4,	two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*lL8", mfloat },
 
-{"fmovem", 4,	two(0xF000, 0xD000), two(0xFFC0, 0xFF00), "IizsL3", cfloat },
-{"fmovem", 4,	two(0xF000, 0xD000), two(0xFFC0, 0xFF00), "Iizs#3", cfloat },
-{"fmovem", 4,	two(0xF000, 0xF000), two(0xFFC0, 0xFF00), "Ii#3ys", cfloat },
-{"fmovem", 4,	two(0xF000, 0xF000), two(0xFFC0, 0xFF00), "IiL3ys", cfloat },
+{"fmovem", 4,	two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Iizsl3", cfloat },
+{"fmovem", 4,	two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Iizs#3", cfloat },
+{"fmovem", 4,	two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Iil3ys", cfloat },
+{"fmovem", 4,	two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Ii#3ys", cfloat },
 
 {"fmovem", 4,	two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s", mfloat },
 {"fmovem", 4,	two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s", mfloat },
Index: opcodes/m68k-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/m68k-dis.c,v
retrieving revision 1.22
diff -u -p -r1.22 m68k-dis.c
--- opcodes/m68k-dis.c	29 Apr 2006 03:11:31 -0000	1.22
+++ opcodes/m68k-dis.c	22 May 2006 09:24:06 -0000
@@ -1204,13 +1204,13 @@ print_insn_arg (const char *d,
 static int
 match_insn_m68k (bfd_vma memaddr,
 		 disassemble_info * info,
-		 const struct m68k_opcode * best,
-		 struct private * priv)
+		 const struct m68k_opcode * best)
 {
   unsigned char *save_p;
   unsigned char *p;
   const char *d;
 
+  struct private *priv = (struct private *) info->private_data;
   bfd_byte *buffer = priv->the_buffer;
   fprintf_ftype save_printer = info->fprintf_func;
   void (* save_print_address) (bfd_vma, struct disassemble_info *)
@@ -1343,21 +1343,22 @@ match_insn_m68k (bfd_vma memaddr,
   return p - buffer;
 }
 
-/* Print the m68k instruction at address MEMADDR in debugged memory,
-   on INFO->STREAM.  Returns length of the instruction, in bytes.  */
+/* Like print_m68k_insn, but restrict the opcode search to the features
+   specified by ARCH_MASK.  Return 0 if no match is found.  */
 
-int
-print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
+static int
+m68k_scan_mask (bfd_vma memaddr, disassemble_info *info,
+		unsigned int arch_mask)
 {
   int i;
   const char *d;
-  unsigned int arch_mask;
-  struct private priv;
-  bfd_byte *buffer = priv.the_buffer;
-  int major_opcode;
-  static int numopcodes[16];
   static const struct m68k_opcode **opcodes[16];
+  static int numopcodes[16];
   int val;
+  int major_opcode;
+
+  struct private *priv = (struct private *) info->private_data;
+  bfd_byte *buffer = priv->the_buffer;
 
   if (!opcodes[0])
     {
@@ -1385,23 +1386,6 @@ print_insn_m68k (bfd_vma memaddr, disass
 	*opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
     }
 
-  info->private_data = (PTR) &priv;
-  /* Tell objdump to use two bytes per chunk
-     and six bytes per line for displaying raw data.  */
-  info->bytes_per_chunk = 2;
-  info->bytes_per_line = 6;
-  info->display_endian = BFD_ENDIAN_BIG;
-  priv.max_fetched = priv.the_buffer;
-  priv.insn_start = memaddr;
-
-  if (setjmp (priv.bailout) != 0)
-    /* Error return.  */
-    return -1;
-
-  arch_mask = bfd_m68k_mach_to_features (info->mach);
-  if (!arch_mask)
-    arch_mask = ~(unsigned int)0;
-
   FETCH_DATA (info, buffer + 2);
   major_opcode = (buffer[0] >> 4) & 15;
 
@@ -1467,10 +1451,57 @@ print_insn_m68k (bfd_vma memaddr, disass
 	    }
 
 	  if (*d == '\0')
-	    if ((val = match_insn_m68k (memaddr, info, opc, & priv)))
+	    if ((val = match_insn_m68k (memaddr, info, opc)))
 	      return val;
 	}
     }
+  return 0;
+}		
+
+/* Print the m68k instruction at address MEMADDR in debugged memory,
+   on INFO->STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
+{
+  unsigned int arch_mask;
+  struct private priv;
+  int val;
+
+  bfd_byte *buffer = priv.the_buffer;
+
+  info->private_data = (PTR) &priv;
+  /* Tell objdump to use two bytes per chunk
+     and six bytes per line for displaying raw data.  */
+  info->bytes_per_chunk = 2;
+  info->bytes_per_line = 6;
+  info->display_endian = BFD_ENDIAN_BIG;
+  priv.max_fetched = priv.the_buffer;
+  priv.insn_start = memaddr;
+
+  if (setjmp (priv.bailout) != 0)
+    /* Error return.  */
+    return -1;
+
+  arch_mask = bfd_m68k_mach_to_features (info->mach);
+  if (!arch_mask)
+    {
+      /* First try printing an m680x0 instruction.  Try printing a Coldfire
+	 one if that fails.  */
+      val = m68k_scan_mask (memaddr, info, m68k_mask);
+      if (val)
+	return val;
+
+      val = m68k_scan_mask (memaddr, info, mcf_mask);
+      if (val)
+	return val;
+    }
+  else
+    {
+      val = m68k_scan_mask (memaddr, info, arch_mask);
+      if (val)
+	return val;
+    }
 
   /* Handle undefined instructions.  */
   info->fprintf_func (info->stream, "0%o", (buffer[0] << 8) + buffer[1]);
Index: gas/testsuite/gas/m68k/mcf-fpu.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/m68k/mcf-fpu.d,v
retrieving revision 1.1
diff -u -p -r1.1 mcf-fpu.d
--- gas/testsuite/gas/m68k/mcf-fpu.d	16 Jan 2006 16:23:29 -0000	1.1
+++ gas/testsuite/gas/m68k/mcf-fpu.d	22 May 2006 09:24:06 -0000
@@ -168,3 +168,11 @@ Disassembly of section .text:
 [ 0-9a-f]+:	f22e 5038 0008 	fcmpw %fp@\(8\),%fp0
 [ 0-9a-f]+:	f22e 5438 0008 	fcmpd %fp@\(8\),%fp0
 [ 0-9a-f]+:	f22e 5838 0008 	fcmpb %fp@\(8\),%fp0
+[ 0-9a-f]+:	f22e f0f2 0008 	fmovemd %fp0-%fp3/%fp6,%fp@\(8\)
+[ 0-9a-f]+:	f22e d02c 0008 	fmovemd %fp@\(8\),%fp2/%fp4-%fp5
+[ 0-9a-f]+:	f22e f027 0008 	fmovemd %fp2/%fp5-%fp7,%fp@\(8\)
+[ 0-9a-f]+:	f22e d0e1 0008 	fmovemd %fp@\(8\),%fp0-%fp2/%fp7
+[ 0-9a-f]+:	f22e f0f2 0008 	fmovemd %fp0-%fp3/%fp6,%fp@\(8\)
+[ 0-9a-f]+:	f22e d02c 0008 	fmovemd %fp@\(8\),%fp2/%fp4-%fp5
+[ 0-9a-f]+:	f22e f027 0008 	fmovemd %fp2/%fp5-%fp7,%fp@\(8\)
+[ 0-9a-f]+:	f22e d0e1 0008 	fmovemd %fp@\(8\),%fp0-%fp2/%fp7
Index: gas/testsuite/gas/m68k/mcf-fpu.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/m68k/mcf-fpu.s,v
retrieving revision 1.1
diff -u -p -r1.1 mcf-fpu.s
--- gas/testsuite/gas/m68k/mcf-fpu.s	16 Jan 2006 16:23:29 -0000	1.1
+++ gas/testsuite/gas/m68k/mcf-fpu.s	22 May 2006 09:24:06 -0000
@@ -163,3 +163,11 @@
 	fcmpw	%fp@(8),%fp0
 	fcmpd	%fp@(8),%fp0
 	fcmpb	%fp@(8),%fp0
+	fmovemd	%fp0-%fp3/%fp6,%fp@(8)
+	fmovemd	%fp@(8),%fp5/%fp4/%fp2
+	fmovemd	#0x27,%fp@(8)
+	fmovemd	%fp@(8),#0xe1
+	fmovem	%fp0-%fp3/%fp6,%fp@(8)
+	fmovem	%fp@(8),%fp5/%fp4/%fp2
+	fmovem	#0x27,%fp@(8)
+	fmovem	%fp@(8),#0xe1


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