Subzero: Fix emission of 16-bit immediates.

The operand type needs to be propagated into EmitImmediate() and EmitComplex() so that we know whether to emit the 2-byte or 4-byte form.

BUG= none
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/607353002
diff --git a/src/assembler_ia32.cpp b/src/assembler_ia32.cpp
index 34e7a42..9545dc0 100644
--- a/src/assembler_ia32.cpp
+++ b/src/assembler_ia32.cpp
@@ -25,6 +25,8 @@
 namespace Ice {
 namespace x86 {
 
+const Type BrokenType = IceType_i32;
+
 class DirectCallRelocation : public AssemblerFixup {
 public:
   static DirectCallRelocation *create(Assembler *Asm, FixupKind Kind,
@@ -105,7 +107,7 @@
 void AssemblerX86::pushl(const Immediate &imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x68);
-  EmitImmediate(imm);
+  EmitImmediate(BrokenType, imm);
 }
 
 void AssemblerX86::popl(GPRRegister reg) {
@@ -139,7 +141,7 @@
 void AssemblerX86::movl(GPRRegister dst, const Immediate &imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xB8 + dst);
-  EmitImmediate(imm);
+  EmitImmediate(BrokenType, imm);
 }
 
 void AssemblerX86::movl(GPRRegister dst, GPRRegister src) {
@@ -164,7 +166,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xC7);
   EmitOperand(0, dst);
-  EmitImmediate(imm);
+  EmitImmediate(BrokenType, imm);
 }
 
 void AssemblerX86::movzxb(GPRRegister dst, ByteRegister src) {
@@ -1131,7 +1133,7 @@
 
 void AssemblerX86::cmpl(GPRRegister reg, const Immediate &imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
-  EmitComplex(7, Operand(reg), imm);
+  EmitComplex(BrokenType, 7, Operand(reg), imm);
 }
 
 void AssemblerX86::cmpl(GPRRegister reg0, GPRRegister reg1) {
@@ -1154,7 +1156,7 @@
 
 void AssemblerX86::cmpl(const Address &address, const Immediate &imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
-  EmitComplex(7, address, imm);
+  EmitComplex(BrokenType, 7, address, imm);
 }
 
 void AssemblerX86::cmpb(const Address &address, const Immediate &imm) {
@@ -1187,11 +1189,11 @@
   } else if (reg == RegX8632::Encoded_Reg_eax) {
     // Use short form if the destination is EAX.
     EmitUint8(0xA9);
-    EmitImmediate(immediate);
+    EmitImmediate(BrokenType, immediate);
   } else {
     EmitUint8(0xF7);
     EmitOperand(0, Operand(reg));
-    EmitImmediate(immediate);
+    EmitImmediate(BrokenType, immediate);
   }
 }
 
@@ -1225,7 +1227,7 @@
   }
   if (Ty == IceType_i16)
     EmitOperandSizeOverride();
-  EmitComplex(4, Operand(dst), imm);
+  EmitComplex(Ty, 4, Operand(dst), imm);
 }
 
 void AssemblerX86::Or(Type Ty, GPRRegister dst, GPRRegister src) {
@@ -1258,7 +1260,7 @@
   }
   if (Ty == IceType_i16)
     EmitOperandSizeOverride();
-  EmitComplex(1, Operand(dst), imm);
+  EmitComplex(Ty, 1, Operand(dst), imm);
 }
 
 void AssemblerX86::Xor(Type Ty, GPRRegister dst, GPRRegister src) {
@@ -1291,7 +1293,7 @@
   }
   if (Ty == IceType_i16)
     EmitOperandSizeOverride();
-  EmitComplex(6, Operand(dst), imm);
+  EmitComplex(Ty, 6, Operand(dst), imm);
 }
 
 void AssemblerX86::add(Type Ty, GPRRegister dst, GPRRegister src) {
@@ -1324,7 +1326,7 @@
   }
   if (Ty == IceType_i16)
     EmitOperandSizeOverride();
-  EmitComplex(0, Operand(reg), imm);
+  EmitComplex(Ty, 0, Operand(reg), imm);
 }
 
 void AssemblerX86::adc(Type Ty, GPRRegister dst, GPRRegister src) {
@@ -1357,7 +1359,7 @@
   }
   if (Ty == IceType_i16)
     EmitOperandSizeOverride();
-  EmitComplex(2, Operand(reg), imm);
+  EmitComplex(Ty, 2, Operand(reg), imm);
 }
 
 void AssemblerX86::sub(Type Ty, GPRRegister dst, GPRRegister src) {
@@ -1390,7 +1392,7 @@
   }
   if (Ty == IceType_i16)
     EmitOperandSizeOverride();
-  EmitComplex(5, Operand(reg), imm);
+  EmitComplex(Ty, 5, Operand(reg), imm);
 }
 
 void AssemblerX86::sbb(Type Ty, GPRRegister dst, GPRRegister src) {
@@ -1423,7 +1425,7 @@
   }
   if (Ty == IceType_i16)
     EmitOperandSizeOverride();
-  EmitComplex(3, Operand(reg), imm);
+  EmitComplex(Ty, 3, Operand(reg), imm);
 }
 
 void AssemblerX86::cbw() {
@@ -1498,7 +1500,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x69);
   EmitOperand(reg, Operand(reg));
-  EmitImmediate(imm);
+  EmitImmediate(BrokenType, imm);
 }
 
 void AssemblerX86::imull(GPRRegister reg, const Address &address) {
@@ -1987,8 +1989,11 @@
   }
 }
 
-void AssemblerX86::EmitImmediate(const Immediate &imm) {
-  EmitInt32(imm.value());
+void AssemblerX86::EmitImmediate(Type Ty, const Immediate &imm) {
+  if (Ty == IceType_i16)
+    EmitInt16(imm.value());
+  else
+    EmitInt32(imm.value());
 }
 
 void AssemblerX86::EmitComplexI8(int rm, const Operand &operand,
@@ -2007,7 +2012,7 @@
   }
 }
 
-void AssemblerX86::EmitComplex(int rm, const Operand &operand,
+void AssemblerX86::EmitComplex(Type Ty, int rm, const Operand &operand,
                                const Immediate &immediate) {
   assert(rm >= 0 && rm < 8);
   if (immediate.is_int8()) {
@@ -2018,11 +2023,11 @@
   } else if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) {
     // Use short form if the destination is eax.
     EmitUint8(0x05 + (rm << 3));
-    EmitImmediate(immediate);
+    EmitImmediate(Ty, immediate);
   } else {
     EmitUint8(0x81);
     EmitOperand(rm, operand);
-    EmitImmediate(immediate);
+    EmitImmediate(Ty, immediate);
   }
 }
 
diff --git a/src/assembler_ia32.h b/src/assembler_ia32.h
index 83c0b66..5066397 100644
--- a/src/assembler_ia32.h
+++ b/src/assembler_ia32.h
@@ -700,6 +700,7 @@
 
 private:
   inline void EmitUint8(uint8_t value);
+  inline void EmitInt16(int16_t value);
   inline void EmitInt32(int32_t value);
   inline void EmitRegisterOperand(int rm, int reg);
   inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
@@ -707,10 +708,11 @@
   inline void EmitOperandSizeOverride();
 
   void EmitOperand(int rm, const Operand &operand);
-  void EmitImmediate(const Immediate &imm);
+  void EmitImmediate(Type ty, const Immediate &imm);
   void EmitComplexI8(int rm, const Operand &operand,
                      const Immediate &immediate);
-  void EmitComplex(int rm, const Operand &operand, const Immediate &immediate);
+  void EmitComplex(Type Ty, int rm, const Operand &operand,
+                   const Immediate &immediate);
   void EmitLabel(Label *label, intptr_t instruction_size);
   void EmitLabelLink(Label *label);
   void EmitNearLabelLink(Label *label);
@@ -728,6 +730,10 @@
   buffer_.Emit<uint8_t>(value);
 }
 
+inline void AssemblerX86::EmitInt16(int16_t value) {
+  buffer_.Emit<int16_t>(value);
+}
+
 inline void AssemblerX86::EmitInt32(int32_t value) {
   buffer_.Emit<int32_t>(value);
 }
diff --git a/tests_lit/assembler/x86/immediate_encodings.ll b/tests_lit/assembler/x86/immediate_encodings.ll
index 2a9fcb4..a80fe5b 100644
--- a/tests_lit/assembler/x86/immediate_encodings.ll
+++ b/tests_lit/assembler/x86/immediate_encodings.ll
@@ -44,6 +44,67 @@
 ; CHECK-LABEL: testXor8Imm8NotEAX
 ; CHECK: 80 f{{[1-3]}} 7f xor {{[^a]}}l, 127
 
+define internal i32 @testXor16Imm8(i32 %arg) {
+entry:
+  %arg_i16 = trunc i32 %arg to i16
+  %result_i16 = xor i16 %arg_i16, 127
+  %result = zext i16 %result_i16 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testXor16Imm8
+; CHECK: 66 83 f0 7f  xor ax, 127
+
+define internal i32 @testXor16Imm8Neg(i32 %arg) {
+entry:
+  %arg_i16 = trunc i32 %arg to i16
+  %result_i16 = xor i16 %arg_i16, -128
+  %result = zext i16 %result_i16 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testXor16Imm8Neg
+; CHECK: 66 83 f0 80  xor ax, 128
+
+define internal i32 @testXor16Imm16Eax(i32 %arg) {
+entry:
+  %arg_i16 = trunc i32 %arg to i16
+  %tmp = xor i16 %arg_i16, 1024
+  %result_i16 = add i16 %tmp, 1
+  %result = zext i16 %result_i16 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testXor16Imm16Eax
+; CHECK: 66 35 00 04  xor ax, 1024
+; CHECK-NEXT: add ax, 1
+
+define internal i32 @testXor16Imm16NegEax(i32 %arg) {
+entry:
+  %arg_i16 = trunc i32 %arg to i16
+  %tmp = xor i16 %arg_i16, -256
+  %result_i16 = add i16 %tmp, 1
+  %result = zext i16 %result_i16 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testXor16Imm16NegEax
+; CHECK: 66 35 00 ff  xor ax, 65280
+; CHECK-NEXT: add ax, 1
+
+define internal i32 @testXor16Imm16NotEAX(i32 %arg_i32, i32 %arg2_i32, i32 %arg3_i32) {
+entry:
+  %arg = trunc i32 %arg_i32 to i16
+  %arg2 = trunc i32 %arg2_i32 to i16
+  %arg3 = trunc i32 %arg3_i32 to i16
+  %x = xor i16 %arg, 32767
+  %x2 = xor i16 %arg2, 32767
+  %x3 = xor i16 %arg3, 32767
+  %add1 = add i16 %x, %x2
+  %add2 = add i16 %add1, %x3
+  %result = zext i16 %add2 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testXor16Imm16NotEAX
+; CHECK: 66 81 f{{[1-3]}} ff 7f  xor {{[^a]}}x, 32767
+; CHECK-NEXT: 66 81 f{{[1-3]}} ff 7f  xor {{[^a]}}x, 32767
+
 define internal i32 @testXor32Imm8(i32 %arg) {
 entry:
   %result = xor i32 %arg, 127