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]

[PATCH] Fix Blackfin instruction mode checking


I have committed this patch to fix instruction mode checking for Blackfin. Initially, the Blackfin gas code was written according to Blackfin programming manual. But finally, it was found that the manual didn't document all valid instruction modes for several instructions. This patch adds all such modes for those instructions. I summarized the Blackfin instruction modes in the following page:

http://docs.blackfin.uclinux.org/doku.php?id=bfin:instruction_modes

This patch also adds mode checking for 16-bit multiply instructions.


Jie
	* config/bfin-parse.y (check_macfunc_option): Fix instruction
	mode checking.
	(asm_1): Check mode for 16-bit multiply instructions.

	testsuite/

	* gas/bfin/arith_mode.d: New test.
	* gas/bfin/arith_mode.s: New test.
	* gas/bfin/invalid_arith_mode.l: New test.
	* gas/bfin/invalid_arith_mode.s: New test.
	* gas/bfin/bfin.exp: Add arith_mode and invalid_arith_mode.


Index: testsuite/gas/bfin/arith_mode.d
===================================================================
--- testsuite/gas/bfin/arith_mode.d	(revision 0)
+++ testsuite/gas/bfin/arith_mode.d	(revision 0)
@@ -0,0 +1,56 @@
+#objdump: -dr
+#name: arith_mode
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	03 c0 00 38 	R0.L = A0;
+   4:	83 c0 00 38 	R0.L = A0 \(FU\);
+   8:	03 c1 00 38 	R0.L = A0 \(IS\);
+   c:	83 c1 00 38 	R0.L = A0 \(IU\);
+  10:	43 c0 00 38 	R0.L = A0 \(T\);
+  14:	c3 c0 00 38 	R0.L = A0 \(TFU\);
+  18:	23 c0 00 38 	R0.L = A0 \(S2RND\);
+  1c:	23 c1 00 38 	R0.L = A0 \(ISS2\);
+  20:	63 c1 00 38 	R0.L = A0 \(IH\);
+  24:	0b c0 00 38 	R0 = A0;
+  28:	8b c0 00 38 	R0 = A0 \(FU\);
+  2c:	0b c1 00 38 	R0 = A0 \(IS\);
+  30:	8b c1 00 38 	R0 = A0 \(IU\);
+  34:	2b c0 00 38 	R0 = A0 \(S2RND\);
+  38:	2b c1 00 38 	R0 = A0 \(ISS2\);
+  3c:	04 c2 0a 40 	R0.H = R1.L \* R2.H;
+  40:	84 c2 0a 40 	R0.H = R1.L \* R2.H \(FU\);
+  44:	04 c3 0a 40 	R0.H = R1.L \* R2.H \(IS\);
+  48:	84 c3 0a 40 	R0.H = R1.L \* R2.H \(IU\);
+  4c:	44 c2 0a 40 	R0.H = R1.L \* R2.H \(T\);
+  50:	c4 c2 0a 40 	R0.H = R1.L \* R2.H \(TFU\);
+  54:	24 c2 0a 40 	R0.H = R1.L \* R2.H \(S2RND\);
+  58:	24 c3 0a 40 	R0.H = R1.L \* R2.H \(ISS2\);
+  5c:	64 c3 0a 40 	R0.H = R1.L \* R2.H \(IH\);
+  60:	08 c2 0a 22 	R0 = R1.L \* R2.H;
+  64:	88 c2 0a 22 	R0 = R1.L \* R2.H \(FU\);
+  68:	08 c3 0a 22 	R0 = R1.L \* R2.H \(IS\);
+  6c:	28 c2 0a 22 	R0 = R1.L \* R2.H \(S2RND\);
+  70:	28 c3 0a 22 	R0 = R1.L \* R2.H \(ISS2\);
+  74:	03 c0 0a 02 	A0 = R1.L \* R2.H;
+  78:	83 c0 0a 02 	A0 = R1.L \* R2.H \(FU\);
+  7c:	03 c1 0a 02 	A0 = R1.L \* R2.H \(IS\);
+  80:	63 c0 0a 02 	A0 = R1.L \* R2.H \(W32\);
+  84:	03 c0 0a 22 	R0.L = \(A0 = R1.L \* R2.H\);
+  88:	83 c0 0a 22 	R0.L = \(A0 = R1.L \* R2.H\) \(FU\);
+  8c:	03 c1 0a 22 	R0.L = \(A0 = R1.L \* R2.H\) \(IS\);
+  90:	83 c1 0a 22 	R0.L = \(A0 = R1.L \* R2.H\) \(IU\);
+  94:	43 c0 0a 22 	R0.L = \(A0 = R1.L \* R2.H\) \(T\);
+  98:	c3 c0 0a 22 	R0.L = \(A0 = R1.L \* R2.H\) \(TFU\);
+  9c:	23 c0 0a 22 	R0.L = \(A0 = R1.L \* R2.H\) \(S2RND\);
+  a0:	23 c1 0a 22 	R0.L = \(A0 = R1.L \* R2.H\) \(ISS2\);
+  a4:	63 c1 0a 22 	R0.L = \(A0 = R1.L \* R2.H\) \(IH\);
+  a8:	0b c0 0a 22 	R0 = \(A0 = R1.L \* R2.H\);
+  ac:	8b c0 0a 22 	R0 = \(A0 = R1.L \* R2.H\) \(FU\);
+  b0:	0b c1 0a 22 	R0 = \(A0 = R1.L \* R2.H\) \(IS\);
+  b4:	8b c1 0a 22 	R0 = \(A0 = R1.L \* R2.H\) \(IU\);
+  b8:	2b c0 0a 22 	R0 = \(A0 = R1.L \* R2.H\) \(S2RND\);
+  bc:	2b c1 0a 22 	R0 = \(A0 = R1.L \* R2.H\) \(ISS2\);
Index: testsuite/gas/bfin/arith_mode.s
===================================================================
--- testsuite/gas/bfin/arith_mode.s	(revision 0)
+++ testsuite/gas/bfin/arith_mode.s	(revision 0)
@@ -0,0 +1,72 @@
+	.text
+
+	// Accumulator to Half D-register Moves
+
+	R0.L = A0;
+	R0.L = A0 (FU);
+	R0.L = A0 (IS);
+	R0.L = A0 (IU);
+	R0.L = A0 (T);
+	R0.L = A0 (TFU); // Not documented
+	R0.L = A0 (S2RND);
+	R0.L = A0 (ISS2);
+	R0.L = A0 (IH);
+
+	// Accumulator to D-register Moves
+
+	R0 = A0;
+	R0 = A0 (FU);
+	R0 = A0 (IS); // Not documented
+	R0 = A0 (IU); // Not documented
+	R0 = A0 (S2RND);
+	R0 = A0 (ISS2);
+
+	// Multiply 16-Bit Operands to Half Dreg
+
+	R0.H = R1.L * R2.H;
+	R0.H = R1.L * R2.H (FU);
+	R0.H = R1.L * R2.H (IS);
+	R0.H = R1.L * R2.H (IU);
+	R0.H = R1.L * R2.H (T);
+	R0.H = R1.L * R2.H (TFU);
+	R0.H = R1.L * R2.H (S2RND);
+	R0.H = R1.L * R2.H (ISS2);
+	R0.H = R1.L * R2.H (IH);
+
+	// Multiply 16-Bit Operands to Dreg
+
+	R0 = R1.L * R2.H;
+	R0 = R1.L * R2.H (FU);
+	R0 = R1.L * R2.H (IS);
+	R0 = R1.L * R2.H (S2RND); // Not documented
+	R0 = R1.L * R2.H (ISS2);
+
+	// Multiply and Multiply-Accumulate to Accumulator
+
+	A0 = R1.L * R2.H;
+	A0 = R1.L * R2.H (FU);
+	A0 = R1.L * R2.H (IS);
+	A0 = R1.L * R2.H (W32);
+
+	// Multiply and Multiply-Accumulate to Half-Register
+
+	R0.L = (A0 = R1.L * R2.H);
+	R0.L = (A0 = R1.L * R2.H) (FU);
+	R0.L = (A0 = R1.L * R2.H) (IS);
+	R0.L = (A0 = R1.L * R2.H) (IU);
+	R0.L = (A0 = R1.L * R2.H) (T);
+	R0.L = (A0 = R1.L * R2.H) (TFU);
+	R0.L = (A0 = R1.L * R2.H) (S2RND);
+	R0.L = (A0 = R1.L * R2.H) (ISS2);
+	R0.L = (A0 = R1.L * R2.H) (IH);
+
+	// Multiply and Multiply-Accumulate to Data Register
+
+	R0 = (A0 = R1.L * R2.H);
+	R0 = (A0 = R1.L * R2.H) (FU);
+	R0 = (A0 = R1.L * R2.H) (IS);
+	R0 = (A0 = R1.L * R2.H) (IU); // Not documented
+	R0 = (A0 = R1.L * R2.H) (S2RND);
+	R0 = (A0 = R1.L * R2.H) (ISS2);
+
+
Index: testsuite/gas/bfin/invalid_arith_mode.l
===================================================================
--- testsuite/gas/bfin/invalid_arith_mode.l	(revision 0)
+++ testsuite/gas/bfin/invalid_arith_mode.l	(revision 0)
@@ -0,0 +1,23 @@
+.*: Assembler messages:
+.*:7: Error: bad option.
+.*:11: Error: bad option.
+.*:12: Error: bad option.
+.*:13: Error: bad option.
+.*:14: Error: bad option.
+.*:18: Error: bad option..
+.*:22: Error: bad option.
+.*:23: Error: bad option.
+.*:24: Error: bad option.
+.*:25: Error: bad option.
+.*:26: Error: bad option.
+.*:30: Error: bad option.
+.*:31: Error: bad option.
+.*:32: Error: bad option.
+.*:33: Error: bad option.
+.*:34: Error: bad option.
+.*:35: Error: bad option.
+.*:39: Error: bad option.
+.*:43: Error: bad option.
+.*:44: Error: bad option.
+.*:45: Error: bad option.
+.*:46: Error: bad option.
Index: testsuite/gas/bfin/invalid_arith_mode.s
===================================================================
--- testsuite/gas/bfin/invalid_arith_mode.s	(revision 0)
+++ testsuite/gas/bfin/invalid_arith_mode.s	(revision 0)
@@ -0,0 +1,46 @@
+	.text
+
+	// All available modes: FU, IS, IU, T, TFU, S2RND, ISS2, IH, W32
+
+	// Accumulator to Half D-register Moves
+
+	R0.L = A0 (W32);
+
+	// Accumulator to D-register Moves
+
+	R0 = A0 (T);
+	R0 = A0 (TFU);
+	R0 = A0 (IH);
+	R0 = A0 (W32);
+
+	// Multiply 16-Bit Operands to Half Dreg
+
+	R0.H = R1.L * R2.H (W32);
+
+	// Multiply 16-Bit Operands to Dreg
+
+	R0 = R1.L * R2.H (IU);
+	R0 = R1.L * R2.H (T);
+	R0 = R1.L * R2.H (TFU);
+	R0 = R1.L * R2.H (IH);
+	R0 = R1.L * R2.H (W32);
+
+	// Multiply and Multiply-Accumulate to Accumulator
+
+	A0 = R1.L * R2.H (IU);
+	A0 = R1.L * R2.H (T);
+	A0 = R1.L * R2.H (TFU);
+	A0 = R1.L * R2.H (S2RND);
+	A0 = R1.L * R2.H (ISS2);
+	A0 = R1.L * R2.H (IH);
+
+	// Multiply and Multiply-Accumulate to Half-Register
+
+	R0.L = (A0 = R1.L * R2.H) (W32);
+
+	// Multiply and Multiply-Accumulate to Data Register
+
+	R0 = (A0 = R1.L * R2.H) (T);
+	R0 = (A0 = R1.L * R2.H) (TFU);
+	R0 = (A0 = R1.L * R2.H) (IH);
+	R0 = (A0 = R1.L * R2.H) (W32);
Index: testsuite/gas/bfin/bfin.exp
===================================================================
--- testsuite/gas/bfin/bfin.exp	(revision 2794)
+++ testsuite/gas/bfin/bfin.exp	(working copy)
@@ -14,6 +14,7 @@ proc run_list_test { name opts } {
 }
 if [istarget bfin*-*-*] {
 	run_dump_test "arithmetic"
+	run_dump_test "arith_mode"
 	run_dump_test "bit"
 	run_dump_test "bit2"
 	run_dump_test "cache"
@@ -27,6 +28,7 @@ if [istarget bfin*-*-*] {
 	run_list_test "expected_comparison_errors" ""
 	run_dump_test "flow"
 	run_dump_test "flow2"
+	run_list_test "invalid_arith_mode" ""
 	run_dump_test "load"
 	run_dump_test "logical"
 	run_dump_test "logical2"
Index: config/bfin-parse.y
===================================================================
--- config/bfin-parse.y	(revision 2771)
+++ config/bfin-parse.y	(working copy)
@@ -268,21 +268,15 @@ check_macfunc_option (Macfunc *a, Opt_mo
   if (opt->mod == 0)
     return 0;
 
-  if ((a->op == 3 && a->w == 1 && a->P == 1
-       && opt->mod != M_FU && opt->mod != M_S2RND && opt->mod != M_ISS2)
-      || (a->op == 3 && a->w == 1 && a->P == 0
-	  && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU
-	  && opt->mod != M_T && opt->mod != M_S2RND && opt->mod != M_ISS2
-	  && opt->mod != M_IH)
-      || (a->w == 0 && a->P == 0
-	  && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_W32)
-      || (a->w == 1 && a->P == 1
-	  && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_S2RND
-	  && opt->mod != M_ISS2 && opt->mod != M_IU)
+  if ((a->w == 1 && a->P == 1
+       && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU
+       && opt->mod != M_S2RND && opt->mod != M_ISS2)
       || (a->w == 1 && a->P == 0
 	  && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU
 	  && opt->mod != M_T && opt->mod != M_TFU && opt->mod != M_S2RND
-	  && opt->mod != M_ISS2 && opt->mod != M_IH))
+	  && opt->mod != M_ISS2 && opt->mod != M_IH)
+      || (a->w == 0 && a->P == 0
+	  && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_W32))
     return -1;
 
   return 0;
@@ -1763,6 +1757,11 @@ asm_1:   
 	  if (!IS_H ($1) && $4.MM)
 	    return yyerror ("(M) not allowed with MAC0");
 
+	  if ($4.mod != 0 && $4.mod != M_FU && $4.mod != M_IS
+	      && $4.mod != M_IU && $4.mod != M_T && $4.mod != M_TFU
+	      && $4.mod != M_S2RND && $4.mod != M_ISS2 && $4.mod != M_IH)
+	    return yyerror ("bad option.");
+
 	  if (IS_H ($1))
 	    {
 	      $$ = DSP32MULT (0, $4.MM, $4.mod, 1, 0,
@@ -1786,6 +1785,10 @@ asm_1:   
 	  if (IS_EVEN ($1) && $4.MM)
 	    return yyerror ("(M) not allowed with MAC0");
 
+	  if ($4.mod != 0 && $4.mod != M_FU && $4.mod != M_IS
+	      && $4.mod != M_S2RND && $4.mod != M_ISS2)
+	    return yyerror ("bad option");
+
 	  if (!IS_EVEN ($1))
 	    {
 	      notethat ("dsp32mult: dregs = multiply_halfregs (opt_mode)\n");

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