blob: 13488feaa8025176e82235b48dfdd3ca994eb57a [file] [log] [blame]
Ian Rogerse32ca232012-03-05 10:20:23 -08001/*
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#ifndef ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_
18#define ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_
19
20#include "../../Dalvik.h"
21#include "../../CompilerInternals.h"
22
23namespace art {
24
25// Set to 1 to measure cost of suspend check
26#define NO_SUSPEND 0
27
28/*
29 * Runtime register conventions. We consider both x86, x86-64 and x32 (32bit mode x86-64), although
30 * we currently only target x86. The ABI has different conventions and we hope to have a single
31 * convention to simplify code generation. Changing something that is callee save and making it
32 * caller save places a burden on up-calls to save/restore the callee save register, however, there
33 * are few registers that are callee save in the ABI. Changing something that is caller save and
34 * making it callee save places a burden on down-calls to save/restore the callee save register.
35 * For these reasons we aim to match native conventions for caller and callee save
36 *
37 * General Purpose Register:
38 * Native: x86 | x86-64 / x32 | ART
39 * r0/eax: caller save | caller save | caller, Method*, scratch, return value
40 * r1/ecx: caller save | caller save, arg4 | caller, arg2, scratch
41 * r2/edx: caller save | caller save, arg3 | caller, arg1, scratch, high half of long return
42 * r3/ebx: callee save | callee save | callee, available for dalvik register promotion
43 * r4/esp: stack pointer
44 * r5/ebp: callee save | callee save | callee, available for dalvik register promotion
45 * r6/esi: callEE save | callER save, arg2 | callee, available for dalvik register promotion
46 * r7/edi: callEE save | callER save, arg1 | callee, available for dalvik register promotion
47 * --- x86-64/x32 registers
48 * Native: x86-64 / x32 | ART
49 * r8: caller save, arg5 | caller, scratch
50 * r9: caller save, arg6 | caller, scratch
51 * r10: caller save | caller, scratch
52 * r11: caller save | caller, scratch
53 * r12: callee save | callee, available for dalvik register promotion
54 * r13: callee save | callee, available for dalvik register promotion
55 * r14: callee save | callee, available for dalvik register promotion
56 * r15: callee save | callee, available for dalvik register promotion
57 *
58 * There is no rSELF, instead on x86 fs: has a base address of Thread::Current, whereas on
59 * x86-64/x32 gs: holds it.
60 *
61 * For floating point we don't support CPUs without SSE2 support (ie newer than PIII):
62 * Native: x86 | x86-64 / x32 | ART
63 * XMM0: caller save |caller save, arg1 | caller, float/double return value (except for native x86 code)
64 * XMM1: caller save |caller save, arg2 | caller, scratch
65 * XMM2: caller save |caller save, arg3 | caller, scratch
66 * XMM3: caller save |caller save, arg4 | caller, scratch
67 * XMM4: caller save |caller save, arg5 | caller, scratch
68 * XMM5: caller save |caller save, arg6 | caller, scratch
69 * XMM6: caller save |caller save, arg7 | caller, scratch
70 * XMM7: caller save |caller save, arg8 | caller, scratch
71 * --- x86-64/x32 registers
72 * XMM8 .. 15: caller save
73 *
74 * X87 is a necessary evil outside of ART code:
75 * ST0: x86 float/double native return value, caller save
76 * ST1 .. ST7: caller save
77 *
78 * Stack frame diagram (stack grows down, higher addresses at top):
79 *
80 * +------------------------+
81 * | IN[ins-1] | {Note: resides in caller's frame}
82 * | . |
83 * | IN[0] |
84 * | caller's Method* |
85 * +========================+ {Note: start of callee's frame}
86 * | return address | {pushed by call}
87 * | spill region | {variable sized}
88 * +------------------------+
89 * | ...filler word... | {Note: used as 2nd word of V[locals-1] if long]
90 * +------------------------+
91 * | V[locals-1] |
92 * | V[locals-2] |
93 * | . |
94 * | . |
95 * | V[1] |
96 * | V[0] |
97 * +------------------------+
98 * | 0 to 3 words padding |
99 * +------------------------+
100 * | OUT[outs-1] |
101 * | OUT[outs-2] |
102 * | . |
103 * | OUT[0] |
104 * | curMethod* | <<== sp w/ 16-byte alignment
105 * +========================+
106 */
107
108/* Offset to distingish FP regs */
109#define FP_REG_OFFSET 16
110/* Offset to distinguish DP FP regs */
111#define FP_DOUBLE 32
112/* Offset to distingish the extra regs */
113#define EXTRA_REG_OFFSET 64
114/* Reg types */
115#define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
116#define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
117#define EXTRAREG(x) ((x & EXTRA_REG_OFFSET) == EXTRA_REG_OFFSET)
118#define LOWREG(x) ((x & 0x1f) == x)
119#define DOUBLEREG(x) ((x & FP_DOUBLE) == FP_DOUBLE)
120#define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
121/*
122 * Note: the low register of a floating point pair is sufficient to
123 * create the name of a double, but require both names to be passed to
124 * allow for asserts to verify that the pair is consecutive if significant
125 * rework is done in this area. Also, it is a good reminder in the calling
126 * code that reg locations always describe doubles as a pair of singles.
127 */
128#define S2D(x,y) ((x) | FP_DOUBLE)
129/* Mask to strip off fp flags */
130#define FP_REG_MASK (FP_REG_OFFSET-1)
131/* non-existent Dalvik register */
132#define vNone (-1)
133/* non-existant physical register */
134#define rNone (-1)
135
buzbeea7678db2012-03-05 15:35:46 -0800136/* RegisterLocation templates return values (r0, or r0/r1) */
137#define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 1, rAX, INVALID_REG,\
138 INVALID_SREG}
139#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, rAX, rDX, INVALID_SREG}
Ian Rogerse32ca232012-03-05 10:20:23 -0800140
141typedef enum ResourceEncodingPos {
142 kGPReg0 = 0,
143 kRegSP = 4,
144 kRegLR = -1,
145 kFPReg0 = 16, // xmm0 .. xmm7/xmm15
146 kFPRegEnd = 32,
147 kRegEnd = kFPRegEnd,
148 kCCode = kRegEnd,
149 // The following four bits are for memory disambiguation
150 kDalvikReg, // 1 Dalvik Frame (can be fully disambiguated)
151 kLiteral, // 2 Literal pool (can be fully disambiguated)
152 kHeapRef, // 3 Somewhere on the heap (alias with any other heap)
153 kMustNotAlias, // 4 Guaranteed to be non-alias (eg *(r6+x))
154} ResourceEncodingPos;
155
156#define ENCODE_REG_LIST(N) ((u8) N)
157#define ENCODE_REG_SP (1ULL << kRegSP)
158#define ENCODE_CCODE (1ULL << kCCode)
159#define ENCODE_FP_STATUS (1ULL << kFPStatus)
160
161/* Abstract memory locations */
162#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
163#define ENCODE_LITERAL (1ULL << kLiteral)
164#define ENCODE_HEAP_REF (1ULL << kHeapRef)
165#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias)
166
167#define ENCODE_ALL (~0ULL)
168#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \
169 ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
170
171#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
172#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
173
174/*
175 * Annotate special-purpose core registers:
176 */
177
178typedef enum NativeRegisterPool {
179 r0 = 0,
180 rAX = r0,
181 r1 = 1,
182 rCX = r1,
183 r2 = 2,
184 rDX = r2,
185 r3 = 3,
186 rBX = r3,
187 r4sp = 4,
188 rSP =r4sp,
189 r5 = 5,
190 rBP = r5,
191 r6 = 6,
192 rSI = r6,
193 r7 = 7,
194 rDI = r7,
195 r8 = 8,
196 r9 = 9,
197 r10 = 10,
198 r11 = 11,
199 r12 = 12,
200 r13 = 13,
201 r14 = 14,
202 r15 = 15,
203 fr0 = 0 + FP_REG_OFFSET,
204 fr1 = 1 + FP_REG_OFFSET,
205 fr2 = 2 + FP_REG_OFFSET,
206 fr3 = 3 + FP_REG_OFFSET,
207 fr4 = 4 + FP_REG_OFFSET,
208 fr5 = 5 + FP_REG_OFFSET,
209 fr6 = 6 + FP_REG_OFFSET,
210 fr7 = 7 + FP_REG_OFFSET,
211 fr8 = 8 + FP_REG_OFFSET,
212 fr9 = 9 + FP_REG_OFFSET,
213 fr10 = 10 + FP_REG_OFFSET,
214 fr11 = 11 + FP_REG_OFFSET,
215 fr12 = 12 + FP_REG_OFFSET,
216 fr13 = 13 + FP_REG_OFFSET,
217 fr14 = 14 + FP_REG_OFFSET,
218 fr15 = 15 + FP_REG_OFFSET,
219} NativeRegisterPool;
220
221/*
222 * Target-independent aliases
223 */
224
225#define rARG0 rAX
226#define rARG1 rDX
227#define rARG2 rCX
228#define rRET0 rAX
229#define rRET1 rDX
230
231#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
232
233/*
234 * The following enum defines the list of supported Thumb instructions by the
235 * assembler. Their corresponding snippet positions will be defined in
236 * Assemble.c.
237 */
238typedef enum X86OpCode {
239 kPseudoSuspendTarget = -15,
240 kPseudoThrowTarget = -14,
241 kPseudoCaseLabel = -13,
242 kPseudoMethodEntry = -12,
243 kPseudoMethodExit = -11,
244 kPseudoBarrier = -10,
245 kPseudoExtended = -9,
246 kPseudoSSARep = -8,
247 kPseudoEntryBlock = -7,
248 kPseudoExitBlock = -6,
249 kPseudoTargetLabel = -5,
250 kPseudoDalvikByteCodeBoundary = -4,
251 kPseudoPseudoAlign4 = -3,
252 kPseudoEHBlockLabel = -2,
253 kPseudoNormalBlockLabel = -1,
Ian Rogerse32ca232012-03-05 10:20:23 -0800254 kX86First,
Ian Rogers96ab4202012-03-05 19:51:02 -0800255 kX8632BitData = kX86First, /* data [31..0] */
256#define BinaryOpCode(opcode) \
257 opcode ## RI, opcode ## MI, opcode ##AI, \
258 opcode ## RR, opcode ## RM, opcode ##RA, \
259 opcode ## MR, opcode ## AR
260 BinaryOpCode(kOpAdd),
261 BinaryOpCode(kOpOr),
262 BinaryOpCode(kOpAdc),
263 BinaryOpCode(kOpSbb),
264 BinaryOpCode(kOpAnd),
265 BinaryOpCode(kOpSub),
266 BinaryOpCode(kOpXor),
267 BinaryOpCode(kOpCmp),
268#undef BinaryOpCode
Ian Rogerse32ca232012-03-05 10:20:23 -0800269 kX86Last
270} X86OpCode;
271
buzbeea7678db2012-03-05 15:35:46 -0800272// FIXME: mem barrier type - what do we do for x86?
273#define kSY 0
274#define kST 0
275
Ian Rogerse32ca232012-03-05 10:20:23 -0800276/* Bit flags describing the behavior of each native opcode */
277typedef enum X86OpFeatureFlags {
278 kIsBranch = 0,
279 kRegDef0,
280 kRegDef1,
281 kRegDefSP,
282 kRegDefList0,
283 kRegDefList1,
284 kRegUse0,
285 kRegUse1,
286 kRegUse2,
287 kRegUse3,
288 kRegUseSP,
289 kRegUseList0,
290 kRegUseList1,
291 kNoOperand,
292 kIsUnaryOp,
293 kIsBinaryOp,
294 kIsTertiaryOp,
295 kIsQuadOp,
296 kIsIT,
297 kSetsCCodes,
298 kUsesCCodes,
299 kMemLoad,
300 kMemStore,
301 kPCRelFixup,
302// FIXME: add NEEDS_FIXUP to instruction attributes
303} X86OpFeatureFlags;
304
305#define IS_LOAD (1 << kMemLoad)
306#define IS_STORE (1 << kMemStore)
307#define IS_BRANCH (1 << kIsBranch)
308#define REG_DEF0 (1 << kRegDef0)
309#define REG_DEF1 (1 << kRegDef1)
310#define REG_DEF_SP (1 << kRegDefSP)
311#define REG_DEF_LR (1 << kRegDefLR)
312#define REG_DEF_LIST0 (1 << kRegDefList0)
313#define REG_DEF_LIST1 (1 << kRegDefList1)
314#define REG_USE0 (1 << kRegUse0)
315#define REG_USE1 (1 << kRegUse1)
316#define REG_USE2 (1 << kRegUse2)
317#define REG_USE3 (1 << kRegUse3)
318#define REG_USE_SP (1 << kRegUseSP)
319#define REG_USE_PC (1 << kRegUsePC)
320#define REG_USE_LIST0 (1 << kRegUseList0)
321#define REG_USE_LIST1 (1 << kRegUseList1)
322#define NO_OPERAND (1 << kNoOperand)
323#define IS_UNARY_OP (1 << kIsUnaryOp)
324#define IS_BINARY_OP (1 << kIsBinaryOp)
325#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
326#define IS_QUAD_OP (1 << kIsQuadOp)
327#define IS_IT (1 << kIsIT)
328#define SETS_CCODES (1 << kSetsCCodes)
329#define USES_CCODES (1 << kUsesCCodes)
330#define NEEDS_FIXUP (1 << kPCRelFixup)
331
332/* attributes, included for compatibility */
333#define REG_DEF_FPCS_LIST0 (0)
334#define REG_DEF_FPCS_LIST2 (0)
335
336
337/* Common combo register usage patterns */
338#define REG_USE01 (REG_USE0 | REG_USE1)
339#define REG_USE02 (REG_USE0 | REG_USE2)
340#define REG_USE012 (REG_USE01 | REG_USE2)
341#define REG_USE12 (REG_USE1 | REG_USE2)
342#define REG_USE23 (REG_USE2 | REG_USE3)
343#define REG_DEF01 (REG_DEF0 | REG_DEF1)
344#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0)
345#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1)
346#define REG_DEF0_USE2 (REG_DEF0 | REG_USE2)
347#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01)
348#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12)
349#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2)
350
351/* Instruction assembly fieldLoc kind */
352typedef enum X86EncodingKind {
Ian Rogers96ab4202012-03-05 19:51:02 -0800353 kData,
354 kRegImm, kMemImm, kArrayImm,
355 kRegReg, kRegMem, kRegArray,
356 kMemReg, kArrayReg
Ian Rogerse32ca232012-03-05 10:20:23 -0800357} X86EncodingKind;
358
359/* Struct used to define the snippet positions for each X86 opcode */
Ian Rogers96ab4202012-03-05 19:51:02 -0800360typedef struct OpcodeModRMOpcode {
361 uint8_t opcode;
362 uint8_t modrm_opcode;
363} OpcodeModRMOpcode;
364
Ian Rogerse32ca232012-03-05 10:20:23 -0800365typedef struct X86EncodingMap {
Ian Rogers96ab4202012-03-05 19:51:02 -0800366 X86OpCode opcode; // e.g. kOpAddRI
367 X86EncodingKind kind; // Used to discriminate in the union below
368 int flags;
369 union {
370 struct {
371 uint8_t rax8_i8_opcode;
372 uint8_t rax32_i32_opcode;
373 OpcodeModRMOpcode rm8_i8_opcode;
374 OpcodeModRMOpcode rm32_i32_opcode;
375 OpcodeModRMOpcode rm32_i8_opcode;
376 } RegMem_Immediate; // kind: kRegImm, kMemImm, kArrayImm
377 struct {
378 uint8_t r8_rm8_opcode;
379 uint8_t r32_rm32_opcode;
380 } Reg_RegMem; // kind: kRegReg, kRegMem, kRegArray,
381 struct {
382 uint8_t rm8_r8_opcode;
383 uint8_t rm32_r32_opcode;
384 } RegMem_Reg; // kind: kMemReg, kArrayReg
385 int unused; // kind: kData
386 } skeleton;
387 const char *name;
388 const char* fmt;
Ian Rogerse32ca232012-03-05 10:20:23 -0800389} X86EncodingMap;
390
391/* Keys for target-specific scheduling and other optimization hints */
392typedef enum X86TargetOptHints {
393 kMaxHoistDistance,
394} X86TargetOptHints;
395
396extern X86EncodingMap EncodingMap[kX86Last];
397
Ian Rogers96ab4202012-03-05 19:51:02 -0800398#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 128))
Ian Rogerse32ca232012-03-05 10:20:23 -0800399
400} // namespace art
401
402#endif // ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_