1/* 2 * Copyright (C) 2016 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 "jni_macro_assembler_x86.h" 18 19#include "utils/assembler.h" 20#include "base/casts.h" 21#include "entrypoints/quick/quick_entrypoints.h" 22#include "thread.h" 23 24namespace art { 25namespace x86 { 26 27// Slowpath entered when Thread::Current()->_exception is non-null 28class X86ExceptionSlowPath FINAL : public SlowPath { 29 public: 30 explicit X86ExceptionSlowPath(size_t stack_adjust) : stack_adjust_(stack_adjust) {} 31 virtual void Emit(Assembler *sp_asm) OVERRIDE; 32 private: 33 const size_t stack_adjust_; 34}; 35 36static dwarf::Reg DWARFReg(Register reg) { 37 return dwarf::Reg::X86Core(static_cast<int>(reg)); 38} 39 40constexpr size_t kFramePointerSize = 4; 41 42#define __ asm_. 43 44void X86JNIMacroAssembler::BuildFrame(size_t frame_size, 45 ManagedRegister method_reg, 46 ArrayRef<const ManagedRegister> spill_regs, 47 const ManagedRegisterEntrySpills& entry_spills) { 48 DCHECK_EQ(CodeSize(), 0U); // Nothing emitted yet. 49 cfi().SetCurrentCFAOffset(4); // Return address on stack. 50 CHECK_ALIGNED(frame_size, kStackAlignment); 51 int gpr_count = 0; 52 for (int i = spill_regs.size() - 1; i >= 0; --i) { 53 Register spill = spill_regs[i].AsX86().AsCpuRegister(); 54 __ pushl(spill); 55 gpr_count++; 56 cfi().AdjustCFAOffset(kFramePointerSize); 57 cfi().RelOffset(DWARFReg(spill), 0); 58 } 59 60 // return address then method on stack. 61 int32_t adjust = frame_size - gpr_count * kFramePointerSize - 62 kFramePointerSize /*method*/ - 63 kFramePointerSize /*return address*/; 64 __ addl(ESP, Immediate(-adjust)); 65 cfi().AdjustCFAOffset(adjust); 66 __ pushl(method_reg.AsX86().AsCpuRegister()); 67 cfi().AdjustCFAOffset(kFramePointerSize); 68 DCHECK_EQ(static_cast<size_t>(cfi().GetCurrentCFAOffset()), frame_size); 69 70 for (size_t i = 0; i < entry_spills.size(); ++i) { 71 ManagedRegisterSpill spill = entry_spills.at(i); 72 if (spill.AsX86().IsCpuRegister()) { 73 int offset = frame_size + spill.getSpillOffset(); 74 __ movl(Address(ESP, offset), spill.AsX86().AsCpuRegister()); 75 } else { 76 DCHECK(spill.AsX86().IsXmmRegister()); 77 if (spill.getSize() == 8) { 78 __ movsd(Address(ESP, frame_size + spill.getSpillOffset()), spill.AsX86().AsXmmRegister()); 79 } else { 80 CHECK_EQ(spill.getSize(), 4); 81 __ movss(Address(ESP, frame_size + spill.getSpillOffset()), spill.AsX86().AsXmmRegister()); 82 } 83 } 84 } 85} 86 87void X86JNIMacroAssembler::RemoveFrame(size_t frame_size, 88 ArrayRef<const ManagedRegister> spill_regs) { 89 CHECK_ALIGNED(frame_size, kStackAlignment); 90 cfi().RememberState(); 91 // -kFramePointerSize for ArtMethod*. 92 int adjust = frame_size - spill_regs.size() * kFramePointerSize - kFramePointerSize; 93 __ addl(ESP, Immediate(adjust)); 94 cfi().AdjustCFAOffset(-adjust); 95 for (size_t i = 0; i < spill_regs.size(); ++i) { 96 Register spill = spill_regs[i].AsX86().AsCpuRegister(); 97 __ popl(spill); 98 cfi().AdjustCFAOffset(-static_cast<int>(kFramePointerSize)); 99 cfi().Restore(DWARFReg(spill)); 100 } 101 __ ret(); 102 // The CFI should be restored for any code that follows the exit block. 103 cfi().RestoreState(); 104 cfi().DefCFAOffset(frame_size); 105} 106 107void X86JNIMacroAssembler::IncreaseFrameSize(size_t adjust) { 108 CHECK_ALIGNED(adjust, kStackAlignment); 109 __ addl(ESP, Immediate(-adjust)); 110 cfi().AdjustCFAOffset(adjust); 111} 112 113static void DecreaseFrameSizeImpl(X86Assembler* assembler, size_t adjust) { 114 CHECK_ALIGNED(adjust, kStackAlignment); 115 assembler->addl(ESP, Immediate(adjust)); 116 assembler->cfi().AdjustCFAOffset(-adjust); 117} 118 119void X86JNIMacroAssembler::DecreaseFrameSize(size_t adjust) { 120 DecreaseFrameSizeImpl(&asm_, adjust); 121} 122 123void X86JNIMacroAssembler::Store(FrameOffset offs, ManagedRegister msrc, size_t size) { 124 X86ManagedRegister src = msrc.AsX86(); 125 if (src.IsNoRegister()) { 126 CHECK_EQ(0u, size); 127 } else if (src.IsCpuRegister()) { 128 CHECK_EQ(4u, size); 129 __ movl(Address(ESP, offs), src.AsCpuRegister()); 130 } else if (src.IsRegisterPair()) { 131 CHECK_EQ(8u, size); 132 __ movl(Address(ESP, offs), src.AsRegisterPairLow()); 133 __ movl(Address(ESP, FrameOffset(offs.Int32Value()+4)), src.AsRegisterPairHigh()); 134 } else if (src.IsX87Register()) { 135 if (size == 4) { 136 __ fstps(Address(ESP, offs)); 137 } else { 138 __ fstpl(Address(ESP, offs)); 139 } 140 } else { 141 CHECK(src.IsXmmRegister()); 142 if (size == 4) { 143 __ movss(Address(ESP, offs), src.AsXmmRegister()); 144 } else { 145 __ movsd(Address(ESP, offs), src.AsXmmRegister()); 146 } 147 } 148} 149 150void X86JNIMacroAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) { 151 X86ManagedRegister src = msrc.AsX86(); 152 CHECK(src.IsCpuRegister()); 153 __ movl(Address(ESP, dest), src.AsCpuRegister()); 154} 155 156void X86JNIMacroAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) { 157 X86ManagedRegister src = msrc.AsX86(); 158 CHECK(src.IsCpuRegister()); 159 __ movl(Address(ESP, dest), src.AsCpuRegister()); 160} 161 162void X86JNIMacroAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister) { 163 __ movl(Address(ESP, dest), Immediate(imm)); 164} 165 166void X86JNIMacroAssembler::StoreStackOffsetToThread(ThreadOffset32 thr_offs, 167 FrameOffset fr_offs, 168 ManagedRegister mscratch) { 169 X86ManagedRegister scratch = mscratch.AsX86(); 170 CHECK(scratch.IsCpuRegister()); 171 __ leal(scratch.AsCpuRegister(), Address(ESP, fr_offs)); 172 __ fs()->movl(Address::Absolute(thr_offs), scratch.AsCpuRegister()); 173} 174 175void X86JNIMacroAssembler::StoreStackPointerToThread(ThreadOffset32 thr_offs) { 176 __ fs()->movl(Address::Absolute(thr_offs), ESP); 177} 178 179void X86JNIMacroAssembler::StoreSpanning(FrameOffset /*dst*/, 180 ManagedRegister /*src*/, 181 FrameOffset /*in_off*/, 182 ManagedRegister /*scratch*/) { 183 UNIMPLEMENTED(FATAL); // this case only currently exists for ARM 184} 185 186void X86JNIMacroAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) { 187 X86ManagedRegister dest = mdest.AsX86(); 188 if (dest.IsNoRegister()) { 189 CHECK_EQ(0u, size); 190 } else if (dest.IsCpuRegister()) { 191 CHECK_EQ(4u, size); 192 __ movl(dest.AsCpuRegister(), Address(ESP, src)); 193 } else if (dest.IsRegisterPair()) { 194 CHECK_EQ(8u, size); 195 __ movl(dest.AsRegisterPairLow(), Address(ESP, src)); 196 __ movl(dest.AsRegisterPairHigh(), Address(ESP, FrameOffset(src.Int32Value()+4))); 197 } else if (dest.IsX87Register()) { 198 if (size == 4) { 199 __ flds(Address(ESP, src)); 200 } else { 201 __ fldl(Address(ESP, src)); 202 } 203 } else { 204 CHECK(dest.IsXmmRegister()); 205 if (size == 4) { 206 __ movss(dest.AsXmmRegister(), Address(ESP, src)); 207 } else { 208 __ movsd(dest.AsXmmRegister(), Address(ESP, src)); 209 } 210 } 211} 212 213void X86JNIMacroAssembler::LoadFromThread(ManagedRegister mdest, ThreadOffset32 src, size_t size) { 214 X86ManagedRegister dest = mdest.AsX86(); 215 if (dest.IsNoRegister()) { 216 CHECK_EQ(0u, size); 217 } else if (dest.IsCpuRegister()) { 218 if (size == 1u) { 219 __ fs()->movzxb(dest.AsCpuRegister(), Address::Absolute(src)); 220 } else { 221 CHECK_EQ(4u, size); 222 __ fs()->movl(dest.AsCpuRegister(), Address::Absolute(src)); 223 } 224 } else if (dest.IsRegisterPair()) { 225 CHECK_EQ(8u, size); 226 __ fs()->movl(dest.AsRegisterPairLow(), Address::Absolute(src)); 227 __ fs()->movl(dest.AsRegisterPairHigh(), Address::Absolute(ThreadOffset32(src.Int32Value()+4))); 228 } else if (dest.IsX87Register()) { 229 if (size == 4) { 230 __ fs()->flds(Address::Absolute(src)); 231 } else { 232 __ fs()->fldl(Address::Absolute(src)); 233 } 234 } else { 235 CHECK(dest.IsXmmRegister()); 236 if (size == 4) { 237 __ fs()->movss(dest.AsXmmRegister(), Address::Absolute(src)); 238 } else { 239 __ fs()->movsd(dest.AsXmmRegister(), Address::Absolute(src)); 240 } 241 } 242} 243 244void X86JNIMacroAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) { 245 X86ManagedRegister dest = mdest.AsX86(); 246 CHECK(dest.IsCpuRegister()); 247 __ movl(dest.AsCpuRegister(), Address(ESP, src)); 248} 249 250void X86JNIMacroAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, 251 bool unpoison_reference) { 252 X86ManagedRegister dest = mdest.AsX86(); 253 CHECK(dest.IsCpuRegister() && dest.IsCpuRegister()); 254 __ movl(dest.AsCpuRegister(), Address(base.AsX86().AsCpuRegister(), offs)); 255 if (unpoison_reference) { 256 __ MaybeUnpoisonHeapReference(dest.AsCpuRegister()); 257 } 258} 259 260void X86JNIMacroAssembler::LoadRawPtr(ManagedRegister mdest, 261 ManagedRegister base, 262 Offset offs) { 263 X86ManagedRegister dest = mdest.AsX86(); 264 CHECK(dest.IsCpuRegister() && dest.IsCpuRegister()); 265 __ movl(dest.AsCpuRegister(), Address(base.AsX86().AsCpuRegister(), offs)); 266} 267 268void X86JNIMacroAssembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset32 offs) { 269 X86ManagedRegister dest = mdest.AsX86(); 270 CHECK(dest.IsCpuRegister()); 271 __ fs()->movl(dest.AsCpuRegister(), Address::Absolute(offs)); 272} 273 274void X86JNIMacroAssembler::SignExtend(ManagedRegister mreg, size_t size) { 275 X86ManagedRegister reg = mreg.AsX86(); 276 CHECK(size == 1 || size == 2) << size; 277 CHECK(reg.IsCpuRegister()) << reg; 278 if (size == 1) { 279 __ movsxb(reg.AsCpuRegister(), reg.AsByteRegister()); 280 } else { 281 __ movsxw(reg.AsCpuRegister(), reg.AsCpuRegister()); 282 } 283} 284 285void X86JNIMacroAssembler::ZeroExtend(ManagedRegister mreg, size_t size) { 286 X86ManagedRegister reg = mreg.AsX86(); 287 CHECK(size == 1 || size == 2) << size; 288 CHECK(reg.IsCpuRegister()) << reg; 289 if (size == 1) { 290 __ movzxb(reg.AsCpuRegister(), reg.AsByteRegister()); 291 } else { 292 __ movzxw(reg.AsCpuRegister(), reg.AsCpuRegister()); 293 } 294} 295 296void X86JNIMacroAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) { 297 X86ManagedRegister dest = mdest.AsX86(); 298 X86ManagedRegister src = msrc.AsX86(); 299 if (!dest.Equals(src)) { 300 if (dest.IsCpuRegister() && src.IsCpuRegister()) { 301 __ movl(dest.AsCpuRegister(), src.AsCpuRegister()); 302 } else if (src.IsX87Register() && dest.IsXmmRegister()) { 303 // Pass via stack and pop X87 register 304 __ subl(ESP, Immediate(16)); 305 if (size == 4) { 306 CHECK_EQ(src.AsX87Register(), ST0); 307 __ fstps(Address(ESP, 0)); 308 __ movss(dest.AsXmmRegister(), Address(ESP, 0)); 309 } else { 310 CHECK_EQ(src.AsX87Register(), ST0); 311 __ fstpl(Address(ESP, 0)); 312 __ movsd(dest.AsXmmRegister(), Address(ESP, 0)); 313 } 314 __ addl(ESP, Immediate(16)); 315 } else { 316 // TODO: x87, SSE 317 UNIMPLEMENTED(FATAL) << ": Move " << dest << ", " << src; 318 } 319 } 320} 321 322void X86JNIMacroAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) { 323 X86ManagedRegister scratch = mscratch.AsX86(); 324 CHECK(scratch.IsCpuRegister()); 325 __ movl(scratch.AsCpuRegister(), Address(ESP, src)); 326 __ movl(Address(ESP, dest), scratch.AsCpuRegister()); 327} 328 329void X86JNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs, 330 ThreadOffset32 thr_offs, 331 ManagedRegister mscratch) { 332 X86ManagedRegister scratch = mscratch.AsX86(); 333 CHECK(scratch.IsCpuRegister()); 334 __ fs()->movl(scratch.AsCpuRegister(), Address::Absolute(thr_offs)); 335 Store(fr_offs, scratch, 4); 336} 337 338void X86JNIMacroAssembler::CopyRawPtrToThread(ThreadOffset32 thr_offs, 339 FrameOffset fr_offs, 340 ManagedRegister mscratch) { 341 X86ManagedRegister scratch = mscratch.AsX86(); 342 CHECK(scratch.IsCpuRegister()); 343 Load(scratch, fr_offs, 4); 344 __ fs()->movl(Address::Absolute(thr_offs), scratch.AsCpuRegister()); 345} 346 347void X86JNIMacroAssembler::Copy(FrameOffset dest, FrameOffset src, 348 ManagedRegister mscratch, 349 size_t size) { 350 X86ManagedRegister scratch = mscratch.AsX86(); 351 if (scratch.IsCpuRegister() && size == 8) { 352 Load(scratch, src, 4); 353 Store(dest, scratch, 4); 354 Load(scratch, FrameOffset(src.Int32Value() + 4), 4); 355 Store(FrameOffset(dest.Int32Value() + 4), scratch, 4); 356 } else { 357 Load(scratch, src, size); 358 Store(dest, scratch, size); 359 } 360} 361 362void X86JNIMacroAssembler::Copy(FrameOffset /*dst*/, 363 ManagedRegister /*src_base*/, 364 Offset /*src_offset*/, 365 ManagedRegister /*scratch*/, 366 size_t /*size*/) { 367 UNIMPLEMENTED(FATAL); 368} 369 370void X86JNIMacroAssembler::Copy(ManagedRegister dest_base, 371 Offset dest_offset, 372 FrameOffset src, 373 ManagedRegister scratch, 374 size_t size) { 375 CHECK(scratch.IsNoRegister()); 376 CHECK_EQ(size, 4u); 377 __ pushl(Address(ESP, src)); 378 __ popl(Address(dest_base.AsX86().AsCpuRegister(), dest_offset)); 379} 380 381void X86JNIMacroAssembler::Copy(FrameOffset dest, 382 FrameOffset src_base, 383 Offset src_offset, 384 ManagedRegister mscratch, 385 size_t size) { 386 Register scratch = mscratch.AsX86().AsCpuRegister(); 387 CHECK_EQ(size, 4u); 388 __ movl(scratch, Address(ESP, src_base)); 389 __ movl(scratch, Address(scratch, src_offset)); 390 __ movl(Address(ESP, dest), scratch); 391} 392 393void X86JNIMacroAssembler::Copy(ManagedRegister dest, 394 Offset dest_offset, 395 ManagedRegister src, 396 Offset src_offset, 397 ManagedRegister scratch, 398 size_t size) { 399 CHECK_EQ(size, 4u); 400 CHECK(scratch.IsNoRegister()); 401 __ pushl(Address(src.AsX86().AsCpuRegister(), src_offset)); 402 __ popl(Address(dest.AsX86().AsCpuRegister(), dest_offset)); 403} 404 405void X86JNIMacroAssembler::Copy(FrameOffset dest, 406 Offset dest_offset, 407 FrameOffset src, 408 Offset src_offset, 409 ManagedRegister mscratch, 410 size_t size) { 411 Register scratch = mscratch.AsX86().AsCpuRegister(); 412 CHECK_EQ(size, 4u); 413 CHECK_EQ(dest.Int32Value(), src.Int32Value()); 414 __ movl(scratch, Address(ESP, src)); 415 __ pushl(Address(scratch, src_offset)); 416 __ popl(Address(scratch, dest_offset)); 417} 418 419void X86JNIMacroAssembler::MemoryBarrier(ManagedRegister) { 420 __ mfence(); 421} 422 423void X86JNIMacroAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg, 424 FrameOffset handle_scope_offset, 425 ManagedRegister min_reg, 426 bool null_allowed) { 427 X86ManagedRegister out_reg = mout_reg.AsX86(); 428 X86ManagedRegister in_reg = min_reg.AsX86(); 429 CHECK(in_reg.IsCpuRegister()); 430 CHECK(out_reg.IsCpuRegister()); 431 VerifyObject(in_reg, null_allowed); 432 if (null_allowed) { 433 Label null_arg; 434 if (!out_reg.Equals(in_reg)) { 435 __ xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister()); 436 } 437 __ testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister()); 438 __ j(kZero, &null_arg); 439 __ leal(out_reg.AsCpuRegister(), Address(ESP, handle_scope_offset)); 440 __ Bind(&null_arg); 441 } else { 442 __ leal(out_reg.AsCpuRegister(), Address(ESP, handle_scope_offset)); 443 } 444} 445 446void X86JNIMacroAssembler::CreateHandleScopeEntry(FrameOffset out_off, 447 FrameOffset handle_scope_offset, 448 ManagedRegister mscratch, 449 bool null_allowed) { 450 X86ManagedRegister scratch = mscratch.AsX86(); 451 CHECK(scratch.IsCpuRegister()); 452 if (null_allowed) { 453 Label null_arg; 454 __ movl(scratch.AsCpuRegister(), Address(ESP, handle_scope_offset)); 455 __ testl(scratch.AsCpuRegister(), scratch.AsCpuRegister()); 456 __ j(kZero, &null_arg); 457 __ leal(scratch.AsCpuRegister(), Address(ESP, handle_scope_offset)); 458 __ Bind(&null_arg); 459 } else { 460 __ leal(scratch.AsCpuRegister(), Address(ESP, handle_scope_offset)); 461 } 462 Store(out_off, scratch, 4); 463} 464 465// Given a handle scope entry, load the associated reference. 466void X86JNIMacroAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg, 467 ManagedRegister min_reg) { 468 X86ManagedRegister out_reg = mout_reg.AsX86(); 469 X86ManagedRegister in_reg = min_reg.AsX86(); 470 CHECK(out_reg.IsCpuRegister()); 471 CHECK(in_reg.IsCpuRegister()); 472 Label null_arg; 473 if (!out_reg.Equals(in_reg)) { 474 __ xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister()); 475 } 476 __ testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister()); 477 __ j(kZero, &null_arg); 478 __ movl(out_reg.AsCpuRegister(), Address(in_reg.AsCpuRegister(), 0)); 479 __ Bind(&null_arg); 480} 481 482void X86JNIMacroAssembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) { 483 // TODO: not validating references 484} 485 486void X86JNIMacroAssembler::VerifyObject(FrameOffset /*src*/, bool /*could_be_null*/) { 487 // TODO: not validating references 488} 489 490void X86JNIMacroAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister) { 491 X86ManagedRegister base = mbase.AsX86(); 492 CHECK(base.IsCpuRegister()); 493 __ call(Address(base.AsCpuRegister(), offset.Int32Value())); 494 // TODO: place reference map on call 495} 496 497void X86JNIMacroAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) { 498 Register scratch = mscratch.AsX86().AsCpuRegister(); 499 __ movl(scratch, Address(ESP, base)); 500 __ call(Address(scratch, offset)); 501} 502 503void X86JNIMacroAssembler::CallFromThread(ThreadOffset32 offset, ManagedRegister /*mscratch*/) { 504 __ fs()->call(Address::Absolute(offset)); 505} 506 507void X86JNIMacroAssembler::GetCurrentThread(ManagedRegister tr) { 508 __ fs()->movl(tr.AsX86().AsCpuRegister(), 509 Address::Absolute(Thread::SelfOffset<kX86PointerSize>())); 510} 511 512void X86JNIMacroAssembler::GetCurrentThread(FrameOffset offset, 513 ManagedRegister mscratch) { 514 X86ManagedRegister scratch = mscratch.AsX86(); 515 __ fs()->movl(scratch.AsCpuRegister(), Address::Absolute(Thread::SelfOffset<kX86PointerSize>())); 516 __ movl(Address(ESP, offset), scratch.AsCpuRegister()); 517} 518 519void X86JNIMacroAssembler::ExceptionPoll(ManagedRegister /*scratch*/, size_t stack_adjust) { 520 X86ExceptionSlowPath* slow = new (__ GetArena()) X86ExceptionSlowPath(stack_adjust); 521 __ GetBuffer()->EnqueueSlowPath(slow); 522 __ fs()->cmpl(Address::Absolute(Thread::ExceptionOffset<kX86PointerSize>()), Immediate(0)); 523 __ j(kNotEqual, slow->Entry()); 524} 525 526std::unique_ptr<JNIMacroLabel> X86JNIMacroAssembler::CreateLabel() { 527 return std::unique_ptr<JNIMacroLabel>(new X86JNIMacroLabel()); 528} 529 530void X86JNIMacroAssembler::Jump(JNIMacroLabel* label) { 531 CHECK(label != nullptr); 532 __ jmp(X86JNIMacroLabel::Cast(label)->AsX86()); 533} 534 535void X86JNIMacroAssembler::Jump(JNIMacroLabel* label, 536 JNIMacroUnaryCondition condition, 537 ManagedRegister test) { 538 CHECK(label != nullptr); 539 540 art::x86::Condition x86_cond; 541 switch (condition) { 542 case JNIMacroUnaryCondition::kZero: 543 x86_cond = art::x86::kZero; 544 break; 545 case JNIMacroUnaryCondition::kNotZero: 546 x86_cond = art::x86::kNotZero; 547 break; 548 default: 549 LOG(FATAL) << "Not implemented condition: " << static_cast<int>(condition); 550 UNREACHABLE(); 551 } 552 553 // TEST reg, reg 554 // Jcc <Offset> 555 __ testl(test.AsX86().AsCpuRegister(), test.AsX86().AsCpuRegister()); 556 __ j(x86_cond, X86JNIMacroLabel::Cast(label)->AsX86()); 557 558 559 // X86 also has JCZX, JECZX, however it's not worth it to implement 560 // because we aren't likely to codegen with ECX+kZero check. 561} 562 563void X86JNIMacroAssembler::Bind(JNIMacroLabel* label) { 564 CHECK(label != nullptr); 565 __ Bind(X86JNIMacroLabel::Cast(label)->AsX86()); 566} 567 568#undef __ 569 570void X86ExceptionSlowPath::Emit(Assembler *sasm) { 571 X86Assembler* sp_asm = down_cast<X86Assembler*>(sasm); 572#define __ sp_asm-> 573 __ Bind(&entry_); 574 // Note: the return value is dead 575 if (stack_adjust_ != 0) { // Fix up the frame. 576 DecreaseFrameSizeImpl(sp_asm, stack_adjust_); 577 } 578 // Pass exception as argument in EAX 579 __ fs()->movl(EAX, Address::Absolute(Thread::ExceptionOffset<kX86PointerSize>())); 580 __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86PointerSize, pDeliverException))); 581 // this call should never return 582 __ int3(); 583#undef __ 584} 585 586} // namespace x86 587} // namespace art 588