1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "codegen_x86.h" 18 #include "dex/quick/mir_to_lir-inl.h" 19 #include "x86_lir.h" 20 21 namespace art { 22 23 #define MAX_ASSEMBLER_RETRIES 50 24 25 const X86EncodingMap X86Mir2Lir::EncodingMap[kX86Last] = { 26 { kX8632BitData, kData, IS_UNARY_OP, { 0, 0, 0x00, 0, 0, 0, 0, 4 }, "data", "0x!0d" }, 27 { kX86Bkpt, kNullary, NO_OPERAND | IS_BRANCH, { 0, 0, 0xCC, 0, 0, 0, 0, 0 }, "int 3", "" }, 28 { kX86Nop, kNop, IS_UNARY_OP, { 0, 0, 0x90, 0, 0, 0, 0, 0 }, "nop", "" }, 29 30 #define ENCODING_MAP(opname, mem_use, reg_def, uses_ccodes, \ 31 rm8_r8, rm32_r32, \ 32 r8_rm8, r32_rm32, \ 33 ax8_i8, ax32_i32, \ 34 rm8_i8, rm8_i8_modrm, \ 35 rm32_i32, rm32_i32_modrm, \ 36 rm32_i8, rm32_i8_modrm) \ 37 { kX86 ## opname ## 8MR, kMemReg, mem_use | IS_TERTIARY_OP | REG_USE02 | SETS_CCODES | uses_ccodes, { 0, 0, rm8_r8, 0, 0, 0, 0, 0 }, #opname "8MR", "[!0r+!1d],!2r" }, \ 38 { kX86 ## opname ## 8AR, kArrayReg, mem_use | IS_QUIN_OP | REG_USE014 | SETS_CCODES | uses_ccodes, { 0, 0, rm8_r8, 0, 0, 0, 0, 0 }, #opname "8AR", "[!0r+!1r<<!2d+!3d],!4r" }, \ 39 { kX86 ## opname ## 8TR, kThreadReg, mem_use | IS_BINARY_OP | REG_USE1 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, rm8_r8, 0, 0, 0, 0, 0 }, #opname "8TR", "fs:[!0d],!1r" }, \ 40 { kX86 ## opname ## 8RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, r8_rm8, 0, 0, 0, 0, 0 }, #opname "8RR", "!0r,!1r" }, \ 41 { kX86 ## opname ## 8RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, r8_rm8, 0, 0, 0, 0, 0 }, #opname "8RM", "!0r,[!1r+!2d]" }, \ 42 { kX86 ## opname ## 8RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE012 | SETS_CCODES | uses_ccodes, { 0, 0, r8_rm8, 0, 0, 0, 0, 0 }, #opname "8RA", "!0r,[!1r+!2r<<!3d+!4d]" }, \ 43 { kX86 ## opname ## 8RT, kRegThread, IS_LOAD | IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, r8_rm8, 0, 0, 0, 0, 0 }, #opname "8RT", "!0r,fs:[!1d]" }, \ 44 { kX86 ## opname ## 8RI, kRegImm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm8_i8, 0, 0, rm8_i8_modrm, ax8_i8, 1 }, #opname "8RI", "!0r,!1d" }, \ 45 { kX86 ## opname ## 8MI, kMemImm, mem_use | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm8_i8, 0, 0, rm8_i8_modrm, 0, 1 }, #opname "8MI", "[!0r+!1d],!2d" }, \ 46 { kX86 ## opname ## 8AI, kArrayImm, mem_use | IS_QUIN_OP | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, rm8_i8, 0, 0, rm8_i8_modrm, 0, 1 }, #opname "8AI", "[!0r+!1r<<!2d+!3d],!4d" }, \ 47 { kX86 ## opname ## 8TI, kThreadImm, mem_use | IS_BINARY_OP | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, rm8_i8, 0, 0, rm8_i8_modrm, 0, 1 }, #opname "8TI", "fs:[!0d],!1d" }, \ 48 \ 49 { kX86 ## opname ## 16MR, kMemReg, mem_use | IS_TERTIARY_OP | REG_USE02 | SETS_CCODES | uses_ccodes, { 0x66, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "16MR", "[!0r+!1d],!2r" }, \ 50 { kX86 ## opname ## 16AR, kArrayReg, mem_use | IS_QUIN_OP | REG_USE014 | SETS_CCODES | uses_ccodes, { 0x66, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "16AR", "[!0r+!1r<<!2d+!3d],!4r" }, \ 51 { kX86 ## opname ## 16TR, kThreadReg, mem_use | IS_BINARY_OP | REG_USE1 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0x66, rm32_r32, 0, 0, 0, 0, 0 }, #opname "16TR", "fs:[!0d],!1r" }, \ 52 { kX86 ## opname ## 16RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { 0x66, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "16RR", "!0r,!1r" }, \ 53 { kX86 ## opname ## 16RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { 0x66, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "16RM", "!0r,[!1r+!2d]" }, \ 54 { kX86 ## opname ## 16RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE012 | SETS_CCODES | uses_ccodes, { 0x66, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "16RA", "!0r,[!1r+!2r<<!3d+!4d]" }, \ 55 { kX86 ## opname ## 16RT, kRegThread, IS_LOAD | IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0x66, r32_rm32, 0, 0, 0, 0, 0 }, #opname "16RT", "!0r,fs:[!1d]" }, \ 56 { kX86 ## opname ## 16RI, kRegImm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { 0x66, 0, rm32_i32, 0, 0, rm32_i32_modrm, ax32_i32, 2 }, #opname "16RI", "!0r,!1d" }, \ 57 { kX86 ## opname ## 16MI, kMemImm, mem_use | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES | uses_ccodes, { 0x66, 0, rm32_i32, 0, 0, rm32_i32_modrm, 0, 2 }, #opname "16MI", "[!0r+!1d],!2d" }, \ 58 { kX86 ## opname ## 16AI, kArrayImm, mem_use | IS_QUIN_OP | REG_USE01 | SETS_CCODES | uses_ccodes, { 0x66, 0, rm32_i32, 0, 0, rm32_i32_modrm, 0, 2 }, #opname "16AI", "[!0r+!1r<<!2d+!3d],!4d" }, \ 59 { kX86 ## opname ## 16TI, kThreadImm, mem_use | IS_BINARY_OP | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0x66, rm32_i32, 0, 0, rm32_i32_modrm, 0, 2 }, #opname "16TI", "fs:[!0d],!1d" }, \ 60 { kX86 ## opname ## 16RI8, kRegImm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { 0x66, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "16RI8", "!0r,!1d" }, \ 61 { kX86 ## opname ## 16MI8, kMemImm, mem_use | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES | uses_ccodes, { 0x66, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "16MI8", "[!0r+!1d],!2d" }, \ 62 { kX86 ## opname ## 16AI8, kArrayImm, mem_use | IS_QUIN_OP | REG_USE01 | SETS_CCODES | uses_ccodes, { 0x66, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "16AI8", "[!0r+!1r<<!2d+!3d],!4d" }, \ 63 { kX86 ## opname ## 16TI8, kThreadImm, mem_use | IS_BINARY_OP | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0x66, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "16TI8", "fs:[!0d],!1d" }, \ 64 \ 65 { kX86 ## opname ## 32MR, kMemReg, mem_use | IS_TERTIARY_OP | REG_USE02 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "32MR", "[!0r+!1d],!2r" }, \ 66 { kX86 ## opname ## 32AR, kArrayReg, mem_use | IS_QUIN_OP | REG_USE014 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "32AR", "[!0r+!1r<<!2d+!3d],!4r" }, \ 67 { kX86 ## opname ## 32TR, kThreadReg, mem_use | IS_BINARY_OP | REG_USE1 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, rm32_r32, 0, 0, 0, 0, 0 }, #opname "32TR", "fs:[!0d],!1r" }, \ 68 { kX86 ## opname ## 32RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "32RR", "!0r,!1r" }, \ 69 { kX86 ## opname ## 32RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "32RM", "!0r,[!1r+!2d]" }, \ 70 { kX86 ## opname ## 32RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE012 | SETS_CCODES | uses_ccodes, { 0, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "32RA", "!0r,[!1r+!2r<<!3d+!4d]" }, \ 71 { kX86 ## opname ## 32RT, kRegThread, IS_LOAD | IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, r32_rm32, 0, 0, 0, 0, 0 }, #opname "32RT", "!0r,fs:[!1d]" }, \ 72 { kX86 ## opname ## 32RI, kRegImm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i32, 0, 0, rm32_i32_modrm, ax32_i32, 4 }, #opname "32RI", "!0r,!1d" }, \ 73 { kX86 ## opname ## 32MI, kMemImm, mem_use | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i32, 0, 0, rm32_i32_modrm, 0, 4 }, #opname "32MI", "[!0r+!1d],!2d" }, \ 74 { kX86 ## opname ## 32AI, kArrayImm, mem_use | IS_QUIN_OP | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i32, 0, 0, rm32_i32_modrm, 0, 4 }, #opname "32AI", "[!0r+!1r<<!2d+!3d],!4d" }, \ 75 { kX86 ## opname ## 32TI, kThreadImm, mem_use | IS_BINARY_OP | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, rm32_i32, 0, 0, rm32_i32_modrm, 0, 4 }, #opname "32TI", "fs:[!0d],!1d" }, \ 76 { kX86 ## opname ## 32RI8, kRegImm, IS_BINARY_OP | reg_def | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "32RI8", "!0r,!1d" }, \ 77 { kX86 ## opname ## 32MI8, kMemImm, mem_use | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "32MI8", "[!0r+!1d],!2d" }, \ 78 { kX86 ## opname ## 32AI8, kArrayImm, mem_use | IS_QUIN_OP | REG_USE01 | SETS_CCODES | uses_ccodes, { 0, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "32AI8", "[!0r+!1r<<!2d+!3d],!4d" }, \ 79 { kX86 ## opname ## 32TI8, kThreadImm, mem_use | IS_BINARY_OP | SETS_CCODES | uses_ccodes, { THREAD_PREFIX, 0, rm32_i8, 0, 0, rm32_i8_modrm, 0, 1 }, #opname "32TI8", "fs:[!0d],!1d" } 80 81 ENCODING_MAP(Add, IS_LOAD | IS_STORE, REG_DEF0, 0, 82 0x00 /* RegMem8/Reg8 */, 0x01 /* RegMem32/Reg32 */, 83 0x02 /* Reg8/RegMem8 */, 0x03 /* Reg32/RegMem32 */, 84 0x04 /* Rax8/imm8 opcode */, 0x05 /* Rax32/imm32 */, 85 0x80, 0x0 /* RegMem8/imm8 */, 86 0x81, 0x0 /* RegMem32/imm32 */, 0x83, 0x0 /* RegMem32/imm8 */), 87 ENCODING_MAP(Or, IS_LOAD | IS_STORE, REG_DEF0, 0, 88 0x08 /* RegMem8/Reg8 */, 0x09 /* RegMem32/Reg32 */, 89 0x0A /* Reg8/RegMem8 */, 0x0B /* Reg32/RegMem32 */, 90 0x0C /* Rax8/imm8 opcode */, 0x0D /* Rax32/imm32 */, 91 0x80, 0x1 /* RegMem8/imm8 */, 92 0x81, 0x1 /* RegMem32/imm32 */, 0x83, 0x1 /* RegMem32/imm8 */), 93 ENCODING_MAP(Adc, IS_LOAD | IS_STORE, REG_DEF0, USES_CCODES, 94 0x10 /* RegMem8/Reg8 */, 0x11 /* RegMem32/Reg32 */, 95 0x12 /* Reg8/RegMem8 */, 0x13 /* Reg32/RegMem32 */, 96 0x14 /* Rax8/imm8 opcode */, 0x15 /* Rax32/imm32 */, 97 0x80, 0x2 /* RegMem8/imm8 */, 98 0x81, 0x2 /* RegMem32/imm32 */, 0x83, 0x2 /* RegMem32/imm8 */), 99 ENCODING_MAP(Sbb, IS_LOAD | IS_STORE, REG_DEF0, USES_CCODES, 100 0x18 /* RegMem8/Reg8 */, 0x19 /* RegMem32/Reg32 */, 101 0x1A /* Reg8/RegMem8 */, 0x1B /* Reg32/RegMem32 */, 102 0x1C /* Rax8/imm8 opcode */, 0x1D /* Rax32/imm32 */, 103 0x80, 0x3 /* RegMem8/imm8 */, 104 0x81, 0x3 /* RegMem32/imm32 */, 0x83, 0x3 /* RegMem32/imm8 */), 105 ENCODING_MAP(And, IS_LOAD | IS_STORE, REG_DEF0, 0, 106 0x20 /* RegMem8/Reg8 */, 0x21 /* RegMem32/Reg32 */, 107 0x22 /* Reg8/RegMem8 */, 0x23 /* Reg32/RegMem32 */, 108 0x24 /* Rax8/imm8 opcode */, 0x25 /* Rax32/imm32 */, 109 0x80, 0x4 /* RegMem8/imm8 */, 110 0x81, 0x4 /* RegMem32/imm32 */, 0x83, 0x4 /* RegMem32/imm8 */), 111 ENCODING_MAP(Sub, IS_LOAD | IS_STORE, REG_DEF0, 0, 112 0x28 /* RegMem8/Reg8 */, 0x29 /* RegMem32/Reg32 */, 113 0x2A /* Reg8/RegMem8 */, 0x2B /* Reg32/RegMem32 */, 114 0x2C /* Rax8/imm8 opcode */, 0x2D /* Rax32/imm32 */, 115 0x80, 0x5 /* RegMem8/imm8 */, 116 0x81, 0x5 /* RegMem32/imm32 */, 0x83, 0x5 /* RegMem32/imm8 */), 117 ENCODING_MAP(Xor, IS_LOAD | IS_STORE, REG_DEF0, 0, 118 0x30 /* RegMem8/Reg8 */, 0x31 /* RegMem32/Reg32 */, 119 0x32 /* Reg8/RegMem8 */, 0x33 /* Reg32/RegMem32 */, 120 0x34 /* Rax8/imm8 opcode */, 0x35 /* Rax32/imm32 */, 121 0x80, 0x6 /* RegMem8/imm8 */, 122 0x81, 0x6 /* RegMem32/imm32 */, 0x83, 0x6 /* RegMem32/imm8 */), 123 ENCODING_MAP(Cmp, IS_LOAD, 0, 0, 124 0x38 /* RegMem8/Reg8 */, 0x39 /* RegMem32/Reg32 */, 125 0x3A /* Reg8/RegMem8 */, 0x3B /* Reg32/RegMem32 */, 126 0x3C /* Rax8/imm8 opcode */, 0x3D /* Rax32/imm32 */, 127 0x80, 0x7 /* RegMem8/imm8 */, 128 0x81, 0x7 /* RegMem32/imm32 */, 0x83, 0x7 /* RegMem32/imm8 */), 129 #undef ENCODING_MAP 130 131 { kX86Imul16RRI, kRegRegImm, IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, { 0x66, 0, 0x69, 0, 0, 0, 0, 2 }, "Imul16RRI", "!0r,!1r,!2d" }, 132 { kX86Imul16RMI, kRegMemImm, IS_LOAD | IS_QUAD_OP | REG_DEF0_USE1 | SETS_CCODES, { 0x66, 0, 0x69, 0, 0, 0, 0, 2 }, "Imul16RMI", "!0r,[!1r+!2d],!3d" }, 133 { kX86Imul16RAI, kRegArrayImm, IS_LOAD | IS_SEXTUPLE_OP | REG_DEF0_USE12 | SETS_CCODES, { 0x66, 0, 0x69, 0, 0, 0, 0, 2 }, "Imul16RAI", "!0r,[!1r+!2r<<!3d+!4d],!5d" }, 134 135 { kX86Imul32RRI, kRegRegImm, IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 4 }, "Imul32RRI", "!0r,!1r,!2d" }, 136 { kX86Imul32RMI, kRegMemImm, IS_LOAD | IS_QUAD_OP | REG_DEF0_USE1 | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 4 }, "Imul32RMI", "!0r,[!1r+!2d],!3d" }, 137 { kX86Imul32RAI, kRegArrayImm, IS_LOAD | IS_SEXTUPLE_OP | REG_DEF0_USE12 | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 4 }, "Imul32RAI", "!0r,[!1r+!2r<<!3d+!4d],!5d" }, 138 { kX86Imul32RRI8, kRegRegImm, IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES, { 0, 0, 0x6B, 0, 0, 0, 0, 1 }, "Imul32RRI8", "!0r,!1r,!2d" }, 139 { kX86Imul32RMI8, kRegMemImm, IS_LOAD | IS_QUAD_OP | REG_DEF0_USE1 | SETS_CCODES, { 0, 0, 0x6B, 0, 0, 0, 0, 1 }, "Imul32RMI8", "!0r,[!1r+!2d],!3d" }, 140 { kX86Imul32RAI8, kRegArrayImm, IS_LOAD | IS_SEXTUPLE_OP | REG_DEF0_USE12 | SETS_CCODES, { 0, 0, 0x6B, 0, 0, 0, 0, 1 }, "Imul32RAI8", "!0r,[!1r+!2r<<!3d+!4d],!5d" }, 141 142 { kX86Mov8MR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0, 0, 0x88, 0, 0, 0, 0, 0 }, "Mov8MR", "[!0r+!1d],!2r" }, 143 { kX86Mov8AR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0, 0, 0x88, 0, 0, 0, 0, 0 }, "Mov8AR", "[!0r+!1r<<!2d+!3d],!4r" }, 144 { kX86Mov8TR, kThreadReg, IS_STORE | IS_BINARY_OP | REG_USE1, { THREAD_PREFIX, 0, 0x88, 0, 0, 0, 0, 0 }, "Mov8TR", "fs:[!0d],!1r" }, 145 { kX86Mov8RR, kRegReg, IS_BINARY_OP | REG_DEF0_USE1, { 0, 0, 0x8A, 0, 0, 0, 0, 0 }, "Mov8RR", "!0r,!1r" }, 146 { kX86Mov8RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | REG_DEF0_USE1, { 0, 0, 0x8A, 0, 0, 0, 0, 0 }, "Mov8RM", "!0r,[!1r+!2d]" }, 147 { kX86Mov8RA, kRegArray, IS_LOAD | IS_QUIN_OP | REG_DEF0_USE12, { 0, 0, 0x8A, 0, 0, 0, 0, 0 }, "Mov8RA", "!0r,[!1r+!2r<<!3d+!4d]" }, 148 { kX86Mov8RT, kRegThread, IS_LOAD | IS_BINARY_OP | REG_DEF0, { THREAD_PREFIX, 0, 0x8A, 0, 0, 0, 0, 0 }, "Mov8RT", "!0r,fs:[!1d]" }, 149 { kX86Mov8RI, kMovRegImm, IS_BINARY_OP | REG_DEF0, { 0, 0, 0xB0, 0, 0, 0, 0, 1 }, "Mov8RI", "!0r,!1d" }, 150 { kX86Mov8MI, kMemImm, IS_STORE | IS_TERTIARY_OP | REG_USE0, { 0, 0, 0xC6, 0, 0, 0, 0, 1 }, "Mov8MI", "[!0r+!1d],!2d" }, 151 { kX86Mov8AI, kArrayImm, IS_STORE | IS_QUIN_OP | REG_USE01, { 0, 0, 0xC6, 0, 0, 0, 0, 1 }, "Mov8AI", "[!0r+!1r<<!2d+!3d],!4d" }, 152 { kX86Mov8TI, kThreadImm, IS_STORE | IS_BINARY_OP, { THREAD_PREFIX, 0, 0xC6, 0, 0, 0, 0, 1 }, "Mov8TI", "fs:[!0d],!1d" }, 153 154 { kX86Mov16MR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x66, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov16MR", "[!0r+!1d],!2r" }, 155 { kX86Mov16AR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0x66, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov16AR", "[!0r+!1r<<!2d+!3d],!4r" }, 156 { kX86Mov16TR, kThreadReg, IS_STORE | IS_BINARY_OP | REG_USE1, { THREAD_PREFIX, 0x66, 0x89, 0, 0, 0, 0, 0 }, "Mov16TR", "fs:[!0d],!1r" }, 157 { kX86Mov16RR, kRegReg, IS_BINARY_OP | REG_DEF0_USE1, { 0x66, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov16RR", "!0r,!1r" }, 158 { kX86Mov16RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | REG_DEF0_USE1, { 0x66, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov16RM", "!0r,[!1r+!2d]" }, 159 { kX86Mov16RA, kRegArray, IS_LOAD | IS_QUIN_OP | REG_DEF0_USE12, { 0x66, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov16RA", "!0r,[!1r+!2r<<!3d+!4d]" }, 160 { kX86Mov16RT, kRegThread, IS_LOAD | IS_BINARY_OP | REG_DEF0, { THREAD_PREFIX, 0x66, 0x8B, 0, 0, 0, 0, 0 }, "Mov16RT", "!0r,fs:[!1d]" }, 161 { kX86Mov16RI, kMovRegImm, IS_BINARY_OP | REG_DEF0, { 0x66, 0, 0xB8, 0, 0, 0, 0, 2 }, "Mov16RI", "!0r,!1d" }, 162 { kX86Mov16MI, kMemImm, IS_STORE | IS_TERTIARY_OP | REG_USE0, { 0x66, 0, 0xC7, 0, 0, 0, 0, 2 }, "Mov16MI", "[!0r+!1d],!2d" }, 163 { kX86Mov16AI, kArrayImm, IS_STORE | IS_QUIN_OP | REG_USE01, { 0x66, 0, 0xC7, 0, 0, 0, 0, 2 }, "Mov16AI", "[!0r+!1r<<!2d+!3d],!4d" }, 164 { kX86Mov16TI, kThreadImm, IS_STORE | IS_BINARY_OP, { THREAD_PREFIX, 0x66, 0xC7, 0, 0, 0, 0, 2 }, "Mov16TI", "fs:[!0d],!1d" }, 165 166 { kX86Mov32MR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov32MR", "[!0r+!1d],!2r" }, 167 { kX86Mov32AR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov32AR", "[!0r+!1r<<!2d+!3d],!4r" }, 168 { kX86Mov32TR, kThreadReg, IS_STORE | IS_BINARY_OP | REG_USE1, { THREAD_PREFIX, 0, 0x89, 0, 0, 0, 0, 0 }, "Mov32TR", "fs:[!0d],!1r" }, 169 { kX86Mov32RR, kRegReg, IS_BINARY_OP | REG_DEF0_USE1, { 0, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov32RR", "!0r,!1r" }, 170 { kX86Mov32RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | REG_DEF0_USE1, { 0, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov32RM", "!0r,[!1r+!2d]" }, 171 { kX86Mov32RA, kRegArray, IS_LOAD | IS_QUIN_OP | REG_DEF0_USE12, { 0, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov32RA", "!0r,[!1r+!2r<<!3d+!4d]" }, 172 { kX86Mov32RT, kRegThread, IS_LOAD | IS_BINARY_OP | REG_DEF0, { THREAD_PREFIX, 0, 0x8B, 0, 0, 0, 0, 0 }, "Mov32RT", "!0r,fs:[!1d]" }, 173 { kX86Mov32RI, kMovRegImm, IS_BINARY_OP | REG_DEF0, { 0, 0, 0xB8, 0, 0, 0, 0, 4 }, "Mov32RI", "!0r,!1d" }, 174 { kX86Mov32MI, kMemImm, IS_STORE | IS_TERTIARY_OP | REG_USE0, { 0, 0, 0xC7, 0, 0, 0, 0, 4 }, "Mov32MI", "[!0r+!1d],!2d" }, 175 { kX86Mov32AI, kArrayImm, IS_STORE | IS_QUIN_OP | REG_USE01, { 0, 0, 0xC7, 0, 0, 0, 0, 4 }, "Mov32AI", "[!0r+!1r<<!2d+!3d],!4d" }, 176 { kX86Mov32TI, kThreadImm, IS_STORE | IS_BINARY_OP, { THREAD_PREFIX, 0, 0xC7, 0, 0, 0, 0, 4 }, "Mov32TI", "fs:[!0d],!1d" }, 177 178 { kX86Lea32RA, kRegArray, IS_QUIN_OP | REG_DEF0_USE12, { 0, 0, 0x8D, 0, 0, 0, 0, 0 }, "Lea32RA", "!0r,[!1r+!2r<<!3d+!4d]" }, 179 180 #define SHIFT_ENCODING_MAP(opname, modrm_opcode) \ 181 { kX86 ## opname ## 8RI, kShiftRegImm, IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES, { 0, 0, 0xC0, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "8RI", "!0r,!1d" }, \ 182 { kX86 ## opname ## 8MI, kShiftMemImm, IS_LOAD | IS_STORE | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES, { 0, 0, 0xC0, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "8MI", "[!0r+!1d],!2d" }, \ 183 { kX86 ## opname ## 8AI, kShiftArrayImm, IS_LOAD | IS_STORE | IS_QUIN_OP | REG_USE01 | SETS_CCODES, { 0, 0, 0xC0, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "8AI", "[!0r+!1r<<!2d+!3d],!4d" }, \ 184 { kX86 ## opname ## 8RC, kShiftRegCl, IS_BINARY_OP | REG_DEF0_USE0 | REG_USEC | SETS_CCODES, { 0, 0, 0xD2, 0, 0, modrm_opcode, 0, 1 }, #opname "8RC", "!0r,cl" }, \ 185 { kX86 ## opname ## 8MC, kShiftMemCl, IS_LOAD | IS_STORE | IS_TERTIARY_OP | REG_USE0 | REG_USEC | SETS_CCODES, { 0, 0, 0xD2, 0, 0, modrm_opcode, 0, 1 }, #opname "8MC", "[!0r+!1d],cl" }, \ 186 { kX86 ## opname ## 8AC, kShiftArrayCl, IS_LOAD | IS_STORE | IS_QUIN_OP | REG_USE01 | REG_USEC | SETS_CCODES, { 0, 0, 0xD2, 0, 0, modrm_opcode, 0, 1 }, #opname "8AC", "[!0r+!1r<<!2d+!3d],cl" }, \ 187 \ 188 { kX86 ## opname ## 16RI, kShiftRegImm, IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES, { 0x66, 0, 0xC1, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "16RI", "!0r,!1d" }, \ 189 { kX86 ## opname ## 16MI, kShiftMemImm, IS_LOAD | IS_STORE | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES, { 0x66, 0, 0xC1, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "16MI", "[!0r+!1d],!2d" }, \ 190 { kX86 ## opname ## 16AI, kShiftArrayImm, IS_LOAD | IS_STORE | IS_QUIN_OP | REG_USE01 | SETS_CCODES, { 0x66, 0, 0xC1, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "16AI", "[!0r+!1r<<!2d+!3d],!4d" }, \ 191 { kX86 ## opname ## 16RC, kShiftRegCl, IS_BINARY_OP | REG_DEF0_USE0 | REG_USEC | SETS_CCODES, { 0x66, 0, 0xD3, 0, 0, modrm_opcode, 0, 1 }, #opname "16RC", "!0r,cl" }, \ 192 { kX86 ## opname ## 16MC, kShiftMemCl, IS_LOAD | IS_STORE | IS_TERTIARY_OP | REG_USE0 | REG_USEC | SETS_CCODES, { 0x66, 0, 0xD3, 0, 0, modrm_opcode, 0, 1 }, #opname "16MC", "[!0r+!1d],cl" }, \ 193 { kX86 ## opname ## 16AC, kShiftArrayCl, IS_LOAD | IS_STORE | IS_QUIN_OP | REG_USE01 | REG_USEC | SETS_CCODES, { 0x66, 0, 0xD3, 0, 0, modrm_opcode, 0, 1 }, #opname "16AC", "[!0r+!1r<<!2d+!3d],cl" }, \ 194 \ 195 { kX86 ## opname ## 32RI, kShiftRegImm, IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES, { 0, 0, 0xC1, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "32RI", "!0r,!1d" }, \ 196 { kX86 ## opname ## 32MI, kShiftMemImm, IS_LOAD | IS_STORE | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES, { 0, 0, 0xC1, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "32MI", "[!0r+!1d],!2d" }, \ 197 { kX86 ## opname ## 32AI, kShiftArrayImm, IS_LOAD | IS_STORE | IS_QUIN_OP | REG_USE01 | SETS_CCODES, { 0, 0, 0xC1, 0, 0, modrm_opcode, 0xD1, 1 }, #opname "32AI", "[!0r+!1r<<!2d+!3d],!4d" }, \ 198 { kX86 ## opname ## 32RC, kShiftRegCl, IS_BINARY_OP | REG_DEF0_USE0 | REG_USEC | SETS_CCODES, { 0, 0, 0xD3, 0, 0, modrm_opcode, 0, 0 }, #opname "32RC", "!0r,cl" }, \ 199 { kX86 ## opname ## 32MC, kShiftMemCl, IS_LOAD | IS_STORE | IS_TERTIARY_OP | REG_USE0 | REG_USEC | SETS_CCODES, { 0, 0, 0xD3, 0, 0, modrm_opcode, 0, 0 }, #opname "32MC", "[!0r+!1d],cl" }, \ 200 { kX86 ## opname ## 32AC, kShiftArrayCl, IS_LOAD | IS_STORE | IS_QUIN_OP | REG_USE01 | REG_USEC | SETS_CCODES, { 0, 0, 0xD3, 0, 0, modrm_opcode, 0, 0 }, #opname "32AC", "[!0r+!1r<<!2d+!3d],cl" } 201 202 SHIFT_ENCODING_MAP(Rol, 0x0), 203 SHIFT_ENCODING_MAP(Ror, 0x1), 204 SHIFT_ENCODING_MAP(Rcl, 0x2), 205 SHIFT_ENCODING_MAP(Rcr, 0x3), 206 SHIFT_ENCODING_MAP(Sal, 0x4), 207 SHIFT_ENCODING_MAP(Shr, 0x5), 208 SHIFT_ENCODING_MAP(Sar, 0x7), 209 #undef SHIFT_ENCODING_MAP 210 211 { kX86Cmc, kNullary, NO_OPERAND, { 0, 0, 0xF5, 0, 0, 0, 0, 0}, "Cmc", "" }, 212 213 { kX86Test8RI, kRegImm, IS_BINARY_OP | REG_USE0 | SETS_CCODES, { 0, 0, 0xF6, 0, 0, 0, 0, 1}, "Test8RI", "!0r,!1d" }, 214 { kX86Test8MI, kMemImm, IS_LOAD | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES, { 0, 0, 0xF6, 0, 0, 0, 0, 1}, "Test8MI", "[!0r+!1d],!2d" }, 215 { kX86Test8AI, kArrayImm, IS_LOAD | IS_QUIN_OP | REG_USE01 | SETS_CCODES, { 0, 0, 0xF6, 0, 0, 0, 0, 1}, "Test8AI", "[!0r+!1r<<!2d+!3d],!4d" }, 216 { kX86Test16RI, kRegImm, IS_BINARY_OP | REG_USE0 | SETS_CCODES, { 0x66, 0, 0xF7, 0, 0, 0, 0, 2}, "Test16RI", "!0r,!1d" }, 217 { kX86Test16MI, kMemImm, IS_LOAD | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES, { 0x66, 0, 0xF7, 0, 0, 0, 0, 2}, "Test16MI", "[!0r+!1d],!2d" }, 218 { kX86Test16AI, kArrayImm, IS_LOAD | IS_QUIN_OP | REG_USE01 | SETS_CCODES, { 0x66, 0, 0xF7, 0, 0, 0, 0, 2}, "Test16AI", "[!0r+!1r<<!2d+!3d],!4d" }, 219 { kX86Test32RI, kRegImm, IS_BINARY_OP | REG_USE0 | SETS_CCODES, { 0, 0, 0xF7, 0, 0, 0, 0, 4}, "Test32RI", "!0r,!1d" }, 220 { kX86Test32MI, kMemImm, IS_LOAD | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES, { 0, 0, 0xF7, 0, 0, 0, 0, 4}, "Test32MI", "[!0r+!1d],!2d" }, 221 { kX86Test32AI, kArrayImm, IS_LOAD | IS_QUIN_OP | REG_USE01 | SETS_CCODES, { 0, 0, 0xF7, 0, 0, 0, 0, 4}, "Test32AI", "[!0r+!1r<<!2d+!3d],!4d" }, 222 { kX86Test32RR, kRegReg, IS_BINARY_OP | REG_USE01 | SETS_CCODES, { 0, 0, 0x85, 0, 0, 0, 0, 0}, "Test32RR", "!0r,!1r" }, 223 224 #define UNARY_ENCODING_MAP(opname, modrm, is_store, sets_ccodes, \ 225 reg, reg_kind, reg_flags, \ 226 mem, mem_kind, mem_flags, \ 227 arr, arr_kind, arr_flags, imm, \ 228 b_flags, hw_flags, w_flags, \ 229 b_format, hw_format, w_format) \ 230 { kX86 ## opname ## 8 ## reg, reg_kind, reg_flags | b_flags | sets_ccodes, { 0, 0, 0xF6, 0, 0, modrm, 0, imm << 0}, #opname "8" #reg, #b_format "!0r" }, \ 231 { kX86 ## opname ## 8 ## mem, mem_kind, IS_LOAD | is_store | mem_flags | b_flags | sets_ccodes, { 0, 0, 0xF6, 0, 0, modrm, 0, imm << 0}, #opname "8" #mem, #b_format "[!0r+!1d]" }, \ 232 { kX86 ## opname ## 8 ## arr, arr_kind, IS_LOAD | is_store | arr_flags | b_flags | sets_ccodes, { 0, 0, 0xF6, 0, 0, modrm, 0, imm << 0}, #opname "8" #arr, #b_format "[!0r+!1r<<!2d+!3d]" }, \ 233 { kX86 ## opname ## 16 ## reg, reg_kind, reg_flags | hw_flags | sets_ccodes, { 0x66, 0, 0xF7, 0, 0, modrm, 0, imm << 1}, #opname "16" #reg, #hw_format "!0r" }, \ 234 { kX86 ## opname ## 16 ## mem, mem_kind, IS_LOAD | is_store | mem_flags | hw_flags | sets_ccodes, { 0x66, 0, 0xF7, 0, 0, modrm, 0, imm << 1}, #opname "16" #mem, #hw_format "[!0r+!1d]" }, \ 235 { kX86 ## opname ## 16 ## arr, arr_kind, IS_LOAD | is_store | arr_flags | hw_flags | sets_ccodes, { 0x66, 0, 0xF7, 0, 0, modrm, 0, imm << 1}, #opname "16" #arr, #hw_format "[!0r+!1r<<!2d+!3d]" }, \ 236 { kX86 ## opname ## 32 ## reg, reg_kind, reg_flags | w_flags | sets_ccodes, { 0, 0, 0xF7, 0, 0, modrm, 0, imm << 2}, #opname "32" #reg, #w_format "!0r" }, \ 237 { kX86 ## opname ## 32 ## mem, mem_kind, IS_LOAD | is_store | mem_flags | w_flags | sets_ccodes, { 0, 0, 0xF7, 0, 0, modrm, 0, imm << 2}, #opname "32" #mem, #w_format "[!0r+!1d]" }, \ 238 { kX86 ## opname ## 32 ## arr, arr_kind, IS_LOAD | is_store | arr_flags | w_flags | sets_ccodes, { 0, 0, 0xF7, 0, 0, modrm, 0, imm << 2}, #opname "32" #arr, #w_format "[!0r+!1r<<!2d+!3d]" } 239 240 UNARY_ENCODING_MAP(Not, 0x2, IS_STORE, 0, R, kReg, IS_UNARY_OP | REG_DEF0_USE0, M, kMem, IS_BINARY_OP | REG_USE0, A, kArray, IS_QUAD_OP | REG_USE01, 0, 0, 0, 0, "", "", ""), 241 UNARY_ENCODING_MAP(Neg, 0x3, IS_STORE, SETS_CCODES, R, kReg, IS_UNARY_OP | REG_DEF0_USE0, M, kMem, IS_BINARY_OP | REG_USE0, A, kArray, IS_QUAD_OP | REG_USE01, 0, 0, 0, 0, "", "", ""), 242 243 UNARY_ENCODING_MAP(Mul, 0x4, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEA, REG_DEFAD_USEA, "ax,al,", "dx:ax,ax,", "edx:eax,eax,"), 244 UNARY_ENCODING_MAP(Imul, 0x5, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEA, REG_DEFAD_USEA, "ax,al,", "dx:ax,ax,", "edx:eax,eax,"), 245 UNARY_ENCODING_MAP(Divmod, 0x6, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEAD, REG_DEFAD_USEAD, "ah:al,ax,", "dx:ax,dx:ax,", "edx:eax,edx:eax,"), 246 UNARY_ENCODING_MAP(Idivmod, 0x7, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEAD, REG_DEFAD_USEAD, "ah:al,ax,", "dx:ax,dx:ax,", "edx:eax,edx:eax,"), 247 #undef UNARY_ENCODING_MAP 248 249 #define EXT_0F_ENCODING_MAP(opname, prefix, opcode, reg_def) \ 250 { kX86 ## opname ## RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE01, { prefix, 0, 0x0F, opcode, 0, 0, 0, 0 }, #opname "RR", "!0r,!1r" }, \ 251 { kX86 ## opname ## RM, kRegMem, IS_LOAD | IS_TERTIARY_OP | reg_def | REG_USE01, { prefix, 0, 0x0F, opcode, 0, 0, 0, 0 }, #opname "RM", "!0r,[!1r+!2d]" }, \ 252 { kX86 ## opname ## RA, kRegArray, IS_LOAD | IS_QUIN_OP | reg_def | REG_USE012, { prefix, 0, 0x0F, opcode, 0, 0, 0, 0 }, #opname "RA", "!0r,[!1r+!2r<<!3d+!4d]" } 253 254 EXT_0F_ENCODING_MAP(Movsd, 0xF2, 0x10, REG_DEF0), 255 { kX86MovsdMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0xF2, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovsdMR", "[!0r+!1d],!2r" }, 256 { kX86MovsdAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0xF2, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovsdAR", "[!0r+!1r<<!2d+!3d],!4r" }, 257 258 EXT_0F_ENCODING_MAP(Movss, 0xF3, 0x10, REG_DEF0), 259 { kX86MovssMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0xF3, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovssMR", "[!0r+!1d],!2r" }, 260 { kX86MovssAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0xF3, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovssAR", "[!0r+!1r<<!2d+!3d],!4r" }, 261 262 EXT_0F_ENCODING_MAP(Cvtsi2sd, 0xF2, 0x2A, REG_DEF0), 263 EXT_0F_ENCODING_MAP(Cvtsi2ss, 0xF3, 0x2A, REG_DEF0), 264 EXT_0F_ENCODING_MAP(Cvttsd2si, 0xF2, 0x2C, REG_DEF0), 265 EXT_0F_ENCODING_MAP(Cvttss2si, 0xF3, 0x2C, REG_DEF0), 266 EXT_0F_ENCODING_MAP(Cvtsd2si, 0xF2, 0x2D, REG_DEF0), 267 EXT_0F_ENCODING_MAP(Cvtss2si, 0xF3, 0x2D, REG_DEF0), 268 EXT_0F_ENCODING_MAP(Ucomisd, 0x66, 0x2E, SETS_CCODES), 269 EXT_0F_ENCODING_MAP(Ucomiss, 0x00, 0x2E, SETS_CCODES), 270 EXT_0F_ENCODING_MAP(Comisd, 0x66, 0x2F, SETS_CCODES), 271 EXT_0F_ENCODING_MAP(Comiss, 0x00, 0x2F, SETS_CCODES), 272 EXT_0F_ENCODING_MAP(Orps, 0x00, 0x56, REG_DEF0), 273 EXT_0F_ENCODING_MAP(Xorps, 0x00, 0x57, REG_DEF0), 274 EXT_0F_ENCODING_MAP(Addsd, 0xF2, 0x58, REG_DEF0), 275 EXT_0F_ENCODING_MAP(Addss, 0xF3, 0x58, REG_DEF0), 276 EXT_0F_ENCODING_MAP(Mulsd, 0xF2, 0x59, REG_DEF0), 277 EXT_0F_ENCODING_MAP(Mulss, 0xF3, 0x59, REG_DEF0), 278 EXT_0F_ENCODING_MAP(Cvtsd2ss, 0xF2, 0x5A, REG_DEF0), 279 EXT_0F_ENCODING_MAP(Cvtss2sd, 0xF3, 0x5A, REG_DEF0), 280 EXT_0F_ENCODING_MAP(Subsd, 0xF2, 0x5C, REG_DEF0), 281 EXT_0F_ENCODING_MAP(Subss, 0xF3, 0x5C, REG_DEF0), 282 EXT_0F_ENCODING_MAP(Divsd, 0xF2, 0x5E, REG_DEF0), 283 EXT_0F_ENCODING_MAP(Divss, 0xF3, 0x5E, REG_DEF0), 284 285 { kX86PsrlqRI, kRegImm, IS_BINARY_OP | REG_DEF0_USE0, { 0x66, 0, 0x0F, 0x73, 0, 2, 0, 1 }, "PsrlqRI", "!0r,!1d" }, 286 { kX86PsllqRI, kRegImm, IS_BINARY_OP | REG_DEF0_USE0, { 0x66, 0, 0x0F, 0x73, 0, 6, 0, 1 }, "PsllqRI", "!0r,!1d" }, 287 288 EXT_0F_ENCODING_MAP(Movdxr, 0x66, 0x6E, REG_DEF0), 289 { kX86MovdrxRR, kRegRegStore, IS_BINARY_OP | REG_DEF0 | REG_USE01, { 0x66, 0, 0x0F, 0x7E, 0, 0, 0, 0 }, "MovdrxRR", "!0r,!1r" }, 290 { kX86MovdrxMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x66, 0, 0x0F, 0x7E, 0, 0, 0, 0 }, "MovdrxMR", "[!0r+!1d],!2r" }, 291 { kX86MovdrxAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0x66, 0, 0x0F, 0x7E, 0, 0, 0, 0 }, "MovdrxAR", "[!0r+!1r<<!2d+!3d],!4r" }, 292 293 { kX86Set8R, kRegCond, IS_BINARY_OP | REG_DEF0 | USES_CCODES, { 0, 0, 0x0F, 0x90, 0, 0, 0, 0 }, "Set8R", "!1c !0r" }, 294 { kX86Set8M, kMemCond, IS_STORE | IS_TERTIARY_OP | REG_USE0 | USES_CCODES, { 0, 0, 0x0F, 0x90, 0, 0, 0, 0 }, "Set8M", "!2c [!0r+!1d]" }, 295 { kX86Set8A, kArrayCond, IS_STORE | IS_QUIN_OP | REG_USE01 | USES_CCODES, { 0, 0, 0x0F, 0x90, 0, 0, 0, 0 }, "Set8A", "!4c [!0r+!1r<<!2d+!3d]" }, 296 297 // TODO: load/store? 298 // Encode the modrm opcode as an extra opcode byte to avoid computation during assembly. 299 { kX86Mfence, kReg, NO_OPERAND, { 0, 0, 0x0F, 0xAE, 0, 6, 0, 0 }, "Mfence", "" }, 300 301 EXT_0F_ENCODING_MAP(Imul16, 0x66, 0xAF, REG_DEF0 | SETS_CCODES), 302 EXT_0F_ENCODING_MAP(Imul32, 0x00, 0xAF, REG_DEF0 | SETS_CCODES), 303 304 { kX86CmpxchgRR, kRegRegStore, IS_BINARY_OP | REG_DEF0 | REG_USE01 | REG_DEFA_USEA | SETS_CCODES, { 0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Cmpxchg", "!0r,!1r" }, 305 { kX86CmpxchgMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02 | REG_DEFA_USEA | SETS_CCODES, { 0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Cmpxchg", "[!0r+!1d],!2r" }, 306 { kX86CmpxchgAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014 | REG_DEFA_USEA | SETS_CCODES, { 0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Cmpxchg", "[!0r+!1r<<!2d+!3d],!4r" }, 307 { kX86LockCmpxchgRR, kRegRegStore, IS_BINARY_OP | REG_DEF0 | REG_USE01 | REG_DEFA_USEA | SETS_CCODES, { 0xF0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Lock Cmpxchg", "!0r,!1r" }, 308 { kX86LockCmpxchgMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02 | REG_DEFA_USEA | SETS_CCODES, { 0xF0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Lock Cmpxchg", "[!0r+!1d],!2r" }, 309 { kX86LockCmpxchgAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014 | REG_DEFA_USEA | SETS_CCODES, { 0xF0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Lock Cmpxchg", "[!0r+!1r<<!2d+!3d],!4r" }, 310 311 EXT_0F_ENCODING_MAP(Movzx8, 0x00, 0xB6, REG_DEF0), 312 EXT_0F_ENCODING_MAP(Movzx16, 0x00, 0xB7, REG_DEF0), 313 EXT_0F_ENCODING_MAP(Movsx8, 0x00, 0xBE, REG_DEF0), 314 EXT_0F_ENCODING_MAP(Movsx16, 0x00, 0xBF, REG_DEF0), 315 #undef EXT_0F_ENCODING_MAP 316 317 { kX86Jcc8, kJcc, IS_BINARY_OP | IS_BRANCH | NEEDS_FIXUP | USES_CCODES, { 0, 0, 0x70, 0, 0, 0, 0, 0 }, "Jcc8", "!1c !0t" }, 318 { kX86Jcc32, kJcc, IS_BINARY_OP | IS_BRANCH | NEEDS_FIXUP | USES_CCODES, { 0, 0, 0x0F, 0x80, 0, 0, 0, 0 }, "Jcc32", "!1c !0t" }, 319 { kX86Jmp8, kJmp, IS_UNARY_OP | IS_BRANCH | NEEDS_FIXUP, { 0, 0, 0xEB, 0, 0, 0, 0, 0 }, "Jmp8", "!0t" }, 320 { kX86Jmp32, kJmp, IS_UNARY_OP | IS_BRANCH | NEEDS_FIXUP, { 0, 0, 0xE9, 0, 0, 0, 0, 0 }, "Jmp32", "!0t" }, 321 { kX86JmpR, kJmp, IS_UNARY_OP | IS_BRANCH | REG_USE0, { 0, 0, 0xFF, 0, 0, 4, 0, 0 }, "JmpR", "!0r" }, 322 { kX86JmpT, kJmp, IS_UNARY_OP | IS_BRANCH | IS_LOAD, { THREAD_PREFIX, 0, 0xFF, 0, 0, 4, 0, 0 }, "JmpT", "fs:[!0d]" }, 323 { kX86CallR, kCall, IS_UNARY_OP | IS_BRANCH | REG_USE0, { 0, 0, 0xE8, 0, 0, 0, 0, 0 }, "CallR", "!0r" }, 324 { kX86CallM, kCall, IS_BINARY_OP | IS_BRANCH | IS_LOAD | REG_USE0, { 0, 0, 0xFF, 0, 0, 2, 0, 0 }, "CallM", "[!0r+!1d]" }, 325 { kX86CallA, kCall, IS_QUAD_OP | IS_BRANCH | IS_LOAD | REG_USE01, { 0, 0, 0xFF, 0, 0, 2, 0, 0 }, "CallA", "[!0r+!1r<<!2d+!3d]" }, 326 { kX86CallT, kCall, IS_UNARY_OP | IS_BRANCH | IS_LOAD, { THREAD_PREFIX, 0, 0xFF, 0, 0, 2, 0, 0 }, "CallT", "fs:[!0d]" }, 327 { kX86Ret, kNullary, NO_OPERAND | IS_BRANCH, { 0, 0, 0xC3, 0, 0, 0, 0, 0 }, "Ret", "" }, 328 329 { kX86StartOfMethod, kMacro, IS_UNARY_OP | SETS_CCODES, { 0, 0, 0, 0, 0, 0, 0, 0 }, "StartOfMethod", "!0r" }, 330 { kX86PcRelLoadRA, kPcRel, IS_LOAD | IS_QUIN_OP | REG_DEF0_USE12, { 0, 0, 0x8B, 0, 0, 0, 0, 0 }, "PcRelLoadRA", "!0r,[!1r+!2r<<!3d+!4p]" }, 331 { kX86PcRelAdr, kPcRel, IS_LOAD | IS_BINARY_OP | REG_DEF0, { 0, 0, 0xB8, 0, 0, 0, 0, 4 }, "PcRelAdr", "!0r,!1d" }, 332 }; 333 334 static size_t ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib) { 335 size_t size = 0; 336 if (entry->skeleton.prefix1 > 0) { 337 ++size; 338 if (entry->skeleton.prefix2 > 0) { 339 ++size; 340 } 341 } 342 ++size; // opcode 343 if (entry->skeleton.opcode == 0x0F) { 344 ++size; 345 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode1 == 0x3A) { 346 ++size; 347 } 348 } 349 ++size; // modrm 350 if (has_sib || base == rX86_SP) { 351 // SP requires a SIB byte. 352 ++size; 353 } 354 if (displacement != 0 || base == rBP) { 355 // BP requires an explicit displacement, even when it's 0. 356 if (entry->opcode != kX86Lea32RA) { 357 DCHECK_NE(entry->flags & (IS_LOAD | IS_STORE), 0ULL) << entry->name; 358 } 359 size += IS_SIMM8(displacement) ? 1 : 4; 360 } 361 size += entry->skeleton.immediate_bytes; 362 return size; 363 } 364 365 int X86Mir2Lir::GetInsnSize(LIR* lir) { 366 const X86EncodingMap* entry = &X86Mir2Lir::EncodingMap[lir->opcode]; 367 switch (entry->kind) { 368 case kData: 369 return 4; // 4 bytes of data 370 case kNop: 371 return lir->operands[0]; // length of nop is sole operand 372 case kNullary: 373 return 1; // 1 byte of opcode 374 case kReg: // lir operands - 0: reg 375 return ComputeSize(entry, 0, 0, false); 376 case kMem: // lir operands - 0: base, 1: disp 377 return ComputeSize(entry, lir->operands[0], lir->operands[1], false); 378 case kArray: // lir operands - 0: base, 1: index, 2: scale, 3: disp 379 return ComputeSize(entry, lir->operands[0], lir->operands[3], true); 380 case kMemReg: // lir operands - 0: base, 1: disp, 2: reg 381 return ComputeSize(entry, lir->operands[0], lir->operands[1], false); 382 case kArrayReg: // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg 383 return ComputeSize(entry, lir->operands[0], lir->operands[3], true); 384 case kThreadReg: // lir operands - 0: disp, 1: reg 385 return ComputeSize(entry, 0, lir->operands[0], false); 386 case kRegReg: 387 return ComputeSize(entry, 0, 0, false); 388 case kRegRegStore: 389 return ComputeSize(entry, 0, 0, false); 390 case kRegMem: // lir operands - 0: reg, 1: base, 2: disp 391 return ComputeSize(entry, lir->operands[1], lir->operands[2], false); 392 case kRegArray: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp 393 return ComputeSize(entry, lir->operands[1], lir->operands[4], true); 394 case kRegThread: // lir operands - 0: reg, 1: disp 395 return ComputeSize(entry, 0, 0x12345678, false); // displacement size is always 32bit 396 case kRegImm: { // lir operands - 0: reg, 1: immediate 397 size_t size = ComputeSize(entry, 0, 0, false); 398 if (entry->skeleton.ax_opcode == 0) { 399 return size; 400 } else { 401 // AX opcodes don't require the modrm byte. 402 int reg = lir->operands[0]; 403 return size - (reg == rAX ? 1 : 0); 404 } 405 } 406 case kMemImm: // lir operands - 0: base, 1: disp, 2: immediate 407 return ComputeSize(entry, lir->operands[0], lir->operands[1], false); 408 case kArrayImm: // lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate 409 return ComputeSize(entry, lir->operands[0], lir->operands[3], true); 410 case kThreadImm: // lir operands - 0: disp, 1: imm 411 return ComputeSize(entry, 0, 0x12345678, false); // displacement size is always 32bit 412 case kRegRegImm: // lir operands - 0: reg, 1: reg, 2: imm 413 return ComputeSize(entry, 0, 0, false); 414 case kRegMemImm: // lir operands - 0: reg, 1: base, 2: disp, 3: imm 415 return ComputeSize(entry, lir->operands[1], lir->operands[2], false); 416 case kRegArrayImm: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp, 5: imm 417 return ComputeSize(entry, lir->operands[1], lir->operands[4], true); 418 case kMovRegImm: // lir operands - 0: reg, 1: immediate 419 return 1 + entry->skeleton.immediate_bytes; 420 case kShiftRegImm: // lir operands - 0: reg, 1: immediate 421 // Shift by immediate one has a shorter opcode. 422 return ComputeSize(entry, 0, 0, false) - (lir->operands[1] == 1 ? 1 : 0); 423 case kShiftMemImm: // lir operands - 0: base, 1: disp, 2: immediate 424 // Shift by immediate one has a shorter opcode. 425 return ComputeSize(entry, lir->operands[0], lir->operands[1], false) - 426 (lir->operands[2] == 1 ? 1 : 0); 427 case kShiftArrayImm: // lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate 428 // Shift by immediate one has a shorter opcode. 429 return ComputeSize(entry, lir->operands[0], lir->operands[3], true) - 430 (lir->operands[4] == 1 ? 1 : 0); 431 case kShiftRegCl: 432 return ComputeSize(entry, 0, 0, false); 433 case kShiftMemCl: // lir operands - 0: base, 1: disp, 2: cl 434 return ComputeSize(entry, lir->operands[0], lir->operands[1], false); 435 case kShiftArrayCl: // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg 436 return ComputeSize(entry, lir->operands[0], lir->operands[3], true); 437 case kRegCond: // lir operands - 0: reg, 1: cond 438 return ComputeSize(entry, 0, 0, false); 439 case kMemCond: // lir operands - 0: base, 1: disp, 2: cond 440 return ComputeSize(entry, lir->operands[0], lir->operands[1], false); 441 case kArrayCond: // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: cond 442 return ComputeSize(entry, lir->operands[0], lir->operands[3], true); 443 case kJcc: 444 if (lir->opcode == kX86Jcc8) { 445 return 2; // opcode + rel8 446 } else { 447 DCHECK(lir->opcode == kX86Jcc32); 448 return 6; // 2 byte opcode + rel32 449 } 450 case kJmp: 451 if (lir->opcode == kX86Jmp8) { 452 return 2; // opcode + rel8 453 } else if (lir->opcode == kX86Jmp32) { 454 return 5; // opcode + rel32 455 } else if (lir->opcode == kX86JmpT) { 456 return ComputeSize(entry, 0, 0x12345678, false); // displacement size is always 32bit 457 } else { 458 DCHECK(lir->opcode == kX86JmpR); 459 return 2; // opcode + modrm 460 } 461 case kCall: 462 switch (lir->opcode) { 463 case kX86CallR: return 2; // opcode modrm 464 case kX86CallM: // lir operands - 0: base, 1: disp 465 return ComputeSize(entry, lir->operands[0], lir->operands[1], false); 466 case kX86CallA: // lir operands - 0: base, 1: index, 2: scale, 3: disp 467 return ComputeSize(entry, lir->operands[0], lir->operands[3], true); 468 case kX86CallT: // lir operands - 0: disp 469 return ComputeSize(entry, 0, 0x12345678, false); // displacement size is always 32bit 470 default: 471 break; 472 } 473 break; 474 case kPcRel: 475 if (entry->opcode == kX86PcRelLoadRA) { 476 // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table 477 return ComputeSize(entry, lir->operands[1], 0x12345678, true); 478 } else { 479 DCHECK(entry->opcode == kX86PcRelAdr); 480 return 5; // opcode with reg + 4 byte immediate 481 } 482 case kMacro: 483 DCHECK_EQ(lir->opcode, static_cast<int>(kX86StartOfMethod)); 484 return 5 /* call opcode + 4 byte displacement */ + 1 /* pop reg */ + 485 ComputeSize(&X86Mir2Lir::EncodingMap[kX86Sub32RI], 0, 0, false) - 486 (lir->operands[0] == rAX ? 1 : 0); // shorter ax encoding 487 default: 488 break; 489 } 490 UNIMPLEMENTED(FATAL) << "Unimplemented size encoding for: " << entry->name; 491 return 0; 492 } 493 494 static uint8_t ModrmForDisp(int base, int disp) { 495 // BP requires an explicit disp, so do not omit it in the 0 case 496 if (disp == 0 && base != rBP) { 497 return 0; 498 } else if (IS_SIMM8(disp)) { 499 return 1; 500 } else { 501 return 2; 502 } 503 } 504 505 void X86Mir2Lir::EmitDisp(int base, int disp) { 506 // BP requires an explicit disp, so do not omit it in the 0 case 507 if (disp == 0 && base != rBP) { 508 return; 509 } else if (IS_SIMM8(disp)) { 510 code_buffer_.push_back(disp & 0xFF); 511 } else { 512 code_buffer_.push_back(disp & 0xFF); 513 code_buffer_.push_back((disp >> 8) & 0xFF); 514 code_buffer_.push_back((disp >> 16) & 0xFF); 515 code_buffer_.push_back((disp >> 24) & 0xFF); 516 } 517 } 518 519 void X86Mir2Lir::EmitOpReg(const X86EncodingMap* entry, uint8_t reg) { 520 if (entry->skeleton.prefix1 != 0) { 521 code_buffer_.push_back(entry->skeleton.prefix1); 522 if (entry->skeleton.prefix2 != 0) { 523 code_buffer_.push_back(entry->skeleton.prefix2); 524 } 525 } else { 526 DCHECK_EQ(0, entry->skeleton.prefix2); 527 } 528 code_buffer_.push_back(entry->skeleton.opcode); 529 if (entry->skeleton.opcode == 0x0F) { 530 code_buffer_.push_back(entry->skeleton.extra_opcode1); 531 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 532 code_buffer_.push_back(entry->skeleton.extra_opcode2); 533 } else { 534 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 535 } 536 } else { 537 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 538 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 539 } 540 if (X86_FPREG(reg)) { 541 reg = reg & X86_FP_REG_MASK; 542 } 543 if (reg >= 4) { 544 DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) 545 << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); 546 } 547 DCHECK_LT(reg, 8); 548 uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; 549 code_buffer_.push_back(modrm); 550 DCHECK_EQ(0, entry->skeleton.ax_opcode); 551 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 552 } 553 554 void X86Mir2Lir::EmitOpMem(const X86EncodingMap* entry, uint8_t base, int disp) { 555 if (entry->skeleton.prefix1 != 0) { 556 code_buffer_.push_back(entry->skeleton.prefix1); 557 if (entry->skeleton.prefix2 != 0) { 558 code_buffer_.push_back(entry->skeleton.prefix2); 559 } 560 } else { 561 DCHECK_EQ(0, entry->skeleton.prefix2); 562 } 563 code_buffer_.push_back(entry->skeleton.opcode); 564 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 565 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 566 DCHECK_LT(entry->skeleton.modrm_opcode, 8); 567 DCHECK_LT(base, 8); 568 uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (entry->skeleton.modrm_opcode << 3) | base; 569 code_buffer_.push_back(modrm); 570 EmitDisp(base, disp); 571 DCHECK_EQ(0, entry->skeleton.ax_opcode); 572 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 573 } 574 575 void X86Mir2Lir::EmitMemReg(const X86EncodingMap* entry, 576 uint8_t base, int disp, uint8_t reg) { 577 if (entry->skeleton.prefix1 != 0) { 578 code_buffer_.push_back(entry->skeleton.prefix1); 579 if (entry->skeleton.prefix2 != 0) { 580 code_buffer_.push_back(entry->skeleton.prefix2); 581 } 582 } else { 583 DCHECK_EQ(0, entry->skeleton.prefix2); 584 } 585 code_buffer_.push_back(entry->skeleton.opcode); 586 if (entry->skeleton.opcode == 0x0F) { 587 code_buffer_.push_back(entry->skeleton.extra_opcode1); 588 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 589 code_buffer_.push_back(entry->skeleton.extra_opcode2); 590 } else { 591 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 592 } 593 } else { 594 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 595 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 596 } 597 if (X86_FPREG(reg)) { 598 reg = reg & X86_FP_REG_MASK; 599 } 600 if (reg >= 4) { 601 DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) 602 << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); 603 } 604 DCHECK_LT(reg, 8); 605 DCHECK_LT(base, 8); 606 uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (reg << 3) | base; 607 code_buffer_.push_back(modrm); 608 if (base == rX86_SP) { 609 // Special SIB for SP base 610 code_buffer_.push_back(0 << 6 | (rX86_SP << 3) | rX86_SP); 611 } 612 EmitDisp(base, disp); 613 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 614 DCHECK_EQ(0, entry->skeleton.ax_opcode); 615 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 616 } 617 618 void X86Mir2Lir::EmitRegMem(const X86EncodingMap* entry, 619 uint8_t reg, uint8_t base, int disp) { 620 // Opcode will flip operands. 621 EmitMemReg(entry, base, disp, reg); 622 } 623 624 void X86Mir2Lir::EmitRegArray(const X86EncodingMap* entry, uint8_t reg, uint8_t base, uint8_t index, 625 int scale, int disp) { 626 if (entry->skeleton.prefix1 != 0) { 627 code_buffer_.push_back(entry->skeleton.prefix1); 628 if (entry->skeleton.prefix2 != 0) { 629 code_buffer_.push_back(entry->skeleton.prefix2); 630 } 631 } else { 632 DCHECK_EQ(0, entry->skeleton.prefix2); 633 } 634 code_buffer_.push_back(entry->skeleton.opcode); 635 if (entry->skeleton.opcode == 0x0F) { 636 code_buffer_.push_back(entry->skeleton.extra_opcode1); 637 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 638 code_buffer_.push_back(entry->skeleton.extra_opcode2); 639 } else { 640 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 641 } 642 } else { 643 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 644 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 645 } 646 if (X86_FPREG(reg)) { 647 reg = reg & X86_FP_REG_MASK; 648 } 649 DCHECK_LT(reg, 8); 650 uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (reg << 3) | rX86_SP; 651 code_buffer_.push_back(modrm); 652 DCHECK_LT(scale, 4); 653 DCHECK_LT(index, 8); 654 DCHECK_LT(base, 8); 655 uint8_t sib = (scale << 6) | (index << 3) | base; 656 code_buffer_.push_back(sib); 657 EmitDisp(base, disp); 658 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 659 DCHECK_EQ(0, entry->skeleton.ax_opcode); 660 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 661 } 662 663 void X86Mir2Lir::EmitArrayReg(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp, 664 uint8_t reg) { 665 // Opcode will flip operands. 666 EmitRegArray(entry, reg, base, index, scale, disp); 667 } 668 669 void X86Mir2Lir::EmitRegThread(const X86EncodingMap* entry, uint8_t reg, int disp) { 670 DCHECK_NE(entry->skeleton.prefix1, 0); 671 code_buffer_.push_back(entry->skeleton.prefix1); 672 if (entry->skeleton.prefix2 != 0) { 673 code_buffer_.push_back(entry->skeleton.prefix2); 674 } 675 code_buffer_.push_back(entry->skeleton.opcode); 676 if (entry->skeleton.opcode == 0x0F) { 677 code_buffer_.push_back(entry->skeleton.extra_opcode1); 678 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 679 code_buffer_.push_back(entry->skeleton.extra_opcode2); 680 } else { 681 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 682 } 683 } else { 684 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 685 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 686 } 687 if (X86_FPREG(reg)) { 688 reg = reg & X86_FP_REG_MASK; 689 } 690 if (reg >= 4) { 691 DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) 692 << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); 693 } 694 DCHECK_LT(reg, 8); 695 uint8_t modrm = (0 << 6) | (reg << 3) | rBP; 696 code_buffer_.push_back(modrm); 697 code_buffer_.push_back(disp & 0xFF); 698 code_buffer_.push_back((disp >> 8) & 0xFF); 699 code_buffer_.push_back((disp >> 16) & 0xFF); 700 code_buffer_.push_back((disp >> 24) & 0xFF); 701 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 702 DCHECK_EQ(0, entry->skeleton.ax_opcode); 703 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 704 } 705 706 void X86Mir2Lir::EmitRegReg(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2) { 707 if (entry->skeleton.prefix1 != 0) { 708 code_buffer_.push_back(entry->skeleton.prefix1); 709 if (entry->skeleton.prefix2 != 0) { 710 code_buffer_.push_back(entry->skeleton.prefix2); 711 } 712 } else { 713 DCHECK_EQ(0, entry->skeleton.prefix2); 714 } 715 code_buffer_.push_back(entry->skeleton.opcode); 716 if (entry->skeleton.opcode == 0x0F) { 717 code_buffer_.push_back(entry->skeleton.extra_opcode1); 718 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 719 code_buffer_.push_back(entry->skeleton.extra_opcode2); 720 } else { 721 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 722 } 723 } else { 724 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 725 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 726 } 727 if (X86_FPREG(reg1)) { 728 reg1 = reg1 & X86_FP_REG_MASK; 729 } 730 if (X86_FPREG(reg2)) { 731 reg2 = reg2 & X86_FP_REG_MASK; 732 } 733 DCHECK_LT(reg1, 8); 734 DCHECK_LT(reg2, 8); 735 uint8_t modrm = (3 << 6) | (reg1 << 3) | reg2; 736 code_buffer_.push_back(modrm); 737 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 738 DCHECK_EQ(0, entry->skeleton.ax_opcode); 739 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 740 } 741 742 void X86Mir2Lir::EmitRegRegImm(const X86EncodingMap* entry, 743 uint8_t reg1, uint8_t reg2, int32_t imm) { 744 if (entry->skeleton.prefix1 != 0) { 745 code_buffer_.push_back(entry->skeleton.prefix1); 746 if (entry->skeleton.prefix2 != 0) { 747 code_buffer_.push_back(entry->skeleton.prefix2); 748 } 749 } else { 750 DCHECK_EQ(0, entry->skeleton.prefix2); 751 } 752 code_buffer_.push_back(entry->skeleton.opcode); 753 if (entry->skeleton.opcode == 0x0F) { 754 code_buffer_.push_back(entry->skeleton.extra_opcode1); 755 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 756 code_buffer_.push_back(entry->skeleton.extra_opcode2); 757 } else { 758 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 759 } 760 } else { 761 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 762 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 763 } 764 if (X86_FPREG(reg1)) { 765 reg1 = reg1 & X86_FP_REG_MASK; 766 } 767 if (X86_FPREG(reg2)) { 768 reg2 = reg2 & X86_FP_REG_MASK; 769 } 770 DCHECK_LT(reg1, 8); 771 DCHECK_LT(reg2, 8); 772 uint8_t modrm = (3 << 6) | (reg1 << 3) | reg2; 773 code_buffer_.push_back(modrm); 774 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 775 DCHECK_EQ(0, entry->skeleton.ax_opcode); 776 switch (entry->skeleton.immediate_bytes) { 777 case 1: 778 DCHECK(IS_SIMM8(imm)); 779 code_buffer_.push_back(imm & 0xFF); 780 break; 781 case 2: 782 DCHECK(IS_SIMM16(imm)); 783 code_buffer_.push_back(imm & 0xFF); 784 code_buffer_.push_back((imm >> 8) & 0xFF); 785 break; 786 case 4: 787 code_buffer_.push_back(imm & 0xFF); 788 code_buffer_.push_back((imm >> 8) & 0xFF); 789 code_buffer_.push_back((imm >> 16) & 0xFF); 790 code_buffer_.push_back((imm >> 24) & 0xFF); 791 break; 792 default: 793 LOG(FATAL) << "Unexpected immediate bytes (" << entry->skeleton.immediate_bytes 794 << ") for instruction: " << entry->name; 795 break; 796 } 797 } 798 799 void X86Mir2Lir::EmitRegImm(const X86EncodingMap* entry, uint8_t reg, int imm) { 800 if (entry->skeleton.prefix1 != 0) { 801 code_buffer_.push_back(entry->skeleton.prefix1); 802 if (entry->skeleton.prefix2 != 0) { 803 code_buffer_.push_back(entry->skeleton.prefix2); 804 } 805 } else { 806 DCHECK_EQ(0, entry->skeleton.prefix2); 807 } 808 if (reg == rAX && entry->skeleton.ax_opcode != 0) { 809 code_buffer_.push_back(entry->skeleton.ax_opcode); 810 } else { 811 code_buffer_.push_back(entry->skeleton.opcode); 812 if (entry->skeleton.opcode == 0x0F) { 813 code_buffer_.push_back(entry->skeleton.extra_opcode1); 814 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 815 code_buffer_.push_back(entry->skeleton.extra_opcode2); 816 } else { 817 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 818 } 819 } else { 820 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 821 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 822 } 823 if (X86_FPREG(reg)) { 824 reg = reg & X86_FP_REG_MASK; 825 } 826 uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; 827 code_buffer_.push_back(modrm); 828 } 829 switch (entry->skeleton.immediate_bytes) { 830 case 1: 831 DCHECK(IS_SIMM8(imm)); 832 code_buffer_.push_back(imm & 0xFF); 833 break; 834 case 2: 835 DCHECK(IS_SIMM16(imm)); 836 code_buffer_.push_back(imm & 0xFF); 837 code_buffer_.push_back((imm >> 8) & 0xFF); 838 break; 839 case 4: 840 code_buffer_.push_back(imm & 0xFF); 841 code_buffer_.push_back((imm >> 8) & 0xFF); 842 code_buffer_.push_back((imm >> 16) & 0xFF); 843 code_buffer_.push_back((imm >> 24) & 0xFF); 844 break; 845 default: 846 LOG(FATAL) << "Unexpected immediate bytes (" << entry->skeleton.immediate_bytes 847 << ") for instruction: " << entry->name; 848 break; 849 } 850 } 851 852 void X86Mir2Lir::EmitThreadImm(const X86EncodingMap* entry, int disp, int imm) { 853 if (entry->skeleton.prefix1 != 0) { 854 code_buffer_.push_back(entry->skeleton.prefix1); 855 if (entry->skeleton.prefix2 != 0) { 856 code_buffer_.push_back(entry->skeleton.prefix2); 857 } 858 } else { 859 DCHECK_EQ(0, entry->skeleton.prefix2); 860 } 861 code_buffer_.push_back(entry->skeleton.opcode); 862 if (entry->skeleton.opcode == 0x0F) { 863 code_buffer_.push_back(entry->skeleton.extra_opcode1); 864 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 865 code_buffer_.push_back(entry->skeleton.extra_opcode2); 866 } else { 867 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 868 } 869 } else { 870 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 871 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 872 } 873 uint8_t modrm = (0 << 6) | (entry->skeleton.modrm_opcode << 3) | rBP; 874 code_buffer_.push_back(modrm); 875 code_buffer_.push_back(disp & 0xFF); 876 code_buffer_.push_back((disp >> 8) & 0xFF); 877 code_buffer_.push_back((disp >> 16) & 0xFF); 878 code_buffer_.push_back((disp >> 24) & 0xFF); 879 switch (entry->skeleton.immediate_bytes) { 880 case 1: 881 DCHECK(IS_SIMM8(imm)); 882 code_buffer_.push_back(imm & 0xFF); 883 break; 884 case 2: 885 DCHECK(IS_SIMM16(imm)); 886 code_buffer_.push_back(imm & 0xFF); 887 code_buffer_.push_back((imm >> 8) & 0xFF); 888 break; 889 case 4: 890 code_buffer_.push_back(imm & 0xFF); 891 code_buffer_.push_back((imm >> 8) & 0xFF); 892 code_buffer_.push_back((imm >> 16) & 0xFF); 893 code_buffer_.push_back((imm >> 24) & 0xFF); 894 break; 895 default: 896 LOG(FATAL) << "Unexpected immediate bytes (" << entry->skeleton.immediate_bytes 897 << ") for instruction: " << entry->name; 898 break; 899 } 900 DCHECK_EQ(entry->skeleton.ax_opcode, 0); 901 } 902 903 void X86Mir2Lir::EmitMovRegImm(const X86EncodingMap* entry, uint8_t reg, int imm) { 904 DCHECK_LT(reg, 8); 905 code_buffer_.push_back(0xB8 + reg); 906 code_buffer_.push_back(imm & 0xFF); 907 code_buffer_.push_back((imm >> 8) & 0xFF); 908 code_buffer_.push_back((imm >> 16) & 0xFF); 909 code_buffer_.push_back((imm >> 24) & 0xFF); 910 } 911 912 void X86Mir2Lir::EmitShiftRegImm(const X86EncodingMap* entry, uint8_t reg, int imm) { 913 if (entry->skeleton.prefix1 != 0) { 914 code_buffer_.push_back(entry->skeleton.prefix1); 915 if (entry->skeleton.prefix2 != 0) { 916 code_buffer_.push_back(entry->skeleton.prefix2); 917 } 918 } else { 919 DCHECK_EQ(0, entry->skeleton.prefix2); 920 } 921 if (imm != 1) { 922 code_buffer_.push_back(entry->skeleton.opcode); 923 } else { 924 // Shorter encoding for 1 bit shift 925 code_buffer_.push_back(entry->skeleton.ax_opcode); 926 } 927 if (entry->skeleton.opcode == 0x0F) { 928 code_buffer_.push_back(entry->skeleton.extra_opcode1); 929 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 930 code_buffer_.push_back(entry->skeleton.extra_opcode2); 931 } else { 932 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 933 } 934 } else { 935 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 936 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 937 } 938 if (reg >= 4) { 939 DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) 940 << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); 941 } 942 DCHECK_LT(reg, 8); 943 uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; 944 code_buffer_.push_back(modrm); 945 if (imm != 1) { 946 DCHECK_EQ(entry->skeleton.immediate_bytes, 1); 947 DCHECK(IS_SIMM8(imm)); 948 code_buffer_.push_back(imm & 0xFF); 949 } 950 } 951 952 void X86Mir2Lir::EmitShiftRegCl(const X86EncodingMap* entry, uint8_t reg, uint8_t cl) { 953 DCHECK_EQ(cl, static_cast<uint8_t>(rCX)); 954 if (entry->skeleton.prefix1 != 0) { 955 code_buffer_.push_back(entry->skeleton.prefix1); 956 if (entry->skeleton.prefix2 != 0) { 957 code_buffer_.push_back(entry->skeleton.prefix2); 958 } 959 } else { 960 DCHECK_EQ(0, entry->skeleton.prefix2); 961 } 962 code_buffer_.push_back(entry->skeleton.opcode); 963 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 964 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 965 DCHECK_LT(reg, 8); 966 uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; 967 code_buffer_.push_back(modrm); 968 DCHECK_EQ(0, entry->skeleton.ax_opcode); 969 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 970 } 971 972 void X86Mir2Lir::EmitRegCond(const X86EncodingMap* entry, uint8_t reg, uint8_t condition) { 973 if (entry->skeleton.prefix1 != 0) { 974 code_buffer_.push_back(entry->skeleton.prefix1); 975 if (entry->skeleton.prefix2 != 0) { 976 code_buffer_.push_back(entry->skeleton.prefix2); 977 } 978 } else { 979 DCHECK_EQ(0, entry->skeleton.prefix2); 980 } 981 DCHECK_EQ(0, entry->skeleton.ax_opcode); 982 DCHECK_EQ(0x0F, entry->skeleton.opcode); 983 code_buffer_.push_back(0x0F); 984 DCHECK_EQ(0x90, entry->skeleton.extra_opcode1); 985 code_buffer_.push_back(0x90 | condition); 986 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 987 DCHECK_LT(reg, 8); 988 uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; 989 code_buffer_.push_back(modrm); 990 DCHECK_EQ(entry->skeleton.immediate_bytes, 0); 991 } 992 993 void X86Mir2Lir::EmitJmp(const X86EncodingMap* entry, int rel) { 994 if (entry->opcode == kX86Jmp8) { 995 DCHECK(IS_SIMM8(rel)); 996 code_buffer_.push_back(0xEB); 997 code_buffer_.push_back(rel & 0xFF); 998 } else if (entry->opcode == kX86Jmp32) { 999 code_buffer_.push_back(0xE9); 1000 code_buffer_.push_back(rel & 0xFF); 1001 code_buffer_.push_back((rel >> 8) & 0xFF); 1002 code_buffer_.push_back((rel >> 16) & 0xFF); 1003 code_buffer_.push_back((rel >> 24) & 0xFF); 1004 } else { 1005 DCHECK(entry->opcode == kX86JmpR); 1006 code_buffer_.push_back(entry->skeleton.opcode); 1007 uint8_t reg = static_cast<uint8_t>(rel); 1008 DCHECK_LT(reg, 8); 1009 uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; 1010 code_buffer_.push_back(modrm); 1011 } 1012 } 1013 1014 void X86Mir2Lir::EmitJcc(const X86EncodingMap* entry, int rel, uint8_t cc) { 1015 DCHECK_LT(cc, 16); 1016 if (entry->opcode == kX86Jcc8) { 1017 DCHECK(IS_SIMM8(rel)); 1018 code_buffer_.push_back(0x70 | cc); 1019 code_buffer_.push_back(rel & 0xFF); 1020 } else { 1021 DCHECK(entry->opcode == kX86Jcc32); 1022 code_buffer_.push_back(0x0F); 1023 code_buffer_.push_back(0x80 | cc); 1024 code_buffer_.push_back(rel & 0xFF); 1025 code_buffer_.push_back((rel >> 8) & 0xFF); 1026 code_buffer_.push_back((rel >> 16) & 0xFF); 1027 code_buffer_.push_back((rel >> 24) & 0xFF); 1028 } 1029 } 1030 1031 void X86Mir2Lir::EmitCallMem(const X86EncodingMap* entry, uint8_t base, int disp) { 1032 if (entry->skeleton.prefix1 != 0) { 1033 code_buffer_.push_back(entry->skeleton.prefix1); 1034 if (entry->skeleton.prefix2 != 0) { 1035 code_buffer_.push_back(entry->skeleton.prefix2); 1036 } 1037 } else { 1038 DCHECK_EQ(0, entry->skeleton.prefix2); 1039 } 1040 code_buffer_.push_back(entry->skeleton.opcode); 1041 if (entry->skeleton.opcode == 0x0F) { 1042 code_buffer_.push_back(entry->skeleton.extra_opcode1); 1043 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 1044 code_buffer_.push_back(entry->skeleton.extra_opcode2); 1045 } else { 1046 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 1047 } 1048 } else { 1049 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 1050 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 1051 } 1052 uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (entry->skeleton.modrm_opcode << 3) | base; 1053 code_buffer_.push_back(modrm); 1054 if (base == rX86_SP) { 1055 // Special SIB for SP base 1056 code_buffer_.push_back(0 << 6 | (rX86_SP << 3) | rX86_SP); 1057 } 1058 EmitDisp(base, disp); 1059 DCHECK_EQ(0, entry->skeleton.ax_opcode); 1060 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 1061 } 1062 1063 void X86Mir2Lir::EmitCallThread(const X86EncodingMap* entry, int disp) { 1064 DCHECK_NE(entry->skeleton.prefix1, 0); 1065 code_buffer_.push_back(entry->skeleton.prefix1); 1066 if (entry->skeleton.prefix2 != 0) { 1067 code_buffer_.push_back(entry->skeleton.prefix2); 1068 } 1069 code_buffer_.push_back(entry->skeleton.opcode); 1070 if (entry->skeleton.opcode == 0x0F) { 1071 code_buffer_.push_back(entry->skeleton.extra_opcode1); 1072 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { 1073 code_buffer_.push_back(entry->skeleton.extra_opcode2); 1074 } else { 1075 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 1076 } 1077 } else { 1078 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 1079 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 1080 } 1081 uint8_t modrm = (0 << 6) | (entry->skeleton.modrm_opcode << 3) | rBP; 1082 code_buffer_.push_back(modrm); 1083 code_buffer_.push_back(disp & 0xFF); 1084 code_buffer_.push_back((disp >> 8) & 0xFF); 1085 code_buffer_.push_back((disp >> 16) & 0xFF); 1086 code_buffer_.push_back((disp >> 24) & 0xFF); 1087 DCHECK_EQ(0, entry->skeleton.ax_opcode); 1088 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 1089 } 1090 1091 void X86Mir2Lir::EmitPcRel(const X86EncodingMap* entry, uint8_t reg, 1092 int base_or_table, uint8_t index, int scale, int table_or_disp) { 1093 int disp; 1094 if (entry->opcode == kX86PcRelLoadRA) { 1095 Mir2Lir::SwitchTable *tab_rec = reinterpret_cast<Mir2Lir::SwitchTable*>(table_or_disp); 1096 disp = tab_rec->offset; 1097 } else { 1098 DCHECK(entry->opcode == kX86PcRelAdr); 1099 Mir2Lir::FillArrayData *tab_rec = reinterpret_cast<Mir2Lir::FillArrayData*>(base_or_table); 1100 disp = tab_rec->offset; 1101 } 1102 if (entry->skeleton.prefix1 != 0) { 1103 code_buffer_.push_back(entry->skeleton.prefix1); 1104 if (entry->skeleton.prefix2 != 0) { 1105 code_buffer_.push_back(entry->skeleton.prefix2); 1106 } 1107 } else { 1108 DCHECK_EQ(0, entry->skeleton.prefix2); 1109 } 1110 if (X86_FPREG(reg)) { 1111 reg = reg & X86_FP_REG_MASK; 1112 } 1113 DCHECK_LT(reg, 8); 1114 if (entry->opcode == kX86PcRelLoadRA) { 1115 code_buffer_.push_back(entry->skeleton.opcode); 1116 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 1117 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 1118 uint8_t modrm = (2 << 6) | (reg << 3) | rX86_SP; 1119 code_buffer_.push_back(modrm); 1120 DCHECK_LT(scale, 4); 1121 DCHECK_LT(index, 8); 1122 DCHECK_LT(base_or_table, 8); 1123 uint8_t base = static_cast<uint8_t>(base_or_table); 1124 uint8_t sib = (scale << 6) | (index << 3) | base; 1125 code_buffer_.push_back(sib); 1126 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 1127 } else { 1128 code_buffer_.push_back(entry->skeleton.opcode + reg); 1129 } 1130 code_buffer_.push_back(disp & 0xFF); 1131 code_buffer_.push_back((disp >> 8) & 0xFF); 1132 code_buffer_.push_back((disp >> 16) & 0xFF); 1133 code_buffer_.push_back((disp >> 24) & 0xFF); 1134 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 1135 DCHECK_EQ(0, entry->skeleton.ax_opcode); 1136 } 1137 1138 void X86Mir2Lir::EmitMacro(const X86EncodingMap* entry, uint8_t reg, int offset) { 1139 DCHECK(entry->opcode == kX86StartOfMethod) << entry->name; 1140 code_buffer_.push_back(0xE8); // call +0 1141 code_buffer_.push_back(0); 1142 code_buffer_.push_back(0); 1143 code_buffer_.push_back(0); 1144 code_buffer_.push_back(0); 1145 1146 DCHECK_LT(reg, 8); 1147 code_buffer_.push_back(0x58 + reg); // pop reg 1148 1149 EmitRegImm(&X86Mir2Lir::EncodingMap[kX86Sub32RI], reg, offset + 5 /* size of call +0 */); 1150 } 1151 1152 void X86Mir2Lir::EmitUnimplemented(const X86EncodingMap* entry, LIR* lir) { 1153 UNIMPLEMENTED(WARNING) << "encoding kind for " << entry->name << " " 1154 << BuildInsnString(entry->fmt, lir, 0); 1155 for (int i = 0; i < GetInsnSize(lir); ++i) { 1156 code_buffer_.push_back(0xCC); // push breakpoint instruction - int 3 1157 } 1158 } 1159 1160 /* 1161 * Assemble the LIR into binary instruction format. Note that we may 1162 * discover that pc-relative displacements may not fit the selected 1163 * instruction. In those cases we will try to substitute a new code 1164 * sequence or request that the trace be shortened and retried. 1165 */ 1166 AssemblerStatus X86Mir2Lir::AssembleInstructions(uintptr_t start_addr) { 1167 LIR *lir; 1168 AssemblerStatus res = kSuccess; // Assume success 1169 1170 const bool kVerbosePcFixup = false; 1171 for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) { 1172 if (lir->opcode < 0) { 1173 continue; 1174 } 1175 1176 if (lir->flags.is_nop) { 1177 continue; 1178 } 1179 1180 if (lir->flags.pcRelFixup) { 1181 switch (lir->opcode) { 1182 case kX86Jcc8: { 1183 LIR *target_lir = lir->target; 1184 DCHECK(target_lir != NULL); 1185 int delta = 0; 1186 uintptr_t pc; 1187 if (IS_SIMM8(lir->operands[0])) { 1188 pc = lir->offset + 2 /* opcode + rel8 */; 1189 } else { 1190 pc = lir->offset + 6 /* 2 byte opcode + rel32 */; 1191 } 1192 uintptr_t target = target_lir->offset; 1193 delta = target - pc; 1194 if (IS_SIMM8(delta) != IS_SIMM8(lir->operands[0])) { 1195 if (kVerbosePcFixup) { 1196 LOG(INFO) << "Retry for JCC growth at " << lir->offset 1197 << " delta: " << delta << " old delta: " << lir->operands[0]; 1198 } 1199 lir->opcode = kX86Jcc32; 1200 SetupResourceMasks(lir); 1201 res = kRetryAll; 1202 } 1203 if (kVerbosePcFixup) { 1204 LOG(INFO) << "Source:"; 1205 DumpLIRInsn(lir, 0); 1206 LOG(INFO) << "Target:"; 1207 DumpLIRInsn(target_lir, 0); 1208 LOG(INFO) << "Delta " << delta; 1209 } 1210 lir->operands[0] = delta; 1211 break; 1212 } 1213 case kX86Jcc32: { 1214 LIR *target_lir = lir->target; 1215 DCHECK(target_lir != NULL); 1216 uintptr_t pc = lir->offset + 6 /* 2 byte opcode + rel32 */; 1217 uintptr_t target = target_lir->offset; 1218 int delta = target - pc; 1219 if (kVerbosePcFixup) { 1220 LOG(INFO) << "Source:"; 1221 DumpLIRInsn(lir, 0); 1222 LOG(INFO) << "Target:"; 1223 DumpLIRInsn(target_lir, 0); 1224 LOG(INFO) << "Delta " << delta; 1225 } 1226 lir->operands[0] = delta; 1227 break; 1228 } 1229 case kX86Jmp8: { 1230 LIR *target_lir = lir->target; 1231 DCHECK(target_lir != NULL); 1232 int delta = 0; 1233 uintptr_t pc; 1234 if (IS_SIMM8(lir->operands[0])) { 1235 pc = lir->offset + 2 /* opcode + rel8 */; 1236 } else { 1237 pc = lir->offset + 5 /* opcode + rel32 */; 1238 } 1239 uintptr_t target = target_lir->offset; 1240 delta = target - pc; 1241 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && delta == 0) { 1242 // Useless branch 1243 lir->flags.is_nop = true; 1244 if (kVerbosePcFixup) { 1245 LOG(INFO) << "Retry for useless branch at " << lir->offset; 1246 } 1247 res = kRetryAll; 1248 } else if (IS_SIMM8(delta) != IS_SIMM8(lir->operands[0])) { 1249 if (kVerbosePcFixup) { 1250 LOG(INFO) << "Retry for JMP growth at " << lir->offset; 1251 } 1252 lir->opcode = kX86Jmp32; 1253 SetupResourceMasks(lir); 1254 res = kRetryAll; 1255 } 1256 lir->operands[0] = delta; 1257 break; 1258 } 1259 case kX86Jmp32: { 1260 LIR *target_lir = lir->target; 1261 DCHECK(target_lir != NULL); 1262 uintptr_t pc = lir->offset + 5 /* opcode + rel32 */; 1263 uintptr_t target = target_lir->offset; 1264 int delta = target - pc; 1265 lir->operands[0] = delta; 1266 break; 1267 } 1268 default: 1269 break; 1270 } 1271 } 1272 1273 /* 1274 * If one of the pc-relative instructions expanded we'll have 1275 * to make another pass. Don't bother to fully assemble the 1276 * instruction. 1277 */ 1278 if (res != kSuccess) { 1279 continue; 1280 } 1281 CHECK_EQ(static_cast<size_t>(lir->offset), code_buffer_.size()); 1282 const X86EncodingMap *entry = &X86Mir2Lir::EncodingMap[lir->opcode]; 1283 size_t starting_cbuf_size = code_buffer_.size(); 1284 switch (entry->kind) { 1285 case kData: // 4 bytes of data 1286 code_buffer_.push_back(lir->operands[0]); 1287 break; 1288 case kNullary: // 1 byte of opcode 1289 DCHECK_EQ(0, entry->skeleton.prefix1); 1290 DCHECK_EQ(0, entry->skeleton.prefix2); 1291 code_buffer_.push_back(entry->skeleton.opcode); 1292 if (entry->skeleton.extra_opcode1 != 0) { 1293 code_buffer_.push_back(entry->skeleton.extra_opcode1); 1294 if (entry->skeleton.extra_opcode2 != 0) { 1295 code_buffer_.push_back(entry->skeleton.extra_opcode2); 1296 } 1297 } else { 1298 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 1299 } 1300 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 1301 DCHECK_EQ(0, entry->skeleton.ax_opcode); 1302 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 1303 break; 1304 case kReg: // lir operands - 0: reg 1305 EmitOpReg(entry, lir->operands[0]); 1306 break; 1307 case kMem: // lir operands - 0: base, 1: disp 1308 EmitOpMem(entry, lir->operands[0], lir->operands[1]); 1309 break; 1310 case kMemReg: // lir operands - 0: base, 1: disp, 2: reg 1311 EmitMemReg(entry, lir->operands[0], lir->operands[1], lir->operands[2]); 1312 break; 1313 case kArrayReg: // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg 1314 EmitArrayReg(entry, lir->operands[0], lir->operands[1], lir->operands[2], 1315 lir->operands[3], lir->operands[4]); 1316 break; 1317 case kRegMem: // lir operands - 0: reg, 1: base, 2: disp 1318 EmitRegMem(entry, lir->operands[0], lir->operands[1], lir->operands[2]); 1319 break; 1320 case kRegArray: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp 1321 EmitRegArray(entry, lir->operands[0], lir->operands[1], lir->operands[2], 1322 lir->operands[3], lir->operands[4]); 1323 break; 1324 case kRegThread: // lir operands - 0: reg, 1: disp 1325 EmitRegThread(entry, lir->operands[0], lir->operands[1]); 1326 break; 1327 case kRegReg: // lir operands - 0: reg1, 1: reg2 1328 EmitRegReg(entry, lir->operands[0], lir->operands[1]); 1329 break; 1330 case kRegRegStore: // lir operands - 0: reg2, 1: reg1 1331 EmitRegReg(entry, lir->operands[1], lir->operands[0]); 1332 break; 1333 case kRegRegImm: 1334 EmitRegRegImm(entry, lir->operands[0], lir->operands[1], lir->operands[2]); 1335 break; 1336 case kRegImm: // lir operands - 0: reg, 1: immediate 1337 EmitRegImm(entry, lir->operands[0], lir->operands[1]); 1338 break; 1339 case kThreadImm: // lir operands - 0: disp, 1: immediate 1340 EmitThreadImm(entry, lir->operands[0], lir->operands[1]); 1341 break; 1342 case kMovRegImm: // lir operands - 0: reg, 1: immediate 1343 EmitMovRegImm(entry, lir->operands[0], lir->operands[1]); 1344 break; 1345 case kShiftRegImm: // lir operands - 0: reg, 1: immediate 1346 EmitShiftRegImm(entry, lir->operands[0], lir->operands[1]); 1347 break; 1348 case kShiftRegCl: // lir operands - 0: reg, 1: cl 1349 EmitShiftRegCl(entry, lir->operands[0], lir->operands[1]); 1350 break; 1351 case kRegCond: // lir operands - 0: reg, 1: condition 1352 EmitRegCond(entry, lir->operands[0], lir->operands[1]); 1353 break; 1354 case kJmp: // lir operands - 0: rel 1355 if (entry->opcode == kX86JmpT) { 1356 // This works since the instruction format for jmp and call is basically the same and 1357 // EmitCallThread loads opcode info. 1358 EmitCallThread(entry, lir->operands[0]); 1359 } else { 1360 EmitJmp(entry, lir->operands[0]); 1361 } 1362 break; 1363 case kJcc: // lir operands - 0: rel, 1: CC, target assigned 1364 EmitJcc(entry, lir->operands[0], lir->operands[1]); 1365 break; 1366 case kCall: 1367 switch (entry->opcode) { 1368 case kX86CallM: // lir operands - 0: base, 1: disp 1369 EmitCallMem(entry, lir->operands[0], lir->operands[1]); 1370 break; 1371 case kX86CallT: // lir operands - 0: disp 1372 EmitCallThread(entry, lir->operands[0]); 1373 break; 1374 default: 1375 EmitUnimplemented(entry, lir); 1376 break; 1377 } 1378 break; 1379 case kPcRel: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table 1380 EmitPcRel(entry, lir->operands[0], lir->operands[1], lir->operands[2], 1381 lir->operands[3], lir->operands[4]); 1382 break; 1383 case kMacro: 1384 EmitMacro(entry, lir->operands[0], lir->offset); 1385 break; 1386 default: 1387 EmitUnimplemented(entry, lir); 1388 break; 1389 } 1390 CHECK_EQ(static_cast<size_t>(GetInsnSize(lir)), 1391 code_buffer_.size() - starting_cbuf_size) 1392 << "Instruction size mismatch for entry: " << X86Mir2Lir::EncodingMap[lir->opcode].name; 1393 } 1394 return res; 1395 } 1396 1397 } // namespace art 1398