blob: d6f45da0118777be0605e715d2543f95a5ca0d4a [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Ian Rogersbdb03912011-09-14 00:55:44 -070016
17#include "context_x86.h"
18
Ian Rogers67375ac2011-09-14 00:55:44 -070019#include "object.h"
Elliott Hughes85d15452011-09-16 17:33:01 -070020
Ian Rogersbdb03912011-09-14 00:55:44 -070021namespace art {
22namespace x86 {
23
Ian Rogers67375ac2011-09-14 00:55:44 -070024X86Context::X86Context() {
Ian Rogersad42e132011-09-17 20:23:33 -070025#ifndef NDEBUG
Ian Rogers7caad772012-03-30 01:07:54 -070026 // Initialize registers with easy to spot debug values.
Elliott Hughesba8eee12012-01-24 20:25:24 -080027 for (int i = 0; i < 8; i++) {
Elliott Hughes9c750f92012-04-05 12:07:59 -070028 gprs_[i] = kBadGprBase + i;
Ian Rogers67375ac2011-09-14 00:55:44 -070029 }
Ian Rogersad42e132011-09-17 20:23:33 -070030 eip_ = 0xEBAD601F;
31#endif
Ian Rogers67375ac2011-09-14 00:55:44 -070032}
33
34void X86Context::FillCalleeSaves(const Frame& fr) {
35 Method* method = fr.GetMethod();
36 uint32_t core_spills = method->GetCoreSpillMask();
37 size_t spill_count = __builtin_popcount(core_spills);
38 CHECK_EQ(method->GetFpSpillMask(), 0u);
39 if (spill_count > 0) {
Ian Rogers7caad772012-03-30 01:07:54 -070040 // Lowest number spill is furthest away, walk registers and fill into context.
41 int j = 2; // Offset j to skip return address spill.
Elliott Hughes362f9bc2011-10-17 18:56:41 -070042 for (int i = 0; i < 8; i++) {
Ian Rogers67375ac2011-09-14 00:55:44 -070043 if (((core_spills >> i) & 1) != 0) {
44 gprs_[i] = fr.LoadCalleeSave(spill_count - j);
45 j++;
46 }
47 }
48 }
49}
50
Elliott Hughes9c750f92012-04-05 12:07:59 -070051void X86Context::SmashCallerSaves() {
52 gprs_[EAX] = 0; // This needs to be 0 because we want a null/zero return value.
53 gprs_[ECX] = kBadGprBase + ECX;
54 gprs_[EDX] = kBadGprBase + EDX;
55 gprs_[EBX] = kBadGprBase + EBX;
56}
57
Ian Rogersbdb03912011-09-14 00:55:44 -070058void X86Context::DoLongJump() {
Elliott Hughes85d15452011-09-16 17:33:01 -070059#if defined(__i386__)
Ian Rogers7caad772012-03-30 01:07:54 -070060 // We push all the registers using memory-memory pushes, we then pop-all to get the registers
61 // set up, we then pop esp which will move us down the stack to the delivery address. At the frame
62 // where the exception will be delivered, we push EIP so that the return will take us to the
63 // correct delivery instruction.
64 gprs_[ESP] -= 4;
Elliott Hughesba8eee12012-01-24 20:25:24 -080065 *(reinterpret_cast<uintptr_t*>(gprs_[ESP])) = eip_;
Elliott Hughes362f9bc2011-10-17 18:56:41 -070066 asm volatile(
Ian Rogers67375ac2011-09-14 00:55:44 -070067 "pushl %4\n\t"
68 "pushl %0\n\t"
69 "pushl %1\n\t"
70 "pushl %2\n\t"
71 "pushl %3\n\t"
72 "pushl %4\n\t"
73 "pushl %5\n\t"
74 "pushl %6\n\t"
75 "pushl %7\n\t"
76 "popal\n\t"
77 "popl %%esp\n\t"
78 "ret\n\t"
79 : //output
80 : "g"(gprs_[EAX]), "g"(gprs_[ECX]), "g"(gprs_[EDX]), "g"(gprs_[EBX]),
81 "g"(gprs_[ESP]), "g"(gprs_[EBP]), "g"(gprs_[ESI]), "g"(gprs_[EDI])
Ian Rogersbdb03912011-09-14 00:55:44 -070082 :); // clobber
Elliott Hughes85d15452011-09-16 17:33:01 -070083#else
Ian Rogers67375ac2011-09-14 00:55:44 -070084 UNIMPLEMENTED(FATAL);
Elliott Hughes85d15452011-09-16 17:33:01 -070085#endif
Ian Rogersbdb03912011-09-14 00:55:44 -070086}
87
88} // namespace x86
89} // namespace art