1675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool//===-------------------------- DwarfInstructions.hpp ---------------------===//
2675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool//
3675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool//                     The LLVM Compiler Infrastructure
4675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool//
5675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool// This file is dual licensed under the MIT and the University of Illinois Open
6675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool// Source Licenses. See LICENSE.TXT for details.
7675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool//
8675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool//
963469ffb83da03e4fd54185bf14384221dc3b1c5Ed Maste//  Processor specific interpretation of DWARF unwind info.
10675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool//
11675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool//===----------------------------------------------------------------------===//
12675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
13675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#ifndef __DWARF_INSTRUCTIONS_HPP__
14675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#define __DWARF_INSTRUCTIONS_HPP__
15675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
16675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#include <stdint.h>
17675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#include <stdio.h>
18675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#include <stdlib.h>
19675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
20675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#include "dwarf2.h"
21675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#include "Registers.hpp"
22675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#include "DwarfParser.hpp"
23675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#include "config.h"
24675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
25675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
26675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasoolnamespace libunwind {
27675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
28675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
2963469ffb83da03e4fd54185bf14384221dc3b1c5Ed Maste/// DwarfInstructions maps abtract DWARF unwind instructions to a particular
30675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool/// architecture
31675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooltemplate <typename A, typename R>
32675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasoolclass DwarfInstructions {
33675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasoolpublic:
34675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  typedef typename A::pint_t pint_t;
35675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  typedef typename A::sint_t sint_t;
36675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
37675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
38675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                           R &registers);
39675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
40675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasoolprivate:
41675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
42675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  enum {
43675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    DW_X86_64_RET_ADDR = 16
44675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  };
45675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
46675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  enum {
47675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    DW_X86_RET_ADDR = 8
48675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  };
49675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
50675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;
51675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;
52675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;
53675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;
54675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
55675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  static pint_t evaluateExpression(pint_t expression, A &addressSpace,
56675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                   const R &registers,
57675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                   pint_t initialStackValue);
58675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  static pint_t getSavedRegister(A &addressSpace, const R &registers,
59675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                 pint_t cfa, const RegisterLocation &savedReg);
60675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  static double getSavedFloatRegister(A &addressSpace, const R &registers,
61675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                  pint_t cfa, const RegisterLocation &savedReg);
62675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
63675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                  pint_t cfa, const RegisterLocation &savedReg);
64675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
65675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
66675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                       const R &registers) {
67675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    if (prolog.cfaRegister != 0)
68675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
69675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool             prolog.cfaRegisterOffset);
70675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    if (prolog.cfaExpression != 0)
71675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
72675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                registers, 0);
73675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    assert(0 && "getCFA(): unknown location");
74675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    __builtin_unreachable();
75675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  }
76675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool};
77675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
78675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
79675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooltemplate <typename A, typename R>
80675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooltypename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
81675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    A &addressSpace, const R &registers, pint_t cfa,
82675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    const RegisterLocation &savedReg) {
83675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  switch (savedReg.location) {
84675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterInCFA:
85675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    return addressSpace.getP(cfa + (pint_t)savedReg.value);
86675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
87675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterAtExpression:
88675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    return addressSpace.getP(
89675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        evaluateExpression((pint_t)savedReg.value, addressSpace,
90675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                            registers, cfa));
91675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
92675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterIsExpression:
93675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    return evaluateExpression((pint_t)savedReg.value, addressSpace,
94675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                              registers, cfa);
95675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
96675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterInRegister:
97675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    return registers.getRegister((int)savedReg.value);
98675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
99675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterUnused:
100675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterOffsetFromCFA:
101675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    // FIX ME
102675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    break;
103675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  }
104675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  _LIBUNWIND_ABORT("unsupported restore location for register");
105675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool}
106675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
107675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooltemplate <typename A, typename R>
108675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooldouble DwarfInstructions<A, R>::getSavedFloatRegister(
109675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    A &addressSpace, const R &registers, pint_t cfa,
110675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    const RegisterLocation &savedReg) {
111675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  switch (savedReg.location) {
112675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterInCFA:
113675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
114675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
115675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterAtExpression:
116675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    return addressSpace.getDouble(
117675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        evaluateExpression((pint_t)savedReg.value, addressSpace,
118675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                            registers, cfa));
119675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
120675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterIsExpression:
121675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterUnused:
122675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterOffsetFromCFA:
123675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterInRegister:
124675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    // FIX ME
125675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    break;
126675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  }
127675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  _LIBUNWIND_ABORT("unsupported restore location for float register");
128675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool}
129675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
130675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooltemplate <typename A, typename R>
131675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasoolv128 DwarfInstructions<A, R>::getSavedVectorRegister(
132675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    A &addressSpace, const R &registers, pint_t cfa,
133675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    const RegisterLocation &savedReg) {
134675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  switch (savedReg.location) {
135675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterInCFA:
136675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    return addressSpace.getVector(cfa + (pint_t)savedReg.value);
137675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
138675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterAtExpression:
139675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    return addressSpace.getVector(
140675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        evaluateExpression((pint_t)savedReg.value, addressSpace,
141675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                            registers, cfa));
142675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
143675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterIsExpression:
144675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterUnused:
145675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterOffsetFromCFA:
146675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  case CFI_Parser<A>::kRegisterInRegister:
147675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    // FIX ME
148675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    break;
149675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  }
150675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  _LIBUNWIND_ABORT("unsupported restore location for vector register");
151675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool}
152675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
153675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooltemplate <typename A, typename R>
154675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasoolint DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
155675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                           pint_t fdeStart, R &registers) {
156675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  FDE_Info fdeInfo;
157675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  CIE_Info cieInfo;
158675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
159675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                               &cieInfo) == NULL) {
160675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    PrologInfo prolog;
161675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
162675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                            &prolog)) {
163675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // get pointer to cfa (architecture specific)
164675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      pint_t cfa = getCFA(addressSpace, prolog, registers);
165675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
16663469ffb83da03e4fd54185bf14384221dc3b1c5Ed Maste       // restore registers that DWARF says were saved
167675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      R newRegisters = registers;
168675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      pint_t returnAddress = 0;
169675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      const int lastReg = R::lastDwarfRegNum();
170af4b7dd015efae2d12d7387c39eab470d981113aMartin Storsjo      assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
171675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool             "register range too large");
172632aa38f313c507ce3aec732dc2a6d2259502731Ed Maste      assert(lastReg >= (int)cieInfo.returnAddressRegister &&
173675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool             "register range does not contain return address register");
174675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      for (int i = 0; i <= lastReg; ++i) {
1757cb3a4078892fac76919812ab31ad35ccc764f1eLogan Chien        if (prolog.savedRegisters[i].location !=
1767cb3a4078892fac76919812ab31ad35ccc764f1eLogan Chien            CFI_Parser<A>::kRegisterUnused) {
1777cb3a4078892fac76919812ab31ad35ccc764f1eLogan Chien          if (registers.validFloatRegister(i))
178675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool            newRegisters.setFloatRegister(
179675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                i, getSavedFloatRegister(addressSpace, registers, cfa,
180675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                         prolog.savedRegisters[i]));
181675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool          else if (registers.validVectorRegister(i))
182675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool            newRegisters.setVectorRegister(
183675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                i, getSavedVectorRegister(addressSpace, registers, cfa,
184675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                          prolog.savedRegisters[i]));
185675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool          else if (i == (int)cieInfo.returnAddressRegister)
186675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool            returnAddress = getSavedRegister(addressSpace, registers, cfa,
187675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                             prolog.savedRegisters[i]);
188675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool          else if (registers.validRegister(i))
189675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool            newRegisters.setRegister(
190675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                i, getSavedRegister(addressSpace, registers, cfa,
191675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                    prolog.savedRegisters[i]));
192675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool          else
193675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool            return UNW_EBADREG;
194675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        }
195675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      }
196675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
197675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // By definition, the CFA is the stack pointer at the call site, so
198675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // restoring SP means setting it to CFA.
199675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      newRegisters.setSP(cfa);
200675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
201675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // Return address is address after call site instruction, so setting IP to
202675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // that does simualates a return.
203675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      newRegisters.setIP(returnAddress);
204675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
205675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // Simulate the step by replacing the register set with the new ones.
206675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      registers = newRegisters;
207675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
208675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      return UNW_STEP_SUCCESS;
209675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    }
210675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  }
211675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  return UNW_EBADFRAME;
212675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool}
213675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
214675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooltemplate <typename A, typename R>
215675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasooltypename A::pint_t
216675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem AbdulrasoolDwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
217675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                            const R &registers,
218675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool                                            pint_t initialStackValue) {
219675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  const bool log = false;
220675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  pint_t p = expression;
221675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  pint_t expressionEnd = expression + 20; // temp, until len read
222675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
223675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  expressionEnd = p + length;
224675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  if (log)
225675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
226675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool            (uint64_t)length);
227675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  pint_t stack[100];
228675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  pint_t *sp = stack;
229675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  *(++sp) = initialStackValue;
230675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
231675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  while (p < expressionEnd) {
232675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    if (log) {
233675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      for (pint_t *t = sp; t > stack; --t) {
234675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
235675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      }
236675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    }
237675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    uint8_t opcode = addressSpace.get8(p++);
238675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    sint_t svalue, svalue2;
239675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    pint_t value;
240675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    uint32_t reg;
241675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    switch (opcode) {
242675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_addr:
243675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate address sized value
244675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = addressSpace.getP(p);
245675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += sizeof(pint_t);
246675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
247675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
248675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
249675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
250675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
251675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_deref:
252675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // pop stack, dereference, push result
253675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
254675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = addressSpace.getP(value);
255675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
256675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
257675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
258675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
259675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_const1u:
260675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate 1 byte value
261675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = addressSpace.get8(p);
262675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 1;
263675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
264675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
265675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
266675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
267675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
268675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_const1s:
269675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate 1 byte signed value
270675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (int8_t) addressSpace.get8(p);
271675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 1;
272675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = (pint_t)svalue;
273675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
274675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
275675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
276675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
277675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_const2u:
278675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate 2 byte value
279675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = addressSpace.get16(p);
280675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 2;
281675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
282675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
283675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
284675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
285675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
286675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_const2s:
287675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate 2 byte signed value
288675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (int16_t) addressSpace.get16(p);
289675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 2;
290675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = (pint_t)svalue;
291675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
292675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
293675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
294675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
295675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_const4u:
296675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate 4 byte value
297675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = addressSpace.get32(p);
298675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 4;
299675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
300675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
301675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
302675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
303675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
304675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_const4s:
305675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate 4 byte signed value
306675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (int32_t)addressSpace.get32(p);
307675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 4;
308675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = (pint_t)svalue;
309675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
310675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
311675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
312675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
313675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_const8u:
314675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate 8 byte value
315675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = (pint_t)addressSpace.get64(p);
316675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 8;
317675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
318675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
319675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
320675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
321675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
322675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_const8s:
323675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate 8 byte signed value
324675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = (pint_t)addressSpace.get64(p);
325675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 8;
326675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
327675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
328675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
329675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
330675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
331675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_constu:
332675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate ULEB128 value
333675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
334675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
335675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
336675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
337675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
338675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
339675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_consts:
340675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push immediate SLEB128 value
341675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
342675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = (pint_t)svalue;
343675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
344675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
345675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
346675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
347675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_dup:
348675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // push top of stack
349675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp;
350675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
351675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
352675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "duplicate top of stack\n");
353675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
354675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
355675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_drop:
356675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // pop
357675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      --sp;
358675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
359675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "pop top of stack\n");
360675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
361675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
362675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_over:
363675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // dup second
364675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = sp[-1];
365675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
366675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
367675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "duplicate second in stack\n");
368675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
369675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
370675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_pick:
371675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // pick from
372675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      reg = addressSpace.get8(p);
373675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 1;
374675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = sp[-reg];
375675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
376675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
377675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "duplicate %d in stack\n", reg);
378675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
379675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
380675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_swap:
381675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // swap top two
382675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = sp[0];
383675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      sp[0] = sp[-1];
384675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      sp[-1] = value;
385675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
386675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "swap top of stack\n");
387675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
388675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
389675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_rot:
390675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // rotate top three
391675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = sp[0];
392675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      sp[0] = sp[-1];
393675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      sp[-1] = sp[-2];
394675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      sp[-2] = value;
395675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
396675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "rotate top three of stack\n");
397675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
398675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
399675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_xderef:
400675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // pop stack, dereference, push result
401675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
402675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = *((pint_t*)value);
403675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
404675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
405675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
406675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
407675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_abs:
408675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)*sp;
409675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (svalue < 0)
410675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        *sp = (pint_t)(-svalue);
411675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
412675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "abs\n");
413675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
414675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
415675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_and:
416675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
417675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp &= value;
418675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
419675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "and\n");
420675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
421675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
422675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_div:
423675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)(*sp--);
424675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue2 = (sint_t)*sp;
425675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (pint_t)(svalue2 / svalue);
426675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
427675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "div\n");
428675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
429675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
430675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_minus:
431675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
432675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = *sp - value;
433675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
434675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "minus\n");
435675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
436675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
437675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_mod:
438675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)(*sp--);
439675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue2 = (sint_t)*sp;
440675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (pint_t)(svalue2 % svalue);
441675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
442675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "module\n");
443675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
444675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
445675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_mul:
446675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)(*sp--);
447675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue2 = (sint_t)*sp;
448675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (pint_t)(svalue2 * svalue);
449675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
450675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "mul\n");
451675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
452675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
453675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_neg:
454675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = 0 - *sp;
455675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
456675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "neg\n");
457675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
458675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
459675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_not:
460675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)(*sp);
461675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (pint_t)(~svalue);
462675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
463675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "not\n");
464675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
465675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
466675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_or:
467675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
468675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp |= value;
469675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
470675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "or\n");
471675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
472675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
473675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_plus:
474675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
475675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp += value;
476675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
477675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "plus\n");
478675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
479675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
480675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_plus_uconst:
481675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // pop stack, add uelb128 constant, push result
4822fd2d585a530d0564a5ef4b1184e0767c84c93b0Saleem Abdulrasool      *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
483675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
484675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "add constant\n");
485675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
486675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
487675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_shl:
488675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
489675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = *sp << value;
490675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
491675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "shift left\n");
492675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
493675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
494675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_shr:
495675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
496675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = *sp >> value;
497675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
498675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "shift left\n");
499675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
500675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
501675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_shra:
502675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
503675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)*sp;
504675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (pint_t)(svalue >> value);
505675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
506675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "shift left arithmetric\n");
507675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
508675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
509675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_xor:
510675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
511675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp ^= value;
512675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
513675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "xor\n");
514675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
515675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
516675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_skip:
517675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (int16_t) addressSpace.get16(p);
518675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 2;
519675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p = (pint_t)((sint_t)p + svalue);
520675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
521675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
522675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
523675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
524675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_bra:
525675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (int16_t) addressSpace.get16(p);
526675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      p += 2;
527675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (*sp--)
528675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        p = (pint_t)((sint_t)p + svalue);
529675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
530675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
531675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
532675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
533675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_eq:
534675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
535675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (*sp == value);
536675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
537675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "eq\n");
538675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
539675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
540675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_ge:
541675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
542675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (*sp >= value);
543675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
544675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "ge\n");
545675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
546675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
547675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_gt:
548675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
549675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (*sp > value);
550675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
551675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "gt\n");
552675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
553675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
554675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_le:
555675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
556675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (*sp <= value);
557675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
558675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "le\n");
559675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
560675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
561675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lt:
562675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
563675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (*sp < value);
564675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
565675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "lt\n");
566675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
567675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
568675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_ne:
569675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
570675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *sp = (*sp != value);
571675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
572675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "ne\n");
573675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
574675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
575675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit0:
576675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit1:
577675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit2:
578675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit3:
579675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit4:
580675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit5:
581675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit6:
582675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit7:
583675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit8:
584675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit9:
585675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit10:
586675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit11:
587675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit12:
588675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit13:
589675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit14:
590675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit15:
591675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit16:
592675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit17:
593675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit18:
594675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit19:
595675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit20:
596675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit21:
597675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit22:
598675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit23:
599675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit24:
600675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit25:
601675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit26:
602675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit27:
603675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit28:
604675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit29:
605675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit30:
606675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_lit31:
607675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = static_cast<pint_t>(opcode - DW_OP_lit0);
608675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
609675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
610675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
611675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
612675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
613675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg0:
614675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg1:
615675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg2:
616675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg3:
617675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg4:
618675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg5:
619675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg6:
620675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg7:
621675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg8:
622675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg9:
623675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg10:
624675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg11:
625675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg12:
626675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg13:
627675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg14:
628675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg15:
629675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg16:
630675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg17:
631675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg18:
632675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg19:
633675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg20:
634675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg21:
635675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg22:
636675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg23:
637675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg24:
638675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg25:
639675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg26:
640675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg27:
641675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg28:
642675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg29:
643675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg30:
644675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_reg31:
645675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
646675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = registers.getRegister((int)reg);
647675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
648675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push reg %d\n", reg);
649675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
650675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
651675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_regx:
652675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
653675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = registers.getRegister((int)reg);
654675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
655675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
656675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
657675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
658675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg0:
659675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg1:
660675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg2:
661675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg3:
662675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg4:
663675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg5:
664675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg6:
665675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg7:
666675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg8:
667675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg9:
668675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg10:
669675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg11:
670675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg12:
671675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg13:
672675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg14:
673675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg15:
674675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg16:
675675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg17:
676675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg18:
677675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg19:
678675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg20:
679675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg21:
680675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg22:
681675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg23:
682675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg24:
683675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg25:
684675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg26:
685675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg27:
686675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg28:
687675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg29:
688675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg30:
689675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_breg31:
690675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
691675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
692675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue += static_cast<sint_t>(registers.getRegister((int)reg));
693675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = (pint_t)(svalue);
694675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
695675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
696675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
697675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
698675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_bregx:
699675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
700675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
701675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      svalue += static_cast<sint_t>(registers.getRegister((int)reg));
702675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = (pint_t)(svalue);
703675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
704675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
705675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
706675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
707675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_fbreg:
708675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
709675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
710675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
711675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_piece:
712675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      _LIBUNWIND_ABORT("DW_OP_piece not implemented");
713675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
714675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
715675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_deref_size:
716675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      // pop stack, dereference, push result
717675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      value = *sp--;
718675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      switch (addressSpace.get8(p++)) {
719675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      case 1:
720675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        value = addressSpace.get8(value);
721675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        break;
722675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      case 2:
723675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        value = addressSpace.get16(value);
724675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        break;
725675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      case 4:
726675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        value = addressSpace.get32(value);
727675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        break;
728675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      case 8:
729675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        value = (pint_t)addressSpace.get64(value);
730675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        break;
731675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      default:
732675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
733675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      }
734675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      *(++sp) = value;
735675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      if (log)
736675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool        fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
737675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool      break;
738675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
739675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_xderef_size:
740675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_nop:
741675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_push_object_addres:
742675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_call2:
743675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_call4:
744675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    case DW_OP_call_ref:
745675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    default:
74663469ffb83da03e4fd54185bf14384221dc3b1c5Ed Maste      _LIBUNWIND_ABORT("DWARF opcode not implemented");
747675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    }
748675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
749675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  }
750675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  if (log)
751675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool    fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
752675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool  return *sp;
753675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool}
754675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
755675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
756675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
757675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool} // namespace libunwind
758675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool
759675df58e9b2f6c4218ef7d19bfe405772ada5444Saleem Abdulrasool#endif // __DWARF_INSTRUCTIONS_HPP__
760