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