Implement various missing parts of the X86 compiler

Change-Id: I76f08580600befe268328f8cf7102c6146460c5e
diff --git a/src/disassembler_x86.cc b/src/disassembler_x86.cc
index 4c8c09a..d7ee80b 100644
--- a/src/disassembler_x86.cc
+++ b/src/disassembler_x86.cc
@@ -57,16 +57,14 @@
   DumpReg0(os, rex, reg_num, byte_operand, size_override);
 }
 
-static void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg,
-                        bool byte_operand, uint8_t size_override) {
+static void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg) {
   size_t reg_num = reg;  // TODO: combine with REX.B on 64bit
-  DumpReg0(os, rex, reg_num, byte_operand, size_override);
+  DumpReg0(os, rex, reg_num, false, 0);
 }
 
-static void DumpIndexReg(std::ostream& os, uint8_t rex, uint8_t reg,
-                         bool byte_operand, uint8_t size_override) {
+static void DumpIndexReg(std::ostream& os, uint8_t rex, uint8_t reg) {
   int reg_num = reg;  // TODO: combine with REX.X on 64bit
-  DumpReg0(os, rex, reg_num, byte_operand, size_override);
+  DumpReg0(os, rex, reg_num, false, 0);
 }
 
 static void DumpSegmentOverride(std::ostream& os, uint8_t segment_prefix) {
@@ -88,7 +86,7 @@
   const char** modrm_opcodes = NULL;
   do {
     switch (*instr) {
-      // Group 1 - lock and repeat prefixes:
+        // Group 1 - lock and repeat prefixes:
       case 0xF0:
       case 0xF2:
       case 0xF3:
@@ -203,6 +201,20 @@
   case 0x0F:  // 2 byte extended opcode
     instr++;
     switch (*instr) {
+      case 0x10: case 0x11:
+        if (prefix[0] == 0xF2) {
+          opcode << "movsd";
+        } else if (prefix[0] == 0xF3) {
+          opcode << "movss";
+        } else if (prefix[2] == 0x66) {
+          opcode << "movupd";
+        } else {
+          opcode << "movups";
+        }
+        has_modrm = true;
+        load = *instr == 0x10;
+        store = !load;
+        break;
       case 0x38:  // 3 byte extended opcode
         opcode << StringPrintf("unknown opcode '0F 38 %02X'", *instr);
         break;
@@ -214,6 +226,16 @@
         opcode << "j" << condition_codes[*instr & 0xF];
         branch_bytes = 4;
         break;
+      case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+      case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F:
+        opcode << "set" << condition_codes[*instr & 0xF];
+        modrm_opcodes = NULL;
+        reg_is_opcode = true;
+        has_modrm = true;
+        store = true;
+        break;
+      case 0xB6: opcode << "movzxb"; has_modrm = true; load = true; break;
+      case 0xB7: opcode << "movzxw"; has_modrm = true; load = true; break;
       default:
         opcode << StringPrintf("unknown opcode '0F %02X'", *instr);
         break;
@@ -228,6 +250,11 @@
     byte_operand = (*instr & 1) == 0;
     immediate_bytes = *instr == 0x81 ? 4 : 1;
     break;
+  case 0x8D:
+    opcode << "lea";
+    has_modrm = true;
+    load = true;
+    break;
   case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7:
     opcode << "mov";
     immediate_bytes = 1;
@@ -238,7 +265,19 @@
     immediate_bytes = 4;
     reg_in_opcode = true;
     break;
+  case 0xC0: case 0xC1:
+    static const char* shift_opcodes[] =
+        {"rol", "ror", "rcl", "rcr", "shl", "shr", "unknown-shift", "sar"};
+    modrm_opcodes = shift_opcodes;
+    has_modrm = true;
+    reg_is_opcode = true;
+    store = true;
+    immediate_bytes = 1;
+    byte_operand = *instr == 0xC0;
+    break;
   case 0xC3: opcode << "ret"; break;
+  case 0xCC: opcode << "int 3"; break;
+  case 0xE8: opcode << "call"; branch_bytes = 4; break;
   case 0xE9: opcode << "jmp"; branch_bytes = 4; break;
   case 0xEB: opcode << "jmp"; branch_bytes = 1; break;
   case 0xFF:
@@ -276,13 +315,13 @@
       uint8_t base = sib & 7;
       address << "[";
       if (base != 5 || mod != 0) {
-        DumpBaseReg(address, rex, base, byte_operand, prefix[2]);
+        DumpBaseReg(address, rex, base);
         if (index != 4) {
           address << " + ";
         }
       }
       if (index != 4) {
-        DumpIndexReg(address, rex, index, byte_operand, prefix[2]);
+        DumpIndexReg(address, rex, index);
         if (ss != 0) {
           address << StringPrintf(" * %d", 1 << ss);
         }
@@ -299,7 +338,7 @@
       if (mod != 3) {
         address << "[";
       }
-      DumpBaseReg(address, rex, rm, byte_operand, prefix[2]);
+      DumpBaseReg(address, rex, rm);
       if (mod == 1) {
         address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(instr));
         instr++;
@@ -312,7 +351,7 @@
       }
     }
 
-    if (reg_is_opcode) {
+    if (reg_is_opcode && modrm_opcodes != NULL) {
       opcode << modrm_opcodes[reg_or_opcode];
     }
     if (load) {