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 197624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko#include "mirror/art_method-inl.h" 204f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 217624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko#include "quick/quick_method_frame_info.h" 222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "stack.h" 2385d1545e985ac689db4bad7849880e843707c862Elliott Hughes 24bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace art { 25bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace x86 { 26bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 270bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertzstatic constexpr uintptr_t gZero = 0; 286702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier 296702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartiervoid X86Context::Reset() { 30815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier for (size_t i = 0; i < kNumberOfCpuRegisters; i++) { 310bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz gprs_[i] = nullptr; 3267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 336702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[ESP] = &esp_; 346702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // Initialize registers with easy to spot debug values. 356702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier esp_ = X86Context::kBadGprBase + ESP; 366702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier eip_ = X86Context::kBadGprBase + kNumberOfCpuRegisters; 3767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers} 3867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers 390399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid X86Context::FillCalleeSaves(const StackVisitor& fr) { 40ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* method = fr.GetMethod(); 417624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo(); 427624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko size_t spill_count = POPCOUNT(frame_info.CoreSpillMask()); 437624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko DCHECK_EQ(frame_info.FpSpillMask(), 0u); 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++) { 487624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko if (((frame_info.CoreSpillMask() >> i) & 1) != 0) { 497624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes()); 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. 58ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers gprs_[EAX] = const_cast<uintptr_t*>(&gZero); 59ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers gprs_[EDX] = const_cast<uintptr_t*>(&gZero); 600bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz gprs_[ECX] = nullptr; 610bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz gprs_[EBX] = nullptr; 626702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier} 636702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier 640bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertzbool 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); 670bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz if (gprs_[reg] != nullptr) { 680bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz *gprs_[reg] = value; 690bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz return true; 700bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz } else { 710bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz return false; 720bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz } 739c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes} 749c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes 75bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersvoid X86Context::DoLongJump() { 7685d1545e985ac689db4bad7849880e843707c862Elliott Hughes#if defined(__i386__) 776702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // Array of GPR values, filled from the context backward for the long jump pop. We add a slot at 786702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // the top for the stack pointer that doesn't get popped in a pop-all. 796702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier volatile uintptr_t gprs[kNumberOfCpuRegisters + 1]; 806702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) { 810bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz gprs[kNumberOfCpuRegisters - i - 1] = gprs_[i] != nullptr ? *gprs_[i] : X86Context::kBadGprBase + i; 826702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier } 836702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // We want to load the stack pointer one slot below so that the ret will pop eip. 846702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier uintptr_t esp = gprs[kNumberOfCpuRegisters - ESP - 1] - kWordSize; 856702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs[kNumberOfCpuRegisters] = esp; 866702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier *(reinterpret_cast<uintptr_t*>(esp)) = eip_; 877834cbd5d8a0e61db14339910d2223a3e59d7efcElliott Hughes __asm__ __volatile__( 886702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "movl %0, %%esp\n\t" // ESP points to gprs. 896702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "popal\n\t" // Load all registers except ESP and EIP with values in gprs. 906702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "popl %%esp\n\t" // Load stack pointer. 916702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "ret\n\t" // From higher in the stack pop eip. 926702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier : // output. 936702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier : "g"(&gprs[0]) // input. 946702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier :); // clobber. 9585d1545e985ac689db4bad7849880e843707c862Elliott Hughes#else 96ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers UNIMPLEMENTED(FATAL); 9785d1545e985ac689db4bad7849880e843707c862Elliott Hughes#endif 98bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 99bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 100bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} // namespace x86 101bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} // namespace art 102