assemble_x86.cc revision 17088bbded68e35da8050a40206dfd3cbba9e6d2
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 21namespace art { 22 23#define MAX_ASSEMBLER_RETRIES 50 24 25const 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 81ENCODING_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 */), 87ENCODING_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 */), 93ENCODING_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 */), 99ENCODING_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 */), 105ENCODING_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 */), 111ENCODING_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 */), 117ENCODING_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 */), 123ENCODING_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 { kX86CallR, kCall, IS_UNARY_OP | IS_BRANCH | REG_USE0, { 0, 0, 0xE8, 0, 0, 0, 0, 0 }, "CallR", "!0r" }, 323 { kX86CallM, kCall, IS_BINARY_OP | IS_BRANCH | IS_LOAD | REG_USE0, { 0, 0, 0xFF, 0, 0, 2, 0, 0 }, "CallM", "[!0r+!1d]" }, 324 { kX86CallA, kCall, IS_QUAD_OP | IS_BRANCH | IS_LOAD | REG_USE01, { 0, 0, 0xFF, 0, 0, 2, 0, 0 }, "CallA", "[!0r+!1r<<!2d+!3d]" }, 325 { kX86CallT, kCall, IS_UNARY_OP | IS_BRANCH | IS_LOAD, { THREAD_PREFIX, 0, 0xFF, 0, 0, 2, 0, 0 }, "CallT", "fs:[!0d]" }, 326 { kX86Ret, kNullary, NO_OPERAND | IS_BRANCH, { 0, 0, 0xC3, 0, 0, 0, 0, 0 }, "Ret", "" }, 327 328 { kX86StartOfMethod, kMacro, IS_UNARY_OP | SETS_CCODES, { 0, 0, 0, 0, 0, 0, 0, 0 }, "StartOfMethod", "!0r" }, 329 { kX86PcRelLoadRA, kPcRel, IS_LOAD | IS_QUIN_OP | REG_DEF0_USE12, { 0, 0, 0x8B, 0, 0, 0, 0, 0 }, "PcRelLoadRA", "!0r,[!1r+!2r<<!3d+!4p]" }, 330 { kX86PcRelAdr, kPcRel, IS_LOAD | IS_BINARY_OP | REG_DEF0, { 0, 0, 0xB8, 0, 0, 0, 0, 4 }, "PcRelAdr", "!0r,!1d" }, 331}; 332 333static size_t ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib) { 334 size_t size = 0; 335 if (entry->skeleton.prefix1 > 0) { 336 ++size; 337 if (entry->skeleton.prefix2 > 0) { 338 ++size; 339 } 340 } 341 ++size; // opcode 342 if (entry->skeleton.opcode == 0x0F) { 343 ++size; 344 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode1 == 0x3A) { 345 ++size; 346 } 347 } 348 ++size; // modrm 349 if (has_sib || base == rX86_SP) { 350 // SP requires a SIB byte. 351 ++size; 352 } 353 if (displacement != 0 || base == rBP) { 354 // BP requires an explicit displacement, even when it's 0. 355 if (entry->opcode != kX86Lea32RA) { 356 DCHECK_NE(entry->flags & (IS_LOAD | IS_STORE), 0ULL) << entry->name; 357 } 358 size += IS_SIMM8(displacement) ? 1 : 4; 359 } 360 size += entry->skeleton.immediate_bytes; 361 return size; 362} 363 364int X86Mir2Lir::GetInsnSize(LIR* lir) { 365 DCHECK(!IsPseudoLirOp(lir->opcode)); 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 { 456 DCHECK(lir->opcode == kX86JmpR); 457 return 2; // opcode + modrm 458 } 459 case kCall: 460 switch (lir->opcode) { 461 case kX86CallR: return 2; // opcode modrm 462 case kX86CallM: // lir operands - 0: base, 1: disp 463 return ComputeSize(entry, lir->operands[0], lir->operands[1], false); 464 case kX86CallA: // lir operands - 0: base, 1: index, 2: scale, 3: disp 465 return ComputeSize(entry, lir->operands[0], lir->operands[3], true); 466 case kX86CallT: // lir operands - 0: disp 467 return ComputeSize(entry, 0, 0x12345678, false); // displacement size is always 32bit 468 default: 469 break; 470 } 471 break; 472 case kPcRel: 473 if (entry->opcode == kX86PcRelLoadRA) { 474 // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table 475 return ComputeSize(entry, lir->operands[1], 0x12345678, true); 476 } else { 477 DCHECK(entry->opcode == kX86PcRelAdr); 478 return 5; // opcode with reg + 4 byte immediate 479 } 480 case kMacro: 481 DCHECK_EQ(lir->opcode, static_cast<int>(kX86StartOfMethod)); 482 return 5 /* call opcode + 4 byte displacement */ + 1 /* pop reg */ + 483 ComputeSize(&X86Mir2Lir::EncodingMap[kX86Sub32RI], 0, 0, false) - 484 (lir->operands[0] == rAX ? 1 : 0); // shorter ax encoding 485 default: 486 break; 487 } 488 UNIMPLEMENTED(FATAL) << "Unimplemented size encoding for: " << entry->name; 489 return 0; 490} 491 492static uint8_t ModrmForDisp(int base, int disp) { 493 // BP requires an explicit disp, so do not omit it in the 0 case 494 if (disp == 0 && base != rBP) { 495 return 0; 496 } else if (IS_SIMM8(disp)) { 497 return 1; 498 } else { 499 return 2; 500 } 501} 502 503void X86Mir2Lir::EmitDisp(int base, int disp) { 504 // BP requires an explicit disp, so do not omit it in the 0 case 505 if (disp == 0 && base != rBP) { 506 return; 507 } else if (IS_SIMM8(disp)) { 508 code_buffer_.push_back(disp & 0xFF); 509 } else { 510 code_buffer_.push_back(disp & 0xFF); 511 code_buffer_.push_back((disp >> 8) & 0xFF); 512 code_buffer_.push_back((disp >> 16) & 0xFF); 513 code_buffer_.push_back((disp >> 24) & 0xFF); 514 } 515} 516 517void X86Mir2Lir::EmitOpReg(const X86EncodingMap* entry, uint8_t reg) { 518 if (entry->skeleton.prefix1 != 0) { 519 code_buffer_.push_back(entry->skeleton.prefix1); 520 if (entry->skeleton.prefix2 != 0) { 521 code_buffer_.push_back(entry->skeleton.prefix2); 522 } 523 } else { 524 DCHECK_EQ(0, entry->skeleton.prefix2); 525 } 526 code_buffer_.push_back(entry->skeleton.opcode); 527 if (entry->skeleton.opcode == 0x0F) { 528 code_buffer_.push_back(entry->skeleton.extra_opcode1); 529 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode1 == 0x3A) { 530 code_buffer_.push_back(entry->skeleton.extra_opcode2); 531 } else { 532 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 533 } 534 } else { 535 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 536 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 537 } 538 if (X86_FPREG(reg)) { 539 reg = reg & X86_FP_REG_MASK; 540 } 541 if (reg >= 4) { 542 DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) 543 << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); 544 } 545 DCHECK_LT(reg, 8); 546 uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; 547 code_buffer_.push_back(modrm); 548 DCHECK_EQ(0, entry->skeleton.ax_opcode); 549 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 550} 551 552void X86Mir2Lir::EmitOpMem(const X86EncodingMap* entry, uint8_t base, int disp) { 553 if (entry->skeleton.prefix1 != 0) { 554 code_buffer_.push_back(entry->skeleton.prefix1); 555 if (entry->skeleton.prefix2 != 0) { 556 code_buffer_.push_back(entry->skeleton.prefix2); 557 } 558 } else { 559 DCHECK_EQ(0, entry->skeleton.prefix2); 560 } 561 code_buffer_.push_back(entry->skeleton.opcode); 562 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 563 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 564 DCHECK_LT(entry->skeleton.modrm_opcode, 8); 565 DCHECK_LT(base, 8); 566 uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (entry->skeleton.modrm_opcode << 3) | base; 567 code_buffer_.push_back(modrm); 568 EmitDisp(base, disp); 569 DCHECK_EQ(0, entry->skeleton.ax_opcode); 570 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 571} 572 573void X86Mir2Lir::EmitMemReg(const X86EncodingMap* entry, 574 uint8_t base, int disp, uint8_t reg) { 575 if (entry->skeleton.prefix1 != 0) { 576 code_buffer_.push_back(entry->skeleton.prefix1); 577 if (entry->skeleton.prefix2 != 0) { 578 code_buffer_.push_back(entry->skeleton.prefix2); 579 } 580 } else { 581 DCHECK_EQ(0, entry->skeleton.prefix2); 582 } 583 code_buffer_.push_back(entry->skeleton.opcode); 584 if (entry->skeleton.opcode == 0x0F) { 585 code_buffer_.push_back(entry->skeleton.extra_opcode1); 586 if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode1 == 0x3A) { 587 code_buffer_.push_back(entry->skeleton.extra_opcode2); 588 } else { 589 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 590 } 591 } else { 592 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 593 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 594 } 595 if (X86_FPREG(reg)) { 596 reg = reg & X86_FP_REG_MASK; 597 } 598 if (reg >= 4) { 599 DCHECK(strchr(entry->name, '8') == NULL || 600 entry->opcode == kX86Movzx8RM || entry->opcode == kX86Movsx8RM) 601 << 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 618void 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 624void 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_opcode1 == 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 663void 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 669void 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_opcode1 == 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 706void 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_opcode1 == 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 742void 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_opcode1 == 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 799void 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_opcode1 == 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 852void 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_opcode1 == 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 903void 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 912void 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_opcode1 == 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 952void 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 972void 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 993void 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 1014void 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 1031void 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_opcode1 == 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 1063void 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_opcode1 == 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 1091void 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::EmbeddedData *tab_rec = 1096 reinterpret_cast<Mir2Lir::EmbeddedData*>(UnwrapPointer(table_or_disp)); 1097 disp = tab_rec->offset; 1098 } else { 1099 DCHECK(entry->opcode == kX86PcRelAdr); 1100 Mir2Lir::EmbeddedData *tab_rec = 1101 reinterpret_cast<Mir2Lir::EmbeddedData*>(UnwrapPointer(base_or_table)); 1102 disp = tab_rec->offset; 1103 } 1104 if (entry->skeleton.prefix1 != 0) { 1105 code_buffer_.push_back(entry->skeleton.prefix1); 1106 if (entry->skeleton.prefix2 != 0) { 1107 code_buffer_.push_back(entry->skeleton.prefix2); 1108 } 1109 } else { 1110 DCHECK_EQ(0, entry->skeleton.prefix2); 1111 } 1112 if (X86_FPREG(reg)) { 1113 reg = reg & X86_FP_REG_MASK; 1114 } 1115 DCHECK_LT(reg, 8); 1116 if (entry->opcode == kX86PcRelLoadRA) { 1117 code_buffer_.push_back(entry->skeleton.opcode); 1118 DCHECK_EQ(0, entry->skeleton.extra_opcode1); 1119 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 1120 uint8_t modrm = (2 << 6) | (reg << 3) | rX86_SP; 1121 code_buffer_.push_back(modrm); 1122 DCHECK_LT(scale, 4); 1123 DCHECK_LT(index, 8); 1124 DCHECK_LT(base_or_table, 8); 1125 uint8_t base = static_cast<uint8_t>(base_or_table); 1126 uint8_t sib = (scale << 6) | (index << 3) | base; 1127 code_buffer_.push_back(sib); 1128 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 1129 } else { 1130 code_buffer_.push_back(entry->skeleton.opcode + reg); 1131 } 1132 code_buffer_.push_back(disp & 0xFF); 1133 code_buffer_.push_back((disp >> 8) & 0xFF); 1134 code_buffer_.push_back((disp >> 16) & 0xFF); 1135 code_buffer_.push_back((disp >> 24) & 0xFF); 1136 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 1137 DCHECK_EQ(0, entry->skeleton.ax_opcode); 1138} 1139 1140void X86Mir2Lir::EmitMacro(const X86EncodingMap* entry, uint8_t reg, int offset) { 1141 DCHECK(entry->opcode == kX86StartOfMethod) << entry->name; 1142 code_buffer_.push_back(0xE8); // call +0 1143 code_buffer_.push_back(0); 1144 code_buffer_.push_back(0); 1145 code_buffer_.push_back(0); 1146 code_buffer_.push_back(0); 1147 1148 DCHECK_LT(reg, 8); 1149 code_buffer_.push_back(0x58 + reg); // pop reg 1150 1151 EmitRegImm(&X86Mir2Lir::EncodingMap[kX86Sub32RI], reg, offset + 5 /* size of call +0 */); 1152} 1153 1154void X86Mir2Lir::EmitUnimplemented(const X86EncodingMap* entry, LIR* lir) { 1155 UNIMPLEMENTED(WARNING) << "encoding kind for " << entry->name << " " 1156 << BuildInsnString(entry->fmt, lir, 0); 1157 for (int i = 0; i < GetInsnSize(lir); ++i) { 1158 code_buffer_.push_back(0xCC); // push breakpoint instruction - int 3 1159 } 1160} 1161 1162/* 1163 * Assemble the LIR into binary instruction format. Note that we may 1164 * discover that pc-relative displacements may not fit the selected 1165 * instruction. In those cases we will try to substitute a new code 1166 * sequence or request that the trace be shortened and retried. 1167 */ 1168AssemblerStatus X86Mir2Lir::AssembleInstructions(CodeOffset start_addr) { 1169 LIR *lir; 1170 AssemblerStatus res = kSuccess; // Assume success 1171 1172 const bool kVerbosePcFixup = false; 1173 for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) { 1174 if (IsPseudoLirOp(lir->opcode)) { 1175 continue; 1176 } 1177 1178 if (lir->flags.is_nop) { 1179 continue; 1180 } 1181 1182 if (lir->flags.fixup != kFixupNone) { 1183 switch (lir->opcode) { 1184 case kX86Jcc8: { 1185 LIR *target_lir = lir->target; 1186 DCHECK(target_lir != NULL); 1187 int delta = 0; 1188 CodeOffset pc; 1189 if (IS_SIMM8(lir->operands[0])) { 1190 pc = lir->offset + 2 /* opcode + rel8 */; 1191 } else { 1192 pc = lir->offset + 6 /* 2 byte opcode + rel32 */; 1193 } 1194 CodeOffset target = target_lir->offset; 1195 delta = target - pc; 1196 if (IS_SIMM8(delta) != IS_SIMM8(lir->operands[0])) { 1197 if (kVerbosePcFixup) { 1198 LOG(INFO) << "Retry for JCC growth at " << lir->offset 1199 << " delta: " << delta << " old delta: " << lir->operands[0]; 1200 } 1201 lir->opcode = kX86Jcc32; 1202 SetupResourceMasks(lir); 1203 res = kRetryAll; 1204 } 1205 if (kVerbosePcFixup) { 1206 LOG(INFO) << "Source:"; 1207 DumpLIRInsn(lir, 0); 1208 LOG(INFO) << "Target:"; 1209 DumpLIRInsn(target_lir, 0); 1210 LOG(INFO) << "Delta " << delta; 1211 } 1212 lir->operands[0] = delta; 1213 break; 1214 } 1215 case kX86Jcc32: { 1216 LIR *target_lir = lir->target; 1217 DCHECK(target_lir != NULL); 1218 CodeOffset pc = lir->offset + 6 /* 2 byte opcode + rel32 */; 1219 CodeOffset target = target_lir->offset; 1220 int delta = target - pc; 1221 if (kVerbosePcFixup) { 1222 LOG(INFO) << "Source:"; 1223 DumpLIRInsn(lir, 0); 1224 LOG(INFO) << "Target:"; 1225 DumpLIRInsn(target_lir, 0); 1226 LOG(INFO) << "Delta " << delta; 1227 } 1228 lir->operands[0] = delta; 1229 break; 1230 } 1231 case kX86Jmp8: { 1232 LIR *target_lir = lir->target; 1233 DCHECK(target_lir != NULL); 1234 int delta = 0; 1235 CodeOffset pc; 1236 if (IS_SIMM8(lir->operands[0])) { 1237 pc = lir->offset + 2 /* opcode + rel8 */; 1238 } else { 1239 pc = lir->offset + 5 /* opcode + rel32 */; 1240 } 1241 CodeOffset target = target_lir->offset; 1242 delta = target - pc; 1243 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && delta == 0) { 1244 // Useless branch 1245 NopLIR(lir); 1246 if (kVerbosePcFixup) { 1247 LOG(INFO) << "Retry for useless branch at " << lir->offset; 1248 } 1249 res = kRetryAll; 1250 } else if (IS_SIMM8(delta) != IS_SIMM8(lir->operands[0])) { 1251 if (kVerbosePcFixup) { 1252 LOG(INFO) << "Retry for JMP growth at " << lir->offset; 1253 } 1254 lir->opcode = kX86Jmp32; 1255 SetupResourceMasks(lir); 1256 res = kRetryAll; 1257 } 1258 lir->operands[0] = delta; 1259 break; 1260 } 1261 case kX86Jmp32: { 1262 LIR *target_lir = lir->target; 1263 DCHECK(target_lir != NULL); 1264 CodeOffset pc = lir->offset + 5 /* opcode + rel32 */; 1265 CodeOffset target = target_lir->offset; 1266 int delta = target - pc; 1267 lir->operands[0] = delta; 1268 break; 1269 } 1270 default: 1271 break; 1272 } 1273 } 1274 1275 /* 1276 * If one of the pc-relative instructions expanded we'll have 1277 * to make another pass. Don't bother to fully assemble the 1278 * instruction. 1279 */ 1280 if (res != kSuccess) { 1281 continue; 1282 } 1283 CHECK_EQ(static_cast<size_t>(lir->offset), code_buffer_.size()); 1284 const X86EncodingMap *entry = &X86Mir2Lir::EncodingMap[lir->opcode]; 1285 size_t starting_cbuf_size = code_buffer_.size(); 1286 switch (entry->kind) { 1287 case kData: // 4 bytes of data 1288 code_buffer_.push_back(lir->operands[0]); 1289 break; 1290 case kNullary: // 1 byte of opcode 1291 DCHECK_EQ(0, entry->skeleton.prefix1); 1292 DCHECK_EQ(0, entry->skeleton.prefix2); 1293 code_buffer_.push_back(entry->skeleton.opcode); 1294 if (entry->skeleton.extra_opcode1 != 0) { 1295 code_buffer_.push_back(entry->skeleton.extra_opcode1); 1296 if (entry->skeleton.extra_opcode2 != 0) { 1297 code_buffer_.push_back(entry->skeleton.extra_opcode2); 1298 } 1299 } else { 1300 DCHECK_EQ(0, entry->skeleton.extra_opcode2); 1301 } 1302 DCHECK_EQ(0, entry->skeleton.modrm_opcode); 1303 DCHECK_EQ(0, entry->skeleton.ax_opcode); 1304 DCHECK_EQ(0, entry->skeleton.immediate_bytes); 1305 break; 1306 case kReg: // lir operands - 0: reg 1307 EmitOpReg(entry, lir->operands[0]); 1308 break; 1309 case kMem: // lir operands - 0: base, 1: disp 1310 EmitOpMem(entry, lir->operands[0], lir->operands[1]); 1311 break; 1312 case kMemReg: // lir operands - 0: base, 1: disp, 2: reg 1313 EmitMemReg(entry, lir->operands[0], lir->operands[1], lir->operands[2]); 1314 break; 1315 case kArrayReg: // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg 1316 EmitArrayReg(entry, lir->operands[0], lir->operands[1], lir->operands[2], 1317 lir->operands[3], lir->operands[4]); 1318 break; 1319 case kRegMem: // lir operands - 0: reg, 1: base, 2: disp 1320 EmitRegMem(entry, lir->operands[0], lir->operands[1], lir->operands[2]); 1321 break; 1322 case kRegArray: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp 1323 EmitRegArray(entry, lir->operands[0], lir->operands[1], lir->operands[2], 1324 lir->operands[3], lir->operands[4]); 1325 break; 1326 case kRegThread: // lir operands - 0: reg, 1: disp 1327 EmitRegThread(entry, lir->operands[0], lir->operands[1]); 1328 break; 1329 case kRegReg: // lir operands - 0: reg1, 1: reg2 1330 EmitRegReg(entry, lir->operands[0], lir->operands[1]); 1331 break; 1332 case kRegRegStore: // lir operands - 0: reg2, 1: reg1 1333 EmitRegReg(entry, lir->operands[1], lir->operands[0]); 1334 break; 1335 case kRegRegImm: 1336 EmitRegRegImm(entry, lir->operands[0], lir->operands[1], lir->operands[2]); 1337 break; 1338 case kRegImm: // lir operands - 0: reg, 1: immediate 1339 EmitRegImm(entry, lir->operands[0], lir->operands[1]); 1340 break; 1341 case kThreadImm: // lir operands - 0: disp, 1: immediate 1342 EmitThreadImm(entry, lir->operands[0], lir->operands[1]); 1343 break; 1344 case kMovRegImm: // lir operands - 0: reg, 1: immediate 1345 EmitMovRegImm(entry, lir->operands[0], lir->operands[1]); 1346 break; 1347 case kShiftRegImm: // lir operands - 0: reg, 1: immediate 1348 EmitShiftRegImm(entry, lir->operands[0], lir->operands[1]); 1349 break; 1350 case kShiftRegCl: // lir operands - 0: reg, 1: cl 1351 EmitShiftRegCl(entry, lir->operands[0], lir->operands[1]); 1352 break; 1353 case kRegCond: // lir operands - 0: reg, 1: condition 1354 EmitRegCond(entry, lir->operands[0], lir->operands[1]); 1355 break; 1356 case kJmp: // lir operands - 0: rel 1357 EmitJmp(entry, lir->operands[0]); 1358 break; 1359 case kJcc: // lir operands - 0: rel, 1: CC, target assigned 1360 EmitJcc(entry, lir->operands[0], lir->operands[1]); 1361 break; 1362 case kCall: 1363 switch (entry->opcode) { 1364 case kX86CallM: // lir operands - 0: base, 1: disp 1365 EmitCallMem(entry, lir->operands[0], lir->operands[1]); 1366 break; 1367 case kX86CallT: // lir operands - 0: disp 1368 EmitCallThread(entry, lir->operands[0]); 1369 break; 1370 default: 1371 EmitUnimplemented(entry, lir); 1372 break; 1373 } 1374 break; 1375 case kPcRel: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table 1376 EmitPcRel(entry, lir->operands[0], lir->operands[1], lir->operands[2], 1377 lir->operands[3], lir->operands[4]); 1378 break; 1379 case kMacro: 1380 EmitMacro(entry, lir->operands[0], lir->offset); 1381 break; 1382 default: 1383 EmitUnimplemented(entry, lir); 1384 break; 1385 } 1386 CHECK_EQ(static_cast<size_t>(GetInsnSize(lir)), 1387 code_buffer_.size() - starting_cbuf_size) 1388 << "Instruction size mismatch for entry: " << X86Mir2Lir::EncodingMap[lir->opcode].name; 1389 } 1390 return res; 1391} 1392 1393// LIR offset assignment. 1394// TODO: consolidate w/ Arm assembly mechanism. 1395int X86Mir2Lir::AssignInsnOffsets() { 1396 LIR* lir; 1397 int offset = 0; 1398 1399 for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) { 1400 lir->offset = offset; 1401 if (LIKELY(!IsPseudoLirOp(lir->opcode))) { 1402 if (!lir->flags.is_nop) { 1403 offset += lir->flags.size; 1404 } 1405 } else if (UNLIKELY(lir->opcode == kPseudoPseudoAlign4)) { 1406 if (offset & 0x2) { 1407 offset += 2; 1408 lir->operands[0] = 1; 1409 } else { 1410 lir->operands[0] = 0; 1411 } 1412 } 1413 /* Pseudo opcodes don't consume space */ 1414 } 1415 return offset; 1416} 1417 1418/* 1419 * Walk the compilation unit and assign offsets to instructions 1420 * and literals and compute the total size of the compiled unit. 1421 * TODO: consolidate w/ Arm assembly mechanism. 1422 */ 1423void X86Mir2Lir::AssignOffsets() { 1424 int offset = AssignInsnOffsets(); 1425 1426 /* Const values have to be word aligned */ 1427 offset = (offset + 3) & ~3; 1428 1429 /* Set up offsets for literals */ 1430 data_offset_ = offset; 1431 1432 offset = AssignLiteralOffset(offset); 1433 1434 offset = AssignSwitchTablesOffset(offset); 1435 1436 offset = AssignFillArrayDataOffset(offset); 1437 1438 total_size_ = offset; 1439} 1440 1441/* 1442 * Go over each instruction in the list and calculate the offset from the top 1443 * before sending them off to the assembler. If out-of-range branch distance is 1444 * seen rearrange the instructions a bit to correct it. 1445 * TODO: consolidate w/ Arm assembly mechanism. 1446 */ 1447void X86Mir2Lir::AssembleLIR() { 1448 cu_->NewTimingSplit("Assemble"); 1449 AssignOffsets(); 1450 int assembler_retries = 0; 1451 /* 1452 * Assemble here. Note that we generate code with optimistic assumptions 1453 * and if found now to work, we'll have to redo the sequence and retry. 1454 */ 1455 1456 while (true) { 1457 AssemblerStatus res = AssembleInstructions(0); 1458 if (res == kSuccess) { 1459 break; 1460 } else { 1461 assembler_retries++; 1462 if (assembler_retries > MAX_ASSEMBLER_RETRIES) { 1463 CodegenDump(); 1464 LOG(FATAL) << "Assembler error - too many retries"; 1465 } 1466 // Redo offsets and try again 1467 AssignOffsets(); 1468 code_buffer_.clear(); 1469 } 1470 } 1471 1472 cu_->NewTimingSplit("LiteralData"); 1473 // Install literals 1474 InstallLiteralPools(); 1475 1476 // Install switch tables 1477 InstallSwitchTables(); 1478 1479 // Install fill array data 1480 InstallFillArrayData(); 1481 1482 // Create the mapping table and native offset to reference map. 1483 cu_->NewTimingSplit("PcMappingTable"); 1484 CreateMappingTables(); 1485 1486 cu_->NewTimingSplit("GcMap"); 1487 CreateNativeGcMap(); 1488} 1489 1490} // namespace art 1491