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 1980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/bit_utils.h" 207624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko#include "quick/quick_method_frame_info.h" 2185d1545e985ac689db4bad7849880e843707c862Elliott Hughes 22bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace art { 23bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace x86 { 24bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 250bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertzstatic constexpr uintptr_t gZero = 0; 266702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier 276702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartiervoid X86Context::Reset() { 2880afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko std::fill_n(gprs_, arraysize(gprs_), nullptr); 2980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko std::fill_n(fprs_, arraysize(fprs_), nullptr); 306702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs_[ESP] = &esp_; 31639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe gprs_[EAX] = &arg0_; 326702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // Initialize registers with easy to spot debug values. 336702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier esp_ = X86Context::kBadGprBase + ESP; 346702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier eip_ = X86Context::kBadGprBase + kNumberOfCpuRegisters; 35639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe arg0_ = 0; 3667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers} 3767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers 38524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffrayvoid X86Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& frame_info) { 3980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko int spill_pos = 0; 4080afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko 4180afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko // Core registers come first, from the highest down to the lowest. 4280afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko uint32_t core_regs = 4380afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko frame_info.CoreSpillMask() & ~(static_cast<uint32_t>(-1) << kNumberOfCpuRegisters); 4480afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko DCHECK_EQ(1, POPCOUNT(frame_info.CoreSpillMask() & ~core_regs)); // Return address spill. 4580afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko for (uint32_t core_reg : HighToLowBits(core_regs)) { 46524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes()); 4780afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko ++spill_pos; 4867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 4980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) - 1); 5080afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko 5180afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko // FP registers come second, from the highest down to the lowest. 5280afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko uint32_t fp_regs = frame_info.FpSpillMask(); 5380afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko DCHECK_EQ(0u, fp_regs & (static_cast<uint32_t>(-1) << kNumberOfFloatRegisters)); 5480afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko for (uint32_t fp_reg : HighToLowBits(fp_regs)) { 5580afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko // Two void* per XMM register. 560eb42511405f3919572a480a009426dfb776cfb5Vladimir Marko fprs_[2 * fp_reg] = reinterpret_cast<uint32_t*>( 57524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray CalleeSaveAddress(frame, spill_pos + 1, frame_info.FrameSizeInBytes())); 580eb42511405f3919572a480a009426dfb776cfb5Vladimir Marko fprs_[2 * fp_reg + 1] = reinterpret_cast<uint32_t*>( 59524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes())); 6080afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko spill_pos += 2; 61966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell } 6280afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko DCHECK_EQ(spill_pos, 6380afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko POPCOUNT(frame_info.CoreSpillMask()) - 1 + 2 * POPCOUNT(frame_info.FpSpillMask())); 6467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers} 6567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers 669c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughesvoid X86Context::SmashCallerSaves() { 676702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // This needs to be 0 because we want a null/zero return value. 68ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers gprs_[EAX] = const_cast<uintptr_t*>(&gZero); 69ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers gprs_[EDX] = const_cast<uintptr_t*>(&gZero); 700bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz gprs_[ECX] = nullptr; 710bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz gprs_[EBX] = nullptr; 72966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell memset(&fprs_[0], '\0', sizeof(fprs_)); 736702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier} 746702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier 7596ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertzvoid X86Context::SetGPR(uint32_t reg, uintptr_t value) { 766f675178900a8a20d6c8c74a4a251a49247c706bBrian Carlstrom CHECK_LT(reg, static_cast<uint32_t>(kNumberOfCpuRegisters)); 7796ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz DCHECK(IsAccessibleGPR(reg)); 786702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier CHECK_NE(gprs_[reg], &gZero); 7996ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz *gprs_[reg] = value; 809c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes} 819c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes 82966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendellvoid X86Context::SetFPR(uint32_t reg, uintptr_t value) { 83966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell CHECK_LT(reg, static_cast<uint32_t>(kNumberOfFloatRegisters)); 84966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell DCHECK(IsAccessibleFPR(reg)); 85966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell CHECK_NE(fprs_[reg], reinterpret_cast<const uint32_t*>(&gZero)); 86966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell *fprs_[reg] = value; 876a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers} 886a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers 89bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersvoid X86Context::DoLongJump() { 9085d1545e985ac689db4bad7849880e843707c862Elliott Hughes#if defined(__i386__) 916702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // Array of GPR values, filled from the context backward for the long jump pop. We add a slot at 926702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // the top for the stack pointer that doesn't get popped in a pop-all. 936702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier volatile uintptr_t gprs[kNumberOfCpuRegisters + 1]; 946702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) { 950bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz gprs[kNumberOfCpuRegisters - i - 1] = gprs_[i] != nullptr ? *gprs_[i] : X86Context::kBadGprBase + i; 966702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier } 97966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell uint32_t fprs[kNumberOfFloatRegisters]; 98966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) { 99966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : X86Context::kBadFprBase + i; 100966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell } 1016702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier // We want to load the stack pointer one slot below so that the ret will pop eip. 10213735955f39b3b304c37d2b2840663c131262c18Ian Rogers uintptr_t esp = gprs[kNumberOfCpuRegisters - ESP - 1] - sizeof(intptr_t); 1036702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier gprs[kNumberOfCpuRegisters] = esp; 1046702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier *(reinterpret_cast<uintptr_t*>(esp)) = eip_; 1057834cbd5d8a0e61db14339910d2223a3e59d7efcElliott Hughes __asm__ __volatile__( 106966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movl %1, %%ebx\n\t" // Address base of FPRs. 107966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movsd 0(%%ebx), %%xmm0\n\t" // Load up XMM0-XMM7. 108966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movsd 8(%%ebx), %%xmm1\n\t" 109966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movsd 16(%%ebx), %%xmm2\n\t" 110966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movsd 24(%%ebx), %%xmm3\n\t" 111966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movsd 32(%%ebx), %%xmm4\n\t" 112966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movsd 40(%%ebx), %%xmm5\n\t" 113966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movsd 48(%%ebx), %%xmm6\n\t" 114966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell "movsd 56(%%ebx), %%xmm7\n\t" 1156702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "movl %0, %%esp\n\t" // ESP points to gprs. 1166702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "popal\n\t" // Load all registers except ESP and EIP with values in gprs. 1176702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "popl %%esp\n\t" // Load stack pointer. 1186702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier "ret\n\t" // From higher in the stack pop eip. 1196702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier : // output. 120966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell : "g"(&gprs[0]), "g"(&fprs[0]) // input. 1216702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier :); // clobber. 12285d1545e985ac689db4bad7849880e843707c862Elliott Hughes#else 123ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers UNIMPLEMENTED(FATAL); 12485d1545e985ac689db4bad7849880e843707c862Elliott Hughes#endif 125794ad76e8d5b5b9132819d5b08a0570e27615644Andreas Gampe UNREACHABLE(); 126bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 127bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 128bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} // namespace x86 129bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} // namespace art 130