From c95354ed1373286584d5729f3c0ce97cded6fbce Mon Sep 17 00:00:00 2001
From: Mingjie Xing <mingjie.xing@gmail.com>
Date: Tue, 11 Jan 2011 07:22:09 +0000
Subject: [PATCH] Take unadjusted offset for loongson3a specific instructions.

---
 gas/ChangeLog                          |  5 +++++
 gas/config/tc-mips.c                   | 17 +++++++++++++----
 gas/testsuite/ChangeLog                |  5 +++++
 gas/testsuite/gas/mips/loongson-3a-2.d |  8 ++++----
 gas/testsuite/gas/mips/loongson-3a-2.s |  8 ++++----
 opcodes/ChangeLog                      |  5 +++++
 opcodes/mips-dis.c                     |  3 ++-
 7 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 2318483169e..449aa73ebaf 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2011-01-11  Mingjie Xing  <mingjie.xing@gmail.com>
+
+	* config/tc-mips.c (mips_ip): Update error messages.  Take an
+	unadjusted offset for "+c" argument.
+
 2011-01-10  Nick Clifton  <nickc@redhat.com>
 
 	* config/tc-i386.c (x86_elf_abi): Only define for targets that use
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index ee9b276c3d9..ae37e02e09d 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -9321,7 +9321,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
 		  if (imm_expr.X_add_number < min_range
 		      || imm_expr.X_add_number > max_range)
 		    {
-		      as_bad (_("immediate not in range %ld..%ld (%ld)"),
+		      as_bad (_("Offset not in range %ld..%ld (%ld)"),
 		              (long) min_range, (long) max_range,
 		              (long) imm_expr.X_add_number);
 		    }
@@ -9338,7 +9338,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
 		  if (imm_expr.X_add_number < min_range
 		      || imm_expr.X_add_number > max_range)
 		    {
-		      as_bad (_("immediate not in range %ld..%ld (%ld)"),
+		      as_bad (_("Offset not in range %ld..%ld (%ld)"),
 		              (long) min_range, (long) max_range,
 		              (long) imm_expr.X_add_number);
 		    }
@@ -9352,14 +9352,23 @@ mips_ip (char *str, struct mips_cl_insn *ip)
 		  check_absolute_expr (ip, &imm_expr);
 		  min_range = -((OP_MASK_OFFSET_C + 1) >> 1);
 		  max_range = ((OP_MASK_OFFSET_C + 1) >> 1) - 1;
+		  /* We check the offset range before adjusted.  */
+		  min_range <<= 4;
+		  max_range <<= 4;
 		  if (imm_expr.X_add_number < min_range
 		      || imm_expr.X_add_number > max_range)
 		    {
-		      as_bad (_("immediate not in range %ld..%ld (%ld)"),
+		      as_bad (_("Offset not in range %ld..%ld (%ld)"),
 		              (long) min_range, (long) max_range,
 		              (long) imm_expr.X_add_number);
 		    }
-		  INSERT_OPERAND (OFFSET_C, *ip, imm_expr.X_add_number);
+		  if (imm_expr.X_add_number & 0xf)
+		    {
+		      as_bad (_("Offset not 16 bytes alignment (%ld)"),
+			      (long) imm_expr.X_add_number);
+		    }
+		  /* Right shift 4 bits to adjust the offset operand.  */
+		  INSERT_OPERAND (OFFSET_C, *ip, imm_expr.X_add_number >> 4);
 		  imm_expr.X_op = O_absent;
 		  s = expr_end;
 		  continue;
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index d28da8dfe78..e63bd6565e1 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-01-11  Mingjie Xing  <mingjie.xing@gmail.com>
+
+	* mips/loongson-3a-2.s, mips/loongson-3a-2.d: Use the real offset
+	value in assembly.
+
 2011-01-10  Nathan Sidwell  <nathan@codesourcery.com>
 	    Glauber de Oliveira Costa  <glommer@gmail.com>
 
diff --git a/gas/testsuite/gas/mips/loongson-3a-2.d b/gas/testsuite/gas/mips/loongson-3a-2.d
index 4029a60d11f..32fea2e94b9 100644
--- a/gas/testsuite/gas/mips/loongson-3a-2.d
+++ b/gas/testsuite/gas/mips/loongson-3a-2.d
@@ -57,9 +57,9 @@ Disassembly of section .text:
 .*:	d8912c07 	gsldxc1	\$f17,-128\(\$4,\$5\)
 .*:	f8d23bfe 	gsswxc1	\$f18,127\(\$6,\$7\)
 .*:	f9134c07 	gssdxc1	\$f19,-128\(\$8,\$9\)
-.*:	c98b3fea 	gslq	\$10,\$11,255\(\$12\)
-.*:	e9ee402d 	gssq	\$13,\$14,-256\(\$15\)
-.*:	ca15bff4 	gslqc1	\$f20,\$f21,255\(\$16\)
-.*:	ea37c036 	gssqc1	\$f22,\$f23,-256\(\$17\)
+.*:	c98b3fea 	gslq	\$10,\$11,4080\(\$12\)
+.*:	e9ee402d 	gssq	\$13,\$14,-4096\(\$15\)
+.*:	ca15bff4 	gslqc1	\$f20,\$f21,4080\(\$16\)
+.*:	ea37c036 	gssqc1	\$f22,\$f23,-4096\(\$17\)
 #pass
 
diff --git a/gas/testsuite/gas/mips/loongson-3a-2.s b/gas/testsuite/gas/mips/loongson-3a-2.s
index 16a38c9032b..c296b06675f 100644
--- a/gas/testsuite/gas/mips/loongson-3a-2.s
+++ b/gas/testsuite/gas/mips/loongson-3a-2.s
@@ -58,8 +58,8 @@
 	gsswxc1		$f18,127($6,$7)
 	gssdxc1		$f19,-128($8,$9)
 
-	gslq		$10,$11,255($12) 
-	gssq		$13,$14,-256($15)
-	gslqc1		$f20,$f21,255($16)
-	gssqc1		$f22,$f23,-256($17)
+	gslq		$10,$11,4080($12)
+	gssq		$13,$14,-4096($15)
+	gslqc1		$f20,$f21,4080($16)
+	gssqc1		$f22,$f23,-4096($17)
 
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index f7b2fa901ba..a8635108682 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,8 @@
+2011-01-11  Mingjie Xing  <mingjie.xing@gmail.com>
+
+	* mips-dis.c (print_insn_args): Adjust the value to print the real
+	offset for "+c" argument.
+
 2011-01-10  Nick Clifton  <nickc@redhat.com>
 
 	* po/da.po: Updated Danish translation.
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index ca65d71f599..c38a7e164c1 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -991,7 +991,8 @@ print_insn_args (const char *d,
 	      delta = (l >> OP_SH_OFFSET_C) & OP_MASK_OFFSET_C;
 	      if (delta & 0x100)
 		delta |= ~OP_MASK_OFFSET_C;
-	      (*info->fprintf_func) (info->stream, "%d", delta);
+	      /* Left shift 4 bits to print the real offset.  */
+	      (*info->fprintf_func) (info->stream, "%d", delta << 4);
 	      break;
 
 	    case 'z':