diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index 850795a..c831972 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -27,7 +27,7 @@ extern struct rtx_def *gen_compare_reg (rtx, machine_mode);
 /* Declarations for various fns used in the .md file.  */
 extern void arc_output_function_epilogue (FILE *, HOST_WIDE_INT, int);
 extern const char *output_shift (rtx *);
-extern bool compact_sda_memory_operand (rtx op,machine_mode  mode);
+extern bool compact_sda_memory_operand (rtx, machine_mode, bool);
 extern bool arc_double_limm_p (rtx);
 extern void arc_print_operand (FILE *, rtx, int);
 extern void arc_print_operand_address (FILE *, rtx);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 89de6cd..091bc89 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -3900,6 +3900,26 @@ arc_print_operand (FILE *file, rtx x, int code)
 		  fputs (".as", file);
 		  output_scaled = 1;
 		}
+	      else if (LEGITIMATE_SMALL_DATA_ADDRESS_P (addr)
+		       && GET_MODE_SIZE (GET_MODE (x)) > 1)
+		{
+		  tree decl = NULL_TREE;
+		  int align = 0;
+		  if (GET_CODE (XEXP (addr, 1)) == SYMBOL_REF)
+		    decl = SYMBOL_REF_DECL (XEXP (addr, 1));
+		  else if (GET_CODE (XEXP (XEXP (XEXP (addr, 1), 0), 0))
+			   == SYMBOL_REF)
+		    decl = SYMBOL_REF_DECL (XEXP (XEXP (XEXP (addr, 1), 0), 0));
+		  if (decl)
+		    align = DECL_ALIGN (decl);
+		  align = align / BITS_PER_UNIT;
+		  if ((GET_MODE_SIZE (GET_MODE (x)) == 2)
+		      && align && ((align & 1) == 0))
+		    fputs (".as", file);
+		  if ((GET_MODE_SIZE (GET_MODE (x)) >= 4)
+		      && align && ((align & 3) == 0))
+		    fputs (".as", file);
+		}
 	      break;
 	    case REG:
 	      break;
@@ -7571,12 +7591,10 @@ arc_in_small_data_p (const_tree decl)
 {
   HOST_WIDE_INT size;
 
+  /* Strings and functions are never in small data area.  */
   if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
     return false;
 
-
-  /* We don't yet generate small-data references for -mabicalls.  See related
-     -G handling in override_options.  */
   if (TARGET_NO_SDATA_SET)
     return false;
 
@@ -7595,7 +7613,7 @@ arc_in_small_data_p (const_tree decl)
 	  return true;
     }
   /* Only global variables go into sdata section for now.  */
-  else if (1)
+  else
     {
       /* Don't put constants into the small data section: we want them
 	 to be in ROM rather than RAM.  */
@@ -7625,9 +7643,6 @@ arc_in_small_data_p (const_tree decl)
 
   size = int_size_in_bytes (TREE_TYPE (decl));
 
-/*   if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
-/*     return false; */
-
   /* Allow only <=4B long data types into sdata.  */
   return (size > 0 && size <= 4);
 }
@@ -7719,10 +7734,13 @@ small_data_pattern (rtx op, machine_mode)
 /* volatile cache option still to be handled.  */
 
 bool
-compact_sda_memory_operand (rtx op, machine_mode mode)
+compact_sda_memory_operand (rtx op, machine_mode mode, bool short_p)
 {
   rtx addr;
   int size;
+  tree decl = NULL_TREE;
+  int align = 0;
+  int mask = 0;
 
   /* Eliminate non-memory operations.  */
   if (GET_CODE (op) != MEM)
@@ -7740,7 +7758,35 @@ compact_sda_memory_operand (rtx op, machine_mode mode)
   /* Decode the address now.  */
   addr = XEXP (op, 0);
 
-  return LEGITIMATE_SMALL_DATA_ADDRESS_P  (addr);
+  if (!LEGITIMATE_SMALL_DATA_ADDRESS_P (addr))
+    return false;
+
+  if (!short_p || size == 1)
+    return true;
+
+  /* Now check for the alignment, the short loads using gp require the
+     addresses to be aligned.  */
+  if (GET_CODE (XEXP (addr, 1)) == SYMBOL_REF)
+    decl = SYMBOL_REF_DECL (XEXP (addr, 1));
+  else if (GET_CODE (XEXP (XEXP (XEXP (addr, 1), 0), 0)) == SYMBOL_REF)
+    decl = SYMBOL_REF_DECL (XEXP (XEXP (XEXP (addr, 1), 0), 0));
+  if (decl)
+    align = DECL_ALIGN (decl);
+  align = align / BITS_PER_UNIT;
+
+  switch (mode)
+    {
+    case HImode:
+      mask = 1;
+      break;
+    default:
+      mask = 3;
+      break;
+    }
+
+  if (align && ((align & mask) == 0))
+    return true;
+  return false;
 }
 
 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL.  */
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index 6620daf..0ad318c 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -355,7 +355,7 @@
    "@internal
     A valid _small-data_ memory operand for ARCompact instructions"
    (and (match_code "mem")
-	(match_test "compact_sda_memory_operand (op, VOIDmode)")))
+	(match_test "compact_sda_memory_operand (op, VOIDmode, true)")))
 
 (define_memory_constraint "Usc"
   "@internal
@@ -363,7 +363,7 @@
   (and (match_code "mem")
        (match_test "!CONSTANT_P (XEXP (op,0))")
 ;; ??? the assembler rejects stores of immediates to small data.
-       (match_test "!compact_sda_memory_operand (op, VOIDmode)")))
+       (match_test "!compact_sda_memory_operand (op, VOIDmode, false)")))
 
 (define_constraint "Us<"
   "@internal
diff --git a/gcc/testsuite/gcc.target/arc/sdata-3.c b/gcc/testsuite/gcc.target/arc/sdata-3.c
new file mode 100644
index 0000000..cdf3b6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/sdata-3.c
@@ -0,0 +1,32 @@
+/* Check if sdata access is done correctly, specially
+   for variables which are having a different alignment
+   than the default data type indicates.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int g_a __attribute__ ((aligned (1)));
+int g_b;
+short g_c;
+char g_d;
+
+#define TEST(name, optype)			\
+  void test_ ## name (optype x)			\
+  {						\
+    g_ ## name += x;				\
+  }
+
+TEST (a, int)
+TEST (b, int)
+TEST (c, short)
+TEST (d, char)
+
+/* { dg-final { scan-assembler "ld r2,\\\[gp,@g_a@sda\\\]" } } */
+/* { dg-final { scan-assembler "ld.as r2,\\\[gp,@g_b@sda\\\]" } } */
+/* { dg-final { scan-assembler "ld\[hw\]\\\.as r2,\\\[gp,@g_c@sda\\\]" } } */
+/* { dg-final { scan-assembler "ldb r2,\\\[gp,@g_d@sda\\\]" } } */
+
+/* { dg-final { scan-assembler "st r0,\\\[gp,@g_a@sda\\\]" } } */
+/* { dg-final { scan-assembler "st_s r0,\\\[gp,@g_b@sda\\\]" { target { arcem || archs } } } } */
+/* { dg-final { scan-assembler "st\\\.as r0,\\\[gp,@g_b@sda\\\]" { target { arc700 || arc6xx } } } } */
+/* { dg-final { scan-assembler "st\[hw\]\\\.as r0,\\\[gp,@g_c@sda\\\]" } } */
+/* { dg-final { scan-assembler "stb r0,\\\[gp,@g_d@sda\\\]" } } */
diff --git a/gcc/testsuite/gcc.target/arc/sdata-4.c b/gcc/testsuite/gcc.target/arc/sdata-4.c
new file mode 100644
index 0000000..45fe712
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/sdata-4.c
@@ -0,0 +1,15 @@
+/* Check if sdata access is done correctly, specially
+   for variables which are having a different alignment
+   than the default data type indicates.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+short gA  __attribute__ ((aligned(1)));
+
+void foo (void)
+{
+  gA += gA + 3;
+}
+
+/* { dg-final { scan-assembler-not "ld\[wh\]_s r0,\\\[gp" } } */
+/* { dg-final { scan-assembler-not "st\[wh\]\\\.as.*gp" } } */
