1723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris/*
2723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Copyright (C) 2016 The Android Open Source Project
3723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *
4723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License");
5723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * you may not use this file except in compliance with the License.
6723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * You may obtain a copy of the License at
7723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *
8723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *      http://www.apache.org/licenses/LICENSE-2.0
9723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *
10723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Unless required by applicable law or agreed to in writing, software
11723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS,
12723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * See the License for the specific language governing permissions and
14723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * limitations under the License.
15723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris */
16723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
17723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <stdint.h>
18723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
19723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <deque>
20723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <string>
21723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
22723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <android-base/stringprintf.h>
23723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
24d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Log.h>
2553914165e4a19e4a320cf3394e4fabff4e89d7c6Christopher Ferris#include <unwindstack/MachineArm.h>
26d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Memory.h>
27d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris#include <unwindstack/RegsArm.h>
28d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
29723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include "ArmExidx.h"
309416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris#include "Check.h"
31d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
32d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisnamespace unwindstack {
33723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
34723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisvoid ArmExidx::LogRawData() {
35723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::string log_str("Raw Data:");
36723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (const uint8_t data : data_) {
37723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log_str += android::base::StringPrintf(" 0x%02x", data);
38723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
39723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  log(log_indent_, log_str.c_str());
40723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
41723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
42723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisbool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
43723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  data_.clear();
44723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  status_ = ARM_STATUS_NONE;
45723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
46723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (entry_offset & 1) {
47723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // The offset needs to be at least two byte aligned.
48723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_INVALID_ALIGNMENT;
49723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
50723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
51723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
52723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // Each entry is a 32 bit prel31 offset followed by 32 bits
53723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // of unwind information. If bit 31 of the unwind data is zero,
54723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // then this is a prel31 offset to the start of the unwind data.
55723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // If the unwind data is 1, then this is a cant unwind entry.
56723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // Otherwise, this data is the compact form of the unwind information.
57723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint32_t data;
58723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (!elf_memory_->Read32(entry_offset + 4, &data)) {
59723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_READ_FAILED;
602fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    status_address_ = entry_offset + 4;
61723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
62723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
63723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (data == 1) {
64723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // This is a CANT UNWIND entry.
65723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_NO_UNWIND;
66723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
67723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01");
68723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "[cantunwind]");
69723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
70723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
71723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
72723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
73723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (data & (1UL << 31)) {
74723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // This is a compact table entry.
75723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if ((data >> 24) & 0xf) {
76723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      // This is a non-zero index, this code doesn't support
77723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      // other formats.
78723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_INVALID_PERSONALITY;
79723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
80723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
81723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back((data >> 16) & 0xff);
82723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back((data >> 8) & 0xff);
83723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    uint8_t last_op = data & 0xff;
84723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back(last_op);
85723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (last_op != ARM_OP_FINISH) {
86723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      // If this didn't end with a finish op, add one.
87723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      data_.push_back(ARM_OP_FINISH);
88723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
89723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
90723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      LogRawData();
91723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
92723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return true;
93723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
94723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
95723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // Get the address of the ops.
96723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // Sign extend the data value if necessary.
97723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  int32_t signed_data = static_cast<int32_t>(data << 1) >> 1;
98723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint32_t addr = (entry_offset + 4) + signed_data;
99723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (!elf_memory_->Read32(addr, &data)) {
100723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_READ_FAILED;
1012fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    status_address_ = addr;
102723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
103723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
104723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
105723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  size_t num_table_words;
106723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (data & (1UL << 31)) {
107723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // Compact model.
108723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    switch ((data >> 24) & 0xf) {
109723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    case 0:
110723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      num_table_words = 0;
111723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      data_.push_back((data >> 16) & 0xff);
112723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      break;
113723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    case 1:
114723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    case 2:
115723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      num_table_words = (data >> 16) & 0xff;
116723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      addr += 4;
117723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      break;
118723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    default:
119723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      // Only a personality of 0, 1, 2 is valid.
120723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_INVALID_PERSONALITY;
121723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
122723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
123723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back((data >> 8) & 0xff);
124723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back(data & 0xff);
125723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  } else {
126723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // Generic model.
127723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
128723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // Skip the personality routine data, it doesn't contain any data
129723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // needed to decode the unwind information.
130723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    addr += 4;
131723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!elf_memory_->Read32(addr, &data)) {
132723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_READ_FAILED;
1332fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris      status_address_ = addr;
134723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
135723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
136723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    num_table_words = (data >> 24) & 0xff;
137723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back((data >> 16) & 0xff);
138723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back((data >> 8) & 0xff);
139723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back(data & 0xff);
140723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    addr += 4;
141723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
142723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
143723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (num_table_words > 5) {
144723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_MALFORMED;
145723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
146723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
147723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
148723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t i = 0; i < num_table_words; i++) {
149723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!elf_memory_->Read32(addr, &data)) {
150723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_READ_FAILED;
1512fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris      status_address_ = addr;
152723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
153723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
154723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back((data >> 24) & 0xff);
155723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back((data >> 16) & 0xff);
156723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back((data >> 8) & 0xff);
157723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back(data & 0xff);
158723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    addr += 4;
159723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
160723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
161723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (data_.back() != ARM_OP_FINISH) {
162723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // If this didn't end with a finish op, add one.
163723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data_.push_back(ARM_OP_FINISH);
164723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
165723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
166723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
167723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    LogRawData();
168723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
169723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
170723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
171723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
172723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::GetByte(uint8_t* byte) {
173723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (data_.empty()) {
174723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_TRUNCATED;
175723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
176723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
177723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  *byte = data_.front();
178723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  data_.pop_front();
179723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
180723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
181723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
182723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) {
1839416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte >> 4) == 0x8);
184723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
185723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint16_t registers = (byte & 0xf) << 8;
186723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (!GetByte(&byte)) {
187723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
188723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
189723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
190723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  registers |= byte;
191723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (registers == 0) {
192723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 10000000 00000000: Refuse to unwind
193723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
194723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "Refuse to unwind");
195723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
196723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_NO_UNWIND;
197723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
198723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
199723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}
200723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
201723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    bool add_comma = false;
202723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    std::string msg = "pop {";
203723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    for (size_t i = 0; i < 12; i++) {
204723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (registers & (1 << i)) {
205723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        if (add_comma) {
206723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris          msg += ", ";
207723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        }
208723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        msg += android::base::StringPrintf("r%zu", i + 4);
209723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        add_comma = true;
210723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
211723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
212723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "%s}", msg.c_str());
213723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
214723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return true;
215723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
216723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
217723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
218723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  registers <<= 4;
219723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t reg = 4; reg < 16; reg++) {
220723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (registers & (1 << reg)) {
221723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
222723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        status_ = ARM_STATUS_READ_FAILED;
2232fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris        status_address_ = cfa_;
224723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        return false;
225723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
226723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      cfa_ += 4;
227723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
228723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
2293958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
230723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // If the sp register is modified, change the cfa value.
231723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (registers & (1 << ARM_REG_SP)) {
232723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ = (*regs_)[ARM_REG_SP];
233723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
2343958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2353958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  // Indicate if the pc register was set.
2363958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  if (registers & (1 << ARM_REG_PC)) {
2373958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    pc_set_ = true;
2383958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
239723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
240723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
241723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
242723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_01(uint8_t byte) {
2439416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte >> 4) == 0x9);
244723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
245723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint8_t bits = byte & 0xf;
246723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (bits == 13 || bits == 15) {
247723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 10011101: Reserved as prefix for ARM register to register moves
248723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
249723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
250723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "[Reserved]");
251723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
252723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_RESERVED;
253723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
254723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
255723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
256723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
257723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "vsp = r%d", bits);
258723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
259723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return true;
260723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
261723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
262723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // It is impossible for bits to be larger than the total number of
263723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // arm registers, so don't bother checking if bits is a valid register.
264723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  cfa_ = (*regs_)[bits];
265723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
266723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
267723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
268723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
2699416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte >> 4) == 0xa);
270723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
271723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 10100nnn: Pop r4-r[4+nnn]
272723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 10101nnn: Pop r4-r[4+nnn], r14
273723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
274723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    std::string msg = "pop {r4";
275723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    uint8_t end_reg = byte & 0x7;
276723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (end_reg) {
277723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      msg += android::base::StringPrintf("-r%d", 4 + end_reg);
278723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
279723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (byte & 0x8) {
280723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "%s, r14}", msg.c_str());
281723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    } else {
282723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "%s}", msg.c_str());
283723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
284723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
285723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return true;
286723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
287723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
288723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
289723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t i = 4; i <= 4 + (byte & 0x7); i++) {
290723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!process_memory_->Read32(cfa_, &(*regs_)[i])) {
291723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_READ_FAILED;
2922fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris      status_address_ = cfa_;
293723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
294723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
295723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ += 4;
296723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
297723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (byte & 0x8) {
298723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) {
299723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_READ_FAILED;
3002fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris      status_address_ = cfa_;
301723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
302723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
303723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ += 4;
304723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
305723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
306723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
307723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
308723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_0000() {
309723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 10110000: Finish
310723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
311723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "finish");
312723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
313723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_FINISH;
314723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
315723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
316723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
317723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  status_ = ARM_STATUS_FINISH;
318723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return false;
319723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
320723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
321723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_0001() {
322723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint8_t byte;
323723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (!GetByte(&byte)) {
324723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
325723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
326723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
327723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (byte == 0) {
328723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 10110001 00000000: Spare
329723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
330723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "Spare");
331723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
332723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_SPARE;
333723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
334723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
335723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (byte >> 4) {
336723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 10110001 xxxxyyyy: Spare (xxxx != 0000)
337723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
338723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "Spare");
339723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
340723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_SPARE;
341723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
342723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
343723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
344723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0}
345723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
346723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    bool add_comma = false;
347723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    std::string msg = "pop {";
348723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    for (size_t i = 0; i < 4; i++) {
349723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (byte & (1 << i)) {
350723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        if (add_comma) {
351723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris          msg += ", ";
352723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        }
353723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        msg += android::base::StringPrintf("r%zu", i);
354723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        add_comma = true;
355723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
356723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
357723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "%s}", msg.c_str());
358723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
359723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return true;
360723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
361723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
362723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
363723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t reg = 0; reg < 4; reg++) {
364723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (byte & (1 << reg)) {
365723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
366723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        status_ = ARM_STATUS_READ_FAILED;
3672fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris        status_address_ = cfa_;
368723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        return false;
369723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
370723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      cfa_ += 4;
371723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
372723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
373723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
374723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
375723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
376723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_0010() {
377723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2)
378723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint32_t result = 0;
379723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint32_t shift = 0;
380723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint8_t byte;
381723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  do {
382723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!GetByte(&byte)) {
383723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
384723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
385723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
386723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    result |= (byte & 0x7f) << shift;
387723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    shift += 7;
388723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  } while (byte & 0x80);
389723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  result <<= 2;
390723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
391723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "vsp = vsp + %d", 0x204 + result);
392723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
393723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return true;
394723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
395723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
396723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  cfa_ += 0x204 + result;
397723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
398723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
399723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
400723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_0011() {
401723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX
402723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint8_t byte;
403723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (!GetByte(&byte)) {
404723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
405723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
406723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
407723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
408723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    uint8_t start_reg = byte >> 4;
409723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
410723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    uint8_t end_reg = start_reg + (byte & 0xf);
411723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (end_reg) {
412723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      msg += android::base::StringPrintf("-d%d", end_reg);
413723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
414723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "%s}", msg.c_str());
415723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
416723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return true;
417723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
418723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
419723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  cfa_ += (byte & 0xf) * 8 + 12;
420723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
421723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
422723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
423723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_01nn() {
424723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 101101nn: Spare
425723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
426723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "Spare");
427723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
428723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  status_ = ARM_STATUS_SPARE;
429723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return false;
430723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
431723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
432723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_1nnn(uint8_t byte) {
4339416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte & ~0x07) == 0xb8);
434723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
435723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX
436723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
437723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    std::string msg = "pop {d8";
438723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    uint8_t last_reg = (byte & 0x7);
439723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (last_reg) {
440723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      msg += android::base::StringPrintf("-d%d", last_reg + 8);
441723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
442723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "%s}", msg.c_str());
443723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
444723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return true;
445723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
446723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
447723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // Only update the cfa.
448723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  cfa_ += (byte & 0x7) * 8 + 12;
449723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
450723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
451723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
452723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10(uint8_t byte) {
4539416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte >> 6) == 0x2);
454723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
455723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  switch ((byte >> 4) & 0x3) {
456723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 0:
457723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return DecodePrefix_10_00(byte);
458723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 1:
459723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return DecodePrefix_10_01(byte);
460723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 2:
461723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return DecodePrefix_10_10(byte);
462723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  default:
463723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    switch (byte & 0xf) {
464723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    case 0:
465723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return DecodePrefix_10_11_0000();
466723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    case 1:
467723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return DecodePrefix_10_11_0001();
468723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    case 2:
469723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return DecodePrefix_10_11_0010();
470723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    case 3:
471723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return DecodePrefix_10_11_0011();
472723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    default:
473723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (byte & 0x8) {
474723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        return DecodePrefix_10_11_1nnn(byte);
475723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      } else {
476723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        return DecodePrefix_10_11_01nn();
477723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
478723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
479723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
480723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
481723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
482723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) {
4839416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte & ~0x07) == 0xc0);
484723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
485723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint8_t bits = byte & 0x7;
486723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (bits == 6) {
487723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!GetByte(&byte)) {
488723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
489723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
490723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
491723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
492723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
493723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      uint8_t start_reg = byte >> 4;
494723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      std::string msg = android::base::StringPrintf("pop {wR%d", start_reg);
495723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      uint8_t end_reg = byte & 0xf;
496723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (end_reg) {
497723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        msg += android::base::StringPrintf("-wR%d", start_reg + end_reg);
498723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
499723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "%s}", msg.c_str());
500723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_skip_execution_) {
501723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        return true;
502723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
503723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
504723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // Only update the cfa.
505723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ += (byte & 0xf) * 8 + 8;
506723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  } else if (bits == 7) {
507723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!GetByte(&byte)) {
508723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
509723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
510723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
511723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (byte == 0) {
512723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      // 11000111 00000000: Spare
513723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_) {
514723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        log(log_indent_, "Spare");
515723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
516723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_SPARE;
517723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
518723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    } else if ((byte >> 4) == 0) {
519723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3}
520723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_) {
521723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        bool add_comma = false;
522723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        std::string msg = "pop {";
523723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        for (size_t i = 0; i < 4; i++) {
524723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris          if (byte & (1 << i)) {
525723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris            if (add_comma) {
526723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris              msg += ", ";
527723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris            }
528723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris            msg += android::base::StringPrintf("wCGR%zu", i);
529723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris            add_comma = true;
530723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris          }
531723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        }
532723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        log(log_indent_, "%s}", msg.c_str());
533723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
534723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      // Only update the cfa.
535723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      cfa_ += __builtin_popcount(byte) * 4;
536723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    } else {
537723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      // 11000111 xxxxyyyy: Spare (xxxx != 0000)
538723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_) {
539723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        log(log_indent_, "Spare");
540723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
541723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      status_ = ARM_STATUS_SPARE;
542723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
543723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
544723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  } else {
545723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7)
546723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
547723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      std::string msg = "pop {wR10";
548723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      uint8_t nnn = byte & 0x7;
549723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (nnn) {
550723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        msg += android::base::StringPrintf("-wR%d", 10 + nnn);
551723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
552723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "%s}", msg.c_str());
553723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_skip_execution_) {
554723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        return true;
555723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
556723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
557723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // Only update the cfa.
558723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ += (byte & 0x7) * 8 + 8;
559723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
560723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
561723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
562723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
563723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) {
5649416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte & ~0x07) == 0xc8);
565723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
566723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint8_t bits = byte & 0x7;
567723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (bits == 0) {
568723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 11001000 sssscccc: Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] by VPUSH
569723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!GetByte(&byte)) {
570723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
571723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
572723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
573723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
574723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      uint8_t start_reg = byte >> 4;
575723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg);
576723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      uint8_t end_reg = byte & 0xf;
577723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (end_reg) {
578723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg);
579723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
580723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "%s}", msg.c_str());
581723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_skip_execution_) {
582723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        return true;
583723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
584723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
585723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // Only update the cfa.
586723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ += (byte & 0xf) * 8 + 8;
587723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  } else if (bits == 1) {
588723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 11001001 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by VPUSH
589723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (!GetByte(&byte)) {
590723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return false;
591723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
592723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
593723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
594723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      uint8_t start_reg = byte >> 4;
595723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
596723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      uint8_t end_reg = byte & 0xf;
597723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (end_reg) {
598723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        msg += android::base::StringPrintf("-d%d", start_reg + end_reg);
599723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
600723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "%s}", msg.c_str());
601723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_skip_execution_) {
602723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        return true;
603723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
604723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
605723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // Only update the cfa.
606723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ += (byte & 0xf) * 8 + 8;
607723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  } else {
608723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 11001yyy: Spare (yyy != 000, 001)
609723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
610723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "Spare");
611723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
612723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_SPARE;
613723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
614723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
615723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
616723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
617723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
618723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_11_010(uint8_t byte) {
6199416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte & ~0x07) == 0xd0);
620723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
621723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH
622723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (log_) {
623723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    std::string msg = "pop {d8";
624723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    uint8_t end_reg = byte & 0x7;
625723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (end_reg) {
626723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      msg += android::base::StringPrintf("-d%d", 8 + end_reg);
627723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
628723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    log(log_indent_, "%s}", msg.c_str());
629723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_skip_execution_) {
630723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      return true;
631723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
632723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
633723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  cfa_ += (byte & 0x7) * 8 + 8;
634723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
635723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
636723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
637723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_11(uint8_t byte) {
6389416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris  CHECK((byte >> 6) == 0x3);
639723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
640723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  switch ((byte >> 3) & 0x7) {
641723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 0:
642723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return DecodePrefix_11_000(byte);
643723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 1:
644723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return DecodePrefix_11_001(byte);
645723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 2:
646723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return DecodePrefix_11_010(byte);
647723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  default:
648723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 11xxxyyy: Spare (xxx != 000, 001, 010)
649723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
650723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "Spare");
651723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
652723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    status_ = ARM_STATUS_SPARE;
653723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
654723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
655723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
656723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
657723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisbool ArmExidx::Decode() {
658723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  status_ = ARM_STATUS_NONE;
659723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  uint8_t byte;
660723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  if (!GetByte(&byte)) {
661723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return false;
662723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
663723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
664723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  switch (byte >> 6) {
665723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 0:
666723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4
667723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
668723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "vsp = vsp + %d", ((byte & 0x3f) << 2) + 4);
669723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_skip_execution_) {
670723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        break;
671723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
672723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
673723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ += ((byte & 0x3f) << 2) + 4;
674723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    break;
675723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 1:
676723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4
677723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    if (log_) {
678723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      log(log_indent_, "vsp = vsp - %d", ((byte & 0x3f) << 2) + 4);
679723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      if (log_skip_execution_) {
680723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris        break;
681723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris      }
682723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    }
683723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    cfa_ -= ((byte & 0x3f) << 2) + 4;
684723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    break;
685723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  case 2:
686723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return DecodePrefix_10(byte);
687723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  default:
688723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    return DecodePrefix_11(byte);
689723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
690723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return true;
691723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
692723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
693723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisbool ArmExidx::Eval() {
6943958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  pc_set_ = false;
695723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  while (Decode());
696723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  return status_ == ARM_STATUS_FINISH;
697723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
698d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
699d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris}  // namespace unwindstack
700