blob: 77d716fabc10b69d5401fbe4991726f3ea0eb3fd [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
Brian Carlstrom7940e442013-07-12 13:46:57 -0700105enum X86ResourceEncodingPos {
106 kX86GPReg0 = 0,
107 kX86RegSP = 4,
108 kX86FPReg0 = 16, // xmm0 .. xmm7/xmm15.
Serguei Katkove90501d2014-03-12 15:56:54 +0700109 kX86FPRegEnd = 32,
110 kX86FPStack = 33,
111 kX86RegEnd = kX86FPStack,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700112};
113
Brian Carlstrom7940e442013-07-12 13:46:57 -0700114#define ENCODE_X86_REG_SP (1ULL << kX86RegSP)
Serguei Katkove90501d2014-03-12 15:56:54 +0700115#define ENCODE_X86_FP_STACK (1ULL << kX86FPStack)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700116
buzbee091cc402014-03-31 10:14:40 -0700117// FIXME: for 64-bit, perhaps add an X86_64NativeRegisterPool enum?
Brian Carlstrom7940e442013-07-12 13:46:57 -0700118enum X86NativeRegisterPool {
buzbee091cc402014-03-31 10:14:40 -0700119 r0 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 0,
120 rAX = r0,
121 r1 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 1,
122 rCX = r1,
123 r2 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 2,
124 rDX = r2,
125 r3 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 3,
126 rBX = r3,
127 r4sp = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 4,
128 rX86_SP = r4sp,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700129 r4sib_no_index = r4sp,
buzbee091cc402014-03-31 10:14:40 -0700130 r5 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 5,
131 rBP = r5,
132 r5sib_no_base = r5,
133 r6 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 6,
134 rSI = r6,
135 r7 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 7,
136 rDI = r7,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700137#ifndef TARGET_REX_SUPPORT
buzbee091cc402014-03-31 10:14:40 -0700138 // fake return address register for core spill mask.
139 rRET = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 8,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700140#else
buzbee091cc402014-03-31 10:14:40 -0700141 r8 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 8,
142 r9 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 9,
143 r10 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 10,
144 r11 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 11,
145 r12 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 12,
146 r13 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 13,
147 r14 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 14,
148 r15 = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 15,
149 // fake return address register for core spill mask.
150 rRET = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 16,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700151#endif
buzbee091cc402014-03-31 10:14:40 -0700152
153 // xmm registers, single precision view
154 fr0 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 0,
155 fr1 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 1,
156 fr2 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 2,
157 fr3 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 3,
158 fr4 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 4,
159 fr5 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 5,
160 fr6 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 6,
161 fr7 = RegStorage::k32BitSolo | RegStorage::kFloatingPoint | 7,
162
163 // xmm registers, double precision alises
164 dr0 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 0,
165 dr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 1,
166 dr2 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 2,
167 dr3 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 3,
168 dr4 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 4,
169 dr5 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 5,
170 dr6 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 6,
171 dr7 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 7,
172
173 // xmm registers, quad precision alises
174 qr0 = RegStorage::k128BitSolo | RegStorage::kFloatingPoint | 0,
175 qr1 = RegStorage::k128BitSolo | RegStorage::kFloatingPoint | 1,
176 qr2 = RegStorage::k128BitSolo | RegStorage::kFloatingPoint | 2,
177 qr3 = RegStorage::k128BitSolo | RegStorage::kFloatingPoint | 3,
178 qr4 = RegStorage::k128BitSolo | RegStorage::kFloatingPoint | 4,
179 qr5 = RegStorage::k128BitSolo | RegStorage::kFloatingPoint | 5,
180 qr6 = RegStorage::k128BitSolo | RegStorage::kFloatingPoint | 6,
181 qr7 = RegStorage::k128BitSolo | RegStorage::kFloatingPoint | 7,
182
183 // TODO: as needed, add 256, 512 and 1024-bit xmm views.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700184};
185
buzbee091cc402014-03-31 10:14:40 -0700186constexpr RegStorage rs_r0(RegStorage::kValid | r0);
187constexpr RegStorage rs_rAX = rs_r0;
188constexpr RegStorage rs_r1(RegStorage::kValid | r1);
189constexpr RegStorage rs_rCX = rs_r1;
190constexpr RegStorage rs_r2(RegStorage::kValid | r2);
191constexpr RegStorage rs_rDX = rs_r2;
192constexpr RegStorage rs_r3(RegStorage::kValid | r3);
193constexpr RegStorage rs_rBX = rs_r3;
194constexpr RegStorage rs_r4sp(RegStorage::kValid | r4sp);
195constexpr RegStorage rs_rX86_SP = rs_r4sp;
196constexpr RegStorage rs_r5(RegStorage::kValid | r5);
197constexpr RegStorage rs_rBP = rs_r5;
198constexpr RegStorage rs_r6(RegStorage::kValid | r6);
199constexpr RegStorage rs_rSI = rs_r6;
200constexpr RegStorage rs_r7(RegStorage::kValid | r7);
201constexpr RegStorage rs_rDI = rs_r7;
202constexpr RegStorage rs_rRET(RegStorage::kValid | rRET);
203
204constexpr RegStorage rs_fr0(RegStorage::kValid | fr0);
205constexpr RegStorage rs_fr1(RegStorage::kValid | fr1);
206constexpr RegStorage rs_fr2(RegStorage::kValid | fr2);
207constexpr RegStorage rs_fr3(RegStorage::kValid | fr3);
208constexpr RegStorage rs_fr4(RegStorage::kValid | fr4);
209constexpr RegStorage rs_fr5(RegStorage::kValid | fr5);
210constexpr RegStorage rs_fr6(RegStorage::kValid | fr6);
211constexpr RegStorage rs_fr7(RegStorage::kValid | fr7);
212
213constexpr RegStorage rs_dr0(RegStorage::kValid | dr0);
214constexpr RegStorage rs_dr1(RegStorage::kValid | dr1);
215constexpr RegStorage rs_dr2(RegStorage::kValid | dr2);
216constexpr RegStorage rs_dr3(RegStorage::kValid | dr3);
217constexpr RegStorage rs_dr4(RegStorage::kValid | dr4);
218constexpr RegStorage rs_dr5(RegStorage::kValid | dr5);
219constexpr RegStorage rs_dr6(RegStorage::kValid | dr6);
220constexpr RegStorage rs_dr7(RegStorage::kValid | dr7);
221
222constexpr RegStorage rs_qr0(RegStorage::kValid | qr0);
223constexpr RegStorage rs_qr1(RegStorage::kValid | qr1);
224constexpr RegStorage rs_qr2(RegStorage::kValid | qr2);
225constexpr RegStorage rs_qr3(RegStorage::kValid | qr3);
226constexpr RegStorage rs_qr4(RegStorage::kValid | qr4);
227constexpr RegStorage rs_qr5(RegStorage::kValid | qr5);
228constexpr RegStorage rs_qr6(RegStorage::kValid | qr6);
229constexpr RegStorage rs_qr7(RegStorage::kValid | qr7);
buzbee2700f7e2014-03-07 09:46:20 -0800230
231// TODO: elminate these #defines?
Brian Carlstrom7940e442013-07-12 13:46:57 -0700232#define rX86_ARG0 rAX
buzbee2700f7e2014-03-07 09:46:20 -0800233#define rs_rX86_ARG0 rs_rAX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234#define rX86_ARG1 rCX
buzbee2700f7e2014-03-07 09:46:20 -0800235#define rs_rX86_ARG1 rs_rCX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700236#define rX86_ARG2 rDX
buzbee2700f7e2014-03-07 09:46:20 -0800237#define rs_rX86_ARG2 rs_rDX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700238#define rX86_ARG3 rBX
buzbee2700f7e2014-03-07 09:46:20 -0800239#define rs_rX86_ARG3 rs_rBX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240#define rX86_FARG0 rAX
buzbee2700f7e2014-03-07 09:46:20 -0800241#define rs_rX86_FARG0 rs_rAX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700242#define rX86_FARG1 rCX
buzbee2700f7e2014-03-07 09:46:20 -0800243#define rs_rX86_FARG1 rs_rCX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700244#define rX86_FARG2 rDX
buzbee2700f7e2014-03-07 09:46:20 -0800245#define rs_rX86_FARG2 rs_rDX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700246#define rX86_FARG3 rBX
buzbee2700f7e2014-03-07 09:46:20 -0800247#define rs_rX86_FARG3 rs_rBX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248#define rX86_RET0 rAX
buzbee2700f7e2014-03-07 09:46:20 -0800249#define rs_rX86_RET0 rs_rAX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700250#define rX86_RET1 rDX
buzbee2700f7e2014-03-07 09:46:20 -0800251#define rs_rX86_RET1 rs_rDX
Brian Carlstrom7940e442013-07-12 13:46:57 -0700252#define rX86_INVOKE_TGT rAX
buzbee2700f7e2014-03-07 09:46:20 -0800253#define rs_rX86_INVOKE_TGT rs_rAX
254#define rX86_LR RegStorage::kInvalidRegVal
255#define rX86_SUSPEND RegStorage::kInvalidRegVal
256#define rX86_SELF RegStorage::kInvalidRegVal
Brian Carlstrom7940e442013-07-12 13:46:57 -0700257#define rX86_COUNT rCX
buzbee2700f7e2014-03-07 09:46:20 -0800258#define rs_rX86_COUNT rs_rCX
259#define rX86_PC RegStorage::kInvalidRegVal
Brian Carlstrom7940e442013-07-12 13:46:57 -0700260
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000261// RegisterLocation templates return values (r_V0, or r_V0/r_V1).
262const RegLocation x86_loc_c_return
buzbee091cc402014-03-31 10:14:40 -0700263 {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1,
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000264 RegStorage(RegStorage::k32BitSolo, rAX), INVALID_SREG, INVALID_SREG};
265const RegLocation x86_loc_c_return_wide
buzbee091cc402014-03-31 10:14:40 -0700266 {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1,
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000267 RegStorage(RegStorage::k64BitPair, rAX, rDX), INVALID_SREG, INVALID_SREG};
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000268const RegLocation x86_loc_c_return_float
buzbee091cc402014-03-31 10:14:40 -0700269 {kLocPhysReg, 0, 0, 0, 1, 0, 0, 0, 1,
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000270 RegStorage(RegStorage::k32BitSolo, fr0), INVALID_SREG, INVALID_SREG};
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000271const RegLocation x86_loc_c_return_double
buzbee091cc402014-03-31 10:14:40 -0700272 {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1,
273 RegStorage(RegStorage::k64BitSolo, dr0), INVALID_SREG, INVALID_SREG};
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000274
Brian Carlstrom7940e442013-07-12 13:46:57 -0700275/*
276 * The following enum defines the list of supported X86 instructions by the
277 * assembler. Their corresponding EncodingMap positions will be defined in
278 * Assemble.cc.
279 */
280enum X86OpCode {
281 kX86First = 0,
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700282 kX8632BitData = kX86First, // data [31..0].
Brian Carlstrom7940e442013-07-12 13:46:57 -0700283 kX86Bkpt,
284 kX86Nop,
285 // Define groups of binary operations
286 // MR - Memory Register - opcode [base + disp], reg
287 // - lir operands - 0: base, 1: disp, 2: reg
288 // AR - Array Register - opcode [base + index * scale + disp], reg
289 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
290 // TR - Thread Register - opcode fs:[disp], reg - where fs: is equal to Thread::Current()
291 // - lir operands - 0: disp, 1: reg
292 // RR - Register Register - opcode reg1, reg2
293 // - lir operands - 0: reg1, 1: reg2
294 // RM - Register Memory - opcode reg, [base + disp]
295 // - lir operands - 0: reg, 1: base, 2: disp
296 // RA - Register Array - opcode reg, [base + index * scale + disp]
297 // - lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
298 // RT - Register Thread - opcode reg, fs:[disp] - where fs: is equal to Thread::Current()
299 // - lir operands - 0: reg, 1: disp
300 // RI - Register Immediate - opcode reg, #immediate
301 // - lir operands - 0: reg, 1: immediate
302 // MI - Memory Immediate - opcode [base + disp], #immediate
303 // - lir operands - 0: base, 1: disp, 2: immediate
304 // AI - Array Immediate - opcode [base + index * scale + disp], #immediate
305 // - lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
Vladimir Markoe6ed00b2013-10-24 14:52:37 +0100306 // TI - Thread Immediate - opcode fs:[disp], imm - where fs: is equal to Thread::Current()
Brian Carlstrom7940e442013-07-12 13:46:57 -0700307 // - lir operands - 0: disp, 1: imm
308#define BinaryOpCode(opcode) \
309 opcode ## 8MR, opcode ## 8AR, opcode ## 8TR, \
310 opcode ## 8RR, opcode ## 8RM, opcode ## 8RA, opcode ## 8RT, \
311 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, opcode ## 8TI, \
312 opcode ## 16MR, opcode ## 16AR, opcode ## 16TR, \
313 opcode ## 16RR, opcode ## 16RM, opcode ## 16RA, opcode ## 16RT, \
314 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, opcode ## 16TI, \
315 opcode ## 16RI8, opcode ## 16MI8, opcode ## 16AI8, opcode ## 16TI8, \
316 opcode ## 32MR, opcode ## 32AR, opcode ## 32TR, \
317 opcode ## 32RR, opcode ## 32RM, opcode ## 32RA, opcode ## 32RT, \
318 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, opcode ## 32TI, \
319 opcode ## 32RI8, opcode ## 32MI8, opcode ## 32AI8, opcode ## 32TI8
320 BinaryOpCode(kX86Add),
321 BinaryOpCode(kX86Or),
322 BinaryOpCode(kX86Adc),
323 BinaryOpCode(kX86Sbb),
324 BinaryOpCode(kX86And),
325 BinaryOpCode(kX86Sub),
326 BinaryOpCode(kX86Xor),
327 BinaryOpCode(kX86Cmp),
328#undef BinaryOpCode
329 kX86Imul16RRI, kX86Imul16RMI, kX86Imul16RAI,
330 kX86Imul32RRI, kX86Imul32RMI, kX86Imul32RAI,
331 kX86Imul32RRI8, kX86Imul32RMI8, kX86Imul32RAI8,
332 kX86Mov8MR, kX86Mov8AR, kX86Mov8TR,
333 kX86Mov8RR, kX86Mov8RM, kX86Mov8RA, kX86Mov8RT,
334 kX86Mov8RI, kX86Mov8MI, kX86Mov8AI, kX86Mov8TI,
335 kX86Mov16MR, kX86Mov16AR, kX86Mov16TR,
336 kX86Mov16RR, kX86Mov16RM, kX86Mov16RA, kX86Mov16RT,
337 kX86Mov16RI, kX86Mov16MI, kX86Mov16AI, kX86Mov16TI,
338 kX86Mov32MR, kX86Mov32AR, kX86Mov32TR,
339 kX86Mov32RR, kX86Mov32RM, kX86Mov32RA, kX86Mov32RT,
340 kX86Mov32RI, kX86Mov32MI, kX86Mov32AI, kX86Mov32TI,
Mark Mendell4028a6c2014-02-19 20:06:20 -0800341 kX86Lea32RM,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700342 kX86Lea32RA,
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800343 // RRC - Register Register ConditionCode - cond_opcode reg1, reg2
344 // - lir operands - 0: reg1, 1: reg2, 2: CC
345 kX86Cmov32RRC,
Mark Mendell2637f2e2014-04-30 10:10:47 -0400346 // RMC - Register Memory ConditionCode - cond_opcode reg1, [base + disp]
347 // - lir operands - 0: reg1, 1: base, 2: disp 3: CC
348 kX86Cmov32RMC,
349
Brian Carlstrom7940e442013-07-12 13:46:57 -0700350 // RC - Register CL - opcode reg, CL
351 // - lir operands - 0: reg, 1: CL
352 // MC - Memory CL - opcode [base + disp], CL
353 // - lir operands - 0: base, 1: disp, 2: CL
354 // AC - Array CL - opcode [base + index * scale + disp], CL
355 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: CL
356#define BinaryShiftOpCode(opcode) \
357 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, \
358 opcode ## 8RC, opcode ## 8MC, opcode ## 8AC, \
359 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, \
360 opcode ## 16RC, opcode ## 16MC, opcode ## 16AC, \
361 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, \
362 opcode ## 32RC, opcode ## 32MC, opcode ## 32AC
363 BinaryShiftOpCode(kX86Rol),
364 BinaryShiftOpCode(kX86Ror),
365 BinaryShiftOpCode(kX86Rcl),
366 BinaryShiftOpCode(kX86Rcr),
367 BinaryShiftOpCode(kX86Sal),
368 BinaryShiftOpCode(kX86Shr),
369 BinaryShiftOpCode(kX86Sar),
370#undef BinaryShiftOpcode
371 kX86Cmc,
Mark Mendell4708dcd2014-01-22 09:05:18 -0800372 kX86Shld32RRI,
Mark Mendell2637f2e2014-04-30 10:10:47 -0400373 kX86Shld32MRI,
Mark Mendell4708dcd2014-01-22 09:05:18 -0800374 kX86Shrd32RRI,
Mark Mendell2637f2e2014-04-30 10:10:47 -0400375 kX86Shrd32MRI,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700376#define UnaryOpcode(opcode, reg, mem, array) \
377 opcode ## 8 ## reg, opcode ## 8 ## mem, opcode ## 8 ## array, \
378 opcode ## 16 ## reg, opcode ## 16 ## mem, opcode ## 16 ## array, \
379 opcode ## 32 ## reg, opcode ## 32 ## mem, opcode ## 32 ## array
380 UnaryOpcode(kX86Test, RI, MI, AI),
381 kX86Test32RR,
382 UnaryOpcode(kX86Not, R, M, A),
383 UnaryOpcode(kX86Neg, R, M, A),
384 UnaryOpcode(kX86Mul, DaR, DaM, DaA),
385 UnaryOpcode(kX86Imul, DaR, DaM, DaA),
386 UnaryOpcode(kX86Divmod, DaR, DaM, DaA),
387 UnaryOpcode(kX86Idivmod, DaR, DaM, DaA),
Mark Mendell2bf31e62014-01-23 12:13:40 -0800388 kx86Cdq32Da,
Vladimir Markoa8b4caf2013-10-24 15:08:57 +0100389 kX86Bswap32R,
Vladimir Marko70b797d2013-12-03 15:25:24 +0000390 kX86Push32R, kX86Pop32R,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700391#undef UnaryOpcode
392#define Binary0fOpCode(opcode) \
393 opcode ## RR, opcode ## RM, opcode ## RA
394 Binary0fOpCode(kX86Movsd),
395 kX86MovsdMR,
396 kX86MovsdAR,
397 Binary0fOpCode(kX86Movss),
398 kX86MovssMR,
399 kX86MovssAR,
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700400 Binary0fOpCode(kX86Cvtsi2sd), // int to double
401 Binary0fOpCode(kX86Cvtsi2ss), // int to float
402 Binary0fOpCode(kX86Cvttsd2si), // truncating double to int
403 Binary0fOpCode(kX86Cvttss2si), // truncating float to int
404 Binary0fOpCode(kX86Cvtsd2si), // rounding double to int
405 Binary0fOpCode(kX86Cvtss2si), // rounding float to int
Brian Carlstrom7940e442013-07-12 13:46:57 -0700406 Binary0fOpCode(kX86Ucomisd), // unordered double compare
407 Binary0fOpCode(kX86Ucomiss), // unordered float compare
408 Binary0fOpCode(kX86Comisd), // double compare
409 Binary0fOpCode(kX86Comiss), // float compare
410 Binary0fOpCode(kX86Orps), // or of floating point registers
411 Binary0fOpCode(kX86Xorps), // xor of floating point registers
412 Binary0fOpCode(kX86Addsd), // double add
413 Binary0fOpCode(kX86Addss), // float add
414 Binary0fOpCode(kX86Mulsd), // double multiply
415 Binary0fOpCode(kX86Mulss), // float multiply
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700416 Binary0fOpCode(kX86Cvtsd2ss), // double to float
417 Binary0fOpCode(kX86Cvtss2sd), // float to double
Brian Carlstrom7940e442013-07-12 13:46:57 -0700418 Binary0fOpCode(kX86Subsd), // double subtract
419 Binary0fOpCode(kX86Subss), // float subtract
420 Binary0fOpCode(kX86Divsd), // double divide
421 Binary0fOpCode(kX86Divss), // float divide
Razvan A Lupusorud3266bc2014-01-24 12:55:31 -0800422 Binary0fOpCode(kX86Punpckldq), // Interleave low-order double words
Brian Carlstrom7940e442013-07-12 13:46:57 -0700423 kX86PsrlqRI, // right shift of floating point registers
424 kX86PsllqRI, // left shift of floating point registers
Mark Mendellbff1ef02013-12-13 13:47:34 -0800425 kX86SqrtsdRR, // sqrt of floating point register
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800426 kX86Fild32M, // push 32-bit integer on x87 stack
427 kX86Fild64M, // push 64-bit integer on x87 stack
428 kX86Fstp32M, // pop top x87 fp stack and do 32-bit store
429 kX86Fstp64M, // pop top x87 fp stack and do 64-bit store
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800430 Binary0fOpCode(kX86Movups), // load unaligned packed single FP values from xmm2/m128 to xmm1
431 kX86MovupsMR, kX86MovupsAR, // store unaligned packed single FP values from xmm1 to m128
432 Binary0fOpCode(kX86Movaps), // load aligned packed single FP values from xmm2/m128 to xmm1
433 kX86MovapsMR, kX86MovapsAR, // store aligned packed single FP values from xmm1 to m128
434 kX86MovlpsRM, kX86MovlpsRA, // load packed single FP values from m64 to low quadword of xmm
435 kX86MovlpsMR, kX86MovlpsAR, // store packed single FP values from low quadword of xmm to m64
436 kX86MovhpsRM, kX86MovhpsRA, // load packed single FP values from m64 to high quadword of xmm
437 kX86MovhpsMR, kX86MovhpsAR, // store packed single FP values from high quadword of xmm to m64
Brian Carlstrom7940e442013-07-12 13:46:57 -0700438 Binary0fOpCode(kX86Movdxr), // move into xmm from gpr
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700439 kX86MovdrxRR, kX86MovdrxMR, kX86MovdrxAR, // move into reg from xmm
440 kX86Set8R, kX86Set8M, kX86Set8A, // set byte depending on condition operand
Brian Carlstrom7940e442013-07-12 13:46:57 -0700441 kX86Mfence, // memory barrier
442 Binary0fOpCode(kX86Imul16), // 16bit multiply
443 Binary0fOpCode(kX86Imul32), // 32bit multiply
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700444 kX86CmpxchgRR, kX86CmpxchgMR, kX86CmpxchgAR, // compare and exchange
Vladimir Markoc29bb612013-11-27 16:47:25 +0000445 kX86LockCmpxchgMR, kX86LockCmpxchgAR, // locked compare and exchange
Vladimir Marko70b797d2013-12-03 15:25:24 +0000446 kX86LockCmpxchg8bM, kX86LockCmpxchg8bA, // locked compare and exchange
Razvan A Lupusoru99ad7232014-02-25 17:41:08 -0800447 kX86XchgMR, // exchange memory with register (automatically locked)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700448 Binary0fOpCode(kX86Movzx8), // zero-extend 8-bit value
449 Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value
450 Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value
451 Binary0fOpCode(kX86Movsx16), // sign-extend 16-bit value
452#undef Binary0fOpCode
453 kX86Jcc8, kX86Jcc32, // jCC rel8/32; lir operands - 0: rel, 1: CC, target assigned
454 kX86Jmp8, kX86Jmp32, // jmp rel8/32; lir operands - 0: rel, target assigned
455 kX86JmpR, // jmp reg; lir operands - 0: reg
Mark Mendell4028a6c2014-02-19 20:06:20 -0800456 kX86Jecxz8, // jcexz rel8; jump relative if ECX is zero.
Brian Carlstrom60d7a652014-03-13 18:10:08 -0700457 kX86JmpT, // jmp fs:[disp]; fs: is equal to Thread::Current(); lir operands - 0: disp
458
Brian Carlstrom7940e442013-07-12 13:46:57 -0700459 kX86CallR, // call reg; lir operands - 0: reg
460 kX86CallM, // call [base + disp]; lir operands - 0: base, 1: disp
461 kX86CallA, // call [base + index * scale + disp]
462 // lir operands - 0: base, 1: index, 2: scale, 3: disp
463 kX86CallT, // call fs:[disp]; fs: is equal to Thread::Current(); lir operands - 0: disp
Mark Mendell55d0eac2014-02-06 11:02:52 -0800464 kX86CallI, // call <relative> - 0: disp; Used for core.oat linking only
Brian Carlstrom7940e442013-07-12 13:46:57 -0700465 kX86Ret, // ret; no lir operands
466 kX86StartOfMethod, // call 0; pop reg; sub reg, # - generate start of method into reg
467 // lir operands - 0: reg
468 kX86PcRelLoadRA, // mov reg, [base + index * scale + PC relative displacement]
469 // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table
470 kX86PcRelAdr, // mov reg, PC relative displacement; lir operands - 0: reg, 1: table
Mark Mendell4028a6c2014-02-19 20:06:20 -0800471 kX86RepneScasw, // repne scasw
Brian Carlstrom7940e442013-07-12 13:46:57 -0700472 kX86Last
473};
474
475/* Instruction assembly field_loc kind */
476enum X86EncodingKind {
477 kData, // Special case for raw data.
478 kNop, // Special case for variable length nop.
479 kNullary, // Opcode that takes no arguments.
Mark Mendell4028a6c2014-02-19 20:06:20 -0800480 kPrefix2Nullary, // Opcode that takes no arguments, but 2 prefixes.
Vladimir Markoa8b4caf2013-10-24 15:08:57 +0100481 kRegOpcode, // Shorter form of R instruction kind (opcode+rd)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700482 kReg, kMem, kArray, // R, M and A instruction kinds.
483 kMemReg, kArrayReg, kThreadReg, // MR, AR and TR instruction kinds.
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700484 kRegReg, kRegMem, kRegArray, kRegThread, // RR, RM, RA and RT instruction kinds.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700485 kRegRegStore, // RR following the store modrm reg-reg encoding rather than the load.
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700486 kRegImm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700487 kRegRegImm, kRegMemImm, kRegArrayImm, // RRI, RMI and RAI instruction kinds.
488 kMovRegImm, // Shorter form move RI.
Mark Mendell4708dcd2014-01-22 09:05:18 -0800489 kRegRegImmRev, // RRI with first reg in r/m
Mark Mendell2637f2e2014-04-30 10:10:47 -0400490 kMemRegImm, // MRI instruction kinds.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700491 kShiftRegImm, kShiftMemImm, kShiftArrayImm, // Shift opcode with immediate.
492 kShiftRegCl, kShiftMemCl, kShiftArrayCl, // Shift opcode with register CL.
493 kRegRegReg, kRegRegMem, kRegRegArray, // RRR, RRM, RRA instruction kinds.
494 kRegCond, kMemCond, kArrayCond, // R, M, A instruction kinds following by a condition.
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800495 kRegRegCond, // RR instruction kind followed by a condition.
Mark Mendell2637f2e2014-04-30 10:10:47 -0400496 kRegMemCond, // RM instruction kind followed by a condition.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700497 kJmp, kJcc, kCall, // Branch instruction kinds.
498 kPcRel, // Operation with displacement that is PC relative
499 kMacro, // An instruction composing multiple others
500 kUnimplemented // Encoding used when an instruction isn't yet implemented.
501};
502
503/* Struct used to define the EncodingMap positions for each X86 opcode */
504struct X86EncodingMap {
505 X86OpCode opcode; // e.g. kOpAddRI
506 X86EncodingKind kind; // Used to discriminate in the union below
507 uint64_t flags;
508 struct {
509 uint8_t prefix1; // non-zero => a prefix byte
510 uint8_t prefix2; // non-zero => a second prefix byte
511 uint8_t opcode; // 1 byte opcode
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700512 uint8_t extra_opcode1; // possible extra opcode byte
513 uint8_t extra_opcode2; // possible second extra opcode byte
Brian Carlstrom7940e442013-07-12 13:46:57 -0700514 // 3bit opcode that gets encoded in the register bits of the modrm byte, use determined by the
515 // encoding kind
516 uint8_t modrm_opcode;
517 uint8_t ax_opcode; // non-zero => shorter encoding for AX as a destination
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700518 uint8_t immediate_bytes; // number of bytes of immediate
Brian Carlstrom7940e442013-07-12 13:46:57 -0700519 } skeleton;
520 const char *name;
521 const char* fmt;
522};
523
524
525// FIXME: mem barrier type - what do we do for x86?
526#define kSY 0
527#define kST 0
528
529// Offsets of high and low halves of a 64bit value.
530#define LOWORD_OFFSET 0
531#define HIWORD_OFFSET 4
532
533// Segment override instruction prefix used for quick TLS access to Thread::Current().
534#define THREAD_PREFIX 0x64
535
536#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 127))
537#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32767))
538
539extern X86EncodingMap EncodingMap[kX86Last];
540extern X86ConditionCode X86ConditionEncoding(ConditionCode cond);
541
542} // namespace art
543
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700544#endif // ART_COMPILER_DEX_QUICK_X86_X86_LIR_H_