blob: c51e9e9003293dfba00bc13ffea506449e43cb58 [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
buzbeefa57c472012-11-21 12:06:18 -080027/*static*/ int core_regs[] = {
buzbeeefc63692012-11-14 16:31:52 -080028 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};
buzbeefa57c472012-11-21 12:06:18 -080034/*static*/ int core_temps[] = {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};
buzbeefa57c472012-11-21 12:06:18 -080041/*static*/ int fp_temps[] = {
buzbeeefc63692012-11-14 16:31:52 -080042 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.
buzbeefa57c472012-11-21 12:06:18 -080098int S2d(int low_reg, int high_reg)
buzbeeefc63692012-11-14 16:31:52 -080099{
buzbeefa57c472012-11-21 12:06:18 -0800100 return X86_S2D(low_reg, high_reg);
buzbeeefc63692012-11-14 16:31:52 -0800101}
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 */
buzbeefa57c472012-11-21 12:06:18 -0800136uint64_t GetRegMaskCommon(CompilationUnit* cu, 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;
buzbeefa57c472012-11-21 12:06:18 -0800140 int reg_id;
buzbeeefc63692012-11-14 16:31:52 -0800141
buzbeefa57c472012-11-21 12:06:18 -0800142 reg_id = reg & 0xf;
buzbeeefc63692012-11-14 16:31:52 -0800143 /* 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 */
buzbeefa57c472012-11-21 12:06:18 -0800148 shift += reg_id;
buzbeeefc63692012-11-14 16:31:52 -0800149 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
buzbeefa57c472012-11-21 12:06:18 -0800162void SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir)
buzbeeefc63692012-11-14 16:31:52 -0800163{
buzbeefa57c472012-11-21 12:06:18 -0800164 DCHECK_EQ(cu->instruction_set, kX86);
buzbeeefc63692012-11-14 16:31:52 -0800165
166 // X86-specific resource map setup here.
167 uint64_t flags = EncodingMap[lir->opcode].flags;
168
169 if (flags & REG_USE_SP) {
buzbeefa57c472012-11-21 12:06:18 -0800170 lir->use_mask |= ENCODE_X86_REG_SP;
buzbeeefc63692012-11-14 16:31:52 -0800171 }
172
173 if (flags & REG_DEF_SP) {
buzbeefa57c472012-11-21 12:06:18 -0800174 lir->def_mask |= ENCODE_X86_REG_SP;
buzbeeefc63692012-11-14 16:31:52 -0800175 }
176
177 if (flags & REG_DEFA) {
buzbeefa57c472012-11-21 12:06:18 -0800178 SetupRegMask(cu, &lir->def_mask, rAX);
buzbeeefc63692012-11-14 16:31:52 -0800179 }
180
181 if (flags & REG_DEFD) {
buzbeefa57c472012-11-21 12:06:18 -0800182 SetupRegMask(cu, &lir->def_mask, rDX);
buzbeeefc63692012-11-14 16:31:52 -0800183 }
184 if (flags & REG_USEA) {
buzbeefa57c472012-11-21 12:06:18 -0800185 SetupRegMask(cu, &lir->use_mask, rAX);
buzbeeefc63692012-11-14 16:31:52 -0800186 }
187
188 if (flags & REG_USEC) {
buzbeefa57c472012-11-21 12:06:18 -0800189 SetupRegMask(cu, &lir->use_mask, rCX);
buzbeeefc63692012-11-14 16:31:52 -0800190 }
191
192 if (flags & REG_USED) {
buzbeefa57c472012-11-21 12:06:18 -0800193 SetupRegMask(cu, &lir->use_mask, 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 */
buzbeefa57c472012-11-21 12:06:18 -0800226std::string BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
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': {
buzbeefa57c472012-11-21 12:06:18 -0800255 SwitchTable *tab_rec = reinterpret_cast<SwitchTable*>(operand);
256 buf += StringPrintf("0x%08x", tab_rec->offset);
buzbeeefc63692012-11-14 16:31:52 -0800257 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)",
buzbeefa57c472012-11-21 12:06:18 -0800270 reinterpret_cast<uint32_t>(base_addr)
buzbeeefc63692012-11-14 16:31:52 -0800271 + 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)) {
buzbeefa57c472012-11-21 12:06:18 -0800307 sprintf(buf + strlen(buf), "dr%d%s", x86LIR->alias_info & 0xffff,
308 (x86LIR->alias_info & 0x80000000) ? "(+1)" : "");
buzbeeefc63692012-11-14 16:31:52 -0800309 }
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}
buzbeefa57c472012-11-21 12:06:18 -0800325void AdjustSpillMask(CompilationUnit* cu) {
buzbeeefc63692012-11-14 16:31:52 -0800326 // Adjustment for LR spilling, x86 has no LR so nothing to do here
buzbeefa57c472012-11-21 12:06:18 -0800327 cu->core_spill_mask |= (1 << rRET);
328 cu->num_core_spills++;
buzbeeefc63692012-11-14 16:31:52 -0800329}
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 */
buzbeefa57c472012-11-21 12:06:18 -0800337void MarkPreservedSingle(CompilationUnit* cu, int v_reg, 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
buzbeefa57c472012-11-21 12:06:18 -0800345void FlushRegWide(CompilationUnit* cu, int reg1, int reg2)
buzbeeefc63692012-11-14 16:31:52 -0800346{
buzbeefa57c472012-11-21 12:06:18 -0800347 RegisterInfo* info1 = GetRegInfo(cu, reg1);
348 RegisterInfo* info2 = GetRegInfo(cu, 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)) {
buzbeefa57c472012-11-21 12:06:18 -0800353 if (!(info1->is_temp && info2->is_temp)) {
354 /* Should not happen. If it does, there's a problem in eval_loc */
buzbeeefc63692012-11-14 16:31:52 -0800355 LOG(FATAL) << "Long half-temp, half-promoted";
356 }
357
358 info1->dirty = false;
359 info2->dirty = false;
buzbeefa57c472012-11-21 12:06:18 -0800360 if (SRegToVReg(cu, info2->s_reg) < SRegToVReg(cu, info1->s_reg))
buzbeeefc63692012-11-14 16:31:52 -0800361 info1 = info2;
buzbeefa57c472012-11-21 12:06:18 -0800362 int v_reg = SRegToVReg(cu, info1->s_reg);
363 StoreBaseDispWide(cu, rX86_SP, VRegOffset(cu, v_reg), info1->reg, info1->partner);
buzbeeefc63692012-11-14 16:31:52 -0800364 }
365}
366
buzbeefa57c472012-11-21 12:06:18 -0800367void FlushReg(CompilationUnit* cu, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800368{
buzbeefa57c472012-11-21 12:06:18 -0800369 RegisterInfo* info = GetRegInfo(cu, reg);
buzbeeefc63692012-11-14 16:31:52 -0800370 if (info->live && info->dirty) {
371 info->dirty = false;
buzbeefa57c472012-11-21 12:06:18 -0800372 int v_reg = SRegToVReg(cu, info->s_reg);
373 StoreBaseDisp(cu, rX86_SP, VRegOffset(cu, v_reg), 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 */
buzbeefa57c472012-11-21 12:06:18 -0800383void ClobberCalleeSave(CompilationUnit *cu)
buzbeeefc63692012-11-14 16:31:52 -0800384{
buzbeefa57c472012-11-21 12:06:18 -0800385 Clobber(cu, rAX);
386 Clobber(cu, rCX);
387 Clobber(cu, rDX);
buzbeeefc63692012-11-14 16:31:52 -0800388}
389
buzbeefa57c472012-11-21 12:06:18 -0800390RegLocation GetReturnWideAlt(CompilationUnit* cu) {
buzbee52a77fc2012-11-20 19:50:46 -0800391 RegLocation res = LocCReturnWide();
buzbeefa57c472012-11-21 12:06:18 -0800392 CHECK(res.low_reg == rAX);
393 CHECK(res.high_reg == rDX);
394 Clobber(cu, rAX);
395 Clobber(cu, rDX);
396 MarkInUse(cu, rAX);
397 MarkInUse(cu, rDX);
398 MarkPair(cu, res.low_reg, res.high_reg);
buzbeeefc63692012-11-14 16:31:52 -0800399 return res;
400}
401
buzbeefa57c472012-11-21 12:06:18 -0800402RegLocation GetReturnAlt(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800403{
buzbee52a77fc2012-11-20 19:50:46 -0800404 RegLocation res = LocCReturn();
buzbeefa57c472012-11-21 12:06:18 -0800405 res.low_reg = rDX;
406 Clobber(cu, rDX);
407 MarkInUse(cu, rDX);
buzbeeefc63692012-11-14 16:31:52 -0800408 return res;
409}
410
buzbeefa57c472012-11-21 12:06:18 -0800411RegisterInfo* GetRegInfo(CompilationUnit* cu, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800412{
buzbeefa57c472012-11-21 12:06:18 -0800413 return X86_FPREG(reg) ? &cu->reg_pool->FPRegs[reg & X86_FP_REG_MASK]
414 : &cu->reg_pool->core_regs[reg];
buzbeeefc63692012-11-14 16:31:52 -0800415}
416
417/* To be used when explicitly managing register use */
buzbeefa57c472012-11-21 12:06:18 -0800418void LockCallTemps(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800419{
buzbeefa57c472012-11-21 12:06:18 -0800420 LockTemp(cu, rX86_ARG0);
421 LockTemp(cu, rX86_ARG1);
422 LockTemp(cu, rX86_ARG2);
423 LockTemp(cu, rX86_ARG3);
buzbeeefc63692012-11-14 16:31:52 -0800424}
425
426/* To be used when explicitly managing register use */
buzbeefa57c472012-11-21 12:06:18 -0800427void FreeCallTemps(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800428{
buzbeefa57c472012-11-21 12:06:18 -0800429 FreeTemp(cu, rX86_ARG0);
430 FreeTemp(cu, rX86_ARG1);
431 FreeTemp(cu, rX86_ARG2);
432 FreeTemp(cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800441void GenMemBarrier(CompilationUnit *cu, MemBarrierKind barrier_kind)
buzbeeefc63692012-11-14 16:31:52 -0800442{
443#if ANDROID_SMP != 0
444 // TODO: optimize fences
buzbeefa57c472012-11-21 12:06:18 -0800445 NewLIR0(cu, 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 */
buzbeefa57c472012-11-21 12:06:18 -0800452int AllocTypedTempPair(CompilationUnit *cu, bool fp_hint,
453 int reg_class)
buzbeeefc63692012-11-14 16:31:52 -0800454{
buzbeefa57c472012-11-21 12:06:18 -0800455 int high_reg;
456 int low_reg;
buzbeeefc63692012-11-14 16:31:52 -0800457 int res = 0;
458
buzbeefa57c472012-11-21 12:06:18 -0800459 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
460 low_reg = AllocTempDouble(cu);
461 high_reg = low_reg + 1;
462 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
buzbeeefc63692012-11-14 16:31:52 -0800463 return res;
464 }
465
buzbeefa57c472012-11-21 12:06:18 -0800466 low_reg = AllocTemp(cu);
467 high_reg = AllocTemp(cu);
468 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
buzbeeefc63692012-11-14 16:31:52 -0800469 return res;
470}
471
buzbeefa57c472012-11-21 12:06:18 -0800472int AllocTypedTemp(CompilationUnit *cu, bool fp_hint, int reg_class) {
473 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
474 return AllocTempFloat(cu);
buzbeeefc63692012-11-14 16:31:52 -0800475 }
buzbeefa57c472012-11-21 12:06:18 -0800476 return AllocTemp(cu);
buzbeeefc63692012-11-14 16:31:52 -0800477}
478
buzbeefa57c472012-11-21 12:06:18 -0800479void CompilerInitializeRegAlloc(CompilationUnit* cu) {
480 int num_regs = sizeof(core_regs)/sizeof(*core_regs);
481 int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
482 int num_temps = sizeof(core_temps)/sizeof(*core_temps);
483 int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs);
484 int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps);
buzbeecbd6d442012-11-17 14:11:25 -0800485 RegisterPool *pool =
buzbeefa57c472012-11-21 12:06:18 -0800486 static_cast<RegisterPool*>(NewMem(cu, sizeof(*pool), true, kAllocRegAlloc));
487 cu->reg_pool = pool;
488 pool->num_core_regs = num_regs;
489 pool->core_regs =
490 static_cast<RegisterInfo*>(NewMem(cu, num_regs * sizeof(*cu->reg_pool->core_regs),
buzbeecbd6d442012-11-17 14:11:25 -0800491 true, kAllocRegAlloc));
buzbeefa57c472012-11-21 12:06:18 -0800492 pool->num_fp_regs = num_fp_regs;
buzbeecbd6d442012-11-17 14:11:25 -0800493 pool->FPRegs =
buzbeefa57c472012-11-21 12:06:18 -0800494 static_cast<RegisterInfo *>(NewMem(cu, num_fp_regs * sizeof(*cu->reg_pool->FPRegs),
buzbeecbd6d442012-11-17 14:11:25 -0800495 true, kAllocRegAlloc));
buzbeefa57c472012-11-21 12:06:18 -0800496 CompilerInitPool(pool->core_regs, core_regs, pool->num_core_regs);
497 CompilerInitPool(pool->FPRegs, FpRegs, pool->num_fp_regs);
buzbeeefc63692012-11-14 16:31:52 -0800498 // Keep special registers from being allocated
buzbeefa57c472012-11-21 12:06:18 -0800499 for (int i = 0; i < num_reserved; i++) {
500 MarkInUse(cu, ReservedRegs[i]);
buzbeeefc63692012-11-14 16:31:52 -0800501 }
502 // Mark temp regs - all others not in use can be used for promotion
buzbeefa57c472012-11-21 12:06:18 -0800503 for (int i = 0; i < num_temps; i++) {
504 MarkTemp(cu, core_temps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800505 }
buzbeefa57c472012-11-21 12:06:18 -0800506 for (int i = 0; i < num_fp_temps; i++) {
507 MarkTemp(cu, fp_temps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800508 }
509 // Construct the alias map.
buzbeefa57c472012-11-21 12:06:18 -0800510 cu->phi_alias_map = static_cast<int*>
511 (NewMem(cu, cu->num_ssa_regs * sizeof(cu->phi_alias_map[0]), false, kAllocDFInfo));
512 for (int i = 0; i < cu->num_ssa_regs; i++) {
513 cu->phi_alias_map[i] = i;
buzbeeefc63692012-11-14 16:31:52 -0800514 }
buzbeefa57c472012-11-21 12:06:18 -0800515 for (MIR* phi = cu->phi_list; phi; phi = phi->meta.phi_next) {
516 int def_reg = phi->ssa_rep->defs[0];
517 for (int i = 0; i < phi->ssa_rep->num_uses; i++) {
518 for (int j = 0; j < cu->num_ssa_regs; j++) {
519 if (cu->phi_alias_map[j] == phi->ssa_rep->uses[i]) {
520 cu->phi_alias_map[j] = def_reg;
buzbeeefc63692012-11-14 16:31:52 -0800521 }
522 }
523 }
524 }
525}
526
buzbeefa57c472012-11-21 12:06:18 -0800527void FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep,
528 RegLocation rl_free)
buzbeeefc63692012-11-14 16:31:52 -0800529{
buzbeefa57c472012-11-21 12:06:18 -0800530 if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) &&
531 (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) {
buzbeeefc63692012-11-14 16:31:52 -0800532 // No overlap, free both
buzbeefa57c472012-11-21 12:06:18 -0800533 FreeTemp(cu, rl_free.low_reg);
534 FreeTemp(cu, rl_free.high_reg);
buzbeeefc63692012-11-14 16:31:52 -0800535 }
536}
537
buzbeefa57c472012-11-21 12:06:18 -0800538void SpillCoreRegs(CompilationUnit* cu) {
539 if (cu->num_core_spills == 0) {
buzbeeefc63692012-11-14 16:31:52 -0800540 return;
541 }
542 // Spill mask not including fake return address register
buzbeefa57c472012-11-21 12:06:18 -0800543 uint32_t mask = cu->core_spill_mask & ~(1 << rRET);
544 int offset = cu->frame_size - (4 * cu->num_core_spills);
buzbeeefc63692012-11-14 16:31:52 -0800545 for (int reg = 0; mask; mask >>= 1, reg++) {
546 if (mask & 0x1) {
buzbeefa57c472012-11-21 12:06:18 -0800547 StoreWordDisp(cu, rX86_SP, offset, reg);
buzbeeefc63692012-11-14 16:31:52 -0800548 offset += 4;
549 }
550 }
551}
552
buzbeefa57c472012-11-21 12:06:18 -0800553void UnSpillCoreRegs(CompilationUnit* cu) {
554 if (cu->num_core_spills == 0) {
buzbeeefc63692012-11-14 16:31:52 -0800555 return;
556 }
557 // Spill mask not including fake return address register
buzbeefa57c472012-11-21 12:06:18 -0800558 uint32_t mask = cu->core_spill_mask & ~(1 << rRET);
559 int offset = cu->frame_size - (4 * cu->num_core_spills);
buzbeeefc63692012-11-14 16:31:52 -0800560 for (int reg = 0; mask; mask >>= 1, reg++) {
561 if (mask & 0x1) {
buzbeefa57c472012-11-21 12:06:18 -0800562 LoadWordDisp(cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800589int LoadHelper(CompilationUnit* cu, 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