Beginning of X86 encoding map and instruction size routine.
Change-Id: Idaa0d5e0852d7bcfeabff443a45223a078ad02d2
diff --git a/src/compiler/codegen/x86/Assemble.cc b/src/compiler/codegen/x86/Assemble.cc
index f098e66..722f7bb 100644
--- a/src/compiler/codegen/x86/Assemble.cc
+++ b/src/compiler/codegen/x86/Assemble.cc
@@ -24,66 +24,121 @@
#define MAX_ASSEMBLER_RETRIES 50
-/*
- * opcode: X86OpCode enum
- * skeleton: pre-designated bit-pattern for this opcode
- * k0: key to applying ds/de
- * ds: dest start bit position
- * de: dest end bit position
- * k1: key to applying s1s/s1e
- * s1s: src1 start bit position
- * s1e: src1 end bit position
- * k2: key to applying s2s/s2e
- * s2s: src2 start bit position
- * s2e: src2 end bit position
- * operands: number of operands (for sanity check purposes)
- * name: mnemonic name
- * fmt: for pretty-printing
- */
-#define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
- k3, k3s, k3e, flags, name, fmt, size) \
- {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
- {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
+#define BINARY_ENCODING_MAP(opcode, \
+ rm8_r8, rm32_r32, \
+ r8_rm8, r32_rm32, \
+ rax8_i8, rax32_i32, \
+ rm8_i8_opcode, rm8_i8_modrm, \
+ rm32_i32_opcode, rm32_i32_modrm, \
+ rm32_i8_opcode, rm32_i8_modrm) \
+{ kOp ## opcode ## RI, \
+ kRegImm, \
+ 0, \
+ { RegMem_Immediate: { rax8_i8, rax32_i32, \
+ {rm8_i8_opcode, rm8_i8_modrm}, \
+ {rm32_i32_opcode, rm32_i32_modrm}, \
+ {rm32_i8_opcode, rm32_i8_modrm} } }, \
+ #opcode "RI", "" \
+}, \
+{ kOp ## opcode ## MI, \
+ kMemImm, \
+ 0, \
+ { RegMem_Immediate: { rax8_i8, rax32_i32, \
+ {rm8_i8_opcode, rm8_i8_modrm}, \
+ {rm32_i32_opcode, rm32_i32_modrm}, \
+ {rm32_i8_opcode, rm32_i8_modrm} } }, \
+ #opcode "MI", "" \
+}, \
+{ kOp ## opcode ## AI, \
+ kArrayImm, \
+ 0, \
+ { RegMem_Immediate: { rax8_i8, rax32_i32, \
+ {rm8_i8_opcode, rm8_i8_modrm}, \
+ {rm32_i32_opcode, rm32_i32_modrm}, \
+ {rm32_i8_opcode, rm32_i8_modrm} } }, \
+ #opcode "AI", "" \
+}, \
+{ kOp ## opcode ## RR, \
+ kRegReg, \
+ 0, \
+ { Reg_RegMem: {r8_rm8, r32_rm32} }, \
+ #opcode "RR", "" \
+}, \
+{ kOp ## opcode ## RM, \
+ kRegMem, \
+ 0, \
+ { Reg_RegMem: {r8_rm8, r32_rm32} }, \
+ #opcode "RM", "" \
+}, \
+{ kOp ## opcode ## RA, \
+ kRegArray, \
+ 0, \
+ { Reg_RegMem: {r8_rm8, r32_rm32} }, \
+ #opcode "RA", "" \
+}, \
+{ kOp ## opcode ## MR, \
+ kMemReg, \
+ 0, \
+ { RegMem_Reg: {rm8_r8, rm32_r32} }, \
+ #opcode "MR", "" \
+}, \
+{ kOp ## opcode ## AR, \
+ kArrayReg, \
+ 0, \
+ { RegMem_Reg: {rm8_r8, rm32_r32} }, \
+ #opcode "AR", "" \
+}
-/* Instruction dump string format keys: !pf, where "!" is the start
- * of the key, "p" is which numeric operand to use and "f" is the
- * print format.
- *
- * [p]ositions:
- * 0 -> operands[0] (dest)
- * 1 -> operands[1] (src1)
- * 2 -> operands[2] (src2)
- * 3 -> operands[3] (extra)
- *
- * [f]ormats:
- * h -> 4-digit hex
- * d -> decimal
- * E -> decimal*4
- * F -> decimal*2
- * c -> branch condition (beq, bne, etc.)
- * t -> pc-relative target
- * T -> pc-region target
- * u -> 1st half of bl[x] target
- * v -> 2nd half ob bl[x] target
- * R -> register list
- * s -> single precision floating point register
- * S -> double precision floating point register
- * m -> Thumb2 modified immediate
- * n -> complimented Thumb2 modified immediate
- * M -> Thumb2 16-bit zero-extended immediate
- * b -> 4-digit binary
- * N -> append a NOP
- *
- * [!] escape. To insert "!", use "!!"
- */
-/* NOTE: must be kept in sync with enum X86Opcode from LIR.h */
-/*
- * TUNING: We're currently punting on the branch delay slots. All branch
- * instructions in this map are given a size of 8, which during assembly
- * is expanded to include a nop. This scheme should be replaced with
- * an assembler pass to fill those slots when possible.
- */
X86EncodingMap EncodingMap[kX86Last] = {
+ { kX8632BitData, kData, 0 /* flags - TODO */, { unused: 0 }, "data", "" },
+BINARY_ENCODING_MAP(Add,
+ 0x00 /* RegMem8/Reg8 */, 0x01 /* RegMem32/Reg32 */,
+ 0x02 /* Reg8/RegMem8 */, 0x03 /* Reg32/RegMem32 */,
+ 0x04 /* Rax8/imm8 opcode */, 0x05 /* Rax32/imm32 */,
+ 0x80, 0x0 /* RegMem8/imm8 */,
+ 0x81, 0x0 /* RegMem32/imm32 */, 0x83, 0x0 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Or,
+ 0x08 /* RegMem8/Reg8 */, 0x09 /* RegMem32/Reg32 */,
+ 0x0A /* Reg8/RegMem8 */, 0x0B /* Reg32/RegMem32 */,
+ 0x0C /* Rax8/imm8 opcode */, 0x0D /* Rax32/imm32 */,
+ 0x80, 0x1 /* RegMem8/imm8 */,
+ 0x81, 0x1 /* RegMem32/imm32 */, 0x83, 0x1 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Adc,
+ 0x10 /* RegMem8/Reg8 */, 0x11 /* RegMem32/Reg32 */,
+ 0x12 /* Reg8/RegMem8 */, 0x13 /* Reg32/RegMem32 */,
+ 0x14 /* Rax8/imm8 opcode */, 0x15 /* Rax32/imm32 */,
+ 0x80, 0x2 /* RegMem8/imm8 */,
+ 0x81, 0x2 /* RegMem32/imm32 */, 0x83, 0x2 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Sbb,
+ 0x18 /* RegMem8/Reg8 */, 0x19 /* RegMem32/Reg32 */,
+ 0x1A /* Reg8/RegMem8 */, 0x1B /* Reg32/RegMem32 */,
+ 0x1C /* Rax8/imm8 opcode */, 0x1D /* Rax32/imm32 */,
+ 0x80, 0x3 /* RegMem8/imm8 */,
+ 0x81, 0x3 /* RegMem32/imm32 */, 0x83, 0x3 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(And,
+ 0x20 /* RegMem8/Reg8 */, 0x21 /* RegMem32/Reg32 */,
+ 0x22 /* Reg8/RegMem8 */, 0x23 /* Reg32/RegMem32 */,
+ 0x24 /* Rax8/imm8 opcode */, 0x25 /* Rax32/imm32 */,
+ 0x80, 0x4 /* RegMem8/imm8 */,
+ 0x81, 0x4 /* RegMem32/imm32 */, 0x83, 0x4 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Sub,
+ 0x28 /* RegMem8/Reg8 */, 0x29 /* RegMem32/Reg32 */,
+ 0x2A /* Reg8/RegMem8 */, 0x2B /* Reg32/RegMem32 */,
+ 0x2C /* Rax8/imm8 opcode */, 0x2D /* Rax32/imm32 */,
+ 0x80, 0x5 /* RegMem8/imm8 */,
+ 0x81, 0x5 /* RegMem32/imm32 */, 0x83, 0x5 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Xor,
+ 0x30 /* RegMem8/Reg8 */, 0x31 /* RegMem32/Reg32 */,
+ 0x32 /* Reg8/RegMem8 */, 0x33 /* Reg32/RegMem32 */,
+ 0x34 /* Rax8/imm8 opcode */, 0x35 /* Rax32/imm32 */,
+ 0x80, 0x6 /* RegMem8/imm8 */,
+ 0x81, 0x6 /* RegMem32/imm32 */, 0x83, 0x6 /* RegMem32/imm8 */),
+BINARY_ENCODING_MAP(Cmp,
+ 0x38 /* RegMem8/Reg8 */, 0x39 /* RegMem32/Reg32 */,
+ 0x3A /* Reg8/RegMem8 */, 0x3B /* Reg32/RegMem32 */,
+ 0x3C /* Rax8/imm8 opcode */, 0x3D /* Rax32/imm32 */,
+ 0x80, 0x7 /* RegMem8/imm8 */,
+ 0x81, 0x7 /* RegMem32/imm32 */, 0x83, 0x7 /* RegMem32/imm8 */)
};
@@ -288,7 +343,55 @@
int oatGetInsnSize(LIR* lir)
{
- return EncodingMap[lir->opcode].size;
+ switch (EncodingMap[lir->opcode].kind) {
+ case kData:
+ return 4;
+ case kRegImm: {
+ int reg = lir->operands[0];
+ int imm = lir->operands[1];
+ return (reg == rAX ? 1 : 2) + // AX opcodes don't require the modrm byte
+ (IS_SIMM8(imm) ? 1 : 4); // 1 or 4 byte immediate
+ break;
+ }
+ case kMemImm: {
+ // int base = lir->operands[0];
+ int disp = lir->operands[1];
+ int imm = lir->operands[2];
+ return 2 + // opcode and modrm bytes
+ (disp == 0 ? 0 : (IS_SIMM8(disp) ? 1 : 4)) + // 0, 1 or 4 byte displacement
+ (IS_SIMM8(imm) ? 1 : 4); // 1 or 4 byte immediate
+ break;
+ }
+ case kArrayImm:
+ UNIMPLEMENTED(FATAL);
+ return 0;
+ case kRegReg:
+ return 2; // opcode and modrm
+ case kRegMem: {
+ // int reg = lir->operands[0];
+ // int base = lir->operands[1];
+ int disp = lir->operands[2];
+ return 2 + // opcode and modrm bytes
+ (disp == 0 ? 0 : (IS_SIMM8(disp) ? 1 : 4)); // 0, 1 or 4 byte displacement
+ break;
+ }
+ case kRegArray:
+ UNIMPLEMENTED(FATAL);
+ return 0;
+ case kMemReg: {
+ // int base = lir->operands[0];
+ int disp = lir->operands[1];
+ // int reg = lir->operands[2];
+ return 2 + // opcode and modrm bytes
+ (disp == 0 ? 0 : (IS_SIMM8(disp) ? 1 : 4)); // 0, 1 or 4 byte displacement
+ break;
+ }
+ case kArrayReg:
+ UNIMPLEMENTED(FATAL);
+ return 0;
+ }
+ UNIMPLEMENTED(FATAL); // unreachable
+ return 0;
}
/*
* Target-dependent offset assignment.
diff --git a/src/compiler/codegen/x86/Codegen.h b/src/compiler/codegen/x86/Codegen.h
index 520d638..2fb2df2 100644
--- a/src/compiler/codegen/x86/Codegen.h
+++ b/src/compiler/codegen/x86/Codegen.h
@@ -40,7 +40,7 @@
LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
int checkValue, LIR* target);
-/* Forward declaraton the portable versions due to circular dependency */
+/* Forward declaration of the portable versions due to circular dependency */
bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
RegLocation rlDest, RegLocation rlSrc1,
RegLocation rlSrc2);
diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h
index 31f86af..13488fe 100644
--- a/src/compiler/codegen/x86/X86LIR.h
+++ b/src/compiler/codegen/x86/X86LIR.h
@@ -251,15 +251,21 @@
kPseudoPseudoAlign4 = -3,
kPseudoEHBlockLabel = -2,
kPseudoNormalBlockLabel = -1,
- kOpAddRR, // add reg, reg
- kOpAddRM, // add reg, [reg + displacement]
- kOpAddMR, // add [reg + displacement], reg
- kOpAddRI, // add reg, #immediate
- kOpAddMI, // add [reg + displacement], #immediate
- kOpAddRA, // add reg, [base reg + index reg * scale + displacment]
- kOpAddAR, // add [base reg + index reg * scale + displacment], reg
- kOpAddAI, // add [base reg + index reg * scale + displacment], #immediate
kX86First,
+ kX8632BitData = kX86First, /* data [31..0] */
+#define BinaryOpCode(opcode) \
+ opcode ## RI, opcode ## MI, opcode ##AI, \
+ opcode ## RR, opcode ## RM, opcode ##RA, \
+ opcode ## MR, opcode ## AR
+ BinaryOpCode(kOpAdd),
+ BinaryOpCode(kOpOr),
+ BinaryOpCode(kOpAdc),
+ BinaryOpCode(kOpSbb),
+ BinaryOpCode(kOpAnd),
+ BinaryOpCode(kOpSub),
+ BinaryOpCode(kOpXor),
+ BinaryOpCode(kOpCmp),
+#undef BinaryOpCode
kX86Last
} X86OpCode;
@@ -344,19 +350,42 @@
/* Instruction assembly fieldLoc kind */
typedef enum X86EncodingKind {
- kFmtUnused,
- kFmtBitBlt, /* Bit string using end/start */
- kFmtDfp, /* Double FP reg */
- kFmtSfp, /* Single FP reg */
+ kData,
+ kRegImm, kMemImm, kArrayImm,
+ kRegReg, kRegMem, kRegArray,
+ kMemReg, kArrayReg
} X86EncodingKind;
/* Struct used to define the snippet positions for each X86 opcode */
+typedef struct OpcodeModRMOpcode {
+ uint8_t opcode;
+ uint8_t modrm_opcode;
+} OpcodeModRMOpcode;
+
typedef struct X86EncodingMap {
- X86OpCode opcode;
- int flags;
- const char *name;
- const char* fmt;
- int size; /* Size in bytes */
+ X86OpCode opcode; // e.g. kOpAddRI
+ X86EncodingKind kind; // Used to discriminate in the union below
+ int flags;
+ union {
+ struct {
+ uint8_t rax8_i8_opcode;
+ uint8_t rax32_i32_opcode;
+ OpcodeModRMOpcode rm8_i8_opcode;
+ OpcodeModRMOpcode rm32_i32_opcode;
+ OpcodeModRMOpcode rm32_i8_opcode;
+ } RegMem_Immediate; // kind: kRegImm, kMemImm, kArrayImm
+ struct {
+ uint8_t r8_rm8_opcode;
+ uint8_t r32_rm32_opcode;
+ } Reg_RegMem; // kind: kRegReg, kRegMem, kRegArray,
+ struct {
+ uint8_t rm8_r8_opcode;
+ uint8_t rm32_r32_opcode;
+ } RegMem_Reg; // kind: kMemReg, kArrayReg
+ int unused; // kind: kData
+ } skeleton;
+ const char *name;
+ const char* fmt;
} X86EncodingMap;
/* Keys for target-specific scheduling and other optimization hints */
@@ -366,9 +395,7 @@
extern X86EncodingMap EncodingMap[kX86Last];
-#define IS_UIMM16(v) ((0 <= (v)) && ((v) <= 65535))
-#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32766))
-#define IS_SIMM16_2WORD(v) ((-32764 <= (v)) && ((v) <= 32763)) /* 2 offsets must fit */
+#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 128))
} // namespace art