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