blob: 9a5d63058aa77003a0cb9f914a083a87334df698 [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.
Ian Rogersb41b33b2012-03-20 14:22:54 -070035 * For these reasons we aim to match native conventions for caller and callee save. The first 4
36 * registers can be used for byte operations, for this reason they are preferred for temporary
37 * scratch registers.
Ian Rogerse32ca232012-03-05 10:20:23 -080038 *
39 * General Purpose Register:
40 * Native: x86 | x86-64 / x32 | ART
41 * r0/eax: caller save | caller save | caller, Method*, scratch, return value
Ian Rogersb41b33b2012-03-20 14:22:54 -070042 * r1/ecx: caller save | caller save, arg4 | caller, arg1, scratch
43 * r2/edx: caller save | caller save, arg3 | caller, arg2, scratch, high half of long return
44 * r3/ebx: callEE save | callEE save | callER, arg3, scratch
Ian Rogerse32ca232012-03-05 10:20:23 -080045 * r4/esp: stack pointer
46 * r5/ebp: callee save | callee save | callee, available for dalvik register promotion
47 * r6/esi: callEE save | callER save, arg2 | callee, available for dalvik register promotion
48 * r7/edi: callEE save | callER save, arg1 | callee, available for dalvik register promotion
49 * --- x86-64/x32 registers
50 * Native: x86-64 / x32 | ART
51 * r8: caller save, arg5 | caller, scratch
52 * r9: caller save, arg6 | caller, scratch
53 * r10: caller save | caller, scratch
54 * r11: caller save | caller, scratch
55 * r12: callee save | callee, available for dalvik register promotion
56 * r13: callee save | callee, available for dalvik register promotion
57 * r14: callee save | callee, available for dalvik register promotion
58 * r15: callee save | callee, available for dalvik register promotion
59 *
60 * There is no rSELF, instead on x86 fs: has a base address of Thread::Current, whereas on
61 * x86-64/x32 gs: holds it.
62 *
63 * For floating point we don't support CPUs without SSE2 support (ie newer than PIII):
64 * Native: x86 | x86-64 / x32 | ART
65 * XMM0: caller save |caller save, arg1 | caller, float/double return value (except for native x86 code)
66 * XMM1: caller save |caller save, arg2 | caller, scratch
67 * XMM2: caller save |caller save, arg3 | caller, scratch
68 * XMM3: caller save |caller save, arg4 | caller, scratch
69 * XMM4: caller save |caller save, arg5 | caller, scratch
70 * XMM5: caller save |caller save, arg6 | caller, scratch
71 * XMM6: caller save |caller save, arg7 | caller, scratch
72 * XMM7: caller save |caller save, arg8 | caller, scratch
73 * --- x86-64/x32 registers
74 * XMM8 .. 15: caller save
75 *
76 * X87 is a necessary evil outside of ART code:
77 * ST0: x86 float/double native return value, caller save
78 * ST1 .. ST7: caller save
79 *
80 * Stack frame diagram (stack grows down, higher addresses at top):
81 *
82 * +------------------------+
83 * | IN[ins-1] | {Note: resides in caller's frame}
84 * | . |
85 * | IN[0] |
86 * | caller's Method* |
87 * +========================+ {Note: start of callee's frame}
88 * | return address | {pushed by call}
89 * | spill region | {variable sized}
90 * +------------------------+
91 * | ...filler word... | {Note: used as 2nd word of V[locals-1] if long]
92 * +------------------------+
93 * | V[locals-1] |
94 * | V[locals-2] |
95 * | . |
96 * | . |
97 * | V[1] |
98 * | V[0] |
99 * +------------------------+
100 * | 0 to 3 words padding |
101 * +------------------------+
102 * | OUT[outs-1] |
103 * | OUT[outs-2] |
104 * | . |
105 * | OUT[0] |
106 * | curMethod* | <<== sp w/ 16-byte alignment
107 * +========================+
108 */
109
110/* Offset to distingish FP regs */
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700111#define FP_REG_OFFSET 32
Ian Rogerse32ca232012-03-05 10:20:23 -0800112/* Offset to distinguish DP FP regs */
jeffhaofdffdf82012-07-11 16:08:43 -0700113#define FP_DOUBLE (FP_REG_OFFSET + 16)
Ian Rogerse32ca232012-03-05 10:20:23 -0800114/* Offset to distingish the extra regs */
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700115#define EXTRA_REG_OFFSET (FP_DOUBLE + 16)
Ian Rogerse32ca232012-03-05 10:20:23 -0800116/* Reg types */
117#define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
118#define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
119#define EXTRAREG(x) ((x & EXTRA_REG_OFFSET) == EXTRA_REG_OFFSET)
120#define LOWREG(x) ((x & 0x1f) == x)
121#define DOUBLEREG(x) ((x & FP_DOUBLE) == FP_DOUBLE)
122#define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
Ian Rogersb5d09b22012-03-06 22:14:17 -0800123
Ian Rogerse32ca232012-03-05 10:20:23 -0800124/*
125 * Note: the low register of a floating point pair is sufficient to
126 * create the name of a double, but require both names to be passed to
127 * allow for asserts to verify that the pair is consecutive if significant
128 * rework is done in this area. Also, it is a good reminder in the calling
129 * code that reg locations always describe doubles as a pair of singles.
130 */
131#define S2D(x,y) ((x) | FP_DOUBLE)
132/* Mask to strip off fp flags */
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700133#define FP_REG_MASK 0xF
Ian Rogerse32ca232012-03-05 10:20:23 -0800134/* non-existent Dalvik register */
135#define vNone (-1)
136/* non-existant physical register */
137#define rNone (-1)
138
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700139/* RegisterLocation templates return values (rAX, rAX/rDX or XMM0) */
buzbee2cfc6392012-05-07 14:51:40 -0700140// location, wide, defined, const, fp, core, ref, highWord, home, lowReg, highReg, sRegLow
141#define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, rAX, INVALID_REG, INVALID_SREG, INVALID_SREG}
142#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, rAX, rDX, INVALID_SREG, INVALID_SREG}
143#define LOC_C_RETURN_FLOAT {kLocPhysReg, 0, 0, 0, 1, 0, 0, 0, 1, fr0, INVALID_REG, INVALID_SREG, INVALID_SREG}
144#define LOC_C_RETURN_WIDE_DOUBLE {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1, fr0, fr1, INVALID_SREG, INVALID_SREG}
Ian Rogerse32ca232012-03-05 10:20:23 -0800145
Elliott Hughes719ace42012-03-09 18:06:03 -0800146enum ResourceEncodingPos {
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 kGPReg0 = 0,
148 kRegSP = 4,
149 kRegLR = -1,
150 kFPReg0 = 16, // xmm0 .. xmm7/xmm15
151 kFPRegEnd = 32,
152 kRegEnd = kFPRegEnd,
153 kCCode = kRegEnd,
154 // The following four bits are for memory disambiguation
155 kDalvikReg, // 1 Dalvik Frame (can be fully disambiguated)
156 kLiteral, // 2 Literal pool (can be fully disambiguated)
157 kHeapRef, // 3 Somewhere on the heap (alias with any other heap)
158 kMustNotAlias, // 4 Guaranteed to be non-alias (eg *(r6+x))
Elliott Hughes719ace42012-03-09 18:06:03 -0800159};
Ian Rogerse32ca232012-03-05 10:20:23 -0800160
161#define ENCODE_REG_LIST(N) ((u8) N)
162#define ENCODE_REG_SP (1ULL << kRegSP)
163#define ENCODE_CCODE (1ULL << kCCode)
164#define ENCODE_FP_STATUS (1ULL << kFPStatus)
165
166/* Abstract memory locations */
167#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
168#define ENCODE_LITERAL (1ULL << kLiteral)
169#define ENCODE_HEAP_REF (1ULL << kHeapRef)
170#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias)
171
172#define ENCODE_ALL (~0ULL)
173#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \
174 ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
175
176#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
177#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
buzbeeb046e162012-10-30 15:48:42 -0700178/* Not used for x86 */
179#define ENCODE_REG_PC (ENCODE_ALL)
Ian Rogerse32ca232012-03-05 10:20:23 -0800180
181/*
182 * Annotate special-purpose core registers:
183 */
184
Elliott Hughes719ace42012-03-09 18:06:03 -0800185enum NativeRegisterPool {
Ian Rogerse32ca232012-03-05 10:20:23 -0800186 r0 = 0,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800187 rAX = r0,
Ian Rogerse32ca232012-03-05 10:20:23 -0800188 r1 = 1,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800189 rCX = r1,
Ian Rogerse32ca232012-03-05 10:20:23 -0800190 r2 = 2,
191 rDX = r2,
192 r3 = 3,
193 rBX = r3,
194 r4sp = 4,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800195 rSP = r4sp,
196 r4sib_no_index = r4sp,
Ian Rogerse32ca232012-03-05 10:20:23 -0800197 r5 = 5,
198 rBP = r5,
Ian Rogers7caad772012-03-30 01:07:54 -0700199 r5sib_no_base = r5,
Ian Rogerse32ca232012-03-05 10:20:23 -0800200 r6 = 6,
201 rSI = r6,
202 r7 = 7,
203 rDI = r7,
jeffhao703f2cd2012-07-13 17:25:52 -0700204#ifndef TARGET_REX_SUPPORT
205 rRET = 8, // fake return address register for core spill mask
206#else
Ian Rogerse32ca232012-03-05 10:20:23 -0800207 r8 = 8,
208 r9 = 9,
209 r10 = 10,
210 r11 = 11,
211 r12 = 12,
212 r13 = 13,
213 r14 = 14,
214 r15 = 15,
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700215 rRET = 16, // fake return address register for core spill mask
jeffhao703f2cd2012-07-13 17:25:52 -0700216#endif
Ian Rogerse32ca232012-03-05 10:20:23 -0800217 fr0 = 0 + FP_REG_OFFSET,
218 fr1 = 1 + FP_REG_OFFSET,
219 fr2 = 2 + FP_REG_OFFSET,
220 fr3 = 3 + FP_REG_OFFSET,
221 fr4 = 4 + FP_REG_OFFSET,
222 fr5 = 5 + FP_REG_OFFSET,
223 fr6 = 6 + FP_REG_OFFSET,
224 fr7 = 7 + FP_REG_OFFSET,
225 fr8 = 8 + FP_REG_OFFSET,
226 fr9 = 9 + FP_REG_OFFSET,
227 fr10 = 10 + FP_REG_OFFSET,
228 fr11 = 11 + FP_REG_OFFSET,
229 fr12 = 12 + FP_REG_OFFSET,
230 fr13 = 13 + FP_REG_OFFSET,
231 fr14 = 14 + FP_REG_OFFSET,
232 fr15 = 15 + FP_REG_OFFSET,
Elliott Hughes719ace42012-03-09 18:06:03 -0800233};
Ian Rogerse32ca232012-03-05 10:20:23 -0800234
235/*
236 * Target-independent aliases
237 */
238
239#define rARG0 rAX
Ian Rogersb41b33b2012-03-20 14:22:54 -0700240#define rARG1 rCX
241#define rARG2 rDX
242#define rARG3 rBX
jeffhao30a33172012-10-22 18:16:22 -0700243#define rFARG0 rAX
244#define rFARG1 rCX
245#define rFARG2 rDX
246#define rFARG3 rBX
Ian Rogerse32ca232012-03-05 10:20:23 -0800247#define rRET0 rAX
248#define rRET1 rDX
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700249#define rINVOKE_TGT rAX
buzbeeb046e162012-10-30 15:48:42 -0700250#define rLR INVALID_REG
251#define rSUSPEND INVALID_REG
252#define rSELF INVALID_REG
253#define rCOUNT rCX
Ian Rogerse32ca232012-03-05 10:20:23 -0800254
255#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
256
257/*
Ian Rogersde797832012-03-06 10:18:10 -0800258 * The following enum defines the list of supported X86 instructions by the
259 * assembler. Their corresponding EncodingMap positions will be defined in
260 * Assemble.cc.
Ian Rogerse32ca232012-03-05 10:20:23 -0800261 */
Elliott Hughes719ace42012-03-09 18:06:03 -0800262enum X86OpCode {
buzbeeb046e162012-10-30 15:48:42 -0700263 kX86First = 0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 kX8632BitData = kX86First, /* data [31..0] */
265 kX86Bkpt,
266 kX86Nop,
267 // Define groups of binary operations
268 // MR - Memory Register - opcode [base + disp], reg
269 // - lir operands - 0: base, 1: disp, 2: reg
270 // AR - Array Register - opcode [base + index * scale + disp], reg
271 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
272 // TR - Thread Register - opcode fs:[disp], reg - where fs: is equal to Thread::Current()
273 // - lir operands - 0: disp, 1: reg
274 // RR - Register Register - opcode reg1, reg2
275 // - lir operands - 0: reg1, 1: reg2
276 // RM - Register Memory - opcode reg, [base + disp]
277 // - lir operands - 0: reg, 1: base, 2: disp
278 // RA - Register Array - opcode reg, [base + index * scale + disp]
279 // - lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
280 // RT - Register Thread - opcode reg, fs:[disp] - where fs: is equal to Thread::Current()
281 // - lir operands - 0: reg, 1: disp
282 // RI - Register Immediate - opcode reg, #immediate
283 // - lir operands - 0: reg, 1: immediate
284 // MI - Memory Immediate - opcode [base + disp], #immediate
285 // - lir operands - 0: base, 1: disp, 2: immediate
286 // AI - Array Immediate - opcode [base + index * scale + disp], #immediate
287 // - lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
288 // TI - Thread Register - opcode fs:[disp], imm - where fs: is equal to Thread::Current()
289 // - lir operands - 0: disp, 1: imm
Ian Rogers96ab4202012-03-05 19:51:02 -0800290#define BinaryOpCode(opcode) \
Ian Rogersb5d09b22012-03-06 22:14:17 -0800291 opcode ## 8MR, opcode ## 8AR, opcode ## 8TR, \
292 opcode ## 8RR, opcode ## 8RM, opcode ## 8RA, opcode ## 8RT, \
293 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, opcode ## 8TI, \
294 opcode ## 16MR, opcode ## 16AR, opcode ## 16TR, \
295 opcode ## 16RR, opcode ## 16RM, opcode ## 16RA, opcode ## 16RT, \
296 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, opcode ## 16TI, \
297 opcode ## 16RI8, opcode ## 16MI8, opcode ## 16AI8, opcode ## 16TI8, \
298 opcode ## 32MR, opcode ## 32AR, opcode ## 32TR, \
299 opcode ## 32RR, opcode ## 32RM, opcode ## 32RA, opcode ## 32RT, \
300 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, opcode ## 32TI, \
301 opcode ## 32RI8, opcode ## 32MI8, opcode ## 32AI8, opcode ## 32TI8
Bill Buzbeea114add2012-05-03 15:00:40 -0700302 BinaryOpCode(kX86Add),
303 BinaryOpCode(kX86Or),
304 BinaryOpCode(kX86Adc),
305 BinaryOpCode(kX86Sbb),
306 BinaryOpCode(kX86And),
307 BinaryOpCode(kX86Sub),
308 BinaryOpCode(kX86Xor),
309 BinaryOpCode(kX86Cmp),
Ian Rogers96ab4202012-03-05 19:51:02 -0800310#undef BinaryOpCode
Bill Buzbeea114add2012-05-03 15:00:40 -0700311 kX86Imul16RRI, kX86Imul16RMI, kX86Imul16RAI,
312 kX86Imul32RRI, kX86Imul32RMI, kX86Imul32RAI,
313 kX86Imul32RRI8, kX86Imul32RMI8, kX86Imul32RAI8,
314 kX86Mov8MR, kX86Mov8AR, kX86Mov8TR,
315 kX86Mov8RR, kX86Mov8RM, kX86Mov8RA, kX86Mov8RT,
316 kX86Mov8RI, kX86Mov8MI, kX86Mov8AI, kX86Mov8TI,
317 kX86Mov16MR, kX86Mov16AR, kX86Mov16TR,
318 kX86Mov16RR, kX86Mov16RM, kX86Mov16RA, kX86Mov16RT,
319 kX86Mov16RI, kX86Mov16MI, kX86Mov16AI, kX86Mov16TI,
320 kX86Mov32MR, kX86Mov32AR, kX86Mov32TR,
321 kX86Mov32RR, kX86Mov32RM, kX86Mov32RA, kX86Mov32RT,
322 kX86Mov32RI, kX86Mov32MI, kX86Mov32AI, kX86Mov32TI,
323 kX86Lea32RA,
324 // RC - Register CL - opcode reg, CL
325 // - lir operands - 0: reg, 1: CL
326 // MC - Memory CL - opcode [base + disp], CL
327 // - lir operands - 0: base, 1: disp, 2: CL
328 // AC - Array CL - opcode [base + index * scale + disp], CL
329 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: CL
Ian Rogersb5d09b22012-03-06 22:14:17 -0800330#define BinaryShiftOpCode(opcode) \
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, \
332 opcode ## 8RC, opcode ## 8MC, opcode ## 8AC, \
333 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, \
334 opcode ## 16RC, opcode ## 16MC, opcode ## 16AC, \
335 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, \
336 opcode ## 32RC, opcode ## 32MC, opcode ## 32AC
337 BinaryShiftOpCode(kX86Rol),
338 BinaryShiftOpCode(kX86Ror),
339 BinaryShiftOpCode(kX86Rcl),
340 BinaryShiftOpCode(kX86Rcr),
341 BinaryShiftOpCode(kX86Sal),
342 BinaryShiftOpCode(kX86Shr),
343 BinaryShiftOpCode(kX86Sar),
Ian Rogersb5d09b22012-03-06 22:14:17 -0800344#undef BinaryShiftOpcode
jeffhao77ae36b2012-08-07 14:18:16 -0700345 kX86Cmc,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800346#define UnaryOpcode(opcode, reg, mem, array) \
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 opcode ## 8 ## reg, opcode ## 8 ## mem, opcode ## 8 ## array, \
348 opcode ## 16 ## reg, opcode ## 16 ## mem, opcode ## 16 ## array, \
349 opcode ## 32 ## reg, opcode ## 32 ## mem, opcode ## 32 ## array
350 UnaryOpcode(kX86Test, RI, MI, AI),
Ian Rogers2e9f7ed2012-09-26 11:30:43 -0700351 kX86Test32RR,
Bill Buzbeea114add2012-05-03 15:00:40 -0700352 UnaryOpcode(kX86Not, R, M, A),
353 UnaryOpcode(kX86Neg, R, M, A),
354 UnaryOpcode(kX86Mul, DaR, DaM, DaA),
355 UnaryOpcode(kX86Imul, DaR, DaM, DaA),
356 UnaryOpcode(kX86Divmod, DaR, DaM, DaA),
357 UnaryOpcode(kX86Idivmod, DaR, DaM, DaA),
Ian Rogersb5d09b22012-03-06 22:14:17 -0800358#undef UnaryOpcode
359#define Binary0fOpCode(opcode) \
360 opcode ## RR, opcode ## RM, opcode ## RA
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 Binary0fOpCode(kX86Movsd),
362 kX86MovsdMR,
363 kX86MovsdAR,
364 Binary0fOpCode(kX86Movss),
365 kX86MovssMR,
366 kX86MovssAR,
367 Binary0fOpCode(kX86Cvtsi2sd), // int to double
368 Binary0fOpCode(kX86Cvtsi2ss), // int to float
369 Binary0fOpCode(kX86Cvttsd2si),// truncating double to int
370 Binary0fOpCode(kX86Cvttss2si),// truncating float to int
371 Binary0fOpCode(kX86Cvtsd2si), // rounding double to int
372 Binary0fOpCode(kX86Cvtss2si), // rounding float to int
373 Binary0fOpCode(kX86Ucomisd), // unordered double compare
374 Binary0fOpCode(kX86Ucomiss), // unordered float compare
375 Binary0fOpCode(kX86Comisd), // double compare
376 Binary0fOpCode(kX86Comiss), // float compare
377 Binary0fOpCode(kX86Orps), // or of floating point registers
378 Binary0fOpCode(kX86Xorps), // xor of floating point registers
379 Binary0fOpCode(kX86Addsd), // double add
380 Binary0fOpCode(kX86Addss), // float add
381 Binary0fOpCode(kX86Mulsd), // double multiply
382 Binary0fOpCode(kX86Mulss), // float multiply
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 Binary0fOpCode(kX86Cvtsd2ss), // double to float
jeffhao292188d2012-05-17 15:45:04 -0700384 Binary0fOpCode(kX86Cvtss2sd), // float to double
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 Binary0fOpCode(kX86Subsd), // double subtract
386 Binary0fOpCode(kX86Subss), // float subtract
387 Binary0fOpCode(kX86Divsd), // double divide
388 Binary0fOpCode(kX86Divss), // float divide
jeffhaofdffdf82012-07-11 16:08:43 -0700389 kX86PsrlqRI, // right shift of floating point registers
390 kX86PsllqRI, // left shift of floating point registers
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 Binary0fOpCode(kX86Movdxr), // move into xmm from gpr
jeffhaofdffdf82012-07-11 16:08:43 -0700392 kX86MovdrxRR, kX86MovdrxMR, kX86MovdrxAR,// move into reg from xmm
Bill Buzbeea114add2012-05-03 15:00:40 -0700393 kX86Set8R, kX86Set8M, kX86Set8A,// set byte depending on condition operand
394 kX86Mfence, // memory barrier
395 Binary0fOpCode(kX86Imul16), // 16bit multiply
396 Binary0fOpCode(kX86Imul32), // 32bit multiply
jeffhao83025762012-08-02 11:08:56 -0700397 kX86CmpxchgRR, kX86CmpxchgMR, kX86CmpxchgAR,// compare and exchange
398 kX86LockCmpxchgRR, kX86LockCmpxchgMR, kX86LockCmpxchgAR,// locked compare and exchange
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 Binary0fOpCode(kX86Movzx8), // zero-extend 8-bit value
400 Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value
401 Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value
402 Binary0fOpCode(kX86Movsx16), // sign-extend 16-bit value
Ian Rogersb5d09b22012-03-06 22:14:17 -0800403#undef Binary0fOpCode
Bill Buzbeea114add2012-05-03 15:00:40 -0700404 kX86Jcc8, kX86Jcc32, // jCC rel8/32; lir operands - 0: rel, 1: CC, target assigned
405 kX86Jmp8, kX86Jmp32, // jmp rel8/32; lir operands - 0: rel, target assigned
406 kX86JmpR, // jmp reg; lir operands - 0: reg
407 kX86CallR, // call reg; lir operands - 0: reg
408 kX86CallM, // call [base + disp]; lir operands - 0: base, 1: disp
409 kX86CallA, // call [base + index * scale + disp]
410 // lir operands - 0: base, 1: index, 2: scale, 3: disp
411 kX86CallT, // call fs:[disp]; fs: is equal to Thread::Current(); lir operands - 0: disp
412 kX86Ret, // ret; no lir operands
413 kX86StartOfMethod, // call 0; pop reg; sub reg, # - generate start of method into reg
414 // lir operands - 0: reg
415 kX86PcRelLoadRA, // mov reg, [base + index * scale + PC relative displacement]
416 // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table
417 kX86PcRelAdr, // mov reg, PC relative displacement; lir operands - 0: reg, 1: table
418 kX86Last
Elliott Hughes719ace42012-03-09 18:06:03 -0800419};
Ian Rogerse32ca232012-03-05 10:20:23 -0800420
Ian Rogersde797832012-03-06 10:18:10 -0800421/* Instruction assembly fieldLoc kind */
Elliott Hughes719ace42012-03-09 18:06:03 -0800422enum X86EncodingKind {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800423 kData, // Special case for raw data.
424 kNop, // Special case for variable length nop.
425 kNullary, // Opcode that takes no arguments.
426 kReg, kMem, kArray, // R, M and A instruction kinds.
427 kMemReg, kArrayReg, kThreadReg, // MR, AR and TR instruction kinds.
428 kRegReg, kRegMem, kRegArray, kRegThread, // RR, RM, RA and RT instruction kinds.
jeffhaofdffdf82012-07-11 16:08:43 -0700429 kRegRegStore, // RR following the store modrm reg-reg encoding rather than the load.
Ian Rogersb5d09b22012-03-06 22:14:17 -0800430 kRegImm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
431 kRegRegImm, kRegMemImm, kRegArrayImm, // RRI, RMI and RAI instruction kinds.
432 kMovRegImm, // Shorter form move RI.
433 kShiftRegImm, kShiftMemImm, kShiftArrayImm, // Shift opcode with immediate.
434 kShiftRegCl, kShiftMemCl, kShiftArrayCl, // Shift opcode with register CL.
435 kRegRegReg, kRegRegMem, kRegRegArray, // RRR, RRM, RRA instruction kinds.
436 kRegCond, kMemCond, kArrayCond, // R, M, A instruction kinds following by a condition.
Bill Buzbeea114add2012-05-03 15:00:40 -0700437 kJmp, kJcc, kCall, // Branch instruction kinds.
438 kPcRel, // Operation with displacement that is PC relative
439 kMacro, // An instruction composing multiple others
440 kUnimplemented // Encoding used when an instruction isn't yet implemented.
Elliott Hughes719ace42012-03-09 18:06:03 -0800441};
Ian Rogersde797832012-03-06 10:18:10 -0800442
Ian Rogersde797832012-03-06 10:18:10 -0800443/* Struct used to define the EncodingMap positions for each X86 opcode */
Elliott Hughes719ace42012-03-09 18:06:03 -0800444struct X86EncodingMap {
Ian Rogersde797832012-03-06 10:18:10 -0800445 X86OpCode opcode; // e.g. kOpAddRI
446 X86EncodingKind kind; // Used to discriminate in the union below
447 int flags;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800448 struct {
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 uint8_t prefix1; // non-zero => a prefix byte
450 uint8_t prefix2; // non-zero => a second prefix byte
451 uint8_t opcode; // 1 byte opcode
452 uint8_t extra_opcode1; // possible extra opcode byte
453 uint8_t extra_opcode2; // possible second extra opcode byte
454 // 3bit opcode that gets encoded in the register bits of the modrm byte, use determined by the
455 // encoding kind
456 uint8_t modrm_opcode;
457 uint8_t ax_opcode; // non-zero => shorter encoding for AX as a destination
458 uint8_t immediate_bytes; // number of bytes of immediate
Ian Rogersde797832012-03-06 10:18:10 -0800459 } skeleton;
460 const char *name;
461 const char* fmt;
Elliott Hughes719ace42012-03-09 18:06:03 -0800462};
Ian Rogersde797832012-03-06 10:18:10 -0800463
464extern X86EncodingMap EncodingMap[kX86Last];
465
buzbeea7678db2012-03-05 15:35:46 -0800466// FIXME: mem barrier type - what do we do for x86?
467#define kSY 0
468#define kST 0
469
Ian Rogerse32ca232012-03-05 10:20:23 -0800470/* Bit flags describing the behavior of each native opcode */
Elliott Hughes719ace42012-03-09 18:06:03 -0800471enum X86OpFeatureFlags {
Bill Buzbeea114add2012-05-03 15:00:40 -0700472 kIsBranch = 0,
473 kRegDef0,
474 kRegDef1,
jeffhaoe2962482012-06-28 11:29:57 -0700475 kRegDefA,
476 kRegDefD,
Bill Buzbeea114add2012-05-03 15:00:40 -0700477 kRegDefSP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 kRegUse0,
479 kRegUse1,
480 kRegUse2,
481 kRegUse3,
jeffhaoe2962482012-06-28 11:29:57 -0700482 kRegUse4,
483 kRegUseA,
484 kRegUseC,
485 kRegUseD,
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 kRegUseSP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 kNoOperand,
488 kIsUnaryOp,
489 kIsBinaryOp,
490 kIsTertiaryOp,
491 kIsQuadOp,
492 kIsQuinOp,
493 kIsSextupleOp,
494 kIsIT,
495 kSetsCCodes,
496 kUsesCCodes,
497 kMemLoad,
498 kMemStore,
499 kPCRelFixup,
Ian Rogerse32ca232012-03-05 10:20:23 -0800500// FIXME: add NEEDS_FIXUP to instruction attributes
Elliott Hughes719ace42012-03-09 18:06:03 -0800501};
Ian Rogerse32ca232012-03-05 10:20:23 -0800502
503#define IS_LOAD (1 << kMemLoad)
504#define IS_STORE (1 << kMemStore)
505#define IS_BRANCH (1 << kIsBranch)
506#define REG_DEF0 (1 << kRegDef0)
507#define REG_DEF1 (1 << kRegDef1)
jeffhaoe2962482012-06-28 11:29:57 -0700508#define REG_DEFA (1 << kRegDefA)
509#define REG_DEFD (1 << kRegDefD)
Ian Rogerse32ca232012-03-05 10:20:23 -0800510#define REG_DEF_SP (1 << kRegDefSP)
Ian Rogerse32ca232012-03-05 10:20:23 -0800511#define REG_USE0 (1 << kRegUse0)
512#define REG_USE1 (1 << kRegUse1)
513#define REG_USE2 (1 << kRegUse2)
514#define REG_USE3 (1 << kRegUse3)
jeffhaoe2962482012-06-28 11:29:57 -0700515#define REG_USE4 (1 << kRegUse4)
516#define REG_USEA (1 << kRegUseA)
517#define REG_USEC (1 << kRegUseC)
518#define REG_USED (1 << kRegUseD)
Ian Rogerse32ca232012-03-05 10:20:23 -0800519#define REG_USE_SP (1 << kRegUseSP)
Ian Rogerse32ca232012-03-05 10:20:23 -0800520#define NO_OPERAND (1 << kNoOperand)
521#define IS_UNARY_OP (1 << kIsUnaryOp)
522#define IS_BINARY_OP (1 << kIsBinaryOp)
523#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
524#define IS_QUAD_OP (1 << kIsQuadOp)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800525#define IS_QUIN_OP (1 << kIsQuinOp)
526#define IS_SEXTUPLE_OP (1 << kIsSextupleOp)
Ian Rogerse32ca232012-03-05 10:20:23 -0800527#define IS_IT (1 << kIsIT)
528#define SETS_CCODES (1 << kSetsCCodes)
529#define USES_CCODES (1 << kUsesCCodes)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800530#define NEEDS_FIXUP (1 << kPCRelFixup)
Ian Rogerse32ca232012-03-05 10:20:23 -0800531
532/* attributes, included for compatibility */
533#define REG_DEF_FPCS_LIST0 (0)
534#define REG_DEF_FPCS_LIST2 (0)
535
536
537/* Common combo register usage patterns */
538#define REG_USE01 (REG_USE0 | REG_USE1)
539#define REG_USE02 (REG_USE0 | REG_USE2)
540#define REG_USE012 (REG_USE01 | REG_USE2)
jeffhaoe2962482012-06-28 11:29:57 -0700541#define REG_USE014 (REG_USE01 | REG_USE4)
Ian Rogerse32ca232012-03-05 10:20:23 -0800542#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0)
543#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1)
jeffhaoe2962482012-06-28 11:29:57 -0700544#define REG_DEF0_USE12 (REG_DEF0_USE1 | REG_USE2)
545#define REG_DEFA_USEA (REG_DEFA | REG_USEA)
546#define REG_DEFAD_USEA (REG_DEFA_USEA | REG_DEFD)
547#define REG_DEFAD_USEAD (REG_DEFAD_USEA | REG_USED)
Ian Rogerse32ca232012-03-05 10:20:23 -0800548
Ian Rogerse32ca232012-03-05 10:20:23 -0800549/* Keys for target-specific scheduling and other optimization hints */
Elliott Hughes719ace42012-03-09 18:06:03 -0800550enum X86TargetOptHints {
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 kMaxHoistDistance,
Elliott Hughes719ace42012-03-09 18:06:03 -0800552};
Ian Rogerse32ca232012-03-05 10:20:23 -0800553
Ian Rogersb5d09b22012-03-06 22:14:17 -0800554/* Offsets of high and low halves of a 64bit value */
555#define LOWORD_OFFSET 0
556#define HIWORD_OFFSET 4
557
558/* Segment override instruction prefix used for quick TLS access to Thread::Current() */
559#define THREAD_PREFIX 0x64
Ian Rogerse32ca232012-03-05 10:20:23 -0800560
Ian Rogersde797832012-03-06 10:18:10 -0800561#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 127))
Ian Rogersb5d09b22012-03-06 22:14:17 -0800562#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32767))
Ian Rogerse32ca232012-03-05 10:20:23 -0800563
564} // namespace art
565
566#endif // ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_