1b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//===-------------------------- DwarfInstructions.hpp ---------------------===//
2b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
3b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//                     The LLVM Compiler Infrastructure
4b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
5b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// This file is dual licensed under the MIT and the University of Illinois Open
6b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// Source Licenses. See LICENSE.TXT for details.
7b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
8b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
9b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//  Processor specific interpretation of dwarf unwind info.
10b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
11b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//===----------------------------------------------------------------------===//
12b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
13b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#ifndef __DWARF_INSTRUCTIONS_HPP__
14b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#define __DWARF_INSTRUCTIONS_HPP__
15b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
16b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdint.h>
17b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdio.h>
18b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdlib.h>
19b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
20b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "dwarf2.h"
21b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "AddressSpace.hpp"
22b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "Registers.hpp"
23b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "DwarfParser.hpp"
24b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "config.h"
25b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
26b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
27b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziknamespace libunwind {
28b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
29b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
30b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// DwarfInstructions maps abtract dwarf unwind instructions to a particular
31b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// architecture
32b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
33b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikclass DwarfInstructions {
34b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
35b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typedef typename A::pint_t pint_t;
36b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typedef typename A::sint_t sint_t;
37b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
38b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
39b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                           R &registers);
40b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
41b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
42b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
43b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  enum {
44b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    DW_X86_64_RET_ADDR = 16
45b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  };
46b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
47b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  enum {
48b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    DW_X86_RET_ADDR = 8
49b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  };
50b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
51b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;
52b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;
53b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;
54b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;
55b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
56b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static pint_t evaluateExpression(pint_t expression, A &addressSpace,
57b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                   const R &registers,
58b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                   pint_t initialStackValue);
59b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static pint_t getSavedRegister(A &addressSpace, const R &registers,
60b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 pint_t cfa, const RegisterLocation &savedReg);
61b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static double getSavedFloatRegister(A &addressSpace, const R &registers,
62b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  pint_t cfa, const RegisterLocation &savedReg);
63b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
64b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  pint_t cfa, const RegisterLocation &savedReg);
65b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
66b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
67e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       const R &registers) {
68e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (prolog.cfaRegister != 0)
69e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
70e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert             prolog.cfaRegisterOffset);
71e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (prolog.cfaExpression != 0)
72e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
73e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                registers, 0);
74e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    assert(0 && "getCFA(): unknown location");
75e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    __builtin_unreachable();
76e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
77b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
78b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
79b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
80b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
81b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktypename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
82b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    A &addressSpace, const R &registers, pint_t cfa,
83b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    const RegisterLocation &savedReg) {
84b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  switch (savedReg.location) {
85b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterInCFA:
86b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return addressSpace.getP(cfa + (pint_t)savedReg.value);
87b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
88b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterAtExpression:
89b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return addressSpace.getP(
90b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        evaluateExpression((pint_t)savedReg.value, addressSpace,
91b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            registers, cfa));
92b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
93b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterIsExpression:
94b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return evaluateExpression((pint_t)savedReg.value, addressSpace,
95b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              registers, cfa);
96b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
97b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterInRegister:
98b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return registers.getRegister((int)savedReg.value);
99b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
100b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterUnused:
101b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterOffsetFromCFA:
102b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // FIX ME
103b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    break;
104b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
105b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_ABORT("unsupported restore location for register");
106b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
107b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
108b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
109b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikdouble DwarfInstructions<A, R>::getSavedFloatRegister(
110b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    A &addressSpace, const R &registers, pint_t cfa,
111b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    const RegisterLocation &savedReg) {
112b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  switch (savedReg.location) {
113b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterInCFA:
114b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
115b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
116b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterAtExpression:
117b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return addressSpace.getDouble(
118b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        evaluateExpression((pint_t)savedReg.value, addressSpace,
119b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            registers, cfa));
120b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
121b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterIsExpression:
122b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterUnused:
123b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterOffsetFromCFA:
124b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterInRegister:
125b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // FIX ME
126b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    break;
127b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
128b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_ABORT("unsupported restore location for float register");
129b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
130b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
131b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
132b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikv128 DwarfInstructions<A, R>::getSavedVectorRegister(
133b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    A &addressSpace, const R &registers, pint_t cfa,
134b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    const RegisterLocation &savedReg) {
135b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  switch (savedReg.location) {
136b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterInCFA:
137b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return addressSpace.getVector(cfa + (pint_t)savedReg.value);
138b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
139b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterAtExpression:
140b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return addressSpace.getVector(
141b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        evaluateExpression((pint_t)savedReg.value, addressSpace,
142b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            registers, cfa));
143b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
144b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterIsExpression:
145b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterUnused:
146b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterOffsetFromCFA:
147b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  case CFI_Parser<A>::kRegisterInRegister:
148b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // FIX ME
149b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    break;
150b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
151b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_ABORT("unsupported restore location for vector register");
152b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
153b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
154b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
155b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikint DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
156b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                           pint_t fdeStart, R &registers) {
157b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  FDE_Info fdeInfo;
158b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  CIE_Info cieInfo;
159b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart,
160b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                  &fdeInfo, &cieInfo) == NULL) {
161b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    PrologInfo prolog;
162b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
163b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                                     &prolog)) {
164b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // get pointer to cfa (architecture specific)
165b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      pint_t cfa = getCFA(addressSpace, prolog, registers);
166b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
167e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert       // restore registers that dwarf says were saved
168e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      R newRegisters = registers;
169b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      pint_t returnAddress = 0;
170e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      const int lastReg = R::lastDwarfRegNum();
171e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      assert((int)CFI_Parser<A>::kMaxRegisterNumber > lastReg
172e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                                && "register range too large");
173e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      assert(lastReg <= (int)cieInfo.returnAddressRegister
174e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 && "register range does not contain return address register");
175e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      for (int i = 0; i <= lastReg; ++i) {
176e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert         if (prolog.savedRegisters[i].location !=
177e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert             CFI_Parser<A>::kRegisterUnused) {
178e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert           if (registers.validFloatRegister(i))
179b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            newRegisters.setFloatRegister(
180b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                i, getSavedFloatRegister(addressSpace, registers, cfa,
181b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                         prolog.savedRegisters[i]));
182b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          else if (registers.validVectorRegister(i))
183b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            newRegisters.setVectorRegister(
184b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                i, getSavedVectorRegister(addressSpace, registers, cfa,
185b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                          prolog.savedRegisters[i]));
186e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          else if (i == (int)cieInfo.returnAddressRegister)
187b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            returnAddress = getSavedRegister(addressSpace, registers, cfa,
188b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                             prolog.savedRegisters[i]);
189b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          else if (registers.validRegister(i))
190b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            newRegisters.setRegister(
191b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                i, getSavedRegister(addressSpace, registers, cfa,
192b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                    prolog.savedRegisters[i]));
193b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          else
194b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            return UNW_EBADREG;
195b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        }
196b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
197b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
198b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // By definition, the CFA is the stack pointer at the call site, so
199b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // restoring SP means setting it to CFA.
200b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      newRegisters.setSP(cfa);
201b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
202b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // Return address is address after call site instruction, so setting IP to
203b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // that does simualates a return.
204b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      newRegisters.setIP(returnAddress);
205b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
206b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // Simulate the step by replacing the register set with the new ones.
207b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      registers = newRegisters;
208b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
209b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return UNW_STEP_SUCCESS;
210b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
211b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
212b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return UNW_EBADFRAME;
213b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
214b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
215b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
216b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktypename A::pint_t
217b78da9875b6e35187b5d584746c78faaf3230a3dNick KledzikDwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
218b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                            const R &registers,
219b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                            pint_t initialStackValue) {
220b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const bool log = false;
221b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t p = expression;
222b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t expressionEnd = expression + 20; // temp, until len read
223b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
224b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  expressionEnd = p + length;
225b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (log)
226b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    fprintf(stderr, "evaluateExpression(): length=%llu\n", (uint64_t)length);
227b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t stack[100];
228b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t *sp = stack;
229b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  *(++sp) = initialStackValue;
230b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
231b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  while (p < expressionEnd) {
232b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (log) {
233b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      for (pint_t *t = sp; t > stack; --t) {
234b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t));
235b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
236b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
237b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    uint8_t opcode = addressSpace.get8(p++);
238b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    sint_t svalue, svalue2;
239b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    pint_t value;
240b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    uint32_t reg;
241b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    switch (opcode) {
242b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_addr:
243b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate address sized value
244b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = addressSpace.getP(p);
245b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += sizeof(pint_t);
246b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
247b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
248b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
249b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
250b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
251b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_deref:
252b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // pop stack, dereference, push result
253b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
254b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = addressSpace.getP(value);
255b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
256b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "dereference 0x%llX\n", (uint64_t) value);
257b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
258b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
259b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_const1u:
260b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate 1 byte value
261b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = addressSpace.get8(p);
262b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 1;
263b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
264b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
265b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
266b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
267b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
268b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_const1s:
269b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate 1 byte signed value
270b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (int8_t) addressSpace.get8(p);
271b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 1;
272b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = (pint_t)svalue;
273b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
274b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
275b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
276b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
277b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_const2u:
278b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate 2 byte value
279b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = addressSpace.get16(p);
280b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 2;
281b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
282b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
283b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
284b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
285b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
286b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_const2s:
287b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate 2 byte signed value
288b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (int16_t) addressSpace.get16(p);
289b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 2;
290b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = (pint_t)svalue;
291b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
292b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
293b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
294b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
295b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_const4u:
296b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate 4 byte value
297b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = addressSpace.get32(p);
298b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 4;
299b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
300b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
301b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
302b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
303b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
304b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_const4s:
305b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate 4 byte signed value
306b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (int32_t)addressSpace.get32(p);
307b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 4;
308b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = (pint_t)svalue;
309b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
310b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
311b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
312b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
313b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_const8u:
314b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate 8 byte value
315b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = (pint_t)addressSpace.get64(p);
316b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 8;
317b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
318b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
319b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
320b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
321b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
322b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_const8s:
323b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate 8 byte signed value
324b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = (pint_t)addressSpace.get64(p);
325b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 8;
326b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
327b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
328b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
329b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
330b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
331b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_constu:
332b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate ULEB128 value
333b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
334b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
335b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
336b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
337b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
338b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
339b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_consts:
340b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push immediate SLEB128 value
341b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
342b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = (pint_t)svalue;
343b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
344b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
345b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
346b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
347b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_dup:
348b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // push top of stack
349b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp;
350b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
351b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
352b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "duplicate top of stack\n");
353b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
354b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
355b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_drop:
356b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // pop
357b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      --sp;
358b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
359b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "pop top of stack\n");
360b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
361b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
362b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_over:
363b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // dup second
364b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = sp[-1];
365b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
366b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
367b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "duplicate second in stack\n");
368b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
369b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
370b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_pick:
371b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // pick from
372b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      reg = addressSpace.get8(p);
373b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 1;
374b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = sp[-reg];
375b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
376b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
377b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "duplicate %d in stack\n", reg);
378b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
379b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
380b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_swap:
381b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // swap top two
382b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = sp[0];
383b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      sp[0] = sp[-1];
384b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      sp[-1] = value;
385b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
386b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "swap top of stack\n");
387b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
388b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
389b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_rot:
390b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // rotate top three
391b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = sp[0];
392b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      sp[0] = sp[-1];
393b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      sp[-1] = sp[-2];
394b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      sp[-2] = value;
395b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
396b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "rotate top three of stack\n");
397b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
398b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
399b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_xderef:
400b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // pop stack, dereference, push result
401b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
402b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = *((pint_t*)value);
403b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
404b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t) value);
405b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
406b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
407b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_abs:
408b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)*sp;
409b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (svalue < 0)
410b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        *sp = (pint_t)(-svalue);
411b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
412b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "abs\n");
413b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
414b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
415b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_and:
416b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
417b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp &= value;
418b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
419b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "and\n");
420b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
421b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
422b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_div:
423b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)(*sp--);
424b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue2 = (sint_t)*sp;
425b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (pint_t)(svalue2 / svalue);
426b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
427b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "div\n");
428b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
429b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
430b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_minus:
431b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
432b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = *sp - value;
433b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
434b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "minus\n");
435b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
436b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
437b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_mod:
438b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)(*sp--);
439b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue2 = (sint_t)*sp;
440b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (pint_t)(svalue2 % svalue);
441b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
442b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "module\n");
443b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
444b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
445b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_mul:
446b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)(*sp--);
447b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue2 = (sint_t)*sp;
448b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (pint_t)(svalue2 * svalue);
449b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
450b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "mul\n");
451b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
452b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
453b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_neg:
454b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = 0 - *sp;
455b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
456b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "neg\n");
457b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
458b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
459b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_not:
460b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)(*sp);
461b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (pint_t)(~svalue);
462b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
463b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "not\n");
464b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
465b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
466b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_or:
467b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
468b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp |= value;
469b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
470b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "or\n");
471b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
472b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
473b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_plus:
474b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
475b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp += value;
476b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
477b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "plus\n");
478b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
479b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
480b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_plus_uconst:
481b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // pop stack, add uelb128 constant, push result
482b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp += addressSpace.getULEB128(p, expressionEnd);
483b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
484b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "add constant\n");
485b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
486b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
487b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_shl:
488b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
489b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = *sp << value;
490b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
491b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "shift left\n");
492b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
493b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
494b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_shr:
495b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
496b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = *sp >> value;
497b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
498b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "shift left\n");
499b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
500b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
501b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_shra:
502b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
503b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)*sp;
504b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (pint_t)(svalue >> value);
505b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
506b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "shift left arithmetric\n");
507b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
508b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
509b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_xor:
510b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
511b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp ^= value;
512b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
513b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "xor\n");
514b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
515b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
516b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_skip:
517b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (int16_t) addressSpace.get16(p);
518b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 2;
519b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p = (pint_t)((sint_t)p + svalue);
520b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
521b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "skip %lld\n", (uint64_t) svalue);
522b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
523b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
524b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_bra:
525b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (int16_t) addressSpace.get16(p);
526b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      p += 2;
527b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (*sp--)
528b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        p = (pint_t)((sint_t)p + svalue);
529b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
530b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "bra %lld\n", (uint64_t) svalue);
531b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
532b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
533b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_eq:
534b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
535b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (*sp == value);
536b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
537b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "eq\n");
538b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
539b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
540b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_ge:
541b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
542b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (*sp >= value);
543b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
544b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "ge\n");
545b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
546b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
547b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_gt:
548b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
549b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (*sp > value);
550b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
551b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "gt\n");
552b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
553b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
554b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_le:
555b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
556b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (*sp <= value);
557b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
558b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "le\n");
559b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
560b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
561b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lt:
562b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
563b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (*sp < value);
564b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
565b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "lt\n");
566b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
567b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
568b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_ne:
569b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
570b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *sp = (*sp != value);
571b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
572b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "ne\n");
573b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
574b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
575b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit0:
576b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit1:
577b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit2:
578b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit3:
579b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit4:
580b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit5:
581b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit6:
582b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit7:
583b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit8:
584b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit9:
585b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit10:
586b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit11:
587b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit12:
588b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit13:
589b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit14:
590b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit15:
591b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit16:
592b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit17:
593b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit18:
594b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit19:
595b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit20:
596b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit21:
597b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit22:
598b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit23:
599b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit24:
600b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit25:
601b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit26:
602b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit27:
603b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit28:
604b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit29:
605b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit30:
606b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_lit31:
607b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = opcode - DW_OP_lit0;
608b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
609b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
610b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push literal 0x%llX\n", (uint64_t) value);
611b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
612b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
613b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg0:
614b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg1:
615b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg2:
616b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg3:
617b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg4:
618b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg5:
619b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg6:
620b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg7:
621b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg8:
622b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg9:
623b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg10:
624b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg11:
625b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg12:
626b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg13:
627b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg14:
628b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg15:
629b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg16:
630b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg17:
631b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg18:
632b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg19:
633b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg20:
634b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg21:
635b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg22:
636b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg23:
637b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg24:
638b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg25:
639b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg26:
640b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg27:
641b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg28:
642b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg29:
643b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg30:
644b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_reg31:
645b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      reg = opcode - DW_OP_reg0;
646b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = registers.getRegister((int)reg);
647b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
648b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push reg %d\n", reg);
649b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
650b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
651b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_regx:
652b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
653b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = registers.getRegister((int)reg);
654b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
655b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
656b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
657b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
658b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg0:
659b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg1:
660b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg2:
661b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg3:
662b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg4:
663b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg5:
664b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg6:
665b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg7:
666b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg8:
667b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg9:
668b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg10:
669b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg11:
670b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg12:
671b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg13:
672b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg14:
673b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg15:
674b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg16:
675b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg17:
676b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg18:
677b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg19:
678b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg20:
679b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg21:
680b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg22:
681b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg23:
682b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg24:
683b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg25:
684b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg26:
685b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg27:
686b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg28:
687b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg29:
688b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg30:
689b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_breg31:
690b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      reg = opcode - DW_OP_breg0;
691b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
692b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue += registers.getRegister((int)reg);
693b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = (pint_t)(svalue);
694b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
695b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
696b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
697b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
698b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_bregx:
699b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
700b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
701b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      svalue += registers.getRegister((int)reg);
702b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = (pint_t)(svalue);
703b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
704b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
705b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
706b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
707b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_fbreg:
708b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
709b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
710b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
711b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_piece:
712b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_ABORT("DW_OP_piece not implemented");
713b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
714b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
715b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_deref_size:
716b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // pop stack, dereference, push result
717b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      value = *sp--;
718b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      switch (addressSpace.get8(p++)) {
719b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case 1:
720b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        value = addressSpace.get8(value);
721b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
722b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case 2:
723b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        value = addressSpace.get16(value);
724b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
725b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case 4:
726b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        value = addressSpace.get32(value);
727b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
728b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case 8:
729b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        value = (pint_t)addressSpace.get64(value);
730b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
731b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      default:
732b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
733b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
734b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      *(++sp) = value;
735b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
736b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t) value);
737b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      break;
738b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
739b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_xderef_size:
740b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_nop:
741b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_push_object_addres:
742b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_call2:
743b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_call4:
744b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    case DW_OP_call_ref:
745b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    default:
746b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_ABORT("dwarf opcode not implemented");
747b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
748b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
749b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
750b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (log)
751b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t) * sp);
752b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return *sp;
753b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
754b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
755b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
756b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
757b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik} // namespace libunwind
758b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
759b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // __DWARF_INSTRUCTIONS_HPP__
760