blob: a767ff862c089bd94ea7895eff89b062e576732c [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 */
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700109#define FP_REG_OFFSET 32
Ian Rogerse32ca232012-03-05 10:20:23 -0800110/* Offset to distinguish DP FP regs */
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700111#define FP_DOUBLE (FP_REG_OFFSET + 16)
Ian Rogerse32ca232012-03-05 10:20:23 -0800112/* Offset to distingish the extra regs */
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700113#define EXTRA_REG_OFFSET (FP_DOUBLE + 16)
Ian Rogerse32ca232012-03-05 10:20:23 -0800114/* 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))
Ian Rogersb5d09b22012-03-06 22:14:17 -0800121
Ian Rogerse32ca232012-03-05 10:20:23 -0800122/*
123 * Note: the low register of a floating point pair is sufficient to
124 * create the name of a double, but require both names to be passed to
125 * allow for asserts to verify that the pair is consecutive if significant
126 * rework is done in this area. Also, it is a good reminder in the calling
127 * code that reg locations always describe doubles as a pair of singles.
128 */
129#define S2D(x,y) ((x) | FP_DOUBLE)
130/* Mask to strip off fp flags */
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700131#define FP_REG_MASK 0xF
Ian Rogerse32ca232012-03-05 10:20:23 -0800132/* non-existent Dalvik register */
133#define vNone (-1)
134/* non-existant physical register */
135#define rNone (-1)
136
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700137/* RegisterLocation templates return values (rAX, rAX/rDX or XMM0) */
138// location, wide, defined, fp, core, highWord, home, lowReg, highReg, sRegLow
139#define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 1, rAX, INVALID_REG, INVALID_SREG}
140#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, rAX, rDX, INVALID_SREG}
141#define LOC_C_RETURN_FLOAT {kLocPhysReg, 0, 0, 1, 0, 0, 1, fr0, INVALID_REG, INVALID_SREG}
142#define LOC_C_RETURN_WIDE_DOUBLE {kLocPhysReg, 1, 0, 1, 0, 0, 1, fr0, fr1, INVALID_SREG}
Ian Rogerse32ca232012-03-05 10:20:23 -0800143
Elliott Hughes719ace42012-03-09 18:06:03 -0800144enum ResourceEncodingPos {
Ian Rogerse32ca232012-03-05 10:20:23 -0800145 kGPReg0 = 0,
146 kRegSP = 4,
147 kRegLR = -1,
148 kFPReg0 = 16, // xmm0 .. xmm7/xmm15
149 kFPRegEnd = 32,
150 kRegEnd = kFPRegEnd,
151 kCCode = kRegEnd,
152 // The following four bits are for memory disambiguation
153 kDalvikReg, // 1 Dalvik Frame (can be fully disambiguated)
154 kLiteral, // 2 Literal pool (can be fully disambiguated)
155 kHeapRef, // 3 Somewhere on the heap (alias with any other heap)
156 kMustNotAlias, // 4 Guaranteed to be non-alias (eg *(r6+x))
Elliott Hughes719ace42012-03-09 18:06:03 -0800157};
Ian Rogerse32ca232012-03-05 10:20:23 -0800158
159#define ENCODE_REG_LIST(N) ((u8) N)
160#define ENCODE_REG_SP (1ULL << kRegSP)
161#define ENCODE_CCODE (1ULL << kCCode)
162#define ENCODE_FP_STATUS (1ULL << kFPStatus)
163
164/* Abstract memory locations */
165#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
166#define ENCODE_LITERAL (1ULL << kLiteral)
167#define ENCODE_HEAP_REF (1ULL << kHeapRef)
168#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias)
169
170#define ENCODE_ALL (~0ULL)
171#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \
172 ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
173
174#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
175#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
176
177/*
178 * Annotate special-purpose core registers:
179 */
180
Elliott Hughes719ace42012-03-09 18:06:03 -0800181enum NativeRegisterPool {
Ian Rogerse32ca232012-03-05 10:20:23 -0800182 r0 = 0,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800183 rAX = r0,
Ian Rogerse32ca232012-03-05 10:20:23 -0800184 r1 = 1,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800185 rCX = r1,
Ian Rogerse32ca232012-03-05 10:20:23 -0800186 r2 = 2,
187 rDX = r2,
188 r3 = 3,
189 rBX = r3,
190 r4sp = 4,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800191 rSP = r4sp,
192 r4sib_no_index = r4sp,
Ian Rogerse32ca232012-03-05 10:20:23 -0800193 r5 = 5,
194 rBP = r5,
195 r6 = 6,
196 rSI = r6,
197 r7 = 7,
198 rDI = r7,
199 r8 = 8,
200 r9 = 9,
201 r10 = 10,
202 r11 = 11,
203 r12 = 12,
204 r13 = 13,
205 r14 = 14,
206 r15 = 15,
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700207 rRET = 16, // fake return address register for core spill mask
Ian Rogerse32ca232012-03-05 10:20:23 -0800208 fr0 = 0 + FP_REG_OFFSET,
209 fr1 = 1 + FP_REG_OFFSET,
210 fr2 = 2 + FP_REG_OFFSET,
211 fr3 = 3 + FP_REG_OFFSET,
212 fr4 = 4 + FP_REG_OFFSET,
213 fr5 = 5 + FP_REG_OFFSET,
214 fr6 = 6 + FP_REG_OFFSET,
215 fr7 = 7 + FP_REG_OFFSET,
216 fr8 = 8 + FP_REG_OFFSET,
217 fr9 = 9 + FP_REG_OFFSET,
218 fr10 = 10 + FP_REG_OFFSET,
219 fr11 = 11 + FP_REG_OFFSET,
220 fr12 = 12 + FP_REG_OFFSET,
221 fr13 = 13 + FP_REG_OFFSET,
222 fr14 = 14 + FP_REG_OFFSET,
223 fr15 = 15 + FP_REG_OFFSET,
Elliott Hughes719ace42012-03-09 18:06:03 -0800224};
Ian Rogerse32ca232012-03-05 10:20:23 -0800225
226/*
227 * Target-independent aliases
228 */
229
230#define rARG0 rAX
231#define rARG1 rDX
232#define rARG2 rCX
233#define rRET0 rAX
234#define rRET1 rDX
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700235#define rINVOKE_TGT rAX
Ian Rogerse32ca232012-03-05 10:20:23 -0800236
237#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
238
Ian Rogersb5d09b22012-03-06 22:14:17 -0800239/* X86 condition encodings */
240enum X86ConditionCode {
241 kX86CondO = 0x0, // overflow
242 kX86CondNo = 0x1, // not overflow
243
244 kX86CondB = 0x2, // below
245 kX86CondNae = kX86CondB, // not-above-equal
246 kX86CondC = kX86CondB, // carry
247
248 kX86CondNb = 0x3, // not-below
249 kX86CondAe = kX86CondNb, // above-equal
250 kX86CondNc = kX86CondNb, // not-carry
251
252 kX86CondZ = 0x4, // zero
253 kX86CondEq = kX86CondZ, // equal
254
255 kX86CondNz = 0x5, // not-zero
256 kX86CondNe = kX86CondNz, // not-equal
257
258 kX86CondBe = 0x6, // below-equal
259 kX86CondNa = kX86CondBe, // not-above
260
261 kX86CondNbe = 0x7, // not-below-equal
262 kX86CondA = kX86CondNbe,// above
263
264 kX86CondS = 0x8, // sign
265 kX86CondNs = 0x9, // not-sign
266
267 kX86CondP = 0xA, // 8-bit parity even
268 kX86CondPE = kX86CondP,
269
270 kX86CondNp = 0xB, // 8-bit parity odd
271 kX86CondPo = kX86CondNp,
272
273 kX86CondL = 0xC, // less-than
274 kX86CondNge = kX86CondL, // not-greater-equal
275
276 kX86CondNl = 0xD, // not-less-than
277 kX86CondGe = kX86CondL, // not-greater-equal
278
279 kX86CondLe = 0xE, // less-than-equal
280 kX86CondNg = kX86CondLe, // not-greater
281
282 kX86CondNle = 0xF, // not-less-than
283 kX86CondG = kX86CondNle,// greater
284};
285
Ian Rogerse32ca232012-03-05 10:20:23 -0800286/*
Ian Rogersde797832012-03-06 10:18:10 -0800287 * The following enum defines the list of supported X86 instructions by the
288 * assembler. Their corresponding EncodingMap positions will be defined in
289 * Assemble.cc.
Ian Rogerse32ca232012-03-05 10:20:23 -0800290 */
Elliott Hughes719ace42012-03-09 18:06:03 -0800291enum X86OpCode {
Ian Rogerse32ca232012-03-05 10:20:23 -0800292 kPseudoSuspendTarget = -15,
293 kPseudoThrowTarget = -14,
294 kPseudoCaseLabel = -13,
295 kPseudoMethodEntry = -12,
296 kPseudoMethodExit = -11,
297 kPseudoBarrier = -10,
298 kPseudoExtended = -9,
299 kPseudoSSARep = -8,
300 kPseudoEntryBlock = -7,
301 kPseudoExitBlock = -6,
302 kPseudoTargetLabel = -5,
303 kPseudoDalvikByteCodeBoundary = -4,
304 kPseudoPseudoAlign4 = -3,
305 kPseudoEHBlockLabel = -2,
306 kPseudoNormalBlockLabel = -1,
Ian Rogerse32ca232012-03-05 10:20:23 -0800307 kX86First,
Ian Rogers96ab4202012-03-05 19:51:02 -0800308 kX8632BitData = kX86First, /* data [31..0] */
Ian Rogersb5d09b22012-03-06 22:14:17 -0800309 kX86Bkpt,
310 kX86Nop,
Ian Rogersde797832012-03-06 10:18:10 -0800311 // Define groups of binary operations
Ian Rogersb5d09b22012-03-06 22:14:17 -0800312 // MR - Memory Register - opcode [base + disp], reg
313 // - lir operands - 0: base, 1: disp, 2: reg
314 // AR - Array Register - opcode [base + index * scale + disp], reg
315 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
316 // TR - Thread Register - opcode fs:[disp], reg - where fs: is equal to Thread::Current()
317 // - lir operands - 0: disp, 1: reg
Ian Rogersde797832012-03-06 10:18:10 -0800318 // RR - Register Register - opcode reg1, reg2
319 // - lir operands - 0: reg1, 1: reg2
320 // RM - Register Memory - opcode reg, [base + disp]
321 // - lir operands - 0: reg, 1: base, 2: disp
322 // RA - Register Array - opcode reg, [base + index * scale + disp]
323 // - lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
Ian Rogersb5d09b22012-03-06 22:14:17 -0800324 // RT - Register Thread - opcode reg, fs:[disp] - where fs: is equal to Thread::Current()
325 // - lir operands - 0: reg, 1: disp
326 // RI - Register Immediate - opcode reg, #immediate
327 // - lir operands - 0: reg, 1: immediate
328 // MI - Memory Immediate - opcode [base + disp], #immediate
329 // - lir operands - 0: base, 1: disp, 2: immediate
330 // AI - Array Immediate - opcode [base + index * scale + disp], #immediate
331 // - lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
332 // TI - Thread Register - opcode fs:[disp], imm - where fs: is equal to Thread::Current()
333 // - lir operands - 0: disp, 1: imm
Ian Rogers96ab4202012-03-05 19:51:02 -0800334#define BinaryOpCode(opcode) \
Ian Rogersb5d09b22012-03-06 22:14:17 -0800335 opcode ## 8MR, opcode ## 8AR, opcode ## 8TR, \
336 opcode ## 8RR, opcode ## 8RM, opcode ## 8RA, opcode ## 8RT, \
337 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, opcode ## 8TI, \
338 opcode ## 16MR, opcode ## 16AR, opcode ## 16TR, \
339 opcode ## 16RR, opcode ## 16RM, opcode ## 16RA, opcode ## 16RT, \
340 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, opcode ## 16TI, \
341 opcode ## 16RI8, opcode ## 16MI8, opcode ## 16AI8, opcode ## 16TI8, \
342 opcode ## 32MR, opcode ## 32AR, opcode ## 32TR, \
343 opcode ## 32RR, opcode ## 32RM, opcode ## 32RA, opcode ## 32RT, \
344 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, opcode ## 32TI, \
345 opcode ## 32RI8, opcode ## 32MI8, opcode ## 32AI8, opcode ## 32TI8
346 BinaryOpCode(kX86Add),
347 BinaryOpCode(kX86Or),
348 BinaryOpCode(kX86Adc),
349 BinaryOpCode(kX86Sbb),
350 BinaryOpCode(kX86And),
351 BinaryOpCode(kX86Sub),
352 BinaryOpCode(kX86Xor),
353 BinaryOpCode(kX86Cmp),
Ian Rogers96ab4202012-03-05 19:51:02 -0800354#undef BinaryOpCode
Ian Rogersb5d09b22012-03-06 22:14:17 -0800355 kX86Imul16RRI, kX86Imul16RMI, kX86Imul16RAI,
356 kX86Imul32RRI, kX86Imul32RMI, kX86Imul32RAI,
357 kX86Imul32RRI8, kX86Imul32RMI8, kX86Imul32RAI8,
358 kX86Mov8MR, kX86Mov8AR, kX86Mov8TR,
359 kX86Mov8RR, kX86Mov8RM, kX86Mov8RA, kX86Mov8RT,
360 kX86Mov8RI, kX86Mov8MI, kX86Mov8AI, kX86Mov8TI,
361 kX86Mov16MR, kX86Mov16AR, kX86Mov16TR,
362 kX86Mov16RR, kX86Mov16RM, kX86Mov16RA, kX86Mov16RT,
363 kX86Mov16RI, kX86Mov16MI, kX86Mov16AI, kX86Mov16TI,
364 kX86Mov32MR, kX86Mov32AR, kX86Mov32TR,
365 kX86Mov32RR, kX86Mov32RM, kX86Mov32RA, kX86Mov32RT,
366 kX86Mov32RI, kX86Mov32MI, kX86Mov32AI, kX86Mov32TI,
367 kX86Lea32RA,
368 // RC - Register CL - opcode reg, CL
369 // - lir operands - 0: reg, 1: CL
370 // MC - Memory CL - opcode [base + disp], CL
371 // - lir operands - 0: base, 1: disp, 2: CL
372 // AC - Array CL - opcode [base + index * scale + disp], CL
373 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: CL
374#define BinaryShiftOpCode(opcode) \
375 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, \
376 opcode ## 8RC, opcode ## 8MC, opcode ## 8AC, \
377 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, \
378 opcode ## 16RC, opcode ## 16MC, opcode ## 16AC, \
379 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, \
380 opcode ## 32RC, opcode ## 32MC, opcode ## 32AC
381 BinaryShiftOpCode(kX86Rol),
382 BinaryShiftOpCode(kX86Ror),
383 BinaryShiftOpCode(kX86Rcl),
384 BinaryShiftOpCode(kX86Rcr),
385 BinaryShiftOpCode(kX86Sal),
386 BinaryShiftOpCode(kX86Shl),
387 BinaryShiftOpCode(kX86Shr),
388 BinaryShiftOpCode(kX86Sar),
389#undef BinaryShiftOpcode
390#define UnaryOpcode(opcode, reg, mem, array) \
391 opcode ## 8 ## reg, opcode ## 8 ## mem, opcode ## 8 ## array, \
392 opcode ## 16 ## reg, opcode ## 16 ## mem, opcode ## 16 ## array, \
393 opcode ## 32 ## reg, opcode ## 32 ## mem, opcode ## 32 ## array
394 UnaryOpcode(kX86Test, RI, MI, AI),
395 UnaryOpcode(kX86Not, R, M, A),
396 UnaryOpcode(kX86Neg, R, M, A),
397 UnaryOpcode(kX86Mul, DaR, DaM, DaA),
398 UnaryOpcode(kX86Imul, DaR, DaM, DaA),
399 UnaryOpcode(kX86Divmod, DaR, DaM, DaA),
400 UnaryOpcode(kX86Idivmod, DaR, DaM, DaA),
401#undef UnaryOpcode
402#define Binary0fOpCode(opcode) \
403 opcode ## RR, opcode ## RM, opcode ## RA
404 Binary0fOpCode(kX86Movsd),
405 kX86MovsdMR,
406 kX86MovsdAR,
407 Binary0fOpCode(kX86Movss),
408 kX86MovssMR,
409 kX86MovssAR,
410 Binary0fOpCode(kX86Cvtsi2sd), // int to double
411 Binary0fOpCode(kX86Cvtsi2ss), // int to float
412 Binary0fOpCode(kX86Cvttsd2si), // truncating double to int
413 Binary0fOpCode(kX86Cvttss2si), // truncating float to int
414 Binary0fOpCode(kX86Cvtsd2si), // rounding double to int
415 Binary0fOpCode(kX86Cvtss2si), // rounding float to int
416 Binary0fOpCode(kX86Ucomisd), // unordered double compare
417 Binary0fOpCode(kX86Ucomiss), // unordered float compare
418 Binary0fOpCode(kX86Comisd), // double compare
419 Binary0fOpCode(kX86Comiss), // float compare
420 Binary0fOpCode(kX86Addsd), // double add
421 Binary0fOpCode(kX86Addss), // float add
422 Binary0fOpCode(kX86Mulsd), // double multiply
423 Binary0fOpCode(kX86Mulss), // float multiply
424 Binary0fOpCode(kX86Cvtss2sd), // float to double
425 Binary0fOpCode(kX86Cvtsd2ss), // double to float
426 Binary0fOpCode(kX86Subsd), // double subtract
427 Binary0fOpCode(kX86Subss), // float subtract
428 Binary0fOpCode(kX86Divsd), // double subtract
429 Binary0fOpCode(kX86Divss), // float subtract
430 Binary0fOpCode(kX86Movdxr), // move into xmm from gpr
431 Binary0fOpCode(kX86Movdrx), // move into reg from xmm
432 kX86Set8R, kX86Set8M, kX86Set8A,// set byte depending on condition operand
433 Binary0fOpCode(kX86Imul16), // 16bit multiply
434 Binary0fOpCode(kX86Imul32), // 32bit multiply
435 Binary0fOpCode(kX86Movzx8), // zero-extend 8-bit value
436 Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value
437 Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value
438 Binary0fOpCode(kX86Movsx16), // sign-extend 16-bit value
439#undef Binary0fOpCode
440 kX86Jcc, // jCC rel; lir operands - 0: rel, 1: CC, target assigned
441 kX86Jmp, // jmp rel; lir operands - 0: rel, target assigned
442 kX86CallR, // call reg; lir operands - 0: reg
443 kX86CallM, // call [base + disp]; lir operands - 0: base, 1: disp
444 kX86CallA, // call [base + index * scale + disp]
445 // lir operands - 0: base, 1: index, 2: scale, 3: disp
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700446 kX86CallT, // call fs:[disp]; fs: is equal to Thread::Current(); lir operands - 0: disp
Ian Rogersb5d09b22012-03-06 22:14:17 -0800447 kX86Ret, // ret; no lir operands
Ian Rogerse32ca232012-03-05 10:20:23 -0800448 kX86Last
Elliott Hughes719ace42012-03-09 18:06:03 -0800449};
Ian Rogerse32ca232012-03-05 10:20:23 -0800450
Ian Rogersde797832012-03-06 10:18:10 -0800451/* Instruction assembly fieldLoc kind */
Elliott Hughes719ace42012-03-09 18:06:03 -0800452enum X86EncodingKind {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800453 kData, // Special case for raw data.
454 kNop, // Special case for variable length nop.
455 kNullary, // Opcode that takes no arguments.
456 kReg, kMem, kArray, // R, M and A instruction kinds.
457 kMemReg, kArrayReg, kThreadReg, // MR, AR and TR instruction kinds.
458 kRegReg, kRegMem, kRegArray, kRegThread, // RR, RM, RA and RT instruction kinds.
459 kRegImm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
460 kRegRegImm, kRegMemImm, kRegArrayImm, // RRI, RMI and RAI instruction kinds.
461 kMovRegImm, // Shorter form move RI.
462 kShiftRegImm, kShiftMemImm, kShiftArrayImm, // Shift opcode with immediate.
463 kShiftRegCl, kShiftMemCl, kShiftArrayCl, // Shift opcode with register CL.
464 kRegRegReg, kRegRegMem, kRegRegArray, // RRR, RRM, RRA instruction kinds.
465 kRegCond, kMemCond, kArrayCond, // R, M, A instruction kinds following by a condition.
466 kJmp, kJcc, kCall, // Branch instruction kinds.
Ian Rogersde797832012-03-06 10:18:10 -0800467 kUnimplemented // Encoding used when an instruction isn't yet implemented.
Elliott Hughes719ace42012-03-09 18:06:03 -0800468};
Ian Rogersde797832012-03-06 10:18:10 -0800469
Ian Rogersde797832012-03-06 10:18:10 -0800470/* Struct used to define the EncodingMap positions for each X86 opcode */
Elliott Hughes719ace42012-03-09 18:06:03 -0800471struct X86EncodingMap {
Ian Rogersde797832012-03-06 10:18:10 -0800472 X86OpCode opcode; // e.g. kOpAddRI
473 X86EncodingKind kind; // Used to discriminate in the union below
474 int flags;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800475 struct {
476 uint8_t prefix1; // non-zero => a prefix byte
477 uint8_t prefix2; // non-zero => a second prefix byte
478 uint8_t opcode; // 1 byte opcode
479 uint8_t extra_opcode1; // possible extra opcode byte
480 uint8_t extra_opcode2; // possible second extra opcode byte
481 // 3bit opcode that gets encoded in the register bits of the modrm byte, use determined by the
482 // encoding kind
483 uint8_t modrm_opcode;
484 uint8_t ax_opcode; // non-zero => shorter encoding for AX as a destination
485 uint8_t immediate_bytes; // number of bytes of immediate
Ian Rogersde797832012-03-06 10:18:10 -0800486 } skeleton;
487 const char *name;
488 const char* fmt;
Elliott Hughes719ace42012-03-09 18:06:03 -0800489};
Ian Rogersde797832012-03-06 10:18:10 -0800490
491extern X86EncodingMap EncodingMap[kX86Last];
492
buzbeea7678db2012-03-05 15:35:46 -0800493// FIXME: mem barrier type - what do we do for x86?
494#define kSY 0
495#define kST 0
496
Ian Rogerse32ca232012-03-05 10:20:23 -0800497/* Bit flags describing the behavior of each native opcode */
Elliott Hughes719ace42012-03-09 18:06:03 -0800498enum X86OpFeatureFlags {
Ian Rogerse32ca232012-03-05 10:20:23 -0800499 kIsBranch = 0,
500 kRegDef0,
501 kRegDef1,
502 kRegDefSP,
503 kRegDefList0,
504 kRegDefList1,
505 kRegUse0,
506 kRegUse1,
507 kRegUse2,
508 kRegUse3,
509 kRegUseSP,
510 kRegUseList0,
511 kRegUseList1,
512 kNoOperand,
513 kIsUnaryOp,
514 kIsBinaryOp,
515 kIsTertiaryOp,
516 kIsQuadOp,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800517 kIsQuinOp,
518 kIsSextupleOp,
Ian Rogerse32ca232012-03-05 10:20:23 -0800519 kIsIT,
520 kSetsCCodes,
521 kUsesCCodes,
522 kMemLoad,
523 kMemStore,
524 kPCRelFixup,
525// FIXME: add NEEDS_FIXUP to instruction attributes
Elliott Hughes719ace42012-03-09 18:06:03 -0800526};
Ian Rogerse32ca232012-03-05 10:20:23 -0800527
528#define IS_LOAD (1 << kMemLoad)
529#define IS_STORE (1 << kMemStore)
530#define IS_BRANCH (1 << kIsBranch)
531#define REG_DEF0 (1 << kRegDef0)
532#define REG_DEF1 (1 << kRegDef1)
533#define REG_DEF_SP (1 << kRegDefSP)
534#define REG_DEF_LR (1 << kRegDefLR)
535#define REG_DEF_LIST0 (1 << kRegDefList0)
536#define REG_DEF_LIST1 (1 << kRegDefList1)
537#define REG_USE0 (1 << kRegUse0)
538#define REG_USE1 (1 << kRegUse1)
539#define REG_USE2 (1 << kRegUse2)
540#define REG_USE3 (1 << kRegUse3)
541#define REG_USE_SP (1 << kRegUseSP)
542#define REG_USE_PC (1 << kRegUsePC)
543#define REG_USE_LIST0 (1 << kRegUseList0)
544#define REG_USE_LIST1 (1 << kRegUseList1)
545#define NO_OPERAND (1 << kNoOperand)
546#define IS_UNARY_OP (1 << kIsUnaryOp)
547#define IS_BINARY_OP (1 << kIsBinaryOp)
548#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
549#define IS_QUAD_OP (1 << kIsQuadOp)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800550#define IS_QUIN_OP (1 << kIsQuinOp)
551#define IS_SEXTUPLE_OP (1 << kIsSextupleOp)
Ian Rogerse32ca232012-03-05 10:20:23 -0800552#define IS_IT (1 << kIsIT)
553#define SETS_CCODES (1 << kSetsCCodes)
554#define USES_CCODES (1 << kUsesCCodes)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800555#define NEEDS_FIXUP (1 << kPCRelFixup)
Ian Rogerse32ca232012-03-05 10:20:23 -0800556
557/* attributes, included for compatibility */
558#define REG_DEF_FPCS_LIST0 (0)
559#define REG_DEF_FPCS_LIST2 (0)
560
561
562/* Common combo register usage patterns */
563#define REG_USE01 (REG_USE0 | REG_USE1)
564#define REG_USE02 (REG_USE0 | REG_USE2)
565#define REG_USE012 (REG_USE01 | REG_USE2)
566#define REG_USE12 (REG_USE1 | REG_USE2)
567#define REG_USE23 (REG_USE2 | REG_USE3)
568#define REG_DEF01 (REG_DEF0 | REG_DEF1)
569#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0)
570#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1)
571#define REG_DEF0_USE2 (REG_DEF0 | REG_USE2)
572#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01)
573#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12)
574#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2)
575
Ian Rogerse32ca232012-03-05 10:20:23 -0800576/* Keys for target-specific scheduling and other optimization hints */
Elliott Hughes719ace42012-03-09 18:06:03 -0800577enum X86TargetOptHints {
Ian Rogerse32ca232012-03-05 10:20:23 -0800578 kMaxHoistDistance,
Elliott Hughes719ace42012-03-09 18:06:03 -0800579};
Ian Rogerse32ca232012-03-05 10:20:23 -0800580
Ian Rogersb5d09b22012-03-06 22:14:17 -0800581/* Offsets of high and low halves of a 64bit value */
582#define LOWORD_OFFSET 0
583#define HIWORD_OFFSET 4
584
585/* Segment override instruction prefix used for quick TLS access to Thread::Current() */
586#define THREAD_PREFIX 0x64
Ian Rogerse32ca232012-03-05 10:20:23 -0800587
Ian Rogersde797832012-03-06 10:18:10 -0800588#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 127))
Ian Rogersb5d09b22012-03-06 22:14:17 -0800589#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32767))
Ian Rogerse32ca232012-03-05 10:20:23 -0800590
591} // namespace art
592
593#endif // ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_