blob: d58f5874f9d3f34df5114e4398a4cad8a17c1c42 [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
buzbeeefc63692012-11-14 16:31:52 -080020#include "../../compiler_internals.h"
Ian Rogerse32ca232012-03-05 10:20:23 -080021
22namespace art {
23
Ian Rogerse32ca232012-03-05 10:20:23 -080024/*
25 * Runtime register conventions. We consider both x86, x86-64 and x32 (32bit mode x86-64), although
26 * we currently only target x86. The ABI has different conventions and we hope to have a single
27 * convention to simplify code generation. Changing something that is callee save and making it
28 * caller save places a burden on up-calls to save/restore the callee save register, however, there
29 * are few registers that are callee save in the ABI. Changing something that is caller save and
30 * making it callee save places a burden on down-calls to save/restore the callee save register.
Ian Rogersb41b33b2012-03-20 14:22:54 -070031 * For these reasons we aim to match native conventions for caller and callee save. The first 4
32 * registers can be used for byte operations, for this reason they are preferred for temporary
33 * scratch registers.
Ian Rogerse32ca232012-03-05 10:20:23 -080034 *
35 * General Purpose Register:
36 * Native: x86 | x86-64 / x32 | ART
37 * r0/eax: caller save | caller save | caller, Method*, scratch, return value
Ian Rogersb41b33b2012-03-20 14:22:54 -070038 * r1/ecx: caller save | caller save, arg4 | caller, arg1, scratch
39 * r2/edx: caller save | caller save, arg3 | caller, arg2, scratch, high half of long return
40 * r3/ebx: callEE save | callEE save | callER, arg3, scratch
Ian Rogerse32ca232012-03-05 10:20:23 -080041 * r4/esp: stack pointer
42 * r5/ebp: callee save | callee save | callee, available for dalvik register promotion
43 * r6/esi: callEE save | callER save, arg2 | callee, available for dalvik register promotion
44 * r7/edi: callEE save | callER save, arg1 | callee, available for dalvik register promotion
45 * --- x86-64/x32 registers
46 * Native: x86-64 / x32 | ART
47 * r8: caller save, arg5 | caller, scratch
48 * r9: caller save, arg6 | caller, scratch
49 * r10: caller save | caller, scratch
50 * r11: caller save | caller, scratch
51 * r12: callee save | callee, available for dalvik register promotion
52 * r13: callee save | callee, available for dalvik register promotion
53 * r14: callee save | callee, available for dalvik register promotion
54 * r15: callee save | callee, available for dalvik register promotion
55 *
56 * There is no rSELF, instead on x86 fs: has a base address of Thread::Current, whereas on
57 * x86-64/x32 gs: holds it.
58 *
59 * For floating point we don't support CPUs without SSE2 support (ie newer than PIII):
60 * Native: x86 | x86-64 / x32 | ART
61 * XMM0: caller save |caller save, arg1 | caller, float/double return value (except for native x86 code)
62 * XMM1: caller save |caller save, arg2 | caller, scratch
63 * XMM2: caller save |caller save, arg3 | caller, scratch
64 * XMM3: caller save |caller save, arg4 | caller, scratch
65 * XMM4: caller save |caller save, arg5 | caller, scratch
66 * XMM5: caller save |caller save, arg6 | caller, scratch
67 * XMM6: caller save |caller save, arg7 | caller, scratch
68 * XMM7: caller save |caller save, arg8 | caller, scratch
69 * --- x86-64/x32 registers
70 * XMM8 .. 15: caller save
71 *
72 * X87 is a necessary evil outside of ART code:
73 * ST0: x86 float/double native return value, caller save
74 * ST1 .. ST7: caller save
75 *
76 * Stack frame diagram (stack grows down, higher addresses at top):
77 *
78 * +------------------------+
79 * | IN[ins-1] | {Note: resides in caller's frame}
80 * | . |
81 * | IN[0] |
82 * | caller's Method* |
83 * +========================+ {Note: start of callee's frame}
84 * | return address | {pushed by call}
85 * | spill region | {variable sized}
86 * +------------------------+
87 * | ...filler word... | {Note: used as 2nd word of V[locals-1] if long]
88 * +------------------------+
89 * | V[locals-1] |
90 * | V[locals-2] |
91 * | . |
92 * | . |
93 * | V[1] |
94 * | V[0] |
95 * +------------------------+
96 * | 0 to 3 words padding |
97 * +------------------------+
98 * | OUT[outs-1] |
99 * | OUT[outs-2] |
100 * | . |
101 * | OUT[0] |
buzbeefa57c472012-11-21 12:06:18 -0800102 * | cur_method* | <<== sp w/ 16-byte alignment
Ian Rogerse32ca232012-03-05 10:20:23 -0800103 * +========================+
104 */
105
106/* Offset to distingish FP regs */
buzbeef0504cd2012-11-13 16:31:10 -0800107#define X86_FP_REG_OFFSET 32
Ian Rogerse32ca232012-03-05 10:20:23 -0800108/* Offset to distinguish DP FP regs */
buzbeef0504cd2012-11-13 16:31:10 -0800109#define X86_FP_DOUBLE (X86_FP_REG_OFFSET + 16)
Ian Rogerse32ca232012-03-05 10:20:23 -0800110/* Offset to distingish the extra regs */
buzbeef0504cd2012-11-13 16:31:10 -0800111#define X86_EXTRA_REG_OFFSET (X86_FP_DOUBLE + 16)
Ian Rogerse32ca232012-03-05 10:20:23 -0800112/* Reg types */
buzbeef0504cd2012-11-13 16:31:10 -0800113#define X86_REGTYPE(x) (x & (X86_FP_REG_OFFSET | X86_FP_DOUBLE))
114#define X86_FPREG(x) ((x & X86_FP_REG_OFFSET) == X86_FP_REG_OFFSET)
115#define X86_EXTRAREG(x) ((x & X86_EXTRA_REG_OFFSET) == X86_EXTRA_REG_OFFSET)
116#define X86_DOUBLEREG(x) ((x & X86_FP_DOUBLE) == X86_FP_DOUBLE)
117#define X86_SINGLEREG(x) (X86_FPREG(x) && !X86_DOUBLEREG(x))
Ian Rogersb5d09b22012-03-06 22:14:17 -0800118
Ian Rogerse32ca232012-03-05 10:20:23 -0800119/*
120 * Note: the low register of a floating point pair is sufficient to
121 * create the name of a double, but require both names to be passed to
122 * allow for asserts to verify that the pair is consecutive if significant
123 * rework is done in this area. Also, it is a good reminder in the calling
124 * code that reg locations always describe doubles as a pair of singles.
125 */
buzbeef0504cd2012-11-13 16:31:10 -0800126#define X86_S2D(x,y) ((x) | X86_FP_DOUBLE)
Ian Rogerse32ca232012-03-05 10:20:23 -0800127/* Mask to strip off fp flags */
buzbeef0504cd2012-11-13 16:31:10 -0800128#define X86_FP_REG_MASK 0xF
Ian Rogerse32ca232012-03-05 10:20:23 -0800129
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700130/* RegisterLocation templates return values (rAX, rAX/rDX or XMM0) */
buzbeefa57c472012-11-21 12:06:18 -0800131// location, wide, defined, const, fp, core, ref, high_word, home, low_reg, high_reg, s_reg_low
buzbeef0504cd2012-11-13 16:31:10 -0800132#define X86_LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, rAX, INVALID_REG, INVALID_SREG, INVALID_SREG}
133#define X86_LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, rAX, rDX, INVALID_SREG, INVALID_SREG}
134#define X86_LOC_C_RETURN_FLOAT {kLocPhysReg, 0, 0, 0, 1, 0, 0, 0, 1, fr0, INVALID_REG, INVALID_SREG, INVALID_SREG}
135#define X86_LOC_C_RETURN_DOUBLE {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1, fr0, fr1, INVALID_SREG, INVALID_SREG}
Ian Rogerse32ca232012-03-05 10:20:23 -0800136
buzbeeec137432012-11-13 12:13:16 -0800137enum X86ResourceEncodingPos {
138 kX86GPReg0 = 0,
139 kX86RegSP = 4,
140 kX86FPReg0 = 16, // xmm0 .. xmm7/xmm15
141 kX86FPRegEnd = 32,
142 kX86RegEnd = kX86FPRegEnd,
Elliott Hughes719ace42012-03-09 18:06:03 -0800143};
Ian Rogerse32ca232012-03-05 10:20:23 -0800144
buzbeeeaf09bc2012-11-15 14:51:41 -0800145#define ENCODE_X86_REG_LIST(N) (static_cast<uint64_t>(N))
buzbeeec137432012-11-13 12:13:16 -0800146#define ENCODE_X86_REG_SP (1ULL << kX86RegSP)
Ian Rogerse32ca232012-03-05 10:20:23 -0800147
148/*
149 * Annotate special-purpose core registers:
150 */
151
buzbeef0504cd2012-11-13 16:31:10 -0800152enum X86NativeRegisterPool {
Ian Rogerse32ca232012-03-05 10:20:23 -0800153 r0 = 0,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800154 rAX = r0,
Ian Rogerse32ca232012-03-05 10:20:23 -0800155 r1 = 1,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800156 rCX = r1,
Ian Rogerse32ca232012-03-05 10:20:23 -0800157 r2 = 2,
158 rDX = r2,
159 r3 = 3,
160 rBX = r3,
161 r4sp = 4,
buzbeef0504cd2012-11-13 16:31:10 -0800162 rX86_SP = r4sp,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800163 r4sib_no_index = r4sp,
Ian Rogerse32ca232012-03-05 10:20:23 -0800164 r5 = 5,
165 rBP = r5,
Ian Rogers7caad772012-03-30 01:07:54 -0700166 r5sib_no_base = r5,
Ian Rogerse32ca232012-03-05 10:20:23 -0800167 r6 = 6,
168 rSI = r6,
169 r7 = 7,
170 rDI = r7,
jeffhao703f2cd2012-07-13 17:25:52 -0700171#ifndef TARGET_REX_SUPPORT
172 rRET = 8, // fake return address register for core spill mask
173#else
Ian Rogerse32ca232012-03-05 10:20:23 -0800174 r8 = 8,
175 r9 = 9,
176 r10 = 10,
177 r11 = 11,
178 r12 = 12,
179 r13 = 13,
180 r14 = 14,
181 r15 = 15,
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700182 rRET = 16, // fake return address register for core spill mask
jeffhao703f2cd2012-07-13 17:25:52 -0700183#endif
buzbeef0504cd2012-11-13 16:31:10 -0800184 fr0 = 0 + X86_FP_REG_OFFSET,
185 fr1 = 1 + X86_FP_REG_OFFSET,
186 fr2 = 2 + X86_FP_REG_OFFSET,
187 fr3 = 3 + X86_FP_REG_OFFSET,
188 fr4 = 4 + X86_FP_REG_OFFSET,
189 fr5 = 5 + X86_FP_REG_OFFSET,
190 fr6 = 6 + X86_FP_REG_OFFSET,
191 fr7 = 7 + X86_FP_REG_OFFSET,
192 fr8 = 8 + X86_FP_REG_OFFSET,
193 fr9 = 9 + X86_FP_REG_OFFSET,
194 fr10 = 10 + X86_FP_REG_OFFSET,
195 fr11 = 11 + X86_FP_REG_OFFSET,
196 fr12 = 12 + X86_FP_REG_OFFSET,
197 fr13 = 13 + X86_FP_REG_OFFSET,
198 fr14 = 14 + X86_FP_REG_OFFSET,
199 fr15 = 15 + X86_FP_REG_OFFSET,
Elliott Hughes719ace42012-03-09 18:06:03 -0800200};
Ian Rogerse32ca232012-03-05 10:20:23 -0800201
202/*
203 * Target-independent aliases
204 */
205
buzbeef0504cd2012-11-13 16:31:10 -0800206#define rX86_ARG0 rAX
207#define rX86_ARG1 rCX
208#define rX86_ARG2 rDX
209#define rX86_ARG3 rBX
210#define rX86_FARG0 rAX
211#define rX86_FARG1 rCX
212#define rX86_FARG2 rDX
213#define rX86_FARG3 rBX
214#define rX86_RET0 rAX
215#define rX86_RET1 rDX
216#define rX86_INVOKE_TGT rAX
217#define rX86_LR INVALID_REG
218#define rX86_SUSPEND INVALID_REG
219#define rX86_SELF INVALID_REG
220#define rX86_COUNT rCX
221#define rX86_PC INVALID_REG
Ian Rogerse32ca232012-03-05 10:20:23 -0800222
Ian Rogerse32ca232012-03-05 10:20:23 -0800223/*
Ian Rogersde797832012-03-06 10:18:10 -0800224 * The following enum defines the list of supported X86 instructions by the
225 * assembler. Their corresponding EncodingMap positions will be defined in
226 * Assemble.cc.
Ian Rogerse32ca232012-03-05 10:20:23 -0800227 */
Elliott Hughes719ace42012-03-09 18:06:03 -0800228enum X86OpCode {
buzbeeb046e162012-10-30 15:48:42 -0700229 kX86First = 0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700230 kX8632BitData = kX86First, /* data [31..0] */
231 kX86Bkpt,
232 kX86Nop,
233 // Define groups of binary operations
234 // MR - Memory Register - opcode [base + disp], reg
235 // - lir operands - 0: base, 1: disp, 2: reg
236 // AR - Array Register - opcode [base + index * scale + disp], reg
237 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
238 // TR - Thread Register - opcode fs:[disp], reg - where fs: is equal to Thread::Current()
239 // - lir operands - 0: disp, 1: reg
240 // RR - Register Register - opcode reg1, reg2
241 // - lir operands - 0: reg1, 1: reg2
242 // RM - Register Memory - opcode reg, [base + disp]
243 // - lir operands - 0: reg, 1: base, 2: disp
244 // RA - Register Array - opcode reg, [base + index * scale + disp]
245 // - lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
246 // RT - Register Thread - opcode reg, fs:[disp] - where fs: is equal to Thread::Current()
247 // - lir operands - 0: reg, 1: disp
248 // RI - Register Immediate - opcode reg, #immediate
249 // - lir operands - 0: reg, 1: immediate
250 // MI - Memory Immediate - opcode [base + disp], #immediate
251 // - lir operands - 0: base, 1: disp, 2: immediate
252 // AI - Array Immediate - opcode [base + index * scale + disp], #immediate
253 // - lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
254 // TI - Thread Register - opcode fs:[disp], imm - where fs: is equal to Thread::Current()
255 // - lir operands - 0: disp, 1: imm
Ian Rogers96ab4202012-03-05 19:51:02 -0800256#define BinaryOpCode(opcode) \
Ian Rogersb5d09b22012-03-06 22:14:17 -0800257 opcode ## 8MR, opcode ## 8AR, opcode ## 8TR, \
258 opcode ## 8RR, opcode ## 8RM, opcode ## 8RA, opcode ## 8RT, \
259 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, opcode ## 8TI, \
260 opcode ## 16MR, opcode ## 16AR, opcode ## 16TR, \
261 opcode ## 16RR, opcode ## 16RM, opcode ## 16RA, opcode ## 16RT, \
262 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, opcode ## 16TI, \
263 opcode ## 16RI8, opcode ## 16MI8, opcode ## 16AI8, opcode ## 16TI8, \
264 opcode ## 32MR, opcode ## 32AR, opcode ## 32TR, \
265 opcode ## 32RR, opcode ## 32RM, opcode ## 32RA, opcode ## 32RT, \
266 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, opcode ## 32TI, \
267 opcode ## 32RI8, opcode ## 32MI8, opcode ## 32AI8, opcode ## 32TI8
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 BinaryOpCode(kX86Add),
269 BinaryOpCode(kX86Or),
270 BinaryOpCode(kX86Adc),
271 BinaryOpCode(kX86Sbb),
272 BinaryOpCode(kX86And),
273 BinaryOpCode(kX86Sub),
274 BinaryOpCode(kX86Xor),
275 BinaryOpCode(kX86Cmp),
Ian Rogers96ab4202012-03-05 19:51:02 -0800276#undef BinaryOpCode
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 kX86Imul16RRI, kX86Imul16RMI, kX86Imul16RAI,
278 kX86Imul32RRI, kX86Imul32RMI, kX86Imul32RAI,
279 kX86Imul32RRI8, kX86Imul32RMI8, kX86Imul32RAI8,
280 kX86Mov8MR, kX86Mov8AR, kX86Mov8TR,
281 kX86Mov8RR, kX86Mov8RM, kX86Mov8RA, kX86Mov8RT,
282 kX86Mov8RI, kX86Mov8MI, kX86Mov8AI, kX86Mov8TI,
283 kX86Mov16MR, kX86Mov16AR, kX86Mov16TR,
284 kX86Mov16RR, kX86Mov16RM, kX86Mov16RA, kX86Mov16RT,
285 kX86Mov16RI, kX86Mov16MI, kX86Mov16AI, kX86Mov16TI,
286 kX86Mov32MR, kX86Mov32AR, kX86Mov32TR,
287 kX86Mov32RR, kX86Mov32RM, kX86Mov32RA, kX86Mov32RT,
288 kX86Mov32RI, kX86Mov32MI, kX86Mov32AI, kX86Mov32TI,
289 kX86Lea32RA,
290 // RC - Register CL - opcode reg, CL
291 // - lir operands - 0: reg, 1: CL
292 // MC - Memory CL - opcode [base + disp], CL
293 // - lir operands - 0: base, 1: disp, 2: CL
294 // AC - Array CL - opcode [base + index * scale + disp], CL
295 // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: CL
Ian Rogersb5d09b22012-03-06 22:14:17 -0800296#define BinaryShiftOpCode(opcode) \
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, \
298 opcode ## 8RC, opcode ## 8MC, opcode ## 8AC, \
299 opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, \
300 opcode ## 16RC, opcode ## 16MC, opcode ## 16AC, \
301 opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, \
302 opcode ## 32RC, opcode ## 32MC, opcode ## 32AC
303 BinaryShiftOpCode(kX86Rol),
304 BinaryShiftOpCode(kX86Ror),
305 BinaryShiftOpCode(kX86Rcl),
306 BinaryShiftOpCode(kX86Rcr),
307 BinaryShiftOpCode(kX86Sal),
308 BinaryShiftOpCode(kX86Shr),
309 BinaryShiftOpCode(kX86Sar),
Ian Rogersb5d09b22012-03-06 22:14:17 -0800310#undef BinaryShiftOpcode
jeffhao77ae36b2012-08-07 14:18:16 -0700311 kX86Cmc,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800312#define UnaryOpcode(opcode, reg, mem, array) \
Bill Buzbeea114add2012-05-03 15:00:40 -0700313 opcode ## 8 ## reg, opcode ## 8 ## mem, opcode ## 8 ## array, \
314 opcode ## 16 ## reg, opcode ## 16 ## mem, opcode ## 16 ## array, \
315 opcode ## 32 ## reg, opcode ## 32 ## mem, opcode ## 32 ## array
316 UnaryOpcode(kX86Test, RI, MI, AI),
Ian Rogers2e9f7ed2012-09-26 11:30:43 -0700317 kX86Test32RR,
Bill Buzbeea114add2012-05-03 15:00:40 -0700318 UnaryOpcode(kX86Not, R, M, A),
319 UnaryOpcode(kX86Neg, R, M, A),
320 UnaryOpcode(kX86Mul, DaR, DaM, DaA),
321 UnaryOpcode(kX86Imul, DaR, DaM, DaA),
322 UnaryOpcode(kX86Divmod, DaR, DaM, DaA),
323 UnaryOpcode(kX86Idivmod, DaR, DaM, DaA),
Ian Rogersb5d09b22012-03-06 22:14:17 -0800324#undef UnaryOpcode
325#define Binary0fOpCode(opcode) \
326 opcode ## RR, opcode ## RM, opcode ## RA
Bill Buzbeea114add2012-05-03 15:00:40 -0700327 Binary0fOpCode(kX86Movsd),
328 kX86MovsdMR,
329 kX86MovsdAR,
330 Binary0fOpCode(kX86Movss),
331 kX86MovssMR,
332 kX86MovssAR,
333 Binary0fOpCode(kX86Cvtsi2sd), // int to double
334 Binary0fOpCode(kX86Cvtsi2ss), // int to float
335 Binary0fOpCode(kX86Cvttsd2si),// truncating double to int
336 Binary0fOpCode(kX86Cvttss2si),// truncating float to int
337 Binary0fOpCode(kX86Cvtsd2si), // rounding double to int
338 Binary0fOpCode(kX86Cvtss2si), // rounding float to int
339 Binary0fOpCode(kX86Ucomisd), // unordered double compare
340 Binary0fOpCode(kX86Ucomiss), // unordered float compare
341 Binary0fOpCode(kX86Comisd), // double compare
342 Binary0fOpCode(kX86Comiss), // float compare
343 Binary0fOpCode(kX86Orps), // or of floating point registers
344 Binary0fOpCode(kX86Xorps), // xor of floating point registers
345 Binary0fOpCode(kX86Addsd), // double add
346 Binary0fOpCode(kX86Addss), // float add
347 Binary0fOpCode(kX86Mulsd), // double multiply
348 Binary0fOpCode(kX86Mulss), // float multiply
Bill Buzbeea114add2012-05-03 15:00:40 -0700349 Binary0fOpCode(kX86Cvtsd2ss), // double to float
jeffhao292188d2012-05-17 15:45:04 -0700350 Binary0fOpCode(kX86Cvtss2sd), // float to double
Bill Buzbeea114add2012-05-03 15:00:40 -0700351 Binary0fOpCode(kX86Subsd), // double subtract
352 Binary0fOpCode(kX86Subss), // float subtract
353 Binary0fOpCode(kX86Divsd), // double divide
354 Binary0fOpCode(kX86Divss), // float divide
jeffhaofdffdf82012-07-11 16:08:43 -0700355 kX86PsrlqRI, // right shift of floating point registers
356 kX86PsllqRI, // left shift of floating point registers
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 Binary0fOpCode(kX86Movdxr), // move into xmm from gpr
jeffhaofdffdf82012-07-11 16:08:43 -0700358 kX86MovdrxRR, kX86MovdrxMR, kX86MovdrxAR,// move into reg from xmm
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 kX86Set8R, kX86Set8M, kX86Set8A,// set byte depending on condition operand
360 kX86Mfence, // memory barrier
361 Binary0fOpCode(kX86Imul16), // 16bit multiply
362 Binary0fOpCode(kX86Imul32), // 32bit multiply
jeffhao83025762012-08-02 11:08:56 -0700363 kX86CmpxchgRR, kX86CmpxchgMR, kX86CmpxchgAR,// compare and exchange
364 kX86LockCmpxchgRR, kX86LockCmpxchgMR, kX86LockCmpxchgAR,// locked compare and exchange
Bill Buzbeea114add2012-05-03 15:00:40 -0700365 Binary0fOpCode(kX86Movzx8), // zero-extend 8-bit value
366 Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value
367 Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value
368 Binary0fOpCode(kX86Movsx16), // sign-extend 16-bit value
Ian Rogersb5d09b22012-03-06 22:14:17 -0800369#undef Binary0fOpCode
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 kX86Jcc8, kX86Jcc32, // jCC rel8/32; lir operands - 0: rel, 1: CC, target assigned
371 kX86Jmp8, kX86Jmp32, // jmp rel8/32; lir operands - 0: rel, target assigned
372 kX86JmpR, // jmp reg; lir operands - 0: reg
373 kX86CallR, // call reg; lir operands - 0: reg
374 kX86CallM, // call [base + disp]; lir operands - 0: base, 1: disp
375 kX86CallA, // call [base + index * scale + disp]
376 // lir operands - 0: base, 1: index, 2: scale, 3: disp
377 kX86CallT, // call fs:[disp]; fs: is equal to Thread::Current(); lir operands - 0: disp
378 kX86Ret, // ret; no lir operands
379 kX86StartOfMethod, // call 0; pop reg; sub reg, # - generate start of method into reg
380 // lir operands - 0: reg
381 kX86PcRelLoadRA, // mov reg, [base + index * scale + PC relative displacement]
382 // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table
383 kX86PcRelAdr, // mov reg, PC relative displacement; lir operands - 0: reg, 1: table
384 kX86Last
Elliott Hughes719ace42012-03-09 18:06:03 -0800385};
Ian Rogerse32ca232012-03-05 10:20:23 -0800386
buzbeefa57c472012-11-21 12:06:18 -0800387/* Instruction assembly field_loc kind */
Elliott Hughes719ace42012-03-09 18:06:03 -0800388enum X86EncodingKind {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800389 kData, // Special case for raw data.
390 kNop, // Special case for variable length nop.
391 kNullary, // Opcode that takes no arguments.
392 kReg, kMem, kArray, // R, M and A instruction kinds.
393 kMemReg, kArrayReg, kThreadReg, // MR, AR and TR instruction kinds.
394 kRegReg, kRegMem, kRegArray, kRegThread, // RR, RM, RA and RT instruction kinds.
jeffhaofdffdf82012-07-11 16:08:43 -0700395 kRegRegStore, // RR following the store modrm reg-reg encoding rather than the load.
Ian Rogersb5d09b22012-03-06 22:14:17 -0800396 kRegImm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
397 kRegRegImm, kRegMemImm, kRegArrayImm, // RRI, RMI and RAI instruction kinds.
398 kMovRegImm, // Shorter form move RI.
399 kShiftRegImm, kShiftMemImm, kShiftArrayImm, // Shift opcode with immediate.
400 kShiftRegCl, kShiftMemCl, kShiftArrayCl, // Shift opcode with register CL.
401 kRegRegReg, kRegRegMem, kRegRegArray, // RRR, RRM, RRA instruction kinds.
402 kRegCond, kMemCond, kArrayCond, // R, M, A instruction kinds following by a condition.
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 kJmp, kJcc, kCall, // Branch instruction kinds.
404 kPcRel, // Operation with displacement that is PC relative
405 kMacro, // An instruction composing multiple others
406 kUnimplemented // Encoding used when an instruction isn't yet implemented.
Elliott Hughes719ace42012-03-09 18:06:03 -0800407};
Ian Rogersde797832012-03-06 10:18:10 -0800408
Ian Rogersde797832012-03-06 10:18:10 -0800409/* Struct used to define the EncodingMap positions for each X86 opcode */
Elliott Hughes719ace42012-03-09 18:06:03 -0800410struct X86EncodingMap {
Ian Rogersde797832012-03-06 10:18:10 -0800411 X86OpCode opcode; // e.g. kOpAddRI
412 X86EncodingKind kind; // Used to discriminate in the union below
buzbeeec137432012-11-13 12:13:16 -0800413 uint64_t flags;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800414 struct {
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 uint8_t prefix1; // non-zero => a prefix byte
416 uint8_t prefix2; // non-zero => a second prefix byte
417 uint8_t opcode; // 1 byte opcode
418 uint8_t extra_opcode1; // possible extra opcode byte
419 uint8_t extra_opcode2; // possible second extra opcode byte
420 // 3bit opcode that gets encoded in the register bits of the modrm byte, use determined by the
421 // encoding kind
422 uint8_t modrm_opcode;
423 uint8_t ax_opcode; // non-zero => shorter encoding for AX as a destination
424 uint8_t immediate_bytes; // number of bytes of immediate
Ian Rogersde797832012-03-06 10:18:10 -0800425 } skeleton;
426 const char *name;
427 const char* fmt;
Elliott Hughes719ace42012-03-09 18:06:03 -0800428};
Ian Rogersde797832012-03-06 10:18:10 -0800429
430extern X86EncodingMap EncodingMap[kX86Last];
431
buzbeea7678db2012-03-05 15:35:46 -0800432// FIXME: mem barrier type - what do we do for x86?
433#define kSY 0
434#define kST 0
435
Ian Rogersb5d09b22012-03-06 22:14:17 -0800436/* Offsets of high and low halves of a 64bit value */
437#define LOWORD_OFFSET 0
438#define HIWORD_OFFSET 4
439
440/* Segment override instruction prefix used for quick TLS access to Thread::Current() */
441#define THREAD_PREFIX 0x64
Ian Rogerse32ca232012-03-05 10:20:23 -0800442
Ian Rogersde797832012-03-06 10:18:10 -0800443#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 127))
Ian Rogersb5d09b22012-03-06 22:14:17 -0800444#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32767))
Ian Rogerse32ca232012-03-05 10:20:23 -0800445
446} // namespace art
447
448#endif // ART_COMPILER_COMPILER_CODEGEN_X86_X86LIR_H_