utility_x86.cc revision 2ce745c06271d5223d57dbf08117b20d5b60694a
1/*
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 "codegen_x86.h"
18#include "dex/quick/mir_to_lir-inl.h"
19#include "x86_lir.h"
20
21namespace art {
22
23/* This file contains codegen for the X86 ISA */
24
25LIR* X86Mir2Lir::OpFpRegCopy(int r_dest, int r_src) {
26  int opcode;
27  /* must be both DOUBLE or both not DOUBLE */
28  DCHECK_EQ(X86_DOUBLEREG(r_dest), X86_DOUBLEREG(r_src));
29  if (X86_DOUBLEREG(r_dest)) {
30    opcode = kX86MovsdRR;
31  } else {
32    if (X86_SINGLEREG(r_dest)) {
33      if (X86_SINGLEREG(r_src)) {
34        opcode = kX86MovssRR;
35      } else {  // Fpr <- Gpr
36        opcode = kX86MovdxrRR;
37      }
38    } else {  // Gpr <- Fpr
39      DCHECK(X86_SINGLEREG(r_src));
40      opcode = kX86MovdrxRR;
41    }
42  }
43  DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
44  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
45  if (r_dest == r_src) {
46    res->flags.is_nop = true;
47  }
48  return res;
49}
50
51bool X86Mir2Lir::InexpensiveConstantInt(int32_t value) {
52  return true;
53}
54
55bool X86Mir2Lir::InexpensiveConstantFloat(int32_t value) {
56  return false;
57}
58
59bool X86Mir2Lir::InexpensiveConstantLong(int64_t value) {
60  return true;
61}
62
63bool X86Mir2Lir::InexpensiveConstantDouble(int64_t value) {
64  return false; // TUNING
65}
66
67/*
68 * Load a immediate using a shortcut if possible; otherwise
69 * grab from the per-translation literal pool.  If target is
70 * a high register, build constant into a low register and copy.
71 *
72 * No additional register clobbering operation performed. Use this version when
73 * 1) r_dest is freshly returned from AllocTemp or
74 * 2) The codegen is under fixed register usage
75 */
76LIR* X86Mir2Lir::LoadConstantNoClobber(int r_dest, int value) {
77  int r_dest_save = r_dest;
78  if (X86_FPREG(r_dest)) {
79    if (value == 0) {
80      return NewLIR2(kX86XorpsRR, r_dest, r_dest);
81    }
82    DCHECK(X86_SINGLEREG(r_dest));
83    r_dest = AllocTemp();
84  }
85
86  LIR *res;
87  if (value == 0) {
88    res = NewLIR2(kX86Xor32RR, r_dest, r_dest);
89  } else {
90    // Note, there is no byte immediate form of a 32 bit immediate move.
91    res = NewLIR2(kX86Mov32RI, r_dest, value);
92  }
93
94  if (X86_FPREG(r_dest_save)) {
95    NewLIR2(kX86MovdxrRR, r_dest_save, r_dest);
96    FreeTemp(r_dest);
97  }
98
99  return res;
100}
101
102LIR* X86Mir2Lir::OpUnconditionalBranch(LIR* target) {
103  LIR* res = NewLIR1(kX86Jmp8, 0 /* offset to be patched during assembly*/ );
104  res->target = target;
105  return res;
106}
107
108LIR* X86Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
109  LIR* branch = NewLIR2(kX86Jcc8, 0 /* offset to be patched */,
110                        X86ConditionEncoding(cc));
111  branch->target = target;
112  return branch;
113}
114
115LIR* X86Mir2Lir::OpReg(OpKind op, int r_dest_src) {
116  X86OpCode opcode = kX86Bkpt;
117  switch (op) {
118    case kOpNeg: opcode = kX86Neg32R; break;
119    case kOpNot: opcode = kX86Not32R; break;
120    case kOpBlx: opcode = kX86CallR; break;
121    default:
122      LOG(FATAL) << "Bad case in OpReg " << op;
123  }
124  return NewLIR1(opcode, r_dest_src);
125}
126
127LIR* X86Mir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value) {
128  X86OpCode opcode = kX86Bkpt;
129  bool byte_imm = IS_SIMM8(value);
130  DCHECK(!X86_FPREG(r_dest_src1));
131  switch (op) {
132    case kOpLsl: opcode = kX86Sal32RI; break;
133    case kOpLsr: opcode = kX86Shr32RI; break;
134    case kOpAsr: opcode = kX86Sar32RI; break;
135    case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
136    case kOpOr:  opcode = byte_imm ? kX86Or32RI8  : kX86Or32RI;  break;
137    case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
138    //case kOpSbb: opcode = kX86Sbb32RI; break;
139    case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
140    case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
141    case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
142    case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
143    case kOpMov: return LoadConstantNoClobber(r_dest_src1, value);
144    case kOpMul:
145      opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
146      return NewLIR3(opcode, r_dest_src1, r_dest_src1, value);
147    default:
148      LOG(FATAL) << "Bad case in OpRegImm " << op;
149  }
150  return NewLIR2(opcode, r_dest_src1, value);
151}
152
153LIR* X86Mir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) {
154    X86OpCode opcode = kX86Nop;
155    bool src2_must_be_cx = false;
156    switch (op) {
157        // X86 unary opcodes
158      case kOpMvn:
159        OpRegCopy(r_dest_src1, r_src2);
160        return OpReg(kOpNot, r_dest_src1);
161      case kOpNeg:
162        OpRegCopy(r_dest_src1, r_src2);
163        return OpReg(kOpNeg, r_dest_src1);
164        // X86 binary opcodes
165      case kOpSub: opcode = kX86Sub32RR; break;
166      case kOpSbc: opcode = kX86Sbb32RR; break;
167      case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
168      case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
169      case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
170      case kOpMov: opcode = kX86Mov32RR; break;
171      case kOpCmp: opcode = kX86Cmp32RR; break;
172      case kOpAdd: opcode = kX86Add32RR; break;
173      case kOpAdc: opcode = kX86Adc32RR; break;
174      case kOpAnd: opcode = kX86And32RR; break;
175      case kOpOr:  opcode = kX86Or32RR; break;
176      case kOpXor: opcode = kX86Xor32RR; break;
177      case kOp2Byte:
178        // Use shifts instead of a byte operand if the source can't be byte accessed.
179        if (r_src2 >= 4) {
180          NewLIR2(kX86Mov32RR, r_dest_src1, r_src2);
181          NewLIR2(kX86Sal32RI, r_dest_src1, 24);
182          return NewLIR2(kX86Sar32RI, r_dest_src1, 24);
183        } else {
184          opcode = kX86Movsx8RR;
185        }
186        break;
187      case kOp2Short: opcode = kX86Movsx16RR; break;
188      case kOp2Char: opcode = kX86Movzx16RR; break;
189      case kOpMul: opcode = kX86Imul32RR; break;
190      default:
191        LOG(FATAL) << "Bad case in OpRegReg " << op;
192        break;
193    }
194    CHECK(!src2_must_be_cx || r_src2 == rCX);
195    return NewLIR2(opcode, r_dest_src1, r_src2);
196}
197
198LIR* X86Mir2Lir::OpRegMem(OpKind op, int r_dest, int rBase,
199              int offset) {
200  X86OpCode opcode = kX86Nop;
201  switch (op) {
202      // X86 binary opcodes
203    case kOpSub: opcode = kX86Sub32RM; break;
204    case kOpMov: opcode = kX86Mov32RM; break;
205    case kOpCmp: opcode = kX86Cmp32RM; break;
206    case kOpAdd: opcode = kX86Add32RM; break;
207    case kOpAnd: opcode = kX86And32RM; break;
208    case kOpOr:  opcode = kX86Or32RM; break;
209    case kOpXor: opcode = kX86Xor32RM; break;
210    case kOp2Byte: opcode = kX86Movsx8RM; break;
211    case kOp2Short: opcode = kX86Movsx16RM; break;
212    case kOp2Char: opcode = kX86Movzx16RM; break;
213    case kOpMul:
214    default:
215      LOG(FATAL) << "Bad case in OpRegMem " << op;
216      break;
217  }
218  return NewLIR3(opcode, r_dest, rBase, offset);
219}
220
221LIR* X86Mir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1,
222                 int r_src2) {
223  if (r_dest != r_src1 && r_dest != r_src2) {
224    if (op == kOpAdd) { // lea special case, except can't encode rbp as base
225      if (r_src1 == r_src2) {
226        OpRegCopy(r_dest, r_src1);
227        return OpRegImm(kOpLsl, r_dest, 1);
228      } else if (r_src1 != rBP) {
229        return NewLIR5(kX86Lea32RA, r_dest, r_src1 /* base */,
230                       r_src2 /* index */, 0 /* scale */, 0 /* disp */);
231      } else {
232        return NewLIR5(kX86Lea32RA, r_dest, r_src2 /* base */,
233                       r_src1 /* index */, 0 /* scale */, 0 /* disp */);
234      }
235    } else {
236      OpRegCopy(r_dest, r_src1);
237      return OpRegReg(op, r_dest, r_src2);
238    }
239  } else if (r_dest == r_src1) {
240    return OpRegReg(op, r_dest, r_src2);
241  } else {  // r_dest == r_src2
242    switch (op) {
243      case kOpSub:  // non-commutative
244        OpReg(kOpNeg, r_dest);
245        op = kOpAdd;
246        break;
247      case kOpSbc:
248      case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
249        int t_reg = AllocTemp();
250        OpRegCopy(t_reg, r_src1);
251        OpRegReg(op, t_reg, r_src2);
252        LIR* res = OpRegCopy(r_dest, t_reg);
253        FreeTemp(t_reg);
254        return res;
255      }
256      case kOpAdd:  // commutative
257      case kOpOr:
258      case kOpAdc:
259      case kOpAnd:
260      case kOpXor:
261        break;
262      default:
263        LOG(FATAL) << "Bad case in OpRegRegReg " << op;
264    }
265    return OpRegReg(op, r_dest, r_src1);
266  }
267}
268
269LIR* X86Mir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src,
270                 int value) {
271  if (op == kOpMul) {
272    X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
273    return NewLIR3(opcode, r_dest, r_src, value);
274  } else if (op == kOpAnd) {
275    if (value == 0xFF && r_src < 4) {
276      return NewLIR2(kX86Movzx8RR, r_dest, r_src);
277    } else if (value == 0xFFFF) {
278      return NewLIR2(kX86Movzx16RR, r_dest, r_src);
279    }
280  }
281  if (r_dest != r_src) {
282    if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
283      // TODO: fix bug in LEA encoding when disp == 0
284      return NewLIR5(kX86Lea32RA, r_dest,  r5sib_no_base /* base */,
285                     r_src /* index */, value /* scale */, 0 /* disp */);
286    } else if (op == kOpAdd) { // lea add special case
287      return NewLIR5(kX86Lea32RA, r_dest, r_src /* base */,
288                     r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
289    }
290    OpRegCopy(r_dest, r_src);
291  }
292  return OpRegImm(op, r_dest, value);
293}
294
295LIR* X86Mir2Lir::OpThreadMem(OpKind op, int thread_offset) {
296  X86OpCode opcode = kX86Bkpt;
297  switch (op) {
298    case kOpBlx: opcode = kX86CallT;  break;
299    default:
300      LOG(FATAL) << "Bad opcode: " << op;
301      break;
302  }
303  return NewLIR1(opcode, thread_offset);
304}
305
306LIR* X86Mir2Lir::OpMem(OpKind op, int rBase, int disp) {
307  X86OpCode opcode = kX86Bkpt;
308  switch (op) {
309    case kOpBlx: opcode = kX86CallM;  break;
310    default:
311      LOG(FATAL) << "Bad opcode: " << op;
312      break;
313  }
314  return NewLIR2(opcode, rBase, disp);
315}
316
317LIR* X86Mir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) {
318    int32_t val_lo = Low32Bits(value);
319    int32_t val_hi = High32Bits(value);
320    LIR *res;
321    if (X86_FPREG(r_dest_lo)) {
322      DCHECK(X86_FPREG(r_dest_hi));  // ignore r_dest_hi
323      if (value == 0) {
324        return NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo);
325      } else {
326        if (val_lo == 0) {
327          res = NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo);
328        } else {
329          res = LoadConstantNoClobber(r_dest_lo, val_lo);
330        }
331        if (val_hi != 0) {
332          LoadConstantNoClobber(r_dest_hi, val_hi);
333          NewLIR2(kX86PsllqRI, r_dest_hi, 32);
334          NewLIR2(kX86OrpsRR, r_dest_lo, r_dest_hi);
335        }
336      }
337    } else {
338      res = LoadConstantNoClobber(r_dest_lo, val_lo);
339      LoadConstantNoClobber(r_dest_hi, val_hi);
340    }
341    return res;
342}
343
344LIR* X86Mir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale,
345                                     int displacement, int r_dest, int r_dest_hi, OpSize size,
346                                     int s_reg) {
347  LIR *load = NULL;
348  LIR *load2 = NULL;
349  bool is_array = r_index != INVALID_REG;
350  bool pair = false;
351  bool is64bit = false;
352  X86OpCode opcode = kX86Nop;
353  switch (size) {
354    case kLong:
355    case kDouble:
356      is64bit = true;
357      if (X86_FPREG(r_dest)) {
358        opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
359        if (X86_SINGLEREG(r_dest)) {
360          DCHECK(X86_FPREG(r_dest_hi));
361          DCHECK_EQ(r_dest, (r_dest_hi - 1));
362          r_dest = S2d(r_dest, r_dest_hi);
363        }
364        r_dest_hi = r_dest + 1;
365      } else {
366        pair = true;
367        opcode = is_array ? kX86Mov32RA  : kX86Mov32RM;
368      }
369      // TODO: double store is to unaligned address
370      DCHECK_EQ((displacement & 0x3), 0);
371      break;
372    case kWord:
373    case kSingle:
374      opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
375      if (X86_FPREG(r_dest)) {
376        opcode = is_array ? kX86MovssRA : kX86MovssRM;
377        DCHECK(X86_SINGLEREG(r_dest));
378      }
379      DCHECK_EQ((displacement & 0x3), 0);
380      break;
381    case kUnsignedHalf:
382      opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM;
383      DCHECK_EQ((displacement & 0x1), 0);
384      break;
385    case kSignedHalf:
386      opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM;
387      DCHECK_EQ((displacement & 0x1), 0);
388      break;
389    case kUnsignedByte:
390      opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM;
391      break;
392    case kSignedByte:
393      opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM;
394      break;
395    default:
396      LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
397  }
398
399  if (!is_array) {
400    if (!pair) {
401      load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
402    } else {
403      if (rBase == r_dest) {
404        load2 = NewLIR3(opcode, r_dest_hi, rBase,
405                        displacement + HIWORD_OFFSET);
406        load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
407      } else {
408        load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
409        load2 = NewLIR3(opcode, r_dest_hi, rBase,
410                        displacement + HIWORD_OFFSET);
411      }
412    }
413    if (rBase == rX86_SP) {
414      AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
415                              true /* is_load */, is64bit);
416      if (pair) {
417        AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
418                                true /* is_load */, is64bit);
419      }
420    }
421  } else {
422    if (!pair) {
423      load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
424                     displacement + LOWORD_OFFSET);
425    } else {
426      if (rBase == r_dest) {
427        load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
428                        displacement + HIWORD_OFFSET);
429        load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
430                       displacement + LOWORD_OFFSET);
431      } else {
432        load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
433                       displacement + LOWORD_OFFSET);
434        load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
435                        displacement + HIWORD_OFFSET);
436      }
437    }
438  }
439
440  return load;
441}
442
443/* Load value from base + scaled index. */
444LIR* X86Mir2Lir::LoadBaseIndexed(int rBase,
445                     int r_index, int r_dest, int scale, OpSize size) {
446  return LoadBaseIndexedDisp(rBase, r_index, scale, 0,
447                             r_dest, INVALID_REG, size, INVALID_SREG);
448}
449
450LIR* X86Mir2Lir::LoadBaseDisp(int rBase, int displacement,
451                  int r_dest, OpSize size, int s_reg) {
452  return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
453                             r_dest, INVALID_REG, size, s_reg);
454}
455
456LIR* X86Mir2Lir::LoadBaseDispWide(int rBase, int displacement,
457                      int r_dest_lo, int r_dest_hi, int s_reg) {
458  return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
459                             r_dest_lo, r_dest_hi, kLong, s_reg);
460}
461
462LIR* X86Mir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale,
463                                      int displacement, int r_src, int r_src_hi, OpSize size,
464                                      int s_reg) {
465  LIR *store = NULL;
466  LIR *store2 = NULL;
467  bool is_array = r_index != INVALID_REG;
468  bool pair = false;
469  bool is64bit = false;
470  X86OpCode opcode = kX86Nop;
471  switch (size) {
472    case kLong:
473    case kDouble:
474      is64bit = true;
475      if (X86_FPREG(r_src)) {
476        opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
477        if (X86_SINGLEREG(r_src)) {
478          DCHECK(X86_FPREG(r_src_hi));
479          DCHECK_EQ(r_src, (r_src_hi - 1));
480          r_src = S2d(r_src, r_src_hi);
481        }
482        r_src_hi = r_src + 1;
483      } else {
484        pair = true;
485        opcode = is_array ? kX86Mov32AR  : kX86Mov32MR;
486      }
487      // TODO: double store is to unaligned address
488      DCHECK_EQ((displacement & 0x3), 0);
489      break;
490    case kWord:
491    case kSingle:
492      opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
493      if (X86_FPREG(r_src)) {
494        opcode = is_array ? kX86MovssAR : kX86MovssMR;
495        DCHECK(X86_SINGLEREG(r_src));
496      }
497      DCHECK_EQ((displacement & 0x3), 0);
498      break;
499    case kUnsignedHalf:
500    case kSignedHalf:
501      opcode = is_array ? kX86Mov16AR : kX86Mov16MR;
502      DCHECK_EQ((displacement & 0x1), 0);
503      break;
504    case kUnsignedByte:
505    case kSignedByte:
506      opcode = is_array ? kX86Mov8AR : kX86Mov8MR;
507      break;
508    default:
509      LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
510  }
511
512  if (!is_array) {
513    if (!pair) {
514      store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src);
515    } else {
516      store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src);
517      store2 = NewLIR3(opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi);
518    }
519    if (rBase == rX86_SP) {
520      AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
521                              false /* is_load */, is64bit);
522      if (pair) {
523        AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
524                                false /* is_load */, is64bit);
525      }
526    }
527  } else {
528    if (!pair) {
529      store = NewLIR5(opcode, rBase, r_index, scale,
530                      displacement + LOWORD_OFFSET, r_src);
531    } else {
532      store = NewLIR5(opcode, rBase, r_index, scale,
533                      displacement + LOWORD_OFFSET, r_src);
534      store2 = NewLIR5(opcode, rBase, r_index, scale,
535                       displacement + HIWORD_OFFSET, r_src_hi);
536    }
537  }
538
539  return store;
540}
541
542/* store value base base + scaled index. */
543LIR* X86Mir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
544                      int scale, OpSize size) {
545  return StoreBaseIndexedDisp(rBase, r_index, scale, 0,
546                              r_src, INVALID_REG, size, INVALID_SREG);
547}
548
549LIR* X86Mir2Lir::StoreBaseDisp(int rBase, int displacement,
550                               int r_src, OpSize size) {
551    return StoreBaseIndexedDisp(rBase, INVALID_REG, 0,
552                                displacement, r_src, INVALID_REG, size,
553                                INVALID_SREG);
554}
555
556LIR* X86Mir2Lir::StoreBaseDispWide(int rBase, int displacement,
557                                   int r_src_lo, int r_src_hi) {
558  return StoreBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
559                              r_src_lo, r_src_hi, kLong, INVALID_SREG);
560}
561
562}  // namespace art
563