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

[PATCH] Fix movem decoding in m68k disassembler


The m68k disassembler does not correctly decode the movem instruction
when the destination is a pre-decrement address.  Although the '&'
operand descriptor is supposed to only match alterable control EAs the
disassembler does not check that, so that "Lw&s" matches where only
"lw-s" should match.

Tested with a ppc-linux/m68k-linux cross.

Andreas.

2004-06-27  Andreas Schwab  <schwab@suse.de>

binutils/testsuite/:
	* binutils-all/m68k/movem.s: New file.

	* binutils-all/m68k/objdump.exp: New file.

include/opcode/:
	* m68k.h: Fix comment.

opcodes/:
	* m68k-dis.c (m68k_valid_ea): Check validity of all codes.


Index: binutils/testsuite/binutils-all/m68k/movem.s
===================================================================
RCS file: binutils/testsuite/binutils-all/m68k/movem.s
diff -N binutils/testsuite/binutils-all/m68k/movem.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ binutils/testsuite/binutils-all/m68k/movem.s	27 Jun 2004 22:14:00 -0000
@@ -0,0 +1,2 @@
+	movem.l	%d0-%d3,-(%sp)
+	movem.l	%d0-%d3,(%sp)
Index: binutils/testsuite/binutils-all/m68k/objdump.exp
===================================================================
RCS file: binutils/testsuite/binutils-all/m68k/objdump.exp
diff -N binutils/testsuite/binutils-all/m68k/objdump.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ binutils/testsuite/binutils-all/m68k/objdump.exp	27 Jun 2004 22:00:09 -0000
@@ -0,0 +1,53 @@
+#   Copyright 2004
+#   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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+if {![istarget "m68*-*-*"] || [istarget "m68h*-*-*"] || [istarget "m681*-*-*"]} then {
+  return
+}
+
+if {[which $OBJDUMP] == 0} then {
+    perror "$OBJDUMP does not exist"
+    return
+}
+
+send_user "Version [binutil_version $OBJDUMP]"
+
+###########################
+# Set up the test of movem.s
+###########################
+
+if {![binutils_assemble $srcdir/$subdir/movem.s tmpdir/movem.o]} then {
+    return
+}
+
+if [is_remote host] {
+    set objfile [remote_download host tmpdir/movem.o]
+} else {
+    set objfile tmpdir/movem.o
+}
+
+# Make sure that the movem is correctly decoded.
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS --disassemble $objfile"]
+
+set want "moveml %d0-%d3,%sp@-.*moveml %d0-%d3,%sp@\[\r\n\]"
+
+if [regexp $want $got] then {
+    pass "movem test"
+} else {
+    fail "movem test"
+}
Index: include/opcode/m68k.h
===================================================================
RCS file: /cvs/src/src/include/opcode/m68k.h,v
retrieving revision 1.8
diff -u -a -p -r1.8 m68k.h
--- include/opcode/m68k.h	24 May 2004 14:33:21 -0000	1.8
+++ include/opcode/m68k.h	27 Jun 2004 22:00:22 -0000
@@ -219,7 +219,7 @@ struct m68k_opcode_alias
    !  control					(modes 2,5,6,7.0-3)
 						(not 0,1,3,4,7.4)
    &  alterable control				(modes 2,5,6,7.0,7.1)
-						(not 0,1,7.2-4)
+						(not 0,1,3,4,7.2-4)
    $  alterable data				(modes 0,2-6,7.0,7.1)
 						(not 1,7.2-4)
    ?  alterable control, or data register	(modes 0,2,5,6,7.0,7.1)
Index: opcodes/m68k-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/m68k-dis.c,v
retrieving revision 1.14
diff -u -a -p -r1.14 m68k-dis.c
--- opcodes/m68k-dis.c	24 May 2004 14:33:22 -0000	1.14
+++ opcodes/m68k-dis.c	27 Jun 2004 22:00:28 -0000
@@ -826,7 +826,7 @@ print_insn_arg (d, buffer, p0, addr, inf
 	val = fetch_arg (buffer, 's', 6, info);
 
       /* If the <ea> is invalid for *d, then reject this match.  */
-      if (m68k_valid_ea (*d, val) == FALSE)
+      if (!m68k_valid_ea (*d, val))
 	return -1;
 
       /* Get register number assuming address register.  */
@@ -1127,19 +1127,101 @@ print_insn_arg (d, buffer, p0, addr, inf
 /* Check if an EA is valid for a particular code.  This is required
    for the EMAC instructions since the type of source address determines
    if it is a EMAC-load instruciton if the EA is mode 2-5, otherwise it
-   is a non-load EMAC instruction and the bits mean register Ry.  */
+   is a non-load EMAC instruction and the bits mean register Ry.
+   A similar case exists for the movem instructions where the register
+   mask is interpreted differently for different EAs.  */
 
 static bfd_boolean
 m68k_valid_ea (char code, int val)
 {
-  int mode;
+  int mode, mask;
+#define M(n0,n1,n2,n3,n4,n5,n6,n70,n71,n72,n73,n74) \
+  (n0 | n1 << 1 | n2 << 2 | n3 << 3 | n4 << 4 | n5 << 5 | n6 << 6 \
+   | n70 << 7 | n71 << 8 | n72 << 9 | n73 << 10 | n74 << 11)
 
-  mode = (val >> 3) & 7;
-  if (code == '4')
-    if (!(mode >= 2 && mode <= 5))
-	return FALSE;
+  switch (code)
+    {
+    case '*':
+      mask = M (1,1,1,1,1,1,1,1,1,1,1,1);
+      break;
+    case '~':
+      mask = M (0,0,1,1,1,1,1,1,1,0,0,0);
+      break;
+    case '%':
+      mask = M (1,1,1,1,1,1,1,1,1,0,0,0);
+      break;
+    case ';':
+      mask = M (1,0,1,1,1,1,1,1,1,1,1,1);
+      break;
+    case '@':
+      mask = M (1,0,1,1,1,1,1,1,1,1,1,0);
+      break;
+    case '!':
+      mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
+      break;
+    case '&':
+      mask = M (0,0,1,0,0,1,1,1,1,0,0,0);
+      break;
+    case '$':
+      mask = M (1,0,1,1,1,1,1,1,1,0,0,0);
+      break;
+    case '?':
+      mask = M (0,1,0,0,1,1,1,1,1,0,0,0);
+      break;
+    case '/':
+      mask = M (1,0,1,0,0,1,1,1,1,1,1,0);
+      break;
+    case '|':
+      mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
+      break;
+    case '>':
+      mask = M (0,0,1,0,1,1,1,1,1,1,1,0);
+      break;
+    case '<':
+      mask = M (0,0,1,1,0,1,1,1,1,0,0,0);
+      break;
+    case 'm':
+      mask = M (1,1,1,1,1,0,0,0,0,0,0,0);
+      break;
+    case 'n':
+      mask = M (0,0,0,0,0,1,0,0,0,1,0,0);
+      break;
+    case 'o':
+      mask = M (0,0,0,0,0,0,1,1,1,0,1,1);
+      break;
+    case 'p':
+      mask = M (1,1,1,1,1,1,0,0,0,0,0,0);
+      break;
+    case 'q':
+      mask = M (1,0,1,1,1,1,0,0,0,0,0,0);
+      break;
+    case 'v':
+      mask = M (1,0,1,1,1,1,0,1,1,0,0,0);
+      break;
+    case 'b':
+      mask = M (1,0,1,1,1,1,0,0,0,1,0,0);
+      break;
+    case 'w':
+      mask = M (0,0,1,1,1,1,0,0,0,1,0,0);
+      break;
+    case 'y':
+      mask = M (0,0,1,0,0,1,0,0,0,0,0,0);
+      break;
+    case 'z':
+      mask = M (0,0,1,0,0,1,0,0,0,1,0,0);
+      break;
+    case '4':
+      mask = M (0,0,1,1,1,1,0,0,0,0,0,0);
+      break;
+    default:
+      abort ();
+    }
+#undef M
 
-  return TRUE;
+  mode = (val >> 3) & 7;
+  if (mode == 7)
+    mode += val & 7;
+  return (mask & (1 << mode)) != 0;
 }
 
 /* Fetch BITS bits from a position in the instruction specified by CODE.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, MaxfeldstraÃe 5, 90409 NÃrnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


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