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]

[RFA] Fix erroneous UNPREDICTABLE message with STMIA


All,

Please can someone review and approve the attached patch?

gas was incorrectly diagnosing 32-bit Thumb STMIA instructions where the
base register was in the register list as UNPREDICTABLE if writeback was
not being used.  Examples are:
	STMIA r0, {r0-r4}
	STMIA r8, {r0-r11}

This patch fixes this issue.

It also changes the message when we are using writeback (and so the
instruction is UNPREDICTABLE) into an error.  This is to maintain
consistency with other messages of a similar nature in the same
function.

However, there does seem to be a general inconsistency in the
gas/config/tc-arm.c about whether an UNPREDICTABLE/UNKNOWN instruction
causes an error or a warning.  Is there a consensus on whether an
UNPREDICTABLE instruction is an error or a warning?

Proposed ChangeLog:

gas/ChangeLog:
2010-05-13  Matthew Gretton-Dann  <matthew.gretton-dann@arm.com>

	* config/tc-arm.c (encode_thumb2_ldmstm): Make warning about 
	writeback when base register is in register list an error, and 
	correct check.
	(do_t_ldmstm): Change warnings.

gas/testsuite/ChangeLog:
2010-05-13  Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
	* gas/arm/thumb2_ldmstm.d: Add new testcases.
	* gas/arm/thumb2_ldmstm.s: Likeiwse.
	* gas/arm/thumb2_ldmstm_bad.d: Add testcases to check for
	UNPREDICTABLE ldm/stm.
	* gas/arm/thumb2_ldmstm_bad.l: Likewise.
	* gas/arm/thumb2_ldmstm_bad.s: Likewise.

Thanks,

Matt 

-- 
Matthew Gretton-Dann
Principal Engineer - PD Software, Tools
ARM Ltd
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.444
diff -u -p -u -p -r1.444 tc-arm.c
--- gas/config/tc-arm.c	13 May 2010 08:15:02 -0000	1.444
+++ gas/config/tc-arm.c	13 May 2010 16:13:11 -0000
@@ -9760,6 +9760,12 @@ encode_thumb2_ldmstm (int base, unsigned
 
   if (mask & (1 << 13))
     inst.error =  _("SP not allowed in register list");
+
+  if ((mask & (1 << base)) != 0
+      && writeback)
+    inst.error = _("having the base register in the register list when "
+		   "using write back is UNPREDICTABLE");
+
   if (load)
     {
       if (mask & (1 << 15))
@@ -9769,19 +9775,11 @@ encode_thumb2_ldmstm (int base, unsigned
           else
             set_it_insn_type_last ();
         }
-
-      if ((mask & (1 << base)) != 0
-	  && writeback)
-	as_warn (_("base register should not be in register list "
-		   "when written back"));
     }
   else
     {
       if (mask & (1 << 15))
 	inst.error = _("PC not allowed in register list");
-
-      if (mask & (1 << base))
-	as_warn (_("value stored for r%d is UNPREDICTABLE"), base);
     }
 
   if ((mask & (mask - 1)) == 0)
@@ -9847,7 +9845,7 @@ do_t_ldmstm (void)
 	      if (inst.instruction == T_MNEM_stmia
 		  && (inst.operands[1].imm & mask)
 		  && (inst.operands[1].imm & (mask - 1)))
-		as_warn (_("value stored for r%d is UNPREDICTABLE"),
+		as_warn (_("value stored for r%d is UNKNOWN"),
 			 inst.operands[0].reg);
 
 	      inst.instruction = THUMB_OP16 (inst.instruction);
@@ -9887,7 +9885,7 @@ do_t_ldmstm (void)
 	    as_warn (_("this instruction will write back the base register"));
 	  if ((inst.operands[1].imm & (1 << inst.operands[0].reg))
 	      && (inst.operands[1].imm & ((1 << inst.operands[0].reg) - 1)))
-	    as_warn (_("value stored for r%d is UNPREDICTABLE"),
+	    as_warn (_("value stored for r%d is UNKNOWN"),
 		     inst.operands[0].reg);
 	}
       else
Index: gas/testsuite/gas/arm/t16-bad.l
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/t16-bad.l,v
retrieving revision 1.5
diff -u -p -u -p -r1.5 t16-bad.l
--- gas/testsuite/gas/arm/t16-bad.l	11 Aug 2009 09:53:40 -0000	1.5
+++ gas/testsuite/gas/arm/t16-bad.l	13 May 2010 16:13:11 -0000
@@ -181,7 +181,7 @@
 [^:]*:124: Error: lo register required -- `stmia r8!,{r1,r2}'
 [^:]*:125: Error: lo register required -- `stmia r7!,{r8}'
 [^:]*:126: Warning: this instruction will write back the base register
-[^:]*:127: Warning: value stored for r7 is UNPREDICTABLE
+[^:]*:127: Warning: value stored for r7 is UNKNOWN
 [^:]*:129: Error: invalid register list to push/pop instruction -- `push {r8,r9}'
 [^:]*:130: Error: invalid register list to push/pop instruction -- `pop {r8,r9}'
 [^:]*:133: Error: immediate value out of range -- `bkpt #257'
Index: gas/testsuite/gas/arm/thumb2_ldmstm.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb2_ldmstm.d,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 thumb2_ldmstm.d
--- gas/testsuite/gas/arm/thumb2_ldmstm.d	30 Mar 2007 14:51:25 -0000	1.1
+++ gas/testsuite/gas/arm/thumb2_ldmstm.d	13 May 2010 16:13:11 -0000
@@ -1,4 +1,4 @@
-# name: Thumb-2 LDM/STM single reg
+# name: Thumb-2 LDM/STM
 # as: -march=armv6t2
 # objdump: -dr --prefix-addresses --show-raw-insn
 
@@ -25,3 +25,27 @@ Disassembly of section .text:
 0[0-9a-f]+ <[^>]+> f846 cc04 	str.w	ip, \[r6, #-4\]
 0[0-9a-f]+ <[^>]+> f846 bd04 	str.w	fp, \[r6, #-4\]!
 0[0-9a-f]+ <[^>]+> f845 8d04 	str.w	r8, \[r5, #-4\]!
+0[0-9a-f]+ <[^>]+> c80e      	ldmia	r0!, {r1, r2, r3}
+0[0-9a-f]+ <[^>]+> c80f      	ldmia	r0, {r0, r1, r2, r3}
+0[0-9a-f]+ <[^>]+> c802      	ldmia	r0!, {r1}
+0[0-9a-f]+ <[^>]+> e890 0f00 	ldmia.w	r0, {r8, r9, sl, fp}
+0[0-9a-f]+ <[^>]+> e8b0 000e 	ldmia.w	r0!, {r1, r2, r3}
+0[0-9a-f]+ <[^>]+> e8b0 0f00 	ldmia.w	r0!, {r8, r9, sl, fp}
+0[0-9a-f]+ <[^>]+> e8b0 5000 	ldmia.w	r0!, {ip, lr}
+0[0-9a-f]+ <[^>]+> e8b0 9000 	ldmia.w	r0!, {ip, pc}
+0[0-9a-f]+ <[^>]+> bf08      	it	eq
+0[0-9a-f]+ <[^>]+> e8b0 9000 	ldmiaeq.w	r0!, {ip, pc}
+0[0-9a-f]+ <[^>]+> c00f      	stmia	r0!, {r0, r1, r2, r3}
+0[0-9a-f]+ <[^>]+> c0f0      	stmia	r0!, {r4, r5, r6, r7}
+0[0-9a-f]+ <[^>]+> e8a0 00f0 	stmia.w	r0!, {r4, r5, r6, r7}
+0[0-9a-f]+ <[^>]+> e8a0 0f00 	stmia.w	r0!, {r8, r9, sl, fp}
+0[0-9a-f]+ <[^>]+> e880 000f 	stmia.w	r0, {r0, r1, r2, r3}
+0[0-9a-f]+ <[^>]+> e880 0f00 	stmia.w	r0, {r8, r9, sl, fp}
+0[0-9a-f]+ <[^>]+> f850 1b04 	ldr.w	r1, \[r0\], #4
+0[0-9a-f]+ <[^>]+> f8d0 1000 	ldr.w	r1, \[r0\]
+0[0-9a-f]+ <[^>]+> f858 9b04 	ldr.w	r9, \[r8\], #4
+0[0-9a-f]+ <[^>]+> f8d8 9000 	ldr.w	r9, \[r8\]
+0[0-9a-f]+ <[^>]+> f840 1b04 	str.w	r1, \[r0\], #4
+0[0-9a-f]+ <[^>]+> f8c0 1000 	str.w	r1, \[r0\]
+0[0-9a-f]+ <[^>]+> f848 9b04 	str.w	r9, \[r8\], #4
+0[0-9a-f]+ <[^>]+> f8c8 9000 	str.w	r9, \[r8\]
Index: gas/testsuite/gas/arm/thumb2_ldmstm.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb2_ldmstm.s,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 thumb2_ldmstm.s
--- gas/testsuite/gas/arm/thumb2_ldmstm.s	30 Mar 2007 14:51:25 -0000	1.1
+++ gas/testsuite/gas/arm/thumb2_ldmstm.s	13 May 2010 16:13:11 -0000
@@ -22,3 +22,36 @@ ldmstm:
 	stmdb r6!, {fp}
 	stmdb r5!, {r8}
 
+	@ Valid Thumb-2 encodings of LDM/LDMIA/LDMFD as specified by section
+	@ A8.6.53 of the ARM ARM
+	ldmia r0!, {r1-r3}	@ Encoding T1
+	ldmia r0, {r0-r3}	@ Encoding T1
+	ldmia r0!, {r1}		@ Encoding T1
+	ldmia r0, {r8-r11}	@ Encoding T2
+	ldmia.w r0!, {r1-r3}	@ Encoding T2
+	ldmia r0!, {r8-r11}	@ Encoding T2
+	ldmia r0!, {r12, r14}	@ Encoding T2
+	ldmia r0!, {r12, pc}	@ Encoding T2
+	it eq
+	ldmiaeq r0!, {r12, pc}	@ Encoding T2
+
+	@ Valid Thumb-2 encodings of STM/STMIA/STMEA as specified by section
+	@ A8.6.189 of the ARMARM.
+	stmia r0!, {r0-r3}	@ Encoding T1, Allowed as r0 is lowest reg
+	stmia r0!, {r4-r7}	@ Encoding T1
+	stmia.w r0!, {r4-r7}	@ Encoding T2
+	stmia r0!, {r8-r11}	@ Encoding T2
+	stmia r0, {r0-r3}	@ Encoding T2
+	stmia r0, {r8-r11}	@ Encoding T2
+
+	@ The following are technically UNPREDICTABLE if we assemble them
+	@ as written, but gas translates (stm|ldm) rn(!), {rd} into an
+	@ equivalent, and well-defined, (ldr, str) rd, [rn], (#4).
+	ldmia.w r0!, {r1}	@ ldr.w r1, [r0], #4
+	ldmia.w r0, {r1}	@ ldr.w r1, [r0]
+	ldmia r8!, {r9}		@ ldr.w r9, [r8], #4
+        ldmia r8, {r9}		@ ldr.w r9, [r8]
+	stmia.w r0!, {r1}	@ str.w r1, [r0], #4
+	stmia r0, {r1}		@ str.w r1, [r0]
+	stmia r8!, {r9}		@ str.w r9, [r8], #4
+	stmia r8, {r9}		@ str.w r9, [r8]
Index: gas/testsuite/gas/arm/thumb2_ldmstm_bad.d
===================================================================
diff -u -p /dev/null gas/testsuite/gas/arm/thumb2_ldmstm_bad.d
--- /dev/null	2010-05-11 13:31:15.270839157 +0100
+++ gas/testsuite/gas/arm/thumb2_ldmstm_bad.d	2010-05-11 16:18:11.681009000 +0100
@@ -0,0 +1,3 @@
+#name: Invalid Thumb-2 LDM/STM instructions
+#as: -march=armv6t2
+#error-output: thumb2_ldmstm_bad.l
Index: gas/testsuite/gas/arm/thumb2_ldmstm_bad.l
===================================================================
diff -u -p /dev/null gas/testsuite/gas/arm/thumb2_ldmstm_bad.l
--- /dev/null	2010-05-11 13:31:15.270839157 +0100
+++ gas/testsuite/gas/arm/thumb2_ldmstm_bad.l	2010-05-11 16:23:12.488388000 +0100
@@ -0,0 +1,12 @@
+[^:]*: Assembler messages:
+[^:]*:6: Error: r15 not allowed here -- `ldmia r15,{r0-r3}'
+[^:]*:7: Error: r15 not allowed here -- `ldmia r15!,{r0-r3}'
+[^:]*:8: Error: LR and PC should not both be in register list -- `ldmia r1,{r14,r15}'
+[^:]*:9: Error: having the base register in the register list when using write back is UNPREDICTABLE -- `ldmia r0!,{r0-r3}'
+[^:]*:12: Error: branch must be last instruction in IT block -- `ldmiaeq r0,{r12,r15}'
+[^:]*:13: Error: having the base register in the register list when using write back is UNPREDICTABLE -- `ldmiaeq r0!,{r0,r1}'
+[^:]*:17: Error: having the base register in the register list when using write back is UNPREDICTABLE -- `stmia.w r0!,{r0-r3}'
+[^:]*:18: Warning: value stored for r1 is UNKNOWN
+[^:]*:19: Error: r15 not allowed here -- `stmia r15!,{r0-r3}'
+[^:]*:20: Error: r15 not allowed here -- `stmia r15,{r0-r3}'
+[^:]*:21: Error: having the base register in the register list when using write back is UNPREDICTABLE -- `stmia r8!,{r0-r11}'
Index: gas/testsuite/gas/arm/thumb2_ldmstm_bad.s
===================================================================
diff -u -p /dev/null gas/testsuite/gas/arm/thumb2_ldmstm_bad.s
--- /dev/null	2010-05-11 13:31:15.270839157 +0100
+++ gas/testsuite/gas/arm/thumb2_ldmstm_bad.s	2010-05-11 16:16:46.661090000 +0100
@@ -0,0 +1,30 @@
+.syntax unified
+.thumb
+ldmstm_bad:
+	@ UNPREDICTABLE Thumb-2 encodings of LDM/LDMIA/LDMFD as specified
+	@ by section A8.6.53 of the ARMARM.
+	ldmia r15, {r0-r3}	@ Encoding T2, UNPREDICTABLE
+	ldmia r15!, {r0-r3}	@ Encoding T2, UNPREDICTABLE
+	ldmia r1, {r14, r15}	@ Encoding T2, UNPREDICTABLE
+	ldmia r0!, {r0-r3}	@ Encoding T2, UNPREDICTABLE
+
+	itt eq
+	ldmiaeq r0, {r12, r15}	@ Encoding T2, UNPREDICTABLE
+	ldmiaeq r0!, {r0, r1}	@ Encoding T2, UNPREDICTABLE
+
+	@ UNPREDICTABLE Thumb-2 encodings of STM/STMIA/STMEA as specified
+	@ by section A8.6.189 of the ARMARM.
+	stmia.w r0!, {r0-r3}	@ Encoding T2, UNPREDICTABLE
+	stmia r1!, {r0-r3}	@ Encoding T1, r1 is UNKNOWN
+	stmia r15!, {r0-r3}	@ Encoding T2, UNPREDICTABLE
+	stmia r15, {r0-r3}	@ Encoding T2, UNPREDICTABLE
+	stmia r8!, {r0-r11}     @ Encoding T2, UNPREDICTABLE
+
+	@ The following are technically UNDEFINED, but gas converts them to
+	@ an equivalent, and well-defined instruction automatically.
+	@stmia.w r0!, {r1}	@ str.w r1, [r0], #4
+	@stmia r8!, {r9}	@ str.w r9, [r8], #4
+	@stmia r8, {r9}		@ str.w r9, [r8]
+	@ldmia.w r0!, {r1}	@ ldr.w r1, [r0], #4
+	@ldmia r8!, {r9}	@ ldr.w r9, [r8], #4
+	@ldmia r8, {r9}		@ ldr.w r9, [r8]

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