12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 17bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers#include "context_x86.h" 18bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 19ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method.h" 204f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "stack.h" 2285d1545e985ac689db4bad7849880e843707c862Elliott Hughes 23bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace art { 24bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace x86 { 25bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 266702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartierstatic const uint32_t gZero = 0; 276702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier 286702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartiervoid X86Context::Reset() { 296702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier for (int i = 0; i < kNumberOfCpuRegisters; i++) { 306702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[i] = NULL; 3167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 326702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[ESP] = &esp_; 336702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // Initialize registers with easy to spot debug values. 346702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier esp_ = X86Context::kBadGprBase + ESP; 356702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier eip_ = X86Context::kBadGprBase + kNumberOfCpuRegisters; 3667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers} 3767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers 380399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid X86Context::FillCalleeSaves(const StackVisitor& fr) { 39ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* method = fr.GetMethod(); 4067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers uint32_t core_spills = method->GetCoreSpillMask(); 4167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers size_t spill_count = __builtin_popcount(core_spills); 420399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers DCHECK_EQ(method->GetFpSpillMask(), 0u); 430399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers size_t frame_size = method->GetFrameSizeInBytes(); 4467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers if (spill_count > 0) { 456702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // Lowest number spill is farthest away, walk registers and fill into context. 467caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers int j = 2; // Offset j to skip return address spill. 476702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier for (int i = 0; i < kNumberOfCpuRegisters; i++) { 4867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers if (((core_spills >> i) & 1) != 0) { 496702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size); 5067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers j++; 5167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 5267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 5367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 5467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers} 5567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers 569c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughesvoid X86Context::SmashCallerSaves() { 576702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // This needs to be 0 because we want a null/zero return value. 586702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[EAX] = const_cast<uint32_t*>(&gZero); 596702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[EDX] = const_cast<uint32_t*>(&gZero); 606702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[ECX] = NULL; 616702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[EBX] = NULL; 626702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier} 636702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier 642ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Context::SetGPR(uint32_t reg, uintptr_t value) { 656f675178900a8a20d6c8c74a4a251a49247c706bBrian Carlstrom CHECK_LT(reg, static_cast<uint32_t>(kNumberOfCpuRegisters)); 666702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier CHECK_NE(gprs_[reg], &gZero); 676702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier CHECK(gprs_[reg] != NULL); 686702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier *gprs_[reg] = value; 699c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes} 709c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes 71bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersvoid X86Context::DoLongJump() { 7285d1545e985ac689db4bad7849880e843707c862Elliott Hughes#if defined(__i386__) 736702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // Array of GPR values, filled from the context backward for the long jump pop. We add a slot at 746702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // the top for the stack pointer that doesn't get popped in a pop-all. 756702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier volatile uintptr_t gprs[kNumberOfCpuRegisters + 1]; 766702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) { 776702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs[kNumberOfCpuRegisters - i - 1] = gprs_[i] != NULL ? *gprs_[i] : X86Context::kBadGprBase + i; 786702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier } 796702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // We want to load the stack pointer one slot below so that the ret will pop eip. 806702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier uintptr_t esp = gprs[kNumberOfCpuRegisters - ESP - 1] - kWordSize; 816702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs[kNumberOfCpuRegisters] = esp; 826702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier *(reinterpret_cast<uintptr_t*>(esp)) = eip_; 837834cbd5d8a0e61db14339910d2223a3e59d7efcElliott Hughes __asm__ __volatile__( 846702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "movl %0, %%esp\n\t" // ESP points to gprs. 856702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "popal\n\t" // Load all registers except ESP and EIP with values in gprs. 866702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "popl %%esp\n\t" // Load stack pointer. 876702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "ret\n\t" // From higher in the stack pop eip. 886702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier : // output. 896702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier : "g"(&gprs[0]) // input. 906702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier :); // clobber. 9185d1545e985ac689db4bad7849880e843707c862Elliott Hughes#else 9267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers UNIMPLEMENTED(FATAL); 9385d1545e985ac689db4bad7849880e843707c862Elliott Hughes#endif 94bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 95bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 96bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} // namespace x86 97bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} // namespace art 98