blob: 2e7605064e403058626fd6db2b405657b76621dc [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_arm.h"
18
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019#include "mirror/abstract_method.h"
20#include "stack.h"
21#include "thread.h"
Ian Rogersbdb03912011-09-14 00:55:44 -070022
23namespace art {
24namespace arm {
25
Mathieu Chartier67022432012-11-29 18:04:50 -080026static const uint32_t gZero = 0;
27
28void ArmContext::Reset() {
29 for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
30 gprs_[i] = NULL;
Ian Rogersbdb03912011-09-14 00:55:44 -070031 }
Mathieu Chartier67022432012-11-29 18:04:50 -080032 for (size_t i = 0; i < kNumberOfSRegisters; i++) {
33 fprs_[i] = NULL;
Ian Rogers15fdb8c2011-09-25 15:45:07 -070034 }
Mathieu Chartier67022432012-11-29 18:04:50 -080035 gprs_[SP] = &sp_;
36 gprs_[PC] = &pc_;
37 // Initialize registers with easy to spot debug values.
38 sp_ = ArmContext::kBadGprBase + SP;
39 pc_ = ArmContext::kBadGprBase + PC;
Ian Rogersbdb03912011-09-14 00:55:44 -070040}
41
Ian Rogers0399dde2012-06-06 17:09:28 -070042void ArmContext::FillCalleeSaves(const StackVisitor& fr) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080043 mirror::AbstractMethod* method = fr.GetMethod();
Ian Rogersbdb03912011-09-14 00:55:44 -070044 uint32_t core_spills = method->GetCoreSpillMask();
Ian Rogers15fdb8c2011-09-25 15:45:07 -070045 uint32_t fp_core_spills = method->GetFpSpillMask();
Ian Rogersbdb03912011-09-14 00:55:44 -070046 size_t spill_count = __builtin_popcount(core_spills);
Ian Rogers15fdb8c2011-09-25 15:45:07 -070047 size_t fp_spill_count = __builtin_popcount(fp_core_spills);
Ian Rogers0399dde2012-06-06 17:09:28 -070048 size_t frame_size = method->GetFrameSizeInBytes();
Ian Rogersbdb03912011-09-14 00:55:44 -070049 if (spill_count > 0) {
Mathieu Chartier67022432012-11-29 18:04:50 -080050 // Lowest number spill is farthest away, walk registers and fill into context
Ian Rogersbdb03912011-09-14 00:55:44 -070051 int j = 1;
Mathieu Chartier67022432012-11-29 18:04:50 -080052 for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
Ian Rogersbdb03912011-09-14 00:55:44 -070053 if (((core_spills >> i) & 1) != 0) {
Mathieu Chartier67022432012-11-29 18:04:50 -080054 gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size);
Ian Rogersbdb03912011-09-14 00:55:44 -070055 j++;
56 }
57 }
58 }
Ian Rogers15fdb8c2011-09-25 15:45:07 -070059 if (fp_spill_count > 0) {
Mathieu Chartier67022432012-11-29 18:04:50 -080060 // Lowest number spill is farthest away, walk registers and fill into context
Ian Rogers15fdb8c2011-09-25 15:45:07 -070061 int j = 1;
Mathieu Chartier67022432012-11-29 18:04:50 -080062 for (size_t i = 0; i < kNumberOfSRegisters; i++) {
Ian Rogers15fdb8c2011-09-25 15:45:07 -070063 if (((fp_core_spills >> i) & 1) != 0) {
Mathieu Chartier67022432012-11-29 18:04:50 -080064 fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j, frame_size);
Ian Rogers15fdb8c2011-09-25 15:45:07 -070065 j++;
66 }
67 }
68 }
Ian Rogersbdb03912011-09-14 00:55:44 -070069}
70
Mathieu Chartier67022432012-11-29 18:04:50 -080071void ArmContext::SetGPR(uint32_t reg, uintptr_t value) {
72 CHECK_LT(reg, kNumberOfCoreRegisters);
73 CHECK_NE(gprs_[reg], &gZero); // Can't overwrite this static value since they are never reset.
74 CHECK(gprs_[reg] != NULL);
75 *gprs_[reg] = value;
76}
77
Elliott Hughes9c750f92012-04-05 12:07:59 -070078void ArmContext::SmashCallerSaves() {
Mathieu Chartier67022432012-11-29 18:04:50 -080079 // This needs to be 0 because we want a null/zero return value.
80 gprs_[R0] = const_cast<uint32_t*>(&gZero);
81 gprs_[R1] = const_cast<uint32_t*>(&gZero);
82 gprs_[R2] = NULL;
83 gprs_[R3] = NULL;
Elliott Hughes9c750f92012-04-05 12:07:59 -070084}
85
Ian Rogers57b86d42012-03-27 16:05:41 -070086extern "C" void art_do_long_jump(uint32_t*, uint32_t*);
87
Ian Rogersbdb03912011-09-14 00:55:44 -070088void ArmContext::DoLongJump() {
Mathieu Chartier67022432012-11-29 18:04:50 -080089 uintptr_t gprs[16];
90 uint32_t fprs[32];
91 for (size_t i = 0; i < kNumberOfCoreRegisters; ++i) {
92 gprs[i] = gprs_[i] != NULL ? *gprs_[i] : ArmContext::kBadGprBase + i;
93 }
94 for (size_t i = 0; i < kNumberOfSRegisters; ++i) {
95 fprs[i] = fprs_[i] != NULL ? *fprs_[i] : ArmContext::kBadGprBase + i;
96 }
97 DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]);
98 art_do_long_jump(gprs, fprs);
Ian Rogersbdb03912011-09-14 00:55:44 -070099}
100
101} // namespace arm
102} // namespace art