From 3a21c15a776c549411131dbb9f26d4e0f9b87d57 Mon Sep 17 00:00:00 2001
From: Nick Clifton <nickc@redhat.com>
Date: Thu, 18 Jun 2009 16:36:05 +0000
Subject: [PATCH]         PR 10169         * gas/tc-arm.c (do_t_ssat): Move
 common code from here...         (do_t_usat): ... and here to...        
 (do_t_ssat_usat): New function: ... here.  Add code to check that         the
 shift value, if present, is in range.

        * gas/arm/thumb2_bad_reg.s: Add tests for SSAT and USAT with an
        out of range shift.
        * gas/arm/thumb2_bad_reg.l: Update expected error messages.
---
 gas/ChangeLog                          |  8 ++++
 gas/config/tc-arm.c                    | 54 ++++++++++----------------
 gas/testsuite/ChangeLog                |  5 +++
 gas/testsuite/gas/arm/thumb2_bad_reg.l |  2 +
 gas/testsuite/gas/arm/thumb2_bad_reg.s |  2 +
 5 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 3f8aa0650fe..2f19a40b6d2 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,11 @@
+2009-06-18  Nick Clifton  <nickc@redhat.com>
+
+	PR 10169
+	* gas/tc-arm.c (do_t_ssat): Move common code from here...
+	(do_t_usat): ... and here to...
+	(do_t_ssat_usat): New function: ... here.  Add code to check that
+	the shift value, if present, is in range.
+
 2009-06-18  Dave Korn  <dave.korn.cygwin@gmail.com>
 
 	Merge cegcc and mingw32ce target name changes
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 67d8cc998f7..1190696d573 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -10654,7 +10654,7 @@ do_t_smc (void)
 }
 
 static void
-do_t_ssat (void)
+do_t_ssat_usat (int bias)
 {
   unsigned Rd, Rn;
 
@@ -10665,24 +10665,37 @@ do_t_ssat (void)
   reject_bad_reg (Rn);
 
   inst.instruction |= Rd << 8;
-  inst.instruction |= inst.operands[1].imm - 1;
+  inst.instruction |= inst.operands[1].imm - bias;
   inst.instruction |= Rn << 16;
 
   if (inst.operands[3].present)
     {
+      offsetT shift_amount = inst.reloc.exp.X_add_number;
+
+      inst.reloc.type = BFD_RELOC_UNUSED;
+
       constraint (inst.reloc.exp.X_op != O_constant,
 		  _("expression too complex"));
 
-      if (inst.reloc.exp.X_add_number != 0)
+      if (shift_amount != 0)
 	{
+	  constraint (shift_amount > 31,
+		      _("shift expression is too large"));
+
 	  if (inst.operands[3].shift_kind == SHIFT_ASR)
-	    inst.instruction |= 0x00200000;  /* sh bit */
-	  inst.instruction |= (inst.reloc.exp.X_add_number & 0x1c) << 10;
-	  inst.instruction |= (inst.reloc.exp.X_add_number & 0x03) << 6;
+	    inst.instruction |= 0x00200000;  /* sh bit.  */
+
+	  inst.instruction |= (shift_amount & 0x1c) << 10;
+	  inst.instruction |= (shift_amount & 0x03) << 6;
 	}
-      inst.reloc.type = BFD_RELOC_UNUSED;
     }
 }
+  
+static void
+do_t_ssat (void)
+{
+  do_t_ssat_usat (1);
+}
 
 static void
 do_t_ssat16 (void)
@@ -10818,32 +10831,7 @@ do_t_tb (void)
 static void
 do_t_usat (void)
 {
-  unsigned Rd, Rn;
-
-  Rd = inst.operands[0].reg;
-  Rn = inst.operands[2].reg;
-
-  reject_bad_reg (Rd);
-  reject_bad_reg (Rn);
-
-  inst.instruction |= Rd << 8;
-  inst.instruction |= inst.operands[1].imm;
-  inst.instruction |= Rn << 16;
-
-  if (inst.operands[3].present)
-    {
-      constraint (inst.reloc.exp.X_op != O_constant,
-		  _("expression too complex"));
-      if (inst.reloc.exp.X_add_number != 0)
-	{
-	  if (inst.operands[3].shift_kind == SHIFT_ASR)
-	    inst.instruction |= 0x00200000;  /* sh bit */
-
-	  inst.instruction |= (inst.reloc.exp.X_add_number & 0x1c) << 10;
-	  inst.instruction |= (inst.reloc.exp.X_add_number & 0x03) << 6;
-	}
-      inst.reloc.type = BFD_RELOC_UNUSED;
-    }
+  do_t_ssat_usat (0);
 }
 
 static void
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 5bac61e2934..a71903fe6a3 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,5 +1,10 @@
 2009-06-18  Nick Clifton  <nickc@redhat.com>
 
+	PR 10169
+	* gas/arm/thumb2_bad_reg.s: Add tests for SSAT and USAT with an
+	out of range shift.
+	* gas/arm/thumb2_bad_reg.l: Update expected error messages.
+
 	PR 10288
 	* gas/arm/align.s: Add labels so that COFF based targets can
 	correctly locate THUMB code.
diff --git a/gas/testsuite/gas/arm/thumb2_bad_reg.l b/gas/testsuite/gas/arm/thumb2_bad_reg.l
index f22df10e017..1da7bac76b1 100644
--- a/gas/testsuite/gas/arm/thumb2_bad_reg.l
+++ b/gas/testsuite/gas/arm/thumb2_bad_reg.l
@@ -504,6 +504,7 @@
 [^:]*:[0-9]+: Error: r15 not allowed here -- `ssat r15,#1,r0'
 [^:]*:[0-9]+: Error: r13 not allowed here -- `ssat r0,#1,r13'
 [^:]*:[0-9]+: Error: r15 not allowed here -- `ssat r0,#1,r15'
+[^:]*:[0-9]+: Error: shift expression is too large -- `ssat r1,#1,r3,asr#32'
 [^:]*:[0-9]+: Error: r13 not allowed here -- `ssat16 r13,#1,r0'
 [^:]*:[0-9]+: Error: r15 not allowed here -- `ssat16 r15,#1,r0'
 [^:]*:[0-9]+: Error: r13 not allowed here -- `ssat16 r0,#1,r13'
@@ -731,6 +732,7 @@
 [^:]*:[0-9]+: Error: r15 not allowed here -- `usat r15,#1,r0'
 [^:]*:[0-9]+: Error: r13 not allowed here -- `usat r0,#1,r13'
 [^:]*:[0-9]+: Error: r15 not allowed here -- `usat r0,#1,r15'
+[^:]*:[0-9]+: Error: shift expression is too large -- `usat r1,#1,r3,asr#32'
 [^:]*:[0-9]+: Error: r13 not allowed here -- `usat16 r13,#1,r0'
 [^:]*:[0-9]+: Error: r15 not allowed here -- `usat16 r15,#1,r0'
 [^:]*:[0-9]+: Error: r13 not allowed here -- `usat16 r0,#1,r13'
diff --git a/gas/testsuite/gas/arm/thumb2_bad_reg.s b/gas/testsuite/gas/arm/thumb2_bad_reg.s
index 90c82e68963..20a26e09021 100644
--- a/gas/testsuite/gas/arm/thumb2_bad_reg.s
+++ b/gas/testsuite/gas/arm/thumb2_bad_reg.s
@@ -630,6 +630,7 @@ test:
 	ssat r15, #1, r0
 	ssat r0, #1, r13
 	ssat r0, #1, r15
+	ssat r1, #1, r3,asr #32
 	@ SSAT16
 	ssat16 r13, #1, r0
 	ssat16 r15, #1, r0
@@ -909,6 +910,7 @@ test:
 	usat r15, #1, r0
 	usat r0, #1, r13
 	usat r0, #1, r15
+	usat r1, #1, r3,asr #32
 	@ USAT16
 	usat16 r13, #1, r0
 	usat16 r15, #1, r0
-- 
GitLab