Beginning of X86 encoding map and instruction size routine.

Change-Id: Idaa0d5e0852d7bcfeabff443a45223a078ad02d2
diff --git a/src/compiler/codegen/x86/Assemble.cc b/src/compiler/codegen/x86/Assemble.cc
index f098e66..722f7bb 100644
--- a/src/compiler/codegen/x86/Assemble.cc
+++ b/src/compiler/codegen/x86/Assemble.cc
@@ -24,66 +24,121 @@
 
 #define MAX_ASSEMBLER_RETRIES 50
 
-/*
- * opcode: X86OpCode enum
- * skeleton: pre-designated bit-pattern for this opcode
- * k0: key to applying ds/de
- * ds: dest start bit position
- * de: dest end bit position
- * k1: key to applying s1s/s1e
- * s1s: src1 start bit position
- * s1e: src1 end bit position
- * k2: key to applying s2s/s2e
- * s2s: src2 start bit position
- * s2e: src2 end bit position
- * operands: number of operands (for sanity check purposes)
- * name: mnemonic name
- * fmt: for pretty-printing
- */
-#define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
-                     k3, k3s, k3e, flags, name, fmt, size) \
-        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
-                    {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
+#define BINARY_ENCODING_MAP(opcode, \
+                            rm8_r8, rm32_r32, \
+                            r8_rm8, r32_rm32, \
+                            rax8_i8, rax32_i32, \
+                            rm8_i8_opcode, rm8_i8_modrm, \
+                            rm32_i32_opcode, rm32_i32_modrm, \
+                            rm32_i8_opcode, rm32_i8_modrm) \
+{ kOp ## opcode ## RI, \
+  kRegImm, \
+  0, \
+  { RegMem_Immediate: { rax8_i8, rax32_i32, \
+                       {rm8_i8_opcode, rm8_i8_modrm}, \
+                       {rm32_i32_opcode, rm32_i32_modrm}, \
+                       {rm32_i8_opcode, rm32_i8_modrm} } }, \
+  #opcode "RI", "" \
+}, \
+{ kOp ## opcode ## MI, \
+  kMemImm, \
+  0, \
+  { RegMem_Immediate: { rax8_i8, rax32_i32, \
+                       {rm8_i8_opcode, rm8_i8_modrm}, \
+                       {rm32_i32_opcode, rm32_i32_modrm}, \
+                       {rm32_i8_opcode, rm32_i8_modrm} } }, \
+  #opcode "MI", "" \
+}, \
+{ kOp ## opcode ## AI, \
+  kArrayImm, \
+  0, \
+  { RegMem_Immediate: { rax8_i8, rax32_i32, \
+                       {rm8_i8_opcode, rm8_i8_modrm}, \
+                       {rm32_i32_opcode, rm32_i32_modrm}, \
+                       {rm32_i8_opcode, rm32_i8_modrm} } }, \
+  #opcode "AI", "" \
+}, \
+{ kOp ## opcode ## RR, \
+  kRegReg, \
+  0, \
+  { Reg_RegMem: {r8_rm8, r32_rm32} }, \
+  #opcode "RR", "" \
+}, \
+{ kOp ## opcode ## RM, \
+  kRegMem, \
+  0, \
+  { Reg_RegMem: {r8_rm8, r32_rm32} }, \
+  #opcode "RM", "" \
+}, \
+{ kOp ## opcode ## RA, \
+  kRegArray, \
+  0, \
+  { Reg_RegMem: {r8_rm8, r32_rm32} }, \
+  #opcode "RA", "" \
+}, \
+{ kOp ## opcode ## MR, \
+  kMemReg, \
+  0, \
+  { RegMem_Reg: {rm8_r8, rm32_r32} }, \
+  #opcode "MR", "" \
+}, \
+{ kOp ## opcode ## AR, \
+  kArrayReg, \
+  0, \
+  { RegMem_Reg: {rm8_r8, rm32_r32} }, \
+  #opcode "AR", "" \
+}
 
-/* Instruction dump string format keys: !pf, where "!" is the start
- * of the key, "p" is which numeric operand to use and "f" is the
- * print format.
- *
- * [p]ositions:
- *     0 -> operands[0] (dest)
- *     1 -> operands[1] (src1)
- *     2 -> operands[2] (src2)
- *     3 -> operands[3] (extra)
- *
- * [f]ormats:
- *     h -> 4-digit hex
- *     d -> decimal
- *     E -> decimal*4
- *     F -> decimal*2
- *     c -> branch condition (beq, bne, etc.)
- *     t -> pc-relative target
- *     T -> pc-region target
- *     u -> 1st half of bl[x] target
- *     v -> 2nd half ob bl[x] target
- *     R -> register list
- *     s -> single precision floating point register
- *     S -> double precision floating point register
- *     m -> Thumb2 modified immediate
- *     n -> complimented Thumb2 modified immediate
- *     M -> Thumb2 16-bit zero-extended immediate
- *     b -> 4-digit binary
- *     N -> append a NOP
- *
- *  [!] escape.  To insert "!", use "!!"
- */
-/* NOTE: must be kept in sync with enum X86Opcode from LIR.h */
-/*
- * TUNING: We're currently punting on the branch delay slots.  All branch
- * instructions in this map are given a size of 8, which during assembly
- * is expanded to include a nop.  This scheme should be replaced with
- * an assembler pass to fill those slots when possible.
- */
 X86EncodingMap EncodingMap[kX86Last] = {
+  { kX8632BitData, kData, 0 /* flags - TODO */, { unused: 0 }, "data", "" },
+BINARY_ENCODING_MAP(Add,
+  0x00 /* RegMem8/Reg8 */,     0x01 /* RegMem32/Reg32 */,
+  0x02 /* Reg8/RegMem8 */,     0x03 /* Reg32/RegMem32 */,
+  0x04 /* Rax8/imm8 opcode */, 0x05 /* Rax32/imm32 */,
+  0x80, 0x0 /* RegMem8/imm8 */,
+  0x81, 0x0 /* RegMem32/imm32 */, 0x83, 0x0 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Or,
+  0x08 /* RegMem8/Reg8 */,     0x09 /* RegMem32/Reg32 */,
+  0x0A /* Reg8/RegMem8 */,     0x0B /* Reg32/RegMem32 */,
+  0x0C /* Rax8/imm8 opcode */, 0x0D /* Rax32/imm32 */,
+  0x80, 0x1 /* RegMem8/imm8 */,
+  0x81, 0x1 /* RegMem32/imm32 */, 0x83, 0x1 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Adc,
+  0x10 /* RegMem8/Reg8 */,     0x11 /* RegMem32/Reg32 */,
+  0x12 /* Reg8/RegMem8 */,     0x13 /* Reg32/RegMem32 */,
+  0x14 /* Rax8/imm8 opcode */, 0x15 /* Rax32/imm32 */,
+  0x80, 0x2 /* RegMem8/imm8 */,
+  0x81, 0x2 /* RegMem32/imm32 */, 0x83, 0x2 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Sbb,
+  0x18 /* RegMem8/Reg8 */,     0x19 /* RegMem32/Reg32 */,
+  0x1A /* Reg8/RegMem8 */,     0x1B /* Reg32/RegMem32 */,
+  0x1C /* Rax8/imm8 opcode */, 0x1D /* Rax32/imm32 */,
+  0x80, 0x3 /* RegMem8/imm8 */,
+  0x81, 0x3 /* RegMem32/imm32 */, 0x83, 0x3 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(And,
+  0x20 /* RegMem8/Reg8 */,     0x21 /* RegMem32/Reg32 */,
+  0x22 /* Reg8/RegMem8 */,     0x23 /* Reg32/RegMem32 */,
+  0x24 /* Rax8/imm8 opcode */, 0x25 /* Rax32/imm32 */,
+  0x80, 0x4 /* RegMem8/imm8 */,
+  0x81, 0x4 /* RegMem32/imm32 */, 0x83, 0x4 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Sub,
+  0x28 /* RegMem8/Reg8 */,     0x29 /* RegMem32/Reg32 */,
+  0x2A /* Reg8/RegMem8 */,     0x2B /* Reg32/RegMem32 */,
+  0x2C /* Rax8/imm8 opcode */, 0x2D /* Rax32/imm32 */,
+  0x80, 0x5 /* RegMem8/imm8 */,
+  0x81, 0x5 /* RegMem32/imm32 */, 0x83, 0x5 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Xor,
+  0x30 /* RegMem8/Reg8 */,     0x31 /* RegMem32/Reg32 */,
+  0x32 /* Reg8/RegMem8 */,     0x33 /* Reg32/RegMem32 */,
+  0x34 /* Rax8/imm8 opcode */, 0x35 /* Rax32/imm32 */,
+  0x80, 0x6 /* RegMem8/imm8 */,
+  0x81, 0x6 /* RegMem32/imm32 */, 0x83, 0x6 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Cmp,
+  0x38 /* RegMem8/Reg8 */,     0x39 /* RegMem32/Reg32 */,
+  0x3A /* Reg8/RegMem8 */,     0x3B /* Reg32/RegMem32 */,
+  0x3C /* Rax8/imm8 opcode */, 0x3D /* Rax32/imm32 */,
+  0x80, 0x7 /* RegMem8/imm8 */,
+  0x81, 0x7 /* RegMem32/imm32 */, 0x83, 0x7 /* RegMem32/imm8 */)
 };
 
 
@@ -288,7 +343,55 @@
 
 int oatGetInsnSize(LIR* lir)
 {
-    return EncodingMap[lir->opcode].size;
+  switch (EncodingMap[lir->opcode].kind) {
+    case kData:
+      return 4;
+    case kRegImm: {
+      int reg = lir->operands[0];
+      int imm = lir->operands[1];
+      return (reg == rAX ? 1 : 2) +  // AX opcodes don't require the modrm byte
+             (IS_SIMM8(imm) ? 1 : 4);  // 1 or 4 byte immediate
+      break;
+    }
+    case kMemImm: {
+      // int base = lir->operands[0];
+      int disp = lir->operands[1];
+      int imm  = lir->operands[2];
+      return 2 +  // opcode and modrm bytes
+          (disp == 0 ? 0 : (IS_SIMM8(disp) ? 1 : 4)) +  // 0, 1 or 4 byte displacement
+          (IS_SIMM8(imm) ? 1 : 4);  // 1 or 4 byte immediate
+      break;
+    }
+    case kArrayImm:
+      UNIMPLEMENTED(FATAL);
+      return 0;
+    case kRegReg:
+      return 2;  // opcode and modrm
+    case kRegMem: {
+      // int reg =  lir->operands[0];
+      // int base = lir->operands[1];
+      int disp = lir->operands[2];
+      return 2 +  // opcode and modrm bytes
+          (disp == 0 ? 0 : (IS_SIMM8(disp) ? 1 : 4));  // 0, 1 or 4 byte displacement
+      break;
+    }
+    case kRegArray:
+      UNIMPLEMENTED(FATAL);
+      return 0;
+    case kMemReg: {
+      // int base =  lir->operands[0];
+      int disp = lir->operands[1];
+      // int reg = lir->operands[2];
+      return 2 +  // opcode and modrm bytes
+          (disp == 0 ? 0 : (IS_SIMM8(disp) ? 1 : 4));  // 0, 1 or 4 byte displacement
+      break;
+    }
+    case kArrayReg:
+      UNIMPLEMENTED(FATAL);
+      return 0;
+  }
+  UNIMPLEMENTED(FATAL);  // unreachable
+  return 0;
 }
 /*
  * Target-dependent offset assignment.