blob: 797bc8260d29baefe0e7989ea9238a42d01e16da [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_DEX_QUICK_X86_X86_LIR_H_
18#define ART_COMPILER_DEX_QUICK_X86_X86_LIR_H_
Brian Carlstrom7940e442013-07-12 13:46:57 -070019
20#include "dex/compiler_internals.h"
21
22namespace art {
23
24/*
Ian Rogers0177e532014-02-11 16:30:46 -080025 * Runtime register conventions. We consider both x86, x86-64 and x32 (32bit mode x86-64). The ABI
26 * has different conventions and we capture those here. Changing something that is callee save and
27 * making it caller save places a burden on up-calls to save/restore the callee save register,
28 * however, there are few registers that are callee save in the ABI. Changing something that is
29 * caller save and making it callee save places a burden on down-calls to save/restore the callee
30 * save register. For these reasons we aim to match native conventions for caller and callee save.
31 * On x86 only the first 4 registers can be used for byte operations, for this reason they are
32 * preferred for temporary scratch registers.
Brian Carlstrom7940e442013-07-12 13:46:57 -070033 *
34 * General Purpose Register:
Ian Rogers0177e532014-02-11 16:30:46 -080035 * Native: x86 | x86-64 / x32 | ART x86 | ART x86-64
36 * r0/eax: caller | caller | caller, Method*, scratch, return value | caller, scratch, return value
37 * r1/ecx: caller | caller, arg4 | caller, arg1, scratch | caller, arg3, scratch
38 * r2/edx: caller | caller, arg3 | caller, arg2, scratch, high half of long return | caller, arg2, scratch
39 * r3/ebx: callEE | callEE | callER, arg3, scratch | callee, promotable
Brian Carlstrom7940e442013-07-12 13:46:57 -070040 * r4/esp: stack pointer
Ian Rogers0177e532014-02-11 16:30:46 -080041 * r5/ebp: callee | callee | callee, promotable | callee, promotable
42 * r6/esi: callEE | callER, arg2 | callee, promotable | caller, arg1, scratch
43 * r7/edi: callEE | callER, arg1 | callee, promotable | caller, Method*, scratch
Brian Carlstrom7940e442013-07-12 13:46:57 -070044 * --- x86-64/x32 registers
45 * Native: x86-64 / x32 | ART
Ian Rogers0177e532014-02-11 16:30:46 -080046 * r8: caller save, arg5 | caller, arg4, scratch
47 * r9: caller save, arg6 | caller, arg5, scratch
Brian Carlstrom7940e442013-07-12 13:46:57 -070048 * r10: caller save | caller, scratch
49 * r11: caller save | caller, scratch
Ian Rogers0177e532014-02-11 16:30:46 -080050 * r12: callee save | callee, available for register promotion (promotable)
51 * r13: callee save | callee, available for register promotion (promotable)
52 * r14: callee save | callee, available for register promotion (promotable)
53 * r15: callee save | callee, available for register promotion (promotable)
Brian Carlstrom7940e442013-07-12 13:46:57 -070054 *
55 * There is no rSELF, instead on x86 fs: has a base address of Thread::Current, whereas on
56 * x86-64/x32 gs: holds it.
57 *
58 * For floating point we don't support CPUs without SSE2 support (ie newer than PIII):
Ian Rogers0177e532014-02-11 16:30:46 -080059 * Native: x86 | x86-64 / x32 | ART x86 | ART x86-64
60 * XMM0: caller | caller, arg1 | caller, float return value | caller, arg1, float return value
61 * XMM1: caller | caller, arg2 | caller, scratch | caller, arg2, scratch
62 * XMM2: caller | caller, arg3 | caller, scratch | caller, arg3, scratch
63 * XMM3: caller | caller, arg4 | caller, scratch | caller, arg4, scratch
64 * XMM4: caller | caller, arg5 | caller, scratch | caller, arg5, scratch
65 * XMM5: caller | caller, arg6 | caller, scratch | caller, arg6, scratch
66 * XMM6: caller | caller, arg7 | caller, scratch | caller, arg7, scratch
67 * XMM7: caller | caller, arg8 | caller, scratch | caller, arg8, scratch
Brian Carlstrom7940e442013-07-12 13:46:57 -070068 * --- x86-64/x32 registers
Ian Rogers0177e532014-02-11 16:30:46 -080069 * XMM8 .. 15: caller save available as scratch registers for ART.
Brian Carlstrom7940e442013-07-12 13:46:57 -070070 *
Ian Rogers0177e532014-02-11 16:30:46 -080071 * X87 is a necessary evil outside of ART code for x86:
Brian Carlstrom7940e442013-07-12 13:46:57 -070072 * ST0: x86 float/double native return value, caller save
73 * ST1 .. ST7: caller save
74 *
75 * Stack frame diagram (stack grows down, higher addresses at top):
76 *
77 * +------------------------+
78 * | IN[ins-1] | {Note: resides in caller's frame}
79 * | . |
80 * | IN[0] |
81 * | caller's Method* |
82 * +========================+ {Note: start of callee's frame}
83 * | return address | {pushed by call}
84 * | spill region | {variable sized}
85 * +------------------------+
86 * | ...filler word... | {Note: used as 2nd word of V[locals-1] if long]
87 * +------------------------+
88 * | V[locals-1] |
89 * | V[locals-2] |
90 * | . |
91 * | . |
92 * | V[1] |
93 * | V[0] |
94 * +------------------------+
95 * | 0 to 3 words padding |
96 * +------------------------+
97 * | OUT[outs-1] |
98 * | OUT[outs-2] |
99 * | . |
100 * | OUT[0] |
101 * | cur_method* | <<== sp w/ 16-byte alignment
102 * +========================+
103 */
104
105// Offset to distingish FP regs.
106#define X86_FP_REG_OFFSET 32
107// Offset to distinguish DP FP regs.
108#define X86_FP_DOUBLE (X86_FP_REG_OFFSET + 16)
109// Offset to distingish the extra regs.
110#define X86_EXTRA_REG_OFFSET (X86_FP_DOUBLE + 16)
111// Reg types.
112#define X86_REGTYPE(x) (x & (X86_FP_REG_OFFSET | X86_FP_DOUBLE))
113#define X86_FPREG(x) ((x & X86_FP_REG_OFFSET) == X86_FP_REG_OFFSET)
114#define X86_EXTRAREG(x) ((x & X86_EXTRA_REG_OFFSET) == X86_EXTRA_REG_OFFSET)
115#define X86_DOUBLEREG(x) ((x & X86_FP_DOUBLE) == X86_FP_DOUBLE)
116#define X86_SINGLEREG(x) (X86_FPREG(x) && !X86_DOUBLEREG(x))
117
118/*
119 * Note: the low register of a floating point pair is sufficient to
120 * create the name of a double, but require both names to be passed to
121 * allow for asserts to verify that the pair is consecutive if significant
122 * rework is done in this area. Also, it is a good reminder in the calling
123 * code that reg locations always describe doubles as a pair of singles.
124 */
Brian Carlstromb1eba212013-07-17 18:07:19 -0700125#define X86_S2D(x, y) ((x) | X86_FP_DOUBLE)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700126/* Mask to strip off fp flags */
127#define X86_FP_REG_MASK 0xF
128
Brian Carlstrom7940e442013-07-12 13:46:57 -0700129enum X86ResourceEncodingPos {
130 kX86GPReg0 = 0,
131 kX86RegSP = 4,
132 kX86FPReg0 = 16, // xmm0 .. xmm7/xmm15.
Serguei Katkove90501d2014-03-12 15:56:54 +0700133 kX86FPRegEnd = 32,
134 kX86FPStack = 33,
135 kX86RegEnd = kX86FPStack,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136};
137
138#define ENCODE_X86_REG_LIST(N) (static_cast<uint64_t>(N))
139#define ENCODE_X86_REG_SP (1ULL << kX86RegSP)
Serguei Katkove90501d2014-03-12 15:56:54 +0700140#define ENCODE_X86_FP_STACK (1ULL << kX86FPStack)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700141
142enum X86NativeRegisterPool {
143 r0 = 0,
144 rAX = r0,
145 r1 = 1,
146 rCX = r1,
147 r2 = 2,
148 rDX = r2,
149 r3 = 3,
150 rBX = r3,
151 r4sp = 4,
152 rX86_SP = r4sp,
153 r4sib_no_index = r4sp,
154 r5 = 5,
155 rBP = r5,
156 r5sib_no_base = r5,
157 r6 = 6,
158 rSI = r6,
159 r7 = 7,
160 rDI = r7,
161#ifndef TARGET_REX_SUPPORT
162 rRET = 8, // fake return address register for core spill mask.
163#else
164 r8 = 8,
165 r9 = 9,
166 r10 = 10,
167 r11 = 11,
168 r12 = 12,
169 r13 = 13,
170 r14 = 14,
171 r15 = 15,
172 rRET = 16, // fake return address register for core spill mask.
173#endif
174 fr0 = 0 + X86_FP_REG_OFFSET,
175 fr1 = 1 + X86_FP_REG_OFFSET,
176 fr2 = 2 + X86_FP_REG_OFFSET,
177 fr3 = 3 + X86_FP_REG_OFFSET,
178 fr4 = 4 + X86_FP_REG_OFFSET,
179 fr5 = 5 + X86_FP_REG_OFFSET,
180 fr6 = 6 + X86_FP_REG_OFFSET,
181 fr7 = 7 + X86_FP_REG_OFFSET,
182 fr8 = 8 + X86_FP_REG_OFFSET,
183 fr9 = 9 + X86_FP_REG_OFFSET,
184 fr10 = 10 + X86_FP_REG_OFFSET,
185 fr11 = 11 + X86_FP_REG_OFFSET,
186 fr12 = 12 + X86_FP_REG_OFFSET,
187 fr13 = 13 + X86_FP_REG_OFFSET,
188 fr14 = 14 + X86_FP_REG_OFFSET,
189 fr15 = 15 + X86_FP_REG_OFFSET,
190};
191
buzbee2700f7e2014-03-07 09:46:20 -0800192const RegStorage rs_r0(RegStorage::k32BitSolo, r0);
193const RegStorage rs_rAX = rs_r0;
194const RegStorage rs_r1(RegStorage::k32BitSolo, r1);
195const RegStorage rs_rCX = rs_r1;
196const RegStorage rs_r2(RegStorage::k32BitSolo, r2);
197const RegStorage rs_rDX = rs_r2;
198const RegStorage rs_r3(RegStorage::k32BitSolo, r3);
199const RegStorage rs_rBX = rs_r3;
200const RegStorage rs_r4sp(RegStorage::k32BitSolo, r4sp);
201const RegStorage rs_rX86_SP = rs_r4sp;
202const RegStorage rs_r5(RegStorage::k32BitSolo, r5);
203const RegStorage rs_rBP = rs_r5;
204const RegStorage rs_r6(RegStorage::k32BitSolo, r6);
205const RegStorage rs_rSI = rs_r6;
206const RegStorage rs_r7(RegStorage::k32BitSolo, r7);
207const RegStorage rs_rDI = rs_r7;
208
209// TODO: elminate these #defines?
Brian Carlstrom7940e442013-07-12 13:46:57 -0700210#define rX86_ARG0 rAX
buzbee2700f7e2014-03-07 09:46:20 -0800211#define rs_rX86_ARG0 rs_rAX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700212#define rX86_ARG1 rCX
buzbee2700f7e2014-03-07 09:46:20 -0800213#define rs_rX86_ARG1 rs_rCX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700214#define rX86_ARG2 rDX
buzbee2700f7e2014-03-07 09:46:20 -0800215#define rs_rX86_ARG2 rs_rDX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700216#define rX86_ARG3 rBX
buzbee2700f7e2014-03-07 09:46:20 -0800217#define rs_rX86_ARG3 rs_rBX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700218#define rX86_FARG0 rAX
buzbee2700f7e2014-03-07 09:46:20 -0800219#define rs_rX86_FARG0 rs_rAX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700220#define rX86_FARG1 rCX
buzbee2700f7e2014-03-07 09:46:20 -0800221#define rs_rX86_FARG1 rs_rCX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700222#define rX86_FARG2 rDX
buzbee2700f7e2014-03-07 09:46:20 -0800223#define rs_rX86_FARG2 rs_rDX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700224#define rX86_FARG3 rBX
buzbee2700f7e2014-03-07 09:46:20 -0800225#define rs_rX86_FARG3 rs_rBX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700226#define rX86_RET0 rAX
buzbee2700f7e2014-03-07 09:46:20 -0800227#define rs_rX86_RET0 rs_rAX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700228#define rX86_RET1 rDX
buzbee2700f7e2014-03-07 09:46:20 -0800229#define rs_rX86_RET1 rs_rDX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700230#define rX86_INVOKE_TGT rAX
buzbee2700f7e2014-03-07 09:46:20 -0800231#define rs_rX86_INVOKE_TGT rs_rAX
232#define rX86_LR RegStorage::kInvalidRegVal
233#define rX86_SUSPEND RegStorage::kInvalidRegVal
234#define rX86_SELF RegStorage::kInvalidRegVal
Brian Carlstrom7940e442013-07-12 13:46:57 -0700235#define rX86_COUNT rCX
buzbee2700f7e2014-03-07 09:46:20 -0800236#define rs_rX86_COUNT rs_rCX
237#define rX86_PC RegStorage::kInvalidRegVal
Brian Carlstrom7940e442013-07-12 13:46:57 -0700238
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000239// RegisterLocation templates return values (r_V0, or r_V0/r_V1).
240const RegLocation x86_loc_c_return
241 {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed,
242 RegStorage(RegStorage::k32BitSolo, rAX), INVALID_SREG, INVALID_SREG};
243const RegLocation x86_loc_c_return_wide
244 {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed,
245 RegStorage(RegStorage::k64BitPair, rAX, rDX), INVALID_SREG, INVALID_SREG};
246// TODO: update to use k32BitVector (must encode in 7 bits, including fp flag).
247const RegLocation x86_loc_c_return_float
248 {kLocPhysReg, 0, 0, 0, 1, 0, 0, 0, 1, kVectorLength4,
249 RegStorage(RegStorage::k32BitSolo, fr0), INVALID_SREG, INVALID_SREG};
250// TODO: update to use k64BitVector (must encode in 7 bits, including fp flag).
251const RegLocation x86_loc_c_return_double
252 {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1, kVectorLength8,
253 RegStorage(RegStorage::k64BitPair, fr0, fr0), INVALID_SREG, INVALID_SREG};
254
Brian Carlstrom7940e442013-07-12 13:46:57 -0700255/*
256 * The following enum defines the list of supported X86 instructions by the
257 * assembler. Their corresponding EncodingMap positions will be defined in
258 * Assemble.cc.
259 */
260enum X86OpCode {
261 kX86First = 0,
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700262 kX8632BitData = kX86First, // data [31..0].
Brian Carlstrom7940e442013-07-12 13:46:57 -0700263 kX86Bkpt,
264 kX86Nop,
265 // Define groups of binary operations
266 // MR - Memory Register - opcode [base + disp], reg
267 // - lir operands - 0: base, 1: disp, 2: reg
268 // AR - Array Register - opcode [base + index * scale + disp], reg
269 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
270 // TR - Thread Register - opcode fs:[disp], reg - where fs: is equal to Thread::Current()
271 // - lir operands - 0: disp, 1: reg
272 // RR - Register Register - opcode reg1, reg2
273 // - lir operands - 0: reg1, 1: reg2
274 // RM - Register Memory - opcode reg, [base + disp]
275 // - lir operands - 0: reg, 1: base, 2: disp
276 // RA - Register Array - opcode reg, [base + index * scale + disp]
277 // - lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
278 // RT - Register Thread - opcode reg, fs:[disp] - where fs: is equal to Thread::Current()
279 // - lir operands - 0: reg, 1: disp
280 // RI - Register Immediate - opcode reg, #immediate
281 // - lir operands - 0: reg, 1: immediate
282 // MI - Memory Immediate - opcode [base + disp], #immediate
283 // - lir operands - 0: base, 1: disp, 2: immediate
284 // AI - Array Immediate - opcode [base + index * scale + disp], #immediate
285 // - lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
Vladimir Markoe6ed00b2013-10-24 14:52:37 +0100286 // TI - Thread Immediate - opcode fs:[disp], imm - where fs: is equal to Thread::Current()
Brian Carlstrom7940e442013-07-12 13:46:57 -0700287 // - lir operands - 0: disp, 1: imm
288#define BinaryOpCode(opcode) \
289 opcode ## 8MR, opcode ## 8AR, opcode ## 8TR, \
290 opcode ## 8RR, opcode ## 8RM, opcode ## 8RA, opcode ## 8RT, \
291 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, opcode ## 8TI, \
292 opcode ## 16MR, opcode ## 16AR, opcode ## 16TR, \
293 opcode ## 16RR, opcode ## 16RM, opcode ## 16RA, opcode ## 16RT, \
294 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, opcode ## 16TI, \
295 opcode ## 16RI8, opcode ## 16MI8, opcode ## 16AI8, opcode ## 16TI8, \
296 opcode ## 32MR, opcode ## 32AR, opcode ## 32TR, \
297 opcode ## 32RR, opcode ## 32RM, opcode ## 32RA, opcode ## 32RT, \
298 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, opcode ## 32TI, \
299 opcode ## 32RI8, opcode ## 32MI8, opcode ## 32AI8, opcode ## 32TI8
300 BinaryOpCode(kX86Add),
301 BinaryOpCode(kX86Or),
302 BinaryOpCode(kX86Adc),
303 BinaryOpCode(kX86Sbb),
304 BinaryOpCode(kX86And),
305 BinaryOpCode(kX86Sub),
306 BinaryOpCode(kX86Xor),
307 BinaryOpCode(kX86Cmp),
308#undef BinaryOpCode
309 kX86Imul16RRI, kX86Imul16RMI, kX86Imul16RAI,
310 kX86Imul32RRI, kX86Imul32RMI, kX86Imul32RAI,
311 kX86Imul32RRI8, kX86Imul32RMI8, kX86Imul32RAI8,
312 kX86Mov8MR, kX86Mov8AR, kX86Mov8TR,
313 kX86Mov8RR, kX86Mov8RM, kX86Mov8RA, kX86Mov8RT,
314 kX86Mov8RI, kX86Mov8MI, kX86Mov8AI, kX86Mov8TI,
315 kX86Mov16MR, kX86Mov16AR, kX86Mov16TR,
316 kX86Mov16RR, kX86Mov16RM, kX86Mov16RA, kX86Mov16RT,
317 kX86Mov16RI, kX86Mov16MI, kX86Mov16AI, kX86Mov16TI,
318 kX86Mov32MR, kX86Mov32AR, kX86Mov32TR,
319 kX86Mov32RR, kX86Mov32RM, kX86Mov32RA, kX86Mov32RT,
320 kX86Mov32RI, kX86Mov32MI, kX86Mov32AI, kX86Mov32TI,
Mark Mendell4028a6c2014-02-19 20:06:20 -0800321 kX86Lea32RM,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700322 kX86Lea32RA,
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800323 // RRC - Register Register ConditionCode - cond_opcode reg1, reg2
324 // - lir operands - 0: reg1, 1: reg2, 2: CC
325 kX86Cmov32RRC,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700326 // RC - Register CL - opcode reg, CL
327 // - lir operands - 0: reg, 1: CL
328 // MC - Memory CL - opcode [base + disp], CL
329 // - lir operands - 0: base, 1: disp, 2: CL
330 // AC - Array CL - opcode [base + index * scale + disp], CL
331 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: CL
332#define BinaryShiftOpCode(opcode) \
333 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, \
334 opcode ## 8RC, opcode ## 8MC, opcode ## 8AC, \
335 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, \
336 opcode ## 16RC, opcode ## 16MC, opcode ## 16AC, \
337 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, \
338 opcode ## 32RC, opcode ## 32MC, opcode ## 32AC
339 BinaryShiftOpCode(kX86Rol),
340 BinaryShiftOpCode(kX86Ror),
341 BinaryShiftOpCode(kX86Rcl),
342 BinaryShiftOpCode(kX86Rcr),
343 BinaryShiftOpCode(kX86Sal),
344 BinaryShiftOpCode(kX86Shr),
345 BinaryShiftOpCode(kX86Sar),
346#undef BinaryShiftOpcode
347 kX86Cmc,
Mark Mendell4708dcd2014-01-22 09:05:18 -0800348 kX86Shld32RRI,
349 kX86Shrd32RRI,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700350#define UnaryOpcode(opcode, reg, mem, array) \
351 opcode ## 8 ## reg, opcode ## 8 ## mem, opcode ## 8 ## array, \
352 opcode ## 16 ## reg, opcode ## 16 ## mem, opcode ## 16 ## array, \
353 opcode ## 32 ## reg, opcode ## 32 ## mem, opcode ## 32 ## array
354 UnaryOpcode(kX86Test, RI, MI, AI),
355 kX86Test32RR,
356 UnaryOpcode(kX86Not, R, M, A),
357 UnaryOpcode(kX86Neg, R, M, A),
358 UnaryOpcode(kX86Mul, DaR, DaM, DaA),
359 UnaryOpcode(kX86Imul, DaR, DaM, DaA),
360 UnaryOpcode(kX86Divmod, DaR, DaM, DaA),
361 UnaryOpcode(kX86Idivmod, DaR, DaM, DaA),
Mark Mendell2bf31e62014-01-23 12:13:40 -0800362 kx86Cdq32Da,
Vladimir Markoa8b4caf2013-10-24 15:08:57 +0100363 kX86Bswap32R,
Vladimir Marko70b797d2013-12-03 15:25:24 +0000364 kX86Push32R, kX86Pop32R,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700365#undef UnaryOpcode
366#define Binary0fOpCode(opcode) \
367 opcode ## RR, opcode ## RM, opcode ## RA
368 Binary0fOpCode(kX86Movsd),
369 kX86MovsdMR,
370 kX86MovsdAR,
371 Binary0fOpCode(kX86Movss),
372 kX86MovssMR,
373 kX86MovssAR,
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700374 Binary0fOpCode(kX86Cvtsi2sd), // int to double
375 Binary0fOpCode(kX86Cvtsi2ss), // int to float
376 Binary0fOpCode(kX86Cvttsd2si), // truncating double to int
377 Binary0fOpCode(kX86Cvttss2si), // truncating float to int
378 Binary0fOpCode(kX86Cvtsd2si), // rounding double to int
379 Binary0fOpCode(kX86Cvtss2si), // rounding float to int
Brian Carlstrom7940e442013-07-12 13:46:57 -0700380 Binary0fOpCode(kX86Ucomisd), // unordered double compare
381 Binary0fOpCode(kX86Ucomiss), // unordered float compare
382 Binary0fOpCode(kX86Comisd), // double compare
383 Binary0fOpCode(kX86Comiss), // float compare
384 Binary0fOpCode(kX86Orps), // or of floating point registers
385 Binary0fOpCode(kX86Xorps), // xor of floating point registers
386 Binary0fOpCode(kX86Addsd), // double add
387 Binary0fOpCode(kX86Addss), // float add
388 Binary0fOpCode(kX86Mulsd), // double multiply
389 Binary0fOpCode(kX86Mulss), // float multiply
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700390 Binary0fOpCode(kX86Cvtsd2ss), // double to float
391 Binary0fOpCode(kX86Cvtss2sd), // float to double
Brian Carlstrom7940e442013-07-12 13:46:57 -0700392 Binary0fOpCode(kX86Subsd), // double subtract
393 Binary0fOpCode(kX86Subss), // float subtract
394 Binary0fOpCode(kX86Divsd), // double divide
395 Binary0fOpCode(kX86Divss), // float divide
Razvan A Lupusorud3266bc2014-01-24 12:55:31 -0800396 Binary0fOpCode(kX86Punpckldq), // Interleave low-order double words
Brian Carlstrom7940e442013-07-12 13:46:57 -0700397 kX86PsrlqRI, // right shift of floating point registers
398 kX86PsllqRI, // left shift of floating point registers
Mark Mendellbff1ef02013-12-13 13:47:34 -0800399 kX86SqrtsdRR, // sqrt of floating point register
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800400 kX86Fild32M, // push 32-bit integer on x87 stack
401 kX86Fild64M, // push 64-bit integer on x87 stack
402 kX86Fstp32M, // pop top x87 fp stack and do 32-bit store
403 kX86Fstp64M, // pop top x87 fp stack and do 64-bit store
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800404 Binary0fOpCode(kX86Movups), // load unaligned packed single FP values from xmm2/m128 to xmm1
405 kX86MovupsMR, kX86MovupsAR, // store unaligned packed single FP values from xmm1 to m128
406 Binary0fOpCode(kX86Movaps), // load aligned packed single FP values from xmm2/m128 to xmm1
407 kX86MovapsMR, kX86MovapsAR, // store aligned packed single FP values from xmm1 to m128
408 kX86MovlpsRM, kX86MovlpsRA, // load packed single FP values from m64 to low quadword of xmm
409 kX86MovlpsMR, kX86MovlpsAR, // store packed single FP values from low quadword of xmm to m64
410 kX86MovhpsRM, kX86MovhpsRA, // load packed single FP values from m64 to high quadword of xmm
411 kX86MovhpsMR, kX86MovhpsAR, // store packed single FP values from high quadword of xmm to m64
Brian Carlstrom7940e442013-07-12 13:46:57 -0700412 Binary0fOpCode(kX86Movdxr), // move into xmm from gpr
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700413 kX86MovdrxRR, kX86MovdrxMR, kX86MovdrxAR, // move into reg from xmm
414 kX86Set8R, kX86Set8M, kX86Set8A, // set byte depending on condition operand
Brian Carlstrom7940e442013-07-12 13:46:57 -0700415 kX86Mfence, // memory barrier
416 Binary0fOpCode(kX86Imul16), // 16bit multiply
417 Binary0fOpCode(kX86Imul32), // 32bit multiply
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700418 kX86CmpxchgRR, kX86CmpxchgMR, kX86CmpxchgAR, // compare and exchange
Vladimir Markoc29bb612013-11-27 16:47:25 +0000419 kX86LockCmpxchgMR, kX86LockCmpxchgAR, // locked compare and exchange
Vladimir Marko70b797d2013-12-03 15:25:24 +0000420 kX86LockCmpxchg8bM, kX86LockCmpxchg8bA, // locked compare and exchange
Razvan A Lupusoru99ad7232014-02-25 17:41:08 -0800421 kX86XchgMR, // exchange memory with register (automatically locked)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700422 Binary0fOpCode(kX86Movzx8), // zero-extend 8-bit value
423 Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value
424 Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value
425 Binary0fOpCode(kX86Movsx16), // sign-extend 16-bit value
426#undef Binary0fOpCode
427 kX86Jcc8, kX86Jcc32, // jCC rel8/32; lir operands - 0: rel, 1: CC, target assigned
428 kX86Jmp8, kX86Jmp32, // jmp rel8/32; lir operands - 0: rel, target assigned
429 kX86JmpR, // jmp reg; lir operands - 0: reg
Mark Mendell4028a6c2014-02-19 20:06:20 -0800430 kX86Jecxz8, // jcexz rel8; jump relative if ECX is zero.
Brian Carlstrom60d7a652014-03-13 18:10:08 -0700431 kX86JmpT, // jmp fs:[disp]; fs: is equal to Thread::Current(); lir operands - 0: disp
432
Brian Carlstrom7940e442013-07-12 13:46:57 -0700433 kX86CallR, // call reg; lir operands - 0: reg
434 kX86CallM, // call [base + disp]; lir operands - 0: base, 1: disp
435 kX86CallA, // call [base + index * scale + disp]
436 // lir operands - 0: base, 1: index, 2: scale, 3: disp
437 kX86CallT, // call fs:[disp]; fs: is equal to Thread::Current(); lir operands - 0: disp
Mark Mendell55d0eac2014-02-06 11:02:52 -0800438 kX86CallI, // call <relative> - 0: disp; Used for core.oat linking only
Brian Carlstrom7940e442013-07-12 13:46:57 -0700439 kX86Ret, // ret; no lir operands
440 kX86StartOfMethod, // call 0; pop reg; sub reg, # - generate start of method into reg
441 // lir operands - 0: reg
442 kX86PcRelLoadRA, // mov reg, [base + index * scale + PC relative displacement]
443 // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table
444 kX86PcRelAdr, // mov reg, PC relative displacement; lir operands - 0: reg, 1: table
Mark Mendell4028a6c2014-02-19 20:06:20 -0800445 kX86RepneScasw, // repne scasw
Brian Carlstrom7940e442013-07-12 13:46:57 -0700446 kX86Last
447};
448
449/* Instruction assembly field_loc kind */
450enum X86EncodingKind {
451 kData, // Special case for raw data.
452 kNop, // Special case for variable length nop.
453 kNullary, // Opcode that takes no arguments.
Mark Mendell4028a6c2014-02-19 20:06:20 -0800454 kPrefix2Nullary, // Opcode that takes no arguments, but 2 prefixes.
Vladimir Markoa8b4caf2013-10-24 15:08:57 +0100455 kRegOpcode, // Shorter form of R instruction kind (opcode+rd)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700456 kReg, kMem, kArray, // R, M and A instruction kinds.
457 kMemReg, kArrayReg, kThreadReg, // MR, AR and TR instruction kinds.
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700458 kRegReg, kRegMem, kRegArray, kRegThread, // RR, RM, RA and RT instruction kinds.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700459 kRegRegStore, // RR following the store modrm reg-reg encoding rather than the load.
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700460 kRegImm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700461 kRegRegImm, kRegMemImm, kRegArrayImm, // RRI, RMI and RAI instruction kinds.
462 kMovRegImm, // Shorter form move RI.
Mark Mendell4708dcd2014-01-22 09:05:18 -0800463 kRegRegImmRev, // RRI with first reg in r/m
Brian Carlstrom7940e442013-07-12 13:46:57 -0700464 kShiftRegImm, kShiftMemImm, kShiftArrayImm, // Shift opcode with immediate.
465 kShiftRegCl, kShiftMemCl, kShiftArrayCl, // Shift opcode with register CL.
466 kRegRegReg, kRegRegMem, kRegRegArray, // RRR, RRM, RRA instruction kinds.
467 kRegCond, kMemCond, kArrayCond, // R, M, A instruction kinds following by a condition.
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800468 kRegRegCond, // RR instruction kind followed by a condition.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700469 kJmp, kJcc, kCall, // Branch instruction kinds.
470 kPcRel, // Operation with displacement that is PC relative
471 kMacro, // An instruction composing multiple others
472 kUnimplemented // Encoding used when an instruction isn't yet implemented.
473};
474
475/* Struct used to define the EncodingMap positions for each X86 opcode */
476struct X86EncodingMap {
477 X86OpCode opcode; // e.g. kOpAddRI
478 X86EncodingKind kind; // Used to discriminate in the union below
479 uint64_t flags;
480 struct {
481 uint8_t prefix1; // non-zero => a prefix byte
482 uint8_t prefix2; // non-zero => a second prefix byte
483 uint8_t opcode; // 1 byte opcode
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700484 uint8_t extra_opcode1; // possible extra opcode byte
485 uint8_t extra_opcode2; // possible second extra opcode byte
Brian Carlstrom7940e442013-07-12 13:46:57 -0700486 // 3bit opcode that gets encoded in the register bits of the modrm byte, use determined by the
487 // encoding kind
488 uint8_t modrm_opcode;
489 uint8_t ax_opcode; // non-zero => shorter encoding for AX as a destination
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700490 uint8_t immediate_bytes; // number of bytes of immediate
Brian Carlstrom7940e442013-07-12 13:46:57 -0700491 } skeleton;
492 const char *name;
493 const char* fmt;
494};
495
496
497// FIXME: mem barrier type - what do we do for x86?
498#define kSY 0
499#define kST 0
500
501// Offsets of high and low halves of a 64bit value.
502#define LOWORD_OFFSET 0
503#define HIWORD_OFFSET 4
504
505// Segment override instruction prefix used for quick TLS access to Thread::Current().
506#define THREAD_PREFIX 0x64
507
508#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 127))
509#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32767))
510
511extern X86EncodingMap EncodingMap[kX86Last];
512extern X86ConditionCode X86ConditionEncoding(ConditionCode cond);
513
514} // namespace art
515
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700516#endif // ART_COMPILER_DEX_QUICK_X86_X86_LIR_H_