From 1a1bccbeceb616920dea3f73e313573af408a3d2 Mon Sep 17 00:00:00 2001
From: Nguyen Anh Quynh <aquynh@gmail.com>
Date: Mon, 23 May 2016 03:20:31 +0800
Subject: [PATCH] x86: a better solution to not to emit SS prefix for stack
 memory operand

---
 .../Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp    | 13 ++++++++++---
 suite/regress/x86_ss_default.py                     |  2 ++
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index e9c7c13..92dd512 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -1238,6 +1238,8 @@ encodeInstruction(MCInst &MI, raw_ostream &OS,
   bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3;
   bool HasMemOp4 = TSFlags & X86II::MemOp4;
   const unsigned MemOp4_I8IMMOperand = 2;
+  unsigned BaseReg = 0;
+  unsigned SegReg = 0;
 
   // It uses the EVEX.aaa field?
   bool HasEVEX_K = TSFlags & X86II::EVEX_K;
@@ -1249,7 +1251,12 @@ encodeInstruction(MCInst &MI, raw_ostream &OS,
 
   // Emit segment override opcode prefix as needed.
   if (MemoryOperand >= 0) {
-    if ((TSFlags & X86II::FormMask) != X86II::MRMSrcMem) {
+    const MCOperand &Base = MI.getOperand(MemoryOperand + X86::AddrBaseReg);
+    BaseReg = Base.getReg();
+    const MCOperand &Seg = MI.getOperand(MemoryOperand + X86::AddrSegmentReg);
+    SegReg = Seg.getReg();
+
+    if ((SegReg != X86::SS) || (BaseReg != X86::ESP && BaseReg != X86::EBP)) {
         EmitSegmentOverridePrefix(CurByte, MemoryOperand+X86::AddrSegmentReg,
                 MI, OS);
     }
@@ -1280,7 +1287,7 @@ encodeInstruction(MCInst &MI, raw_ostream &OS,
     need_address_override = !Is16BitMemOperand(MI, MemoryOperand, STI);
   }
 
-  if ((TSFlags & X86II::FormMask) != X86II::MRMSrcMem) {
+  if ((SegReg != X86::SS) || (BaseReg != X86::ESP && BaseReg != X86::EBP)) {
       if (need_address_override)
           EmitByte(0x67, CurByte, OS);
 
@@ -1459,7 +1466,7 @@ encodeInstruction(MCInst &MI, raw_ostream &OS,
       ++FirstMemOp;
 
     const MCOperand &Base = MI.getOperand(FirstMemOp + X86::AddrBaseReg);
-    unsigned BaseReg = Base.getReg();
+    BaseReg = Base.getReg();
     EmitSegmentOverridePrefix(CurByte, MemoryOperand+X86::AddrSegmentReg,
             MI, OS, BaseReg);
 
diff --git a/suite/regress/x86_ss_default.py b/suite/regress/x86_ss_default.py
index 7e3b156..1a2eebb 100755
--- a/suite/regress/x86_ss_default.py
+++ b/suite/regress/x86_ss_default.py
@@ -20,5 +20,7 @@ class TestX86(regress.RegressTest):
         self.assertEqual(encoding1, [ 0x8B, 0x44, 0x24, 0x08 ])
         self.assertEqual(encoding2, [ 0x8B, 0x45, 0x08 ])
 
+        encoding, _ = ks.asm(b"MOV DWORD PTR SS:[EBP-0xC],0x1994000")
+        self.assertEqual(encoding, [ 0xC7, 0x45, 0xF4, 0x00, 0x40, 0x99, 0x01 ])
 if __name__ == '__main__':
     regress.main()
-- 
GitLab