blob: 2af95bb9d7e058ae41fb834bc0c52408d26dad2b [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++) {
Ian Rogers67375ac2011-09-14 00:55:44 -070028 gprs_[i] = 0xEBAD6070+i;
29 }
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
Ian Rogersbdb03912011-09-14 00:55:44 -070051void X86Context::DoLongJump() {
Elliott Hughes85d15452011-09-16 17:33:01 -070052#if defined(__i386__)
Ian Rogers7caad772012-03-30 01:07:54 -070053 // We push all the registers using memory-memory pushes, we then pop-all to get the registers
54 // set up, we then pop esp which will move us down the stack to the delivery address. At the frame
55 // where the exception will be delivered, we push EIP so that the return will take us to the
56 // correct delivery instruction.
57 gprs_[ESP] -= 4;
Elliott Hughesba8eee12012-01-24 20:25:24 -080058 *(reinterpret_cast<uintptr_t*>(gprs_[ESP])) = eip_;
Elliott Hughes362f9bc2011-10-17 18:56:41 -070059 asm volatile(
Ian Rogers67375ac2011-09-14 00:55:44 -070060 "pushl %4\n\t"
61 "pushl %0\n\t"
62 "pushl %1\n\t"
63 "pushl %2\n\t"
64 "pushl %3\n\t"
65 "pushl %4\n\t"
66 "pushl %5\n\t"
67 "pushl %6\n\t"
68 "pushl %7\n\t"
69 "popal\n\t"
70 "popl %%esp\n\t"
71 "ret\n\t"
72 : //output
73 : "g"(gprs_[EAX]), "g"(gprs_[ECX]), "g"(gprs_[EDX]), "g"(gprs_[EBX]),
74 "g"(gprs_[ESP]), "g"(gprs_[EBP]), "g"(gprs_[ESI]), "g"(gprs_[EDI])
Ian Rogersbdb03912011-09-14 00:55:44 -070075 :); // clobber
Elliott Hughes85d15452011-09-16 17:33:01 -070076#else
Ian Rogers67375ac2011-09-14 00:55:44 -070077 UNIMPLEMENTED(FATAL);
Elliott Hughes85d15452011-09-16 17:33:01 -070078#endif
Ian Rogersbdb03912011-09-14 00:55:44 -070079}
80
81} // namespace x86
82} // namespace art