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