Fix x86 and x64 codegens for 8/16 stores.

Test: 660-store-8-16
Change-Id: I6124818894205ebeed83929f3ff00bf2733292bf
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 73202b4..51a0bae 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -446,6 +446,16 @@
     return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0);
   }
 
+  static int8_t GetInt8ValueOf(HConstant* constant) {
+    DCHECK(constant->IsIntConstant());
+    return constant->AsIntConstant()->GetValue();
+  }
+
+  static int16_t GetInt16ValueOf(HConstant* constant) {
+    DCHECK(constant->IsIntConstant());
+    return constant->AsIntConstant()->GetValue();
+  }
+
   static int32_t GetInt32ValueOf(HConstant* constant) {
     if (constant->IsIntConstant()) {
       return constant->AsIntConstant()->GetValue();
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index af0e646..e5549fe 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4956,8 +4956,8 @@
     case Primitive::kPrimShort:
     case Primitive::kPrimChar: {
       if (value.IsConstant()) {
-        int16_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
-        __ movw(Address(base, offset), Immediate(v));
+        __ movw(Address(base, offset),
+                Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant())));
       } else {
         __ movw(Address(base, offset), value.AsRegister<Register>());
       }
@@ -5404,7 +5404,7 @@
       if (value.IsRegister()) {
         __ movb(address, value.AsRegister<ByteRegister>());
       } else {
-        __ movb(address, Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
+        __ movb(address, Immediate(CodeGenerator::GetInt8ValueOf(value.GetConstant())));
       }
       codegen_->MaybeRecordImplicitNullCheck(instruction);
       break;
@@ -5417,7 +5417,7 @@
       if (value.IsRegister()) {
         __ movw(address, value.AsRegister<Register>());
       } else {
-        __ movw(address, Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
+        __ movw(address, Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant())));
       }
       codegen_->MaybeRecordImplicitNullCheck(instruction);
       break;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 86f6d51..8283887 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -4425,8 +4425,8 @@
     case Primitive::kPrimBoolean:
     case Primitive::kPrimByte: {
       if (value.IsConstant()) {
-        int8_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
-        __ movb(Address(base, offset), Immediate(v));
+        __ movb(Address(base, offset),
+                Immediate(CodeGenerator::GetInt8ValueOf(value.GetConstant())));
       } else {
         __ movb(Address(base, offset), value.AsRegister<CpuRegister>());
       }
@@ -4436,8 +4436,8 @@
     case Primitive::kPrimShort:
     case Primitive::kPrimChar: {
       if (value.IsConstant()) {
-        int16_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
-        __ movw(Address(base, offset), Immediate(v));
+        __ movw(Address(base, offset),
+                Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant())));
       } else {
         __ movw(Address(base, offset), value.AsRegister<CpuRegister>());
       }
@@ -4861,7 +4861,7 @@
       if (value.IsRegister()) {
         __ movb(address, value.AsRegister<CpuRegister>());
       } else {
-        __ movb(address, Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
+        __ movb(address, Immediate(CodeGenerator::GetInt8ValueOf(value.GetConstant())));
       }
       codegen_->MaybeRecordImplicitNullCheck(instruction);
       break;
@@ -4875,7 +4875,7 @@
         __ movw(address, value.AsRegister<CpuRegister>());
       } else {
         DCHECK(value.IsConstant()) << value;
-        __ movw(address, Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
+        __ movw(address, Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant())));
       }
       codegen_->MaybeRecordImplicitNullCheck(instruction);
       break;
diff --git a/test/660-store-8-16/expected.txt b/test/660-store-8-16/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/660-store-8-16/expected.txt
diff --git a/test/660-store-8-16/info.txt b/test/660-store-8-16/info.txt
new file mode 100644
index 0000000..aad6c56
--- /dev/null
+++ b/test/660-store-8-16/info.txt
@@ -0,0 +1,3 @@
+Regression test for the compiler whose x86 and x64 backends
+used to crash on 8bits / 16bits immediate stores when the Java
+input was a wide immediate.
diff --git a/test/660-store-8-16/smali/TestCase.smali b/test/660-store-8-16/smali/TestCase.smali
new file mode 100644
index 0000000..ec8cbd8
--- /dev/null
+++ b/test/660-store-8-16/smali/TestCase.smali
@@ -0,0 +1,102 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LTestCase;
+
+.super Ljava/lang/Object;
+
+.method public static setByteArray([B)V
+  .registers 3
+  const/16 v0, 0x0
+  const/16 v1, 0x0101
+  aput-byte v1, p0, v0
+  return-void
+.end method
+
+.method public static setByteStaticField()V
+  .registers 1
+  const/16 v0, 0x0101
+  sput-byte v0, LTestCase;->staticByteField:B
+  return-void
+.end method
+
+.method public static setByteInstanceField(LTestCase;)V
+  .registers 2
+  const/16 v0, 0x0101
+  iput-byte v0, p0, LTestCase;->instanceByteField:B
+  return-void
+.end method
+
+.method public constructor <init>()V
+    .registers 1
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
+.method public static setShortArray([S)V
+  .registers 3
+  const/16 v0, 0x0
+  const v1, 0x10101
+  aput-short v1, p0, v0
+  return-void
+.end method
+
+.method public static setShortStaticField()V
+  .registers 1
+  const v0, 0x10101
+  sput-short v0, LTestCase;->staticShortField:S
+  return-void
+.end method
+
+.method public static setShortInstanceField(LTestCase;)V
+  .registers 2
+  const v0, 0x10101
+  iput-short v0, p0, LTestCase;->instanceShortField:S
+  return-void
+.end method
+
+.method public static setCharArray([C)V
+  .registers 3
+  const/16 v0, 0x0
+  const v1, 0x10101
+  aput-char v1, p0, v0
+  return-void
+.end method
+
+.method public static setCharStaticField()V
+  .registers 1
+  const v0, 0x10101
+  sput-char v0, LTestCase;->staticCharField:C
+  return-void
+.end method
+
+.method public static setCharInstanceField(LTestCase;)V
+  .registers 2
+  const v0, 0x10101
+  iput-char v0, p0, LTestCase;->instanceCharField:C
+  return-void
+.end method
+
+.method public constructor <init>()V
+    .registers 1
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
+.field public static staticByteField:B
+.field public instanceByteField:B
+.field public static staticShortField:S
+.field public instanceShortField:S
+.field public static staticCharField:C
+.field public instanceCharField:C
diff --git a/test/660-store-8-16/src/Main.java b/test/660-store-8-16/src/Main.java
new file mode 100644
index 0000000..32b2568
--- /dev/null
+++ b/test/660-store-8-16/src/Main.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+  public static void expectEquals(int expected, int actual) {
+    if (expected != actual) {
+      throw new Error("Expected " + expected + ", got " + actual);
+    }
+  }
+
+  public static void main(String[] unused) throws Exception {
+    Class<?> cls = Class.forName("TestCase");
+
+    cls.getMethod("setByteStaticField").invoke(null);
+    expectEquals(1, cls.getField("staticByteField").getByte(null));
+
+    cls.getMethod("setShortStaticField").invoke(null);
+    expectEquals(0x101, cls.getField("staticShortField").getShort(null));
+
+    cls.getMethod("setCharStaticField").invoke(null);
+    expectEquals(0x101, cls.getField("staticCharField").getChar(null));
+
+    {
+      Object[] args = { new byte[2] };
+      cls.getMethod("setByteArray", byte[].class).invoke(null, args);
+      expectEquals(1, ((byte[])args[0])[0]);
+    }
+    {
+      Object[] args = { new short[2] };
+      cls.getMethod("setShortArray", short[].class).invoke(null, args);
+      expectEquals(0x101, ((short[])args[0])[0]);
+    }
+    {
+      Object[] args = { new char[2] };
+      cls.getMethod("setCharArray", char[].class).invoke(null, args);
+      expectEquals(0x101, ((char[])args[0])[0]);
+    }
+    {
+      Object[] args = { cls.newInstance() };
+
+      cls.getMethod("setByteInstanceField", cls).invoke(null, args);
+      expectEquals(1, cls.getField("staticByteField").getByte(args[0]));
+
+      cls.getMethod("setShortInstanceField", cls).invoke(null, args);
+      expectEquals(0x101, cls.getField("staticShortField").getShort(args[0]));
+
+      cls.getMethod("setCharInstanceField", cls).invoke(null, args);
+      expectEquals(0x101, cls.getField("staticCharField").getChar(args[0]));
+    }
+  }
+}