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 21 namespace art { 22 23 /* This file contains codegen for the X86 ISA */ 24 25 LIR* 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 51 bool X86Mir2Lir::InexpensiveConstantInt(int32_t value) { 52 return true; 53 } 54 55 bool X86Mir2Lir::InexpensiveConstantFloat(int32_t value) { 56 return false; 57 } 58 59 bool X86Mir2Lir::InexpensiveConstantLong(int64_t value) { 60 return true; 61 } 62 63 bool 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 */ 76 LIR* 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 102 LIR* 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 108 LIR* 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 115 LIR* 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 127 LIR* 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 153 LIR* 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 198 LIR* 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 221 LIR* 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 269 LIR* 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 295 LIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset thread_offset) { 296 X86OpCode opcode = kX86Bkpt; 297 switch (op) { 298 case kOpBlx: opcode = kX86CallT; break; 299 case kOpBx: opcode = kX86JmpT; break; 300 default: 301 LOG(FATAL) << "Bad opcode: " << op; 302 break; 303 } 304 return NewLIR1(opcode, thread_offset.Int32Value()); 305 } 306 307 LIR* X86Mir2Lir::OpMem(OpKind op, int rBase, int disp) { 308 X86OpCode opcode = kX86Bkpt; 309 switch (op) { 310 case kOpBlx: opcode = kX86CallM; break; 311 default: 312 LOG(FATAL) << "Bad opcode: " << op; 313 break; 314 } 315 return NewLIR2(opcode, rBase, disp); 316 } 317 318 LIR* X86Mir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) { 319 int32_t val_lo = Low32Bits(value); 320 int32_t val_hi = High32Bits(value); 321 LIR *res; 322 if (X86_FPREG(r_dest_lo)) { 323 DCHECK(X86_FPREG(r_dest_hi)); // ignore r_dest_hi 324 if (value == 0) { 325 return NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo); 326 } else { 327 if (val_lo == 0) { 328 res = NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo); 329 } else { 330 res = LoadConstantNoClobber(r_dest_lo, val_lo); 331 } 332 if (val_hi != 0) { 333 LoadConstantNoClobber(r_dest_hi, val_hi); 334 NewLIR2(kX86PsllqRI, r_dest_hi, 32); 335 NewLIR2(kX86OrpsRR, r_dest_lo, r_dest_hi); 336 } 337 } 338 } else { 339 res = LoadConstantNoClobber(r_dest_lo, val_lo); 340 LoadConstantNoClobber(r_dest_hi, val_hi); 341 } 342 return res; 343 } 344 345 LIR* X86Mir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale, 346 int displacement, int r_dest, int r_dest_hi, OpSize size, 347 int s_reg) { 348 LIR *load = NULL; 349 LIR *load2 = NULL; 350 bool is_array = r_index != INVALID_REG; 351 bool pair = false; 352 bool is64bit = false; 353 X86OpCode opcode = kX86Nop; 354 switch (size) { 355 case kLong: 356 case kDouble: 357 is64bit = true; 358 if (X86_FPREG(r_dest)) { 359 opcode = is_array ? kX86MovsdRA : kX86MovsdRM; 360 if (X86_SINGLEREG(r_dest)) { 361 DCHECK(X86_FPREG(r_dest_hi)); 362 DCHECK_EQ(r_dest, (r_dest_hi - 1)); 363 r_dest = S2d(r_dest, r_dest_hi); 364 } 365 r_dest_hi = r_dest + 1; 366 } else { 367 pair = true; 368 opcode = is_array ? kX86Mov32RA : kX86Mov32RM; 369 } 370 // TODO: double store is to unaligned address 371 DCHECK_EQ((displacement & 0x3), 0); 372 break; 373 case kWord: 374 case kSingle: 375 opcode = is_array ? kX86Mov32RA : kX86Mov32RM; 376 if (X86_FPREG(r_dest)) { 377 opcode = is_array ? kX86MovssRA : kX86MovssRM; 378 DCHECK(X86_SINGLEREG(r_dest)); 379 } 380 DCHECK_EQ((displacement & 0x3), 0); 381 break; 382 case kUnsignedHalf: 383 opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM; 384 DCHECK_EQ((displacement & 0x1), 0); 385 break; 386 case kSignedHalf: 387 opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM; 388 DCHECK_EQ((displacement & 0x1), 0); 389 break; 390 case kUnsignedByte: 391 opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM; 392 break; 393 case kSignedByte: 394 opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM; 395 break; 396 default: 397 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody"; 398 } 399 400 if (!is_array) { 401 if (!pair) { 402 load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET); 403 } else { 404 if (rBase == r_dest) { 405 load2 = NewLIR3(opcode, r_dest_hi, rBase, 406 displacement + HIWORD_OFFSET); 407 load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET); 408 } else { 409 load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET); 410 load2 = NewLIR3(opcode, r_dest_hi, rBase, 411 displacement + HIWORD_OFFSET); 412 } 413 } 414 if (rBase == rX86_SP) { 415 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, 416 true /* is_load */, is64bit); 417 if (pair) { 418 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2, 419 true /* is_load */, is64bit); 420 } 421 } 422 } else { 423 if (!pair) { 424 load = NewLIR5(opcode, r_dest, rBase, r_index, scale, 425 displacement + LOWORD_OFFSET); 426 } else { 427 if (rBase == r_dest) { 428 load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale, 429 displacement + HIWORD_OFFSET); 430 load = NewLIR5(opcode, r_dest, rBase, r_index, scale, 431 displacement + LOWORD_OFFSET); 432 } else { 433 load = NewLIR5(opcode, r_dest, rBase, r_index, scale, 434 displacement + LOWORD_OFFSET); 435 load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale, 436 displacement + HIWORD_OFFSET); 437 } 438 } 439 } 440 441 return load; 442 } 443 444 /* Load value from base + scaled index. */ 445 LIR* X86Mir2Lir::LoadBaseIndexed(int rBase, 446 int r_index, int r_dest, int scale, OpSize size) { 447 return LoadBaseIndexedDisp(rBase, r_index, scale, 0, 448 r_dest, INVALID_REG, size, INVALID_SREG); 449 } 450 451 LIR* X86Mir2Lir::LoadBaseDisp(int rBase, int displacement, 452 int r_dest, OpSize size, int s_reg) { 453 return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement, 454 r_dest, INVALID_REG, size, s_reg); 455 } 456 457 LIR* X86Mir2Lir::LoadBaseDispWide(int rBase, int displacement, 458 int r_dest_lo, int r_dest_hi, int s_reg) { 459 return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement, 460 r_dest_lo, r_dest_hi, kLong, s_reg); 461 } 462 463 LIR* X86Mir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale, 464 int displacement, int r_src, int r_src_hi, OpSize size, 465 int s_reg) { 466 LIR *store = NULL; 467 LIR *store2 = NULL; 468 bool is_array = r_index != INVALID_REG; 469 bool pair = false; 470 bool is64bit = false; 471 X86OpCode opcode = kX86Nop; 472 switch (size) { 473 case kLong: 474 case kDouble: 475 is64bit = true; 476 if (X86_FPREG(r_src)) { 477 opcode = is_array ? kX86MovsdAR : kX86MovsdMR; 478 if (X86_SINGLEREG(r_src)) { 479 DCHECK(X86_FPREG(r_src_hi)); 480 DCHECK_EQ(r_src, (r_src_hi - 1)); 481 r_src = S2d(r_src, r_src_hi); 482 } 483 r_src_hi = r_src + 1; 484 } else { 485 pair = true; 486 opcode = is_array ? kX86Mov32AR : kX86Mov32MR; 487 } 488 // TODO: double store is to unaligned address 489 DCHECK_EQ((displacement & 0x3), 0); 490 break; 491 case kWord: 492 case kSingle: 493 opcode = is_array ? kX86Mov32AR : kX86Mov32MR; 494 if (X86_FPREG(r_src)) { 495 opcode = is_array ? kX86MovssAR : kX86MovssMR; 496 DCHECK(X86_SINGLEREG(r_src)); 497 } 498 DCHECK_EQ((displacement & 0x3), 0); 499 break; 500 case kUnsignedHalf: 501 case kSignedHalf: 502 opcode = is_array ? kX86Mov16AR : kX86Mov16MR; 503 DCHECK_EQ((displacement & 0x1), 0); 504 break; 505 case kUnsignedByte: 506 case kSignedByte: 507 opcode = is_array ? kX86Mov8AR : kX86Mov8MR; 508 break; 509 default: 510 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody"; 511 } 512 513 if (!is_array) { 514 if (!pair) { 515 store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src); 516 } else { 517 store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src); 518 store2 = NewLIR3(opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi); 519 } 520 if (rBase == rX86_SP) { 521 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, 522 false /* is_load */, is64bit); 523 if (pair) { 524 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2, 525 false /* is_load */, is64bit); 526 } 527 } 528 } else { 529 if (!pair) { 530 store = NewLIR5(opcode, rBase, r_index, scale, 531 displacement + LOWORD_OFFSET, r_src); 532 } else { 533 store = NewLIR5(opcode, rBase, r_index, scale, 534 displacement + LOWORD_OFFSET, r_src); 535 store2 = NewLIR5(opcode, rBase, r_index, scale, 536 displacement + HIWORD_OFFSET, r_src_hi); 537 } 538 } 539 540 return store; 541 } 542 543 /* store value base base + scaled index. */ 544 LIR* X86Mir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src, 545 int scale, OpSize size) { 546 return StoreBaseIndexedDisp(rBase, r_index, scale, 0, 547 r_src, INVALID_REG, size, INVALID_SREG); 548 } 549 550 LIR* X86Mir2Lir::StoreBaseDisp(int rBase, int displacement, 551 int r_src, OpSize size) { 552 return StoreBaseIndexedDisp(rBase, INVALID_REG, 0, 553 displacement, r_src, INVALID_REG, size, 554 INVALID_SREG); 555 } 556 557 LIR* X86Mir2Lir::StoreBaseDispWide(int rBase, int displacement, 558 int r_src_lo, int r_src_hi) { 559 return StoreBaseIndexedDisp(rBase, INVALID_REG, 0, displacement, 560 r_src_lo, r_src_hi, kLong, INVALID_SREG); 561 } 562 563 } // namespace art 564