summaryrefslogtreecommitdiffstats
path: root/src/compiler/codegen
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2012-03-05 10:28:57 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-03-05 10:28:57 -0800
commit9831bfac0d2ef54a996ae02e0755600ecb5f66ea (patch)
tree0931a3b4b09af073876805bde7f0784ab6503d4e /src/compiler/codegen
parent4455f7816c697b36fc3c158234770c6f1176b41e (diff)
parente32ca23c21187f62aaef70d33de3c362e2bbd0e3 (diff)
downloadart-9831bfac0d2ef54a996ae02e0755600ecb5f66ea.zip
art-9831bfac0d2ef54a996ae02e0755600ecb5f66ea.tar.gz
art-9831bfac0d2ef54a996ae02e0755600ecb5f66ea.tar.bz2
Merge "Start of X86 LIR description." into dalvik-dev
Diffstat (limited to 'src/compiler/codegen')
-rw-r--r--src/compiler/codegen/x86/X86LIR.h367
1 files changed, 367 insertions, 0 deletions
diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h
new file mode 100644
index 0000000..3681cdb
--- /dev/null
+++ b/src/compiler/codegen/x86/X86LIR.h
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_
+#define ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_
+
+#include "../../Dalvik.h"
+#include "../../CompilerInternals.h"
+
+namespace art {
+
+// Set to 1 to measure cost of suspend check
+#define NO_SUSPEND 0
+
+/*
+ * Runtime register conventions. We consider both x86, x86-64 and x32 (32bit mode x86-64), although
+ * we currently only target x86. The ABI has different conventions and we hope to have a single
+ * convention to simplify code generation. Changing something that is callee save and making it
+ * caller save places a burden on up-calls to save/restore the callee save register, however, there
+ * are few registers that are callee save in the ABI. Changing something that is caller save and
+ * making it callee save places a burden on down-calls to save/restore the callee save register.
+ * For these reasons we aim to match native conventions for caller and callee save
+ *
+ * General Purpose Register:
+ * Native: x86 | x86-64 / x32 | ART
+ * r0/eax: caller save | caller save | caller, Method*, scratch, return value
+ * r1/ecx: caller save | caller save, arg4 | caller, arg2, scratch
+ * r2/edx: caller save | caller save, arg3 | caller, arg1, scratch, high half of long return
+ * r3/ebx: callee save | callee save | callee, available for dalvik register promotion
+ * r4/esp: stack pointer
+ * r5/ebp: callee save | callee save | callee, available for dalvik register promotion
+ * r6/esi: callEE save | callER save, arg2 | callee, available for dalvik register promotion
+ * r7/edi: callEE save | callER save, arg1 | callee, available for dalvik register promotion
+ * --- x86-64/x32 registers
+ * Native: x86-64 / x32 | ART
+ * r8: caller save, arg5 | caller, scratch
+ * r9: caller save, arg6 | caller, scratch
+ * r10: caller save | caller, scratch
+ * r11: caller save | caller, scratch
+ * r12: callee save | callee, available for dalvik register promotion
+ * r13: callee save | callee, available for dalvik register promotion
+ * r14: callee save | callee, available for dalvik register promotion
+ * r15: callee save | callee, available for dalvik register promotion
+ *
+ * There is no rSELF, instead on x86 fs: has a base address of Thread::Current, whereas on
+ * x86-64/x32 gs: holds it.
+ *
+ * For floating point we don't support CPUs without SSE2 support (ie newer than PIII):
+ * Native: x86 | x86-64 / x32 | ART
+ * XMM0: caller save |caller save, arg1 | caller, float/double return value (except for native x86 code)
+ * XMM1: caller save |caller save, arg2 | caller, scratch
+ * XMM2: caller save |caller save, arg3 | caller, scratch
+ * XMM3: caller save |caller save, arg4 | caller, scratch
+ * XMM4: caller save |caller save, arg5 | caller, scratch
+ * XMM5: caller save |caller save, arg6 | caller, scratch
+ * XMM6: caller save |caller save, arg7 | caller, scratch
+ * XMM7: caller save |caller save, arg8 | caller, scratch
+ * --- x86-64/x32 registers
+ * XMM8 .. 15: caller save
+ *
+ * X87 is a necessary evil outside of ART code:
+ * ST0: x86 float/double native return value, caller save
+ * ST1 .. ST7: caller save
+ *
+ * Stack frame diagram (stack grows down, higher addresses at top):
+ *
+ * +------------------------+
+ * | IN[ins-1] | {Note: resides in caller's frame}
+ * | . |
+ * | IN[0] |
+ * | caller's Method* |
+ * +========================+ {Note: start of callee's frame}
+ * | return address | {pushed by call}
+ * | spill region | {variable sized}
+ * +------------------------+
+ * | ...filler word... | {Note: used as 2nd word of V[locals-1] if long]
+ * +------------------------+
+ * | V[locals-1] |
+ * | V[locals-2] |
+ * | . |
+ * | . |
+ * | V[1] |
+ * | V[0] |
+ * +------------------------+
+ * | 0 to 3 words padding |
+ * +------------------------+
+ * | OUT[outs-1] |
+ * | OUT[outs-2] |
+ * | . |
+ * | OUT[0] |
+ * | curMethod* | <<== sp w/ 16-byte alignment
+ * +========================+
+ */
+
+/* Offset to distingish FP regs */
+#define FP_REG_OFFSET 16
+/* Offset to distinguish DP FP regs */
+#define FP_DOUBLE 32
+/* Offset to distingish the extra regs */
+#define EXTRA_REG_OFFSET 64
+/* Reg types */
+#define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
+#define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
+#define EXTRAREG(x) ((x & EXTRA_REG_OFFSET) == EXTRA_REG_OFFSET)
+#define LOWREG(x) ((x & 0x1f) == x)
+#define DOUBLEREG(x) ((x & FP_DOUBLE) == FP_DOUBLE)
+#define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
+/*
+ * Note: the low register of a floating point pair is sufficient to
+ * create the name of a double, but require both names to be passed to
+ * allow for asserts to verify that the pair is consecutive if significant
+ * rework is done in this area. Also, it is a good reminder in the calling
+ * code that reg locations always describe doubles as a pair of singles.
+ */
+#define S2D(x,y) ((x) | FP_DOUBLE)
+/* Mask to strip off fp flags */
+#define FP_REG_MASK (FP_REG_OFFSET-1)
+/* non-existent Dalvik register */
+#define vNone (-1)
+/* non-existant physical register */
+#define rNone (-1)
+
+
+typedef enum ResourceEncodingPos {
+ kGPReg0 = 0,
+ kRegSP = 4,
+ kRegLR = -1,
+ kFPReg0 = 16, // xmm0 .. xmm7/xmm15
+ kFPRegEnd = 32,
+ kRegEnd = kFPRegEnd,
+ kCCode = kRegEnd,
+ // The following four bits are for memory disambiguation
+ kDalvikReg, // 1 Dalvik Frame (can be fully disambiguated)
+ kLiteral, // 2 Literal pool (can be fully disambiguated)
+ kHeapRef, // 3 Somewhere on the heap (alias with any other heap)
+ kMustNotAlias, // 4 Guaranteed to be non-alias (eg *(r6+x))
+} ResourceEncodingPos;
+
+#define ENCODE_REG_LIST(N) ((u8) N)
+#define ENCODE_REG_SP (1ULL << kRegSP)
+#define ENCODE_CCODE (1ULL << kCCode)
+#define ENCODE_FP_STATUS (1ULL << kFPStatus)
+
+/* Abstract memory locations */
+#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
+#define ENCODE_LITERAL (1ULL << kLiteral)
+#define ENCODE_HEAP_REF (1ULL << kHeapRef)
+#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias)
+
+#define ENCODE_ALL (~0ULL)
+#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \
+ ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
+
+#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
+#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
+
+/*
+ * Annotate special-purpose core registers:
+ */
+
+typedef enum NativeRegisterPool {
+ r0 = 0,
+ rAX = r0,
+ r1 = 1,
+ rCX = r1,
+ r2 = 2,
+ rDX = r2,
+ r3 = 3,
+ rBX = r3,
+ r4sp = 4,
+ rSP =r4sp,
+ r5 = 5,
+ rBP = r5,
+ r6 = 6,
+ rSI = r6,
+ r7 = 7,
+ rDI = r7,
+ r8 = 8,
+ r9 = 9,
+ r10 = 10,
+ r11 = 11,
+ r12 = 12,
+ r13 = 13,
+ r14 = 14,
+ r15 = 15,
+ fr0 = 0 + FP_REG_OFFSET,
+ fr1 = 1 + FP_REG_OFFSET,
+ fr2 = 2 + FP_REG_OFFSET,
+ fr3 = 3 + FP_REG_OFFSET,
+ fr4 = 4 + FP_REG_OFFSET,
+ fr5 = 5 + FP_REG_OFFSET,
+ fr6 = 6 + FP_REG_OFFSET,
+ fr7 = 7 + FP_REG_OFFSET,
+ fr8 = 8 + FP_REG_OFFSET,
+ fr9 = 9 + FP_REG_OFFSET,
+ fr10 = 10 + FP_REG_OFFSET,
+ fr11 = 11 + FP_REG_OFFSET,
+ fr12 = 12 + FP_REG_OFFSET,
+ fr13 = 13 + FP_REG_OFFSET,
+ fr14 = 14 + FP_REG_OFFSET,
+ fr15 = 15 + FP_REG_OFFSET,
+} NativeRegisterPool;
+
+/*
+ * Target-independent aliases
+ */
+
+#define rARG0 rAX
+#define rARG1 rDX
+#define rARG2 rCX
+#define rRET0 rAX
+#define rRET1 rDX
+
+#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
+
+/*
+ * The following enum defines the list of supported Thumb instructions by the
+ * assembler. Their corresponding snippet positions will be defined in
+ * Assemble.c.
+ */
+typedef enum X86OpCode {
+ kPseudoSuspendTarget = -15,
+ kPseudoThrowTarget = -14,
+ kPseudoCaseLabel = -13,
+ kPseudoMethodEntry = -12,
+ kPseudoMethodExit = -11,
+ kPseudoBarrier = -10,
+ kPseudoExtended = -9,
+ kPseudoSSARep = -8,
+ kPseudoEntryBlock = -7,
+ kPseudoExitBlock = -6,
+ kPseudoTargetLabel = -5,
+ kPseudoDalvikByteCodeBoundary = -4,
+ 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,
+ kX86Last
+} X86OpCode;
+
+/* Bit flags describing the behavior of each native opcode */
+typedef enum X86OpFeatureFlags {
+ kIsBranch = 0,
+ kRegDef0,
+ kRegDef1,
+ kRegDefSP,
+ kRegDefList0,
+ kRegDefList1,
+ kRegUse0,
+ kRegUse1,
+ kRegUse2,
+ kRegUse3,
+ kRegUseSP,
+ kRegUseList0,
+ kRegUseList1,
+ kNoOperand,
+ kIsUnaryOp,
+ kIsBinaryOp,
+ kIsTertiaryOp,
+ kIsQuadOp,
+ kIsIT,
+ kSetsCCodes,
+ kUsesCCodes,
+ kMemLoad,
+ kMemStore,
+ kPCRelFixup,
+// FIXME: add NEEDS_FIXUP to instruction attributes
+} X86OpFeatureFlags;
+
+#define IS_LOAD (1 << kMemLoad)
+#define IS_STORE (1 << kMemStore)
+#define IS_BRANCH (1 << kIsBranch)
+#define REG_DEF0 (1 << kRegDef0)
+#define REG_DEF1 (1 << kRegDef1)
+#define REG_DEF_SP (1 << kRegDefSP)
+#define REG_DEF_LR (1 << kRegDefLR)
+#define REG_DEF_LIST0 (1 << kRegDefList0)
+#define REG_DEF_LIST1 (1 << kRegDefList1)
+#define REG_USE0 (1 << kRegUse0)
+#define REG_USE1 (1 << kRegUse1)
+#define REG_USE2 (1 << kRegUse2)
+#define REG_USE3 (1 << kRegUse3)
+#define REG_USE_SP (1 << kRegUseSP)
+#define REG_USE_PC (1 << kRegUsePC)
+#define REG_USE_LIST0 (1 << kRegUseList0)
+#define REG_USE_LIST1 (1 << kRegUseList1)
+#define NO_OPERAND (1 << kNoOperand)
+#define IS_UNARY_OP (1 << kIsUnaryOp)
+#define IS_BINARY_OP (1 << kIsBinaryOp)
+#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
+#define IS_QUAD_OP (1 << kIsQuadOp)
+#define IS_IT (1 << kIsIT)
+#define SETS_CCODES (1 << kSetsCCodes)
+#define USES_CCODES (1 << kUsesCCodes)
+#define NEEDS_FIXUP (1 << kPCRelFixup)
+
+/* attributes, included for compatibility */
+#define REG_DEF_FPCS_LIST0 (0)
+#define REG_DEF_FPCS_LIST2 (0)
+
+
+/* Common combo register usage patterns */
+#define REG_USE01 (REG_USE0 | REG_USE1)
+#define REG_USE02 (REG_USE0 | REG_USE2)
+#define REG_USE012 (REG_USE01 | REG_USE2)
+#define REG_USE12 (REG_USE1 | REG_USE2)
+#define REG_USE23 (REG_USE2 | REG_USE3)
+#define REG_DEF01 (REG_DEF0 | REG_DEF1)
+#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0)
+#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1)
+#define REG_DEF0_USE2 (REG_DEF0 | REG_USE2)
+#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01)
+#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12)
+#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2)
+
+/* Instruction assembly fieldLoc kind */
+typedef enum X86EncodingKind {
+ kFmtUnused,
+ kFmtBitBlt, /* Bit string using end/start */
+ kFmtDfp, /* Double FP reg */
+ kFmtSfp, /* Single FP reg */
+} X86EncodingKind;
+
+/* Struct used to define the snippet positions for each X86 opcode */
+typedef struct X86EncodingMap {
+ X86OpCode opcode;
+ int flags;
+ const char *name;
+ const char* fmt;
+ int size; /* Size in bytes */
+} X86EncodingMap;
+
+/* Keys for target-specific scheduling and other optimization hints */
+typedef enum X86TargetOptHints {
+ kMaxHoistDistance,
+} X86TargetOptHints;
+
+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 */
+
+} // namespace art
+
+#endif // ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_