context_x86.cc revision 9c750f9b6283f62b3e6a93c0c6b2838abde5000e
19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* 29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Copyright (C) 2011 The Android Open Source Project 39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * 49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Licensed under the Apache License, Version 2.0 (the "License"); 59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * you may not use this file except in compliance with the License. 69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * You may obtain a copy of the License at 79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * 89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * http://www.apache.org/licenses/LICENSE-2.0 99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * 109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Unless required by applicable law or agreed to in writing, software 119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * distributed under the License is distributed on an "AS IS" BASIS, 129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * See the License for the specific language governing permissions and 149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * limitations under the License. 159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */ 169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "context_x86.h" 189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "object.h" 209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallnamespace art { 229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallnamespace x86 { 239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallX86Context::X86Context() { 259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef NDEBUG 269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall // Initialize registers with easy to spot debug values. 279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall for (int i = 0; i < 8; i++) { 289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gprs_[i] = kBadGprBase + i; 299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall eip_ = 0xEBAD601F; 319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif 329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid X86Context::FillCalleeSaves(const Frame& fr) { 359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Method* method = fr.GetMethod(); 369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall uint32_t core_spills = method->GetCoreSpillMask(); 379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall size_t spill_count = __builtin_popcount(core_spills); 389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall CHECK_EQ(method->GetFpSpillMask(), 0u); 399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (spill_count > 0) { 409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall // Lowest number spill is furthest away, walk registers and fill into context. 419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall int j = 2; // Offset j to skip return address spill. 429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall for (int i = 0; i < 8; i++) { 439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (((core_spills >> i) & 1) != 0) { 449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gprs_[i] = fr.LoadCalleeSave(spill_count - j); 459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall j++; 469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid X86Context::SmashCallerSaves() { 529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gprs_[EAX] = 0; // This needs to be 0 because we want a null/zero return value. 539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gprs_[ECX] = kBadGprBase + ECX; 549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gprs_[EDX] = kBadGprBase + EDX; 559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gprs_[EBX] = kBadGprBase + EBX; 569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid X86Context::DoLongJump() { 599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(__i386__) 609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall // We push all the registers using memory-memory pushes, we then pop-all to get the registers 619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall // set up, we then pop esp which will move us down the stack to the delivery address. At the frame 629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall // where the exception will be delivered, we push EIP so that the return will take us to the 639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall // correct delivery instruction. 649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gprs_[ESP] -= 4; 659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *(reinterpret_cast<uintptr_t*>(gprs_[ESP])) = eip_; 669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall asm volatile( 679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %4\n\t" 689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %0\n\t" 699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %1\n\t" 709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %2\n\t" 719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %3\n\t" 729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %4\n\t" 739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %5\n\t" 749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %6\n\t" 759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "pushl %7\n\t" 769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "popal\n\t" 779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "popl %%esp\n\t" 789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "ret\n\t" 799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall : //output 809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall : "g"(gprs_[EAX]), "g"(gprs_[ECX]), "g"(gprs_[EDX]), "g"(gprs_[EBX]), 819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "g"(gprs_[ESP]), "g"(gprs_[EBP]), "g"(gprs_[ESI]), "g"(gprs_[EDI]) 829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall :); // clobber 839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else 849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UNIMPLEMENTED(FATAL); 859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif 869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} // namespace x86 899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} // namespace art 909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall