blob: 64343e502120a70198e9f17ac0ba0c133eef4649 [file] [log] [blame]
buzbeeefc63692012-11-14 16:31:52 -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#include "../../compiler_internals.h"
18#include "x86_lir.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080019#include "../ralloc_util.h"
20#include "../codegen_util.h"
buzbeeefc63692012-11-14 16:31:52 -080021
22#include <string>
23
24namespace art {
25
26//FIXME: restore "static" when usage uncovered
27/*static*/ int coreRegs[] = {
28 rAX, rCX, rDX, rBX, rX86_SP, rBP, rSI, rDI
29#ifdef TARGET_REX_SUPPORT
30 r8, r9, r10, r11, r12, r13, r14, 15
31#endif
32};
buzbee52a77fc2012-11-20 19:50:46 -080033/*static*/ int ReservedRegs[] = {rX86_SP};
buzbeeefc63692012-11-14 16:31:52 -080034/*static*/ int coreTemps[] = {rAX, rCX, rDX, rBX};
buzbee52a77fc2012-11-20 19:50:46 -080035/*static*/ int FpRegs[] = {
buzbeeefc63692012-11-14 16:31:52 -080036 fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
37#ifdef TARGET_REX_SUPPORT
38 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15
39#endif
40};
41/*static*/ int fpTemps[] = {
42 fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
43#ifdef TARGET_REX_SUPPORT
44 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15
45#endif
46};
47
buzbee52a77fc2012-11-20 19:50:46 -080048RegLocation LocCReturn()
buzbeeefc63692012-11-14 16:31:52 -080049{
50 RegLocation res = X86_LOC_C_RETURN;
51 return res;
52}
53
buzbee52a77fc2012-11-20 19:50:46 -080054RegLocation LocCReturnWide()
buzbeeefc63692012-11-14 16:31:52 -080055{
56 RegLocation res = X86_LOC_C_RETURN_WIDE;
57 return res;
58}
59
buzbee52a77fc2012-11-20 19:50:46 -080060RegLocation LocCReturnFloat()
buzbeeefc63692012-11-14 16:31:52 -080061{
62 RegLocation res = X86_LOC_C_RETURN_FLOAT;
63 return res;
64}
65
buzbee52a77fc2012-11-20 19:50:46 -080066RegLocation LocCReturnDouble()
buzbeeefc63692012-11-14 16:31:52 -080067{
68 RegLocation res = X86_LOC_C_RETURN_DOUBLE;
69 return res;
70}
71
72// Return a target-dependent special register.
buzbee52a77fc2012-11-20 19:50:46 -080073int TargetReg(SpecialTargetRegister reg) {
buzbeeefc63692012-11-14 16:31:52 -080074 int res = INVALID_REG;
75 switch (reg) {
76 case kSelf: res = rX86_SELF; break;
77 case kSuspend: res = rX86_SUSPEND; break;
78 case kLr: res = rX86_LR; break;
79 case kPc: res = rX86_PC; break;
80 case kSp: res = rX86_SP; break;
81 case kArg0: res = rX86_ARG0; break;
82 case kArg1: res = rX86_ARG1; break;
83 case kArg2: res = rX86_ARG2; break;
84 case kArg3: res = rX86_ARG3; break;
85 case kFArg0: res = rX86_FARG0; break;
86 case kFArg1: res = rX86_FARG1; break;
87 case kFArg2: res = rX86_FARG2; break;
88 case kFArg3: res = rX86_FARG3; break;
89 case kRet0: res = rX86_RET0; break;
90 case kRet1: res = rX86_RET1; break;
91 case kInvokeTgt: res = rX86_INVOKE_TGT; break;
92 case kCount: res = rX86_COUNT; break;
93 }
94 return res;
95}
96
97// Create a double from a pair of singles.
buzbee52a77fc2012-11-20 19:50:46 -080098int S2d(int lowReg, int highReg)
buzbeeefc63692012-11-14 16:31:52 -080099{
100 return X86_S2D(lowReg, highReg);
101}
102
103// Is reg a single or double?
buzbee52a77fc2012-11-20 19:50:46 -0800104bool FpReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -0800105{
106 return X86_FPREG(reg);
107}
108
109// Is reg a single?
buzbee52a77fc2012-11-20 19:50:46 -0800110bool SingleReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -0800111{
112 return X86_SINGLEREG(reg);
113}
114
115// Is reg a double?
buzbee52a77fc2012-11-20 19:50:46 -0800116bool DoubleReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -0800117{
118 return X86_DOUBLEREG(reg);
119}
120
121// Return mask to strip off fp reg flags and bias.
buzbee52a77fc2012-11-20 19:50:46 -0800122uint32_t FpRegMask()
buzbeeefc63692012-11-14 16:31:52 -0800123{
124 return X86_FP_REG_MASK;
125}
126
127// True if both regs single, both core or both double.
buzbee52a77fc2012-11-20 19:50:46 -0800128bool SameRegType(int reg1, int reg2)
buzbeeefc63692012-11-14 16:31:52 -0800129{
130 return (X86_REGTYPE(reg1) == X86_REGTYPE(reg2));
131}
132
133/*
134 * Decode the register id.
135 */
buzbee52a77fc2012-11-20 19:50:46 -0800136uint64_t GetRegMaskCommon(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800137{
buzbeeeaf09bc2012-11-15 14:51:41 -0800138 uint64_t seed;
buzbeeefc63692012-11-14 16:31:52 -0800139 int shift;
140 int regId;
141
142 regId = reg & 0xf;
143 /* Double registers in x86 are just a single FP register */
144 seed = 1;
145 /* FP register starts at bit position 16 */
146 shift = X86_FPREG(reg) ? kX86FPReg0 : 0;
147 /* Expand the double register id into single offset */
148 shift += regId;
149 return (seed << shift);
150}
151
buzbee52a77fc2012-11-20 19:50:46 -0800152uint64_t GetPCUseDefEncoding()
buzbeeefc63692012-11-14 16:31:52 -0800153{
154 /*
155 * FIXME: might make sense to use a virtual resource encoding bit for pc. Might be
156 * able to clean up some of the x86/Arm_Mips differences
157 */
buzbee52a77fc2012-11-20 19:50:46 -0800158 LOG(FATAL) << "Unexpected call to GetPCUseDefEncoding for x86";
buzbeeefc63692012-11-14 16:31:52 -0800159 return 0ULL;
160}
161
buzbee52a77fc2012-11-20 19:50:46 -0800162void SetupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir)
buzbeeefc63692012-11-14 16:31:52 -0800163{
164 DCHECK_EQ(cUnit->instructionSet, kX86);
165
166 // X86-specific resource map setup here.
167 uint64_t flags = EncodingMap[lir->opcode].flags;
168
169 if (flags & REG_USE_SP) {
170 lir->useMask |= ENCODE_X86_REG_SP;
171 }
172
173 if (flags & REG_DEF_SP) {
174 lir->defMask |= ENCODE_X86_REG_SP;
175 }
176
177 if (flags & REG_DEFA) {
buzbee52a77fc2012-11-20 19:50:46 -0800178 SetupRegMask(cUnit, &lir->defMask, rAX);
buzbeeefc63692012-11-14 16:31:52 -0800179 }
180
181 if (flags & REG_DEFD) {
buzbee52a77fc2012-11-20 19:50:46 -0800182 SetupRegMask(cUnit, &lir->defMask, rDX);
buzbeeefc63692012-11-14 16:31:52 -0800183 }
184 if (flags & REG_USEA) {
buzbee52a77fc2012-11-20 19:50:46 -0800185 SetupRegMask(cUnit, &lir->useMask, rAX);
buzbeeefc63692012-11-14 16:31:52 -0800186 }
187
188 if (flags & REG_USEC) {
buzbee52a77fc2012-11-20 19:50:46 -0800189 SetupRegMask(cUnit, &lir->useMask, rCX);
buzbeeefc63692012-11-14 16:31:52 -0800190 }
191
192 if (flags & REG_USED) {
buzbee52a77fc2012-11-20 19:50:46 -0800193 SetupRegMask(cUnit, &lir->useMask, rDX);
buzbeeefc63692012-11-14 16:31:52 -0800194 }
195}
196
197/* For dumping instructions */
198static const char* x86RegName[] = {
199 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
200 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
201};
202
203static const char* x86CondName[] = {
204 "O",
205 "NO",
206 "B/NAE/C",
207 "NB/AE/NC",
208 "Z/EQ",
209 "NZ/NE",
210 "BE/NA",
211 "NBE/A",
212 "S",
213 "NS",
214 "P/PE",
215 "NP/PO",
216 "L/NGE",
217 "NL/GE",
218 "LE/NG",
219 "NLE/G"
220};
221
222/*
223 * Interpret a format string and build a string no longer than size
224 * See format key in Assemble.cc.
225 */
buzbee52a77fc2012-11-20 19:50:46 -0800226std::string BuildInsnString(const char *fmt, LIR *lir, unsigned char* baseAddr) {
buzbeeefc63692012-11-14 16:31:52 -0800227 std::string buf;
228 size_t i = 0;
229 size_t fmt_len = strlen(fmt);
230 while (i < fmt_len) {
231 if (fmt[i] != '!') {
232 buf += fmt[i];
233 i++;
234 } else {
235 i++;
236 DCHECK_LT(i, fmt_len);
237 char operand_number_ch = fmt[i];
238 i++;
239 if (operand_number_ch == '!') {
240 buf += "!";
241 } else {
242 int operand_number = operand_number_ch - '0';
243 DCHECK_LT(operand_number, 6); // Expect upto 6 LIR operands.
244 DCHECK_LT(i, fmt_len);
245 int operand = lir->operands[operand_number];
246 switch (fmt[i]) {
247 case 'c':
248 DCHECK_LT(static_cast<size_t>(operand), sizeof(x86CondName));
249 buf += x86CondName[operand];
250 break;
251 case 'd':
252 buf += StringPrintf("%d", operand);
253 break;
254 case 'p': {
255 SwitchTable *tabRec = reinterpret_cast<SwitchTable*>(operand);
256 buf += StringPrintf("0x%08x", tabRec->offset);
257 break;
258 }
259 case 'r':
260 if (X86_FPREG(operand) || X86_DOUBLEREG(operand)) {
261 int fp_reg = operand & X86_FP_REG_MASK;
262 buf += StringPrintf("xmm%d", fp_reg);
263 } else {
264 DCHECK_LT(static_cast<size_t>(operand), sizeof(x86RegName));
265 buf += x86RegName[operand];
266 }
267 break;
268 case 't':
269 buf += StringPrintf("0x%08x (L%p)",
270 reinterpret_cast<uint32_t>(baseAddr)
271 + lir->offset + operand, lir->target);
272 break;
273 default:
274 buf += StringPrintf("DecodeError '%c'", fmt[i]);
275 break;
276 }
277 i++;
278 }
279 }
280 }
281 return buf;
282}
283
buzbee52a77fc2012-11-20 19:50:46 -0800284void DumpResourceMask(LIR *x86LIR, uint64_t mask, const char *prefix)
buzbeeefc63692012-11-14 16:31:52 -0800285{
286 char buf[256];
287 buf[0] = 0;
buzbeeefc63692012-11-14 16:31:52 -0800288
289 if (mask == ENCODE_ALL) {
290 strcpy(buf, "all");
291 } else {
292 char num[8];
293 int i;
294
295 for (i = 0; i < kX86RegEnd; i++) {
296 if (mask & (1ULL << i)) {
297 sprintf(num, "%d ", i);
298 strcat(buf, num);
299 }
300 }
301
302 if (mask & ENCODE_CCODE) {
303 strcat(buf, "cc ");
304 }
305 /* Memory bits */
306 if (x86LIR && (mask & ENCODE_DALVIK_REG)) {
307 sprintf(buf + strlen(buf), "dr%d%s", x86LIR->aliasInfo & 0xffff,
308 (x86LIR->aliasInfo & 0x80000000) ? "(+1)" : "");
309 }
310 if (mask & ENCODE_LITERAL) {
311 strcat(buf, "lit ");
312 }
313
314 if (mask & ENCODE_HEAP_REF) {
315 strcat(buf, "heap ");
316 }
317 if (mask & ENCODE_MUST_NOT_ALIAS) {
318 strcat(buf, "noalias ");
319 }
320 }
321 if (buf[0]) {
322 LOG(INFO) << prefix << ": " << buf;
323 }
324}
buzbee52a77fc2012-11-20 19:50:46 -0800325void AdjustSpillMask(CompilationUnit* cUnit) {
buzbeeefc63692012-11-14 16:31:52 -0800326 // Adjustment for LR spilling, x86 has no LR so nothing to do here
327 cUnit->coreSpillMask |= (1 << rRET);
328 cUnit->numCoreSpills++;
329}
330
331/*
332 * Mark a callee-save fp register as promoted. Note that
333 * vpush/vpop uses contiguous register lists so we must
334 * include any holes in the mask. Associate holes with
335 * Dalvik register INVALID_VREG (0xFFFFU).
336 */
buzbee52a77fc2012-11-20 19:50:46 -0800337void MarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800338{
buzbee52a77fc2012-11-20 19:50:46 -0800339 UNIMPLEMENTED(WARNING) << "MarkPreservedSingle";
buzbeeefc63692012-11-14 16:31:52 -0800340#if 0
341 LOG(FATAL) << "No support yet for promoted FP regs";
342#endif
343}
344
buzbee52a77fc2012-11-20 19:50:46 -0800345void FlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
buzbeeefc63692012-11-14 16:31:52 -0800346{
buzbee52a77fc2012-11-20 19:50:46 -0800347 RegisterInfo* info1 = GetRegInfo(cUnit, reg1);
348 RegisterInfo* info2 = GetRegInfo(cUnit, reg2);
buzbeeefc63692012-11-14 16:31:52 -0800349 DCHECK(info1 && info2 && info1->pair && info2->pair &&
350 (info1->partner == info2->reg) &&
351 (info2->partner == info1->reg));
352 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
353 if (!(info1->isTemp && info2->isTemp)) {
354 /* Should not happen. If it does, there's a problem in evalLoc */
355 LOG(FATAL) << "Long half-temp, half-promoted";
356 }
357
358 info1->dirty = false;
359 info2->dirty = false;
360 if (SRegToVReg(cUnit, info2->sReg) < SRegToVReg(cUnit, info1->sReg))
361 info1 = info2;
362 int vReg = SRegToVReg(cUnit, info1->sReg);
buzbee52a77fc2012-11-20 19:50:46 -0800363 StoreBaseDispWide(cUnit, rX86_SP, VRegOffset(cUnit, vReg), info1->reg, info1->partner);
buzbeeefc63692012-11-14 16:31:52 -0800364 }
365}
366
buzbee52a77fc2012-11-20 19:50:46 -0800367void FlushReg(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800368{
buzbee52a77fc2012-11-20 19:50:46 -0800369 RegisterInfo* info = GetRegInfo(cUnit, reg);
buzbeeefc63692012-11-14 16:31:52 -0800370 if (info->live && info->dirty) {
371 info->dirty = false;
372 int vReg = SRegToVReg(cUnit, info->sReg);
buzbee52a77fc2012-11-20 19:50:46 -0800373 StoreBaseDisp(cUnit, rX86_SP, VRegOffset(cUnit, vReg), reg, kWord);
buzbeeefc63692012-11-14 16:31:52 -0800374 }
375}
376
377/* Give access to the target-dependent FP register encoding to common code */
buzbee52a77fc2012-11-20 19:50:46 -0800378bool IsFpReg(int reg) {
buzbeeefc63692012-11-14 16:31:52 -0800379 return X86_FPREG(reg);
380}
381
buzbeeefc63692012-11-14 16:31:52 -0800382/* Clobber all regs that might be used by an external C call */
buzbee52a77fc2012-11-20 19:50:46 -0800383extern void ClobberCalleeSave(CompilationUnit *cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800384{
buzbee52a77fc2012-11-20 19:50:46 -0800385 Clobber(cUnit, rAX);
386 Clobber(cUnit, rCX);
387 Clobber(cUnit, rDX);
buzbeeefc63692012-11-14 16:31:52 -0800388}
389
buzbee52a77fc2012-11-20 19:50:46 -0800390extern RegLocation GetReturnWideAlt(CompilationUnit* cUnit) {
391 RegLocation res = LocCReturnWide();
buzbeeefc63692012-11-14 16:31:52 -0800392 CHECK(res.lowReg == rAX);
393 CHECK(res.highReg == rDX);
buzbee52a77fc2012-11-20 19:50:46 -0800394 Clobber(cUnit, rAX);
395 Clobber(cUnit, rDX);
396 MarkInUse(cUnit, rAX);
397 MarkInUse(cUnit, rDX);
398 MarkPair(cUnit, res.lowReg, res.highReg);
buzbeeefc63692012-11-14 16:31:52 -0800399 return res;
400}
401
buzbee52a77fc2012-11-20 19:50:46 -0800402extern RegLocation GetReturnAlt(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800403{
buzbee52a77fc2012-11-20 19:50:46 -0800404 RegLocation res = LocCReturn();
buzbeeefc63692012-11-14 16:31:52 -0800405 res.lowReg = rDX;
buzbee52a77fc2012-11-20 19:50:46 -0800406 Clobber(cUnit, rDX);
407 MarkInUse(cUnit, rDX);
buzbeeefc63692012-11-14 16:31:52 -0800408 return res;
409}
410
buzbee52a77fc2012-11-20 19:50:46 -0800411extern RegisterInfo* GetRegInfo(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800412{
413 return X86_FPREG(reg) ? &cUnit->regPool->FPRegs[reg & X86_FP_REG_MASK]
414 : &cUnit->regPool->coreRegs[reg];
415}
416
417/* To be used when explicitly managing register use */
buzbee52a77fc2012-11-20 19:50:46 -0800418extern void LockCallTemps(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800419{
buzbee52a77fc2012-11-20 19:50:46 -0800420 LockTemp(cUnit, rX86_ARG0);
421 LockTemp(cUnit, rX86_ARG1);
422 LockTemp(cUnit, rX86_ARG2);
423 LockTemp(cUnit, rX86_ARG3);
buzbeeefc63692012-11-14 16:31:52 -0800424}
425
426/* To be used when explicitly managing register use */
buzbee52a77fc2012-11-20 19:50:46 -0800427extern void FreeCallTemps(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800428{
buzbee52a77fc2012-11-20 19:50:46 -0800429 FreeTemp(cUnit, rX86_ARG0);
430 FreeTemp(cUnit, rX86_ARG1);
431 FreeTemp(cUnit, rX86_ARG2);
432 FreeTemp(cUnit, rX86_ARG3);
buzbeeefc63692012-11-14 16:31:52 -0800433}
434
435/* Architecture-specific initializations and checks go here */
buzbee52a77fc2012-11-20 19:50:46 -0800436bool ArchVariantInit(void)
buzbeeefc63692012-11-14 16:31:52 -0800437{
438 return true;
439}
440
buzbee52a77fc2012-11-20 19:50:46 -0800441void GenMemBarrier(CompilationUnit *cUnit, MemBarrierKind barrierKind)
buzbeeefc63692012-11-14 16:31:52 -0800442{
443#if ANDROID_SMP != 0
444 // TODO: optimize fences
buzbee52a77fc2012-11-20 19:50:46 -0800445 NewLIR0(cUnit, kX86Mfence);
buzbeeefc63692012-11-14 16:31:52 -0800446#endif
447}
448/*
449 * Alloc a pair of core registers, or a double. Low reg in low byte,
450 * high reg in next byte.
451 */
buzbee52a77fc2012-11-20 19:50:46 -0800452int AllocTypedTempPair(CompilationUnit *cUnit, bool fpHint,
buzbeeefc63692012-11-14 16:31:52 -0800453 int regClass)
454{
455 int highReg;
456 int lowReg;
457 int res = 0;
458
459 if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
buzbee52a77fc2012-11-20 19:50:46 -0800460 lowReg = AllocTempDouble(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800461 highReg = lowReg + 1;
462 res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
463 return res;
464 }
465
buzbee52a77fc2012-11-20 19:50:46 -0800466 lowReg = AllocTemp(cUnit);
467 highReg = AllocTemp(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800468 res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
469 return res;
470}
471
buzbee52a77fc2012-11-20 19:50:46 -0800472int AllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass) {
buzbeeefc63692012-11-14 16:31:52 -0800473 if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
buzbee52a77fc2012-11-20 19:50:46 -0800474 return AllocTempFloat(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800475 }
buzbee52a77fc2012-11-20 19:50:46 -0800476 return AllocTemp(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800477}
478
buzbee52a77fc2012-11-20 19:50:46 -0800479void CompilerInitializeRegAlloc(CompilationUnit* cUnit) {
buzbeeefc63692012-11-14 16:31:52 -0800480 int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
buzbee52a77fc2012-11-20 19:50:46 -0800481 int numReserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
buzbeeefc63692012-11-14 16:31:52 -0800482 int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
buzbee52a77fc2012-11-20 19:50:46 -0800483 int numFPRegs = sizeof(FpRegs)/sizeof(*FpRegs);
buzbeeefc63692012-11-14 16:31:52 -0800484 int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
buzbeecbd6d442012-11-17 14:11:25 -0800485 RegisterPool *pool =
buzbee52a77fc2012-11-20 19:50:46 -0800486 static_cast<RegisterPool*>(NewMem(cUnit, sizeof(*pool), true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800487 cUnit->regPool = pool;
488 pool->numCoreRegs = numRegs;
buzbeecbd6d442012-11-17 14:11:25 -0800489 pool->coreRegs =
buzbee52a77fc2012-11-20 19:50:46 -0800490 static_cast<RegisterInfo*>(NewMem(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
buzbeecbd6d442012-11-17 14:11:25 -0800491 true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800492 pool->numFPRegs = numFPRegs;
buzbeecbd6d442012-11-17 14:11:25 -0800493 pool->FPRegs =
buzbee52a77fc2012-11-20 19:50:46 -0800494 static_cast<RegisterInfo *>(NewMem(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs),
buzbeecbd6d442012-11-17 14:11:25 -0800495 true, kAllocRegAlloc));
buzbee52a77fc2012-11-20 19:50:46 -0800496 CompilerInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
497 CompilerInitPool(pool->FPRegs, FpRegs, pool->numFPRegs);
buzbeeefc63692012-11-14 16:31:52 -0800498 // Keep special registers from being allocated
499 for (int i = 0; i < numReserved; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800500 MarkInUse(cUnit, ReservedRegs[i]);
buzbeeefc63692012-11-14 16:31:52 -0800501 }
502 // Mark temp regs - all others not in use can be used for promotion
503 for (int i = 0; i < numTemps; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800504 MarkTemp(cUnit, coreTemps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800505 }
506 for (int i = 0; i < numFPTemps; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800507 MarkTemp(cUnit, fpTemps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800508 }
509 // Construct the alias map.
buzbeecbd6d442012-11-17 14:11:25 -0800510 cUnit->phiAliasMap = static_cast<int*>
buzbee52a77fc2012-11-20 19:50:46 -0800511 (NewMem(cUnit, cUnit->numSSARegs * sizeof(cUnit->phiAliasMap[0]), false, kAllocDFInfo));
buzbeeefc63692012-11-14 16:31:52 -0800512 for (int i = 0; i < cUnit->numSSARegs; i++) {
513 cUnit->phiAliasMap[i] = i;
514 }
515 for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
516 int defReg = phi->ssaRep->defs[0];
517 for (int i = 0; i < phi->ssaRep->numUses; i++) {
518 for (int j = 0; j < cUnit->numSSARegs; j++) {
519 if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
520 cUnit->phiAliasMap[j] = defReg;
521 }
522 }
523 }
524 }
525}
526
buzbee52a77fc2012-11-20 19:50:46 -0800527void FreeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
buzbeeefc63692012-11-14 16:31:52 -0800528 RegLocation rlFree)
529{
530 if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
531 (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
532 // No overlap, free both
buzbee52a77fc2012-11-20 19:50:46 -0800533 FreeTemp(cUnit, rlFree.lowReg);
534 FreeTemp(cUnit, rlFree.highReg);
buzbeeefc63692012-11-14 16:31:52 -0800535 }
536}
537
buzbee52a77fc2012-11-20 19:50:46 -0800538void SpillCoreRegs(CompilationUnit* cUnit) {
buzbeeefc63692012-11-14 16:31:52 -0800539 if (cUnit->numCoreSpills == 0) {
540 return;
541 }
542 // Spill mask not including fake return address register
543 uint32_t mask = cUnit->coreSpillMask & ~(1 << rRET);
544 int offset = cUnit->frameSize - (4 * cUnit->numCoreSpills);
545 for (int reg = 0; mask; mask >>= 1, reg++) {
546 if (mask & 0x1) {
buzbee52a77fc2012-11-20 19:50:46 -0800547 StoreWordDisp(cUnit, rX86_SP, offset, reg);
buzbeeefc63692012-11-14 16:31:52 -0800548 offset += 4;
549 }
550 }
551}
552
buzbee52a77fc2012-11-20 19:50:46 -0800553void UnSpillCoreRegs(CompilationUnit* cUnit) {
buzbeeefc63692012-11-14 16:31:52 -0800554 if (cUnit->numCoreSpills == 0) {
555 return;
556 }
557 // Spill mask not including fake return address register
558 uint32_t mask = cUnit->coreSpillMask & ~(1 << rRET);
559 int offset = cUnit->frameSize - (4 * cUnit->numCoreSpills);
560 for (int reg = 0; mask; mask >>= 1, reg++) {
561 if (mask & 0x1) {
buzbee52a77fc2012-11-20 19:50:46 -0800562 LoadWordDisp(cUnit, rX86_SP, offset, reg);
buzbeeefc63692012-11-14 16:31:52 -0800563 offset += 4;
564 }
565 }
566}
567
buzbee52a77fc2012-11-20 19:50:46 -0800568bool BranchUnconditional(LIR* lir)
buzbeecbd6d442012-11-17 14:11:25 -0800569{
570 return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32);
buzbeeefc63692012-11-14 16:31:52 -0800571}
572
573/* Common initialization routine for an architecture family */
buzbee52a77fc2012-11-20 19:50:46 -0800574bool ArchInit() {
buzbeeefc63692012-11-14 16:31:52 -0800575 int i;
576
577 for (i = 0; i < kX86Last; i++) {
578 if (EncodingMap[i].opcode != i) {
579 LOG(FATAL) << "Encoding order for " << EncodingMap[i].name
580 << " is wrong: expecting " << i << ", seeing "
buzbeecbd6d442012-11-17 14:11:25 -0800581 << static_cast<int>(EncodingMap[i].opcode);
buzbeeefc63692012-11-14 16:31:52 -0800582 }
583 }
584
buzbee52a77fc2012-11-20 19:50:46 -0800585 return ArchVariantInit();
buzbeeefc63692012-11-14 16:31:52 -0800586}
587
588// Not used in x86
buzbee52a77fc2012-11-20 19:50:46 -0800589int LoadHelper(CompilationUnit* cUnit, int offset)
buzbeeefc63692012-11-14 16:31:52 -0800590{
buzbee52a77fc2012-11-20 19:50:46 -0800591 LOG(FATAL) << "Unexpected use of LoadHelper in x86";
buzbeeefc63692012-11-14 16:31:52 -0800592 return INVALID_REG;
593}
594
buzbee52a77fc2012-11-20 19:50:46 -0800595uint64_t GetTargetInstFlags(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800596{
597 return EncodingMap[opcode].flags;
598}
599
buzbee52a77fc2012-11-20 19:50:46 -0800600const char* GetTargetInstName(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800601{
602 return EncodingMap[opcode].name;
603}
604
buzbee52a77fc2012-11-20 19:50:46 -0800605const char* GetTargetInstFmt(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800606{
607 return EncodingMap[opcode].fmt;
608}
609
buzbeeefc63692012-11-14 16:31:52 -0800610} // namespace art