1aa0b96d0Sjoerg //===-------------------------- DwarfInstructions.hpp ---------------------===//
2aa0b96d0Sjoerg //
3aa0b96d0Sjoerg //                     The LLVM Compiler Infrastructure
4aa0b96d0Sjoerg //
5aa0b96d0Sjoerg // This file is dual licensed under the MIT and the University of Illinois Open
6aa0b96d0Sjoerg // Source Licenses. See LICENSE.TXT for details.
7aa0b96d0Sjoerg //
8aa0b96d0Sjoerg //
9aa0b96d0Sjoerg //  Processor specific interpretation of DWARF unwind info.
10aa0b96d0Sjoerg //
11aa0b96d0Sjoerg //===----------------------------------------------------------------------===//
12aa0b96d0Sjoerg 
13aa0b96d0Sjoerg #ifndef __DWARF_INSTRUCTIONS_HPP__
14aa0b96d0Sjoerg #define __DWARF_INSTRUCTIONS_HPP__
15aa0b96d0Sjoerg 
16aa0b96d0Sjoerg #include <cstdint>
17aa0b96d0Sjoerg #include <cstdlib>
18aa0b96d0Sjoerg 
19aa0b96d0Sjoerg #include "dwarf2.h"
20aa0b96d0Sjoerg #include "AddressSpace.hpp"
21aa0b96d0Sjoerg #include "Registers.hpp"
22aa0b96d0Sjoerg #include "DwarfParser.hpp"
23aa0b96d0Sjoerg 
24aa0b96d0Sjoerg namespace _Unwind {
25aa0b96d0Sjoerg 
26aa0b96d0Sjoerg enum step_result {
27aa0b96d0Sjoerg   UNW_STEP_SUCCESS,
28aa0b96d0Sjoerg   UNW_STEP_END,
29aa0b96d0Sjoerg   UNW_STEP_FAILED
30aa0b96d0Sjoerg };
31aa0b96d0Sjoerg 
32aa0b96d0Sjoerg /// DwarfInstructions maps abtract dwarf unwind instructions to a particular
33aa0b96d0Sjoerg /// architecture
34aa0b96d0Sjoerg template <typename A, typename R> class DwarfInstructions {
35aa0b96d0Sjoerg public:
36aa0b96d0Sjoerg   typedef typename A::pint_t pint_t;
37aa0b96d0Sjoerg   typedef typename A::sint_t sint_t;
38aa0b96d0Sjoerg 
39aa0b96d0Sjoerg   static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *);
40aa0b96d0Sjoerg 
41aa0b96d0Sjoerg private:
42aa0b96d0Sjoerg   static pint_t evaluateExpression(pint_t, A &, const R &, pint_t);
43aa0b96d0Sjoerg   static pint_t
44aa0b96d0Sjoerg   getSavedRegister(A &, const R &, pint_t,
45aa0b96d0Sjoerg                    const typename CFI_Parser<A, R>::RegisterLocation &);
46aa0b96d0Sjoerg   static pint_t
47aa0b96d0Sjoerg   computeRegisterLocation(A &, const R &, pint_t,
48aa0b96d0Sjoerg                           const typename CFI_Parser<A, R>::RegisterLocation &);
49aa0b96d0Sjoerg 
lastRestoreReg(const R &)50aa0b96d0Sjoerg   static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; }
51aa0b96d0Sjoerg 
getCFA(A & addressSpace,const typename CFI_Parser<A,R>::PrologInfo & prolog,const R & registers)52aa0b96d0Sjoerg   static pint_t getCFA(A &addressSpace,
53aa0b96d0Sjoerg                        const typename CFI_Parser<A, R>::PrologInfo &prolog,
54aa0b96d0Sjoerg                        const R &registers) {
55aa0b96d0Sjoerg     if (prolog.cfaRegister != 0)
56aa0b96d0Sjoerg       return registers.getRegister(prolog.cfaRegister) +
57aa0b96d0Sjoerg              prolog.cfaRegisterOffset;
58aa0b96d0Sjoerg     if (prolog.cfaExpression != 0)
59aa0b96d0Sjoerg       return evaluateExpression(prolog.cfaExpression, addressSpace, registers,
60aa0b96d0Sjoerg                                 0);
61aa0b96d0Sjoerg     assert(0 && "getCFA(): unknown location");
62aa0b96d0Sjoerg     __builtin_unreachable();
63aa0b96d0Sjoerg   }
64aa0b96d0Sjoerg };
65aa0b96d0Sjoerg 
66aa0b96d0Sjoerg template <typename A, typename R>
getSavedRegister(A & addressSpace,const R & registers,pint_t cfa,const typename CFI_Parser<A,R>::RegisterLocation & savedReg)67aa0b96d0Sjoerg typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
68aa0b96d0Sjoerg     A &addressSpace, const R &registers, pint_t cfa,
69aa0b96d0Sjoerg     const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
70aa0b96d0Sjoerg   switch (savedReg.location) {
71aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterInCFA:
72aa0b96d0Sjoerg     return addressSpace.getP(cfa + savedReg.value);
73aa0b96d0Sjoerg 
74aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterAtExpression:
75aa0b96d0Sjoerg     return addressSpace.getP(
76aa0b96d0Sjoerg         evaluateExpression(savedReg.value, addressSpace, registers, cfa));
77aa0b96d0Sjoerg 
78aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterIsExpression:
79aa0b96d0Sjoerg     return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
80aa0b96d0Sjoerg 
81aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterInRegister:
82aa0b96d0Sjoerg     return registers.getRegister(savedReg.value);
83aa0b96d0Sjoerg 
84aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterUnused:
85aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
86aa0b96d0Sjoerg     assert(0 && "unsupported restore location for register");
87aa0b96d0Sjoerg   }
88aa0b96d0Sjoerg   __builtin_unreachable();
89aa0b96d0Sjoerg }
90aa0b96d0Sjoerg 
91aa0b96d0Sjoerg template <typename A, typename R>
92aa0b96d0Sjoerg typename DwarfInstructions<A, R>::pint_t
computeRegisterLocation(A & addressSpace,const R & registers,pint_t cfa,const typename CFI_Parser<A,R>::RegisterLocation & savedReg)93aa0b96d0Sjoerg DwarfInstructions<A, R>::computeRegisterLocation(
94aa0b96d0Sjoerg     A &addressSpace, const R &registers, pint_t cfa,
95aa0b96d0Sjoerg     const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
96aa0b96d0Sjoerg   switch (savedReg.location) {
97aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterInCFA:
98aa0b96d0Sjoerg     return cfa + savedReg.value;
99aa0b96d0Sjoerg 
100aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterAtExpression:
101aa0b96d0Sjoerg     return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
102aa0b96d0Sjoerg 
103aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterIsExpression:
104aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterUnused:
105aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
106aa0b96d0Sjoerg   case CFI_Parser<A, R>::kRegisterInRegister:
107aa0b96d0Sjoerg     assert(0 && "unsupported restore location for float/vector register");
108aa0b96d0Sjoerg   }
109aa0b96d0Sjoerg   __builtin_unreachable();
110aa0b96d0Sjoerg }
111aa0b96d0Sjoerg 
112aa0b96d0Sjoerg template <typename A, typename R>
stepWithDwarf(A & addressSpace,pint_t pc,pint_t fdeStart,R & registers,unw_proc_info_t * ctx)113aa0b96d0Sjoerg step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
114aa0b96d0Sjoerg                                                    pint_t fdeStart,
115aa0b96d0Sjoerg                                                    R &registers,
116aa0b96d0Sjoerg                                                    unw_proc_info_t *ctx) {
117aa0b96d0Sjoerg   typename CFI_Parser<A, R>::FDE_Info fdeInfo;
118aa0b96d0Sjoerg   typename CFI_Parser<A, R>::CIE_Info cieInfo;
119aa0b96d0Sjoerg   if (!CFI_Parser<A, R>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo,
120aa0b96d0Sjoerg                                    ctx))
121aa0b96d0Sjoerg     return UNW_STEP_FAILED;
122aa0b96d0Sjoerg 
123aa0b96d0Sjoerg   typename CFI_Parser<A, R>::PrologInfo prolog;
124aa0b96d0Sjoerg   if (!CFI_Parser<A, R>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo,
125aa0b96d0Sjoerg                                               pc, &prolog, ctx))
126aa0b96d0Sjoerg     return UNW_STEP_FAILED;
127aa0b96d0Sjoerg 
128aa0b96d0Sjoerg   // Create working copy of the register set.
129aa0b96d0Sjoerg   R newRegisters = registers;
130aa0b96d0Sjoerg 
131aa0b96d0Sjoerg   // Get pointer to CFA by the architecture-specific code.
132aa0b96d0Sjoerg   pint_t cfa = getCFA(addressSpace, prolog, registers);
133aa0b96d0Sjoerg 
134aa0b96d0Sjoerg   // Restore registers according to DWARF instructions
135aa0b96d0Sjoerg   pint_t returnAddress = 0;
136aa0b96d0Sjoerg   for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
137aa0b96d0Sjoerg     if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused)
138aa0b96d0Sjoerg       continue;
139215abdb1Sjoerg     if (i == (int)cieInfo.returnAddressRegister)
140aa0b96d0Sjoerg       returnAddress = getSavedRegister(addressSpace, registers, cfa,
141aa0b96d0Sjoerg                                        prolog.savedRegisters[i]);
142aa0b96d0Sjoerg     else if (registers.validRegister(i))
143aa0b96d0Sjoerg       newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa,
144aa0b96d0Sjoerg                                                    prolog.savedRegisters[i]));
145aa0b96d0Sjoerg     else if (registers.validFloatVectorRegister(i))
146aa0b96d0Sjoerg       newRegisters.copyFloatVectorRegister(
147aa0b96d0Sjoerg           i, computeRegisterLocation(addressSpace, registers, cfa,
148aa0b96d0Sjoerg                                      prolog.savedRegisters[i]));
149aa0b96d0Sjoerg     else
150aa0b96d0Sjoerg       return UNW_STEP_FAILED;
151aa0b96d0Sjoerg   }
152aa0b96d0Sjoerg 
153aa0b96d0Sjoerg   // The CFA is defined as the stack pointer at the call site.
154aa0b96d0Sjoerg   // Therefore the SP is restored by setting it to the CFA.
155aa0b96d0Sjoerg   newRegisters.setSP(cfa);
156*0282220bSjoerg   returnAddress += R::RETURN_OFFSET;
157*0282220bSjoerg   returnAddress &= ~R::RETURN_MASK;
158*0282220bSjoerg   newRegisters.setIP(returnAddress);
159aa0b96d0Sjoerg 
160aa0b96d0Sjoerg   // Now replace register set with the working copy.
161aa0b96d0Sjoerg   registers = newRegisters;
162aa0b96d0Sjoerg 
163aa0b96d0Sjoerg   return UNW_STEP_SUCCESS;
164aa0b96d0Sjoerg }
165aa0b96d0Sjoerg 
166aa0b96d0Sjoerg template <typename A, typename R>
167aa0b96d0Sjoerg typename A::pint_t
evaluateExpression(pint_t expression,A & addressSpace,const R & registers,pint_t initialStackValue)168aa0b96d0Sjoerg DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
169aa0b96d0Sjoerg                                             const R &registers,
170aa0b96d0Sjoerg                                             pint_t initialStackValue) {
171aa0b96d0Sjoerg   pint_t p = expression;
172aa0b96d0Sjoerg   pint_t expressionEnd = expression + 20; // Rough estimate
173aa0b96d0Sjoerg   uint64_t length = addressSpace.getULEB128(p, expressionEnd);
174aa0b96d0Sjoerg   expressionEnd = p + length;
175aa0b96d0Sjoerg   pint_t stack[100];
176aa0b96d0Sjoerg   pint_t *sp = stack;
177aa0b96d0Sjoerg   *(++sp) = initialStackValue;
178aa0b96d0Sjoerg 
179aa0b96d0Sjoerg   while (p < expressionEnd) {
180aa0b96d0Sjoerg     uint8_t opcode = addressSpace.get8(p++);
181aa0b96d0Sjoerg     sint_t svalue;
182aa0b96d0Sjoerg     pint_t value;
183aa0b96d0Sjoerg     uint32_t reg;
184aa0b96d0Sjoerg     switch (opcode) {
185aa0b96d0Sjoerg     case DW_OP_addr:
186aa0b96d0Sjoerg       // push immediate address sized value
187aa0b96d0Sjoerg       value = addressSpace.getP(p);
188aa0b96d0Sjoerg       p += sizeof(pint_t);
189aa0b96d0Sjoerg       *(++sp) = value;
190aa0b96d0Sjoerg       break;
191aa0b96d0Sjoerg 
192aa0b96d0Sjoerg     case DW_OP_deref:
193aa0b96d0Sjoerg       // pop stack, dereference, push result
194aa0b96d0Sjoerg       value = *sp--;
195aa0b96d0Sjoerg       *(++sp) = addressSpace.getP(value);
196aa0b96d0Sjoerg       break;
197aa0b96d0Sjoerg 
198aa0b96d0Sjoerg     case DW_OP_const1u:
199aa0b96d0Sjoerg       // push immediate 1 byte value
200aa0b96d0Sjoerg       value = addressSpace.get8(p);
201aa0b96d0Sjoerg       p += 1;
202aa0b96d0Sjoerg       *(++sp) = value;
203aa0b96d0Sjoerg       break;
204aa0b96d0Sjoerg 
205aa0b96d0Sjoerg     case DW_OP_const1s:
206aa0b96d0Sjoerg       // push immediate 1 byte signed value
207aa0b96d0Sjoerg       svalue = (int8_t)addressSpace.get8(p);
208aa0b96d0Sjoerg       p += 1;
209aa0b96d0Sjoerg       *(++sp) = svalue;
210aa0b96d0Sjoerg       break;
211aa0b96d0Sjoerg 
212aa0b96d0Sjoerg     case DW_OP_const2u:
213aa0b96d0Sjoerg       // push immediate 2 byte value
214aa0b96d0Sjoerg       value = addressSpace.get16(p);
215aa0b96d0Sjoerg       p += 2;
216aa0b96d0Sjoerg       *(++sp) = value;
217aa0b96d0Sjoerg       break;
218aa0b96d0Sjoerg 
219aa0b96d0Sjoerg     case DW_OP_const2s:
220aa0b96d0Sjoerg       // push immediate 2 byte signed value
221aa0b96d0Sjoerg       svalue = (int16_t)addressSpace.get16(p);
222aa0b96d0Sjoerg       p += 2;
223aa0b96d0Sjoerg       *(++sp) = svalue;
224aa0b96d0Sjoerg       break;
225aa0b96d0Sjoerg 
226aa0b96d0Sjoerg     case DW_OP_const4u:
227aa0b96d0Sjoerg       // push immediate 4 byte value
228aa0b96d0Sjoerg       value = addressSpace.get32(p);
229aa0b96d0Sjoerg       p += 4;
230aa0b96d0Sjoerg       *(++sp) = value;
231aa0b96d0Sjoerg       break;
232aa0b96d0Sjoerg 
233aa0b96d0Sjoerg     case DW_OP_const4s:
234aa0b96d0Sjoerg       // push immediate 4 byte signed value
235aa0b96d0Sjoerg       svalue = (int32_t)addressSpace.get32(p);
236aa0b96d0Sjoerg       p += 4;
237aa0b96d0Sjoerg       *(++sp) = svalue;
238aa0b96d0Sjoerg       break;
239aa0b96d0Sjoerg 
240aa0b96d0Sjoerg     case DW_OP_const8u:
241aa0b96d0Sjoerg       // push immediate 8 byte value
242aa0b96d0Sjoerg       value = addressSpace.get64(p);
243aa0b96d0Sjoerg       p += 8;
244aa0b96d0Sjoerg       *(++sp) = value;
245aa0b96d0Sjoerg       break;
246aa0b96d0Sjoerg 
247aa0b96d0Sjoerg     case DW_OP_const8s:
248aa0b96d0Sjoerg       // push immediate 8 byte signed value
249aa0b96d0Sjoerg       value = (int32_t)addressSpace.get64(p);
250aa0b96d0Sjoerg       p += 8;
251aa0b96d0Sjoerg       *(++sp) = value;
252aa0b96d0Sjoerg       break;
253aa0b96d0Sjoerg 
254aa0b96d0Sjoerg     case DW_OP_constu:
255aa0b96d0Sjoerg       // push immediate ULEB128 value
256aa0b96d0Sjoerg       value = addressSpace.getULEB128(p, expressionEnd);
257aa0b96d0Sjoerg       *(++sp) = value;
258aa0b96d0Sjoerg       break;
259aa0b96d0Sjoerg 
260aa0b96d0Sjoerg     case DW_OP_consts:
261aa0b96d0Sjoerg       // push immediate SLEB128 value
262aa0b96d0Sjoerg       svalue = addressSpace.getSLEB128(p, expressionEnd);
263aa0b96d0Sjoerg       *(++sp) = svalue;
264aa0b96d0Sjoerg       break;
265aa0b96d0Sjoerg 
266aa0b96d0Sjoerg     case DW_OP_dup:
267aa0b96d0Sjoerg       // push top of stack
268aa0b96d0Sjoerg       value = *sp;
269aa0b96d0Sjoerg       *(++sp) = value;
270aa0b96d0Sjoerg       break;
271aa0b96d0Sjoerg 
272aa0b96d0Sjoerg     case DW_OP_drop:
273aa0b96d0Sjoerg       // pop
274aa0b96d0Sjoerg       --sp;
275aa0b96d0Sjoerg       break;
276aa0b96d0Sjoerg 
277aa0b96d0Sjoerg     case DW_OP_over:
278aa0b96d0Sjoerg       // dup second
279aa0b96d0Sjoerg       value = sp[-1];
280aa0b96d0Sjoerg       *(++sp) = value;
281aa0b96d0Sjoerg       break;
282aa0b96d0Sjoerg 
283aa0b96d0Sjoerg     case DW_OP_pick:
284aa0b96d0Sjoerg       // pick from
285aa0b96d0Sjoerg       reg = addressSpace.get8(p);
286aa0b96d0Sjoerg       p += 1;
287aa0b96d0Sjoerg       value = sp[-reg];
288aa0b96d0Sjoerg       *(++sp) = value;
289aa0b96d0Sjoerg       break;
290aa0b96d0Sjoerg 
291aa0b96d0Sjoerg     case DW_OP_swap:
292aa0b96d0Sjoerg       // swap top two
293aa0b96d0Sjoerg       value = sp[0];
294aa0b96d0Sjoerg       sp[0] = sp[-1];
295aa0b96d0Sjoerg       sp[-1] = value;
296aa0b96d0Sjoerg       break;
297aa0b96d0Sjoerg 
298aa0b96d0Sjoerg     case DW_OP_rot:
299aa0b96d0Sjoerg       // rotate top three
300aa0b96d0Sjoerg       value = sp[0];
301aa0b96d0Sjoerg       sp[0] = sp[-1];
302aa0b96d0Sjoerg       sp[-1] = sp[-2];
303aa0b96d0Sjoerg       sp[-2] = value;
304aa0b96d0Sjoerg       break;
305aa0b96d0Sjoerg 
306aa0b96d0Sjoerg     case DW_OP_xderef:
307aa0b96d0Sjoerg       // pop stack, dereference, push result
308aa0b96d0Sjoerg       value = *sp--;
309aa0b96d0Sjoerg       *sp = *((uint64_t *)value);
310aa0b96d0Sjoerg       break;
311aa0b96d0Sjoerg 
312aa0b96d0Sjoerg     case DW_OP_abs:
313aa0b96d0Sjoerg       svalue = *sp;
314aa0b96d0Sjoerg       if (svalue < 0)
315aa0b96d0Sjoerg         *sp = -svalue;
316aa0b96d0Sjoerg       break;
317aa0b96d0Sjoerg 
318aa0b96d0Sjoerg     case DW_OP_and:
319aa0b96d0Sjoerg       value = *sp--;
320aa0b96d0Sjoerg       *sp &= value;
321aa0b96d0Sjoerg       break;
322aa0b96d0Sjoerg 
323aa0b96d0Sjoerg     case DW_OP_div:
324aa0b96d0Sjoerg       svalue = *sp--;
325aa0b96d0Sjoerg       *sp = *sp / svalue;
326aa0b96d0Sjoerg       break;
327aa0b96d0Sjoerg 
328aa0b96d0Sjoerg     case DW_OP_minus:
329aa0b96d0Sjoerg       svalue = *sp--;
330aa0b96d0Sjoerg       *sp = *sp - svalue;
331aa0b96d0Sjoerg       break;
332aa0b96d0Sjoerg 
333aa0b96d0Sjoerg     case DW_OP_mod:
334aa0b96d0Sjoerg       svalue = *sp--;
335aa0b96d0Sjoerg       *sp = *sp % svalue;
336aa0b96d0Sjoerg       break;
337aa0b96d0Sjoerg 
338aa0b96d0Sjoerg     case DW_OP_mul:
339aa0b96d0Sjoerg       svalue = *sp--;
340aa0b96d0Sjoerg       *sp = *sp * svalue;
341aa0b96d0Sjoerg       break;
342aa0b96d0Sjoerg 
343aa0b96d0Sjoerg     case DW_OP_neg:
344aa0b96d0Sjoerg       *sp = 0 - *sp;
345aa0b96d0Sjoerg       break;
346aa0b96d0Sjoerg 
347aa0b96d0Sjoerg     case DW_OP_not:
348aa0b96d0Sjoerg       svalue = *sp;
349aa0b96d0Sjoerg       *sp = ~svalue;
350aa0b96d0Sjoerg       break;
351aa0b96d0Sjoerg 
352aa0b96d0Sjoerg     case DW_OP_or:
353aa0b96d0Sjoerg       value = *sp--;
354aa0b96d0Sjoerg       *sp |= value;
355aa0b96d0Sjoerg       break;
356aa0b96d0Sjoerg 
357aa0b96d0Sjoerg     case DW_OP_plus:
358aa0b96d0Sjoerg       value = *sp--;
359aa0b96d0Sjoerg       *sp += value;
360aa0b96d0Sjoerg       break;
361aa0b96d0Sjoerg 
362aa0b96d0Sjoerg     case DW_OP_plus_uconst:
363aa0b96d0Sjoerg       // pop stack, add uelb128 constant, push result
364aa0b96d0Sjoerg       *sp += addressSpace.getULEB128(p, expressionEnd);
365aa0b96d0Sjoerg       break;
366aa0b96d0Sjoerg 
367aa0b96d0Sjoerg     case DW_OP_shl:
368aa0b96d0Sjoerg       value = *sp--;
369aa0b96d0Sjoerg       *sp = *sp << value;
370aa0b96d0Sjoerg       break;
371aa0b96d0Sjoerg 
372aa0b96d0Sjoerg     case DW_OP_shr:
373aa0b96d0Sjoerg       value = *sp--;
374aa0b96d0Sjoerg       *sp = *sp >> value;
375aa0b96d0Sjoerg       break;
376aa0b96d0Sjoerg 
377aa0b96d0Sjoerg     case DW_OP_shra:
378aa0b96d0Sjoerg       value = *sp--;
379aa0b96d0Sjoerg       svalue = *sp;
380aa0b96d0Sjoerg       *sp = svalue >> value;
381aa0b96d0Sjoerg       break;
382aa0b96d0Sjoerg 
383aa0b96d0Sjoerg     case DW_OP_xor:
384aa0b96d0Sjoerg       value = *sp--;
385aa0b96d0Sjoerg       *sp ^= value;
386aa0b96d0Sjoerg       break;
387aa0b96d0Sjoerg 
388aa0b96d0Sjoerg     case DW_OP_skip:
389aa0b96d0Sjoerg       svalue = (int16_t)addressSpace.get16(p);
390aa0b96d0Sjoerg       p += 2;
391aa0b96d0Sjoerg       p += svalue;
392aa0b96d0Sjoerg       break;
393aa0b96d0Sjoerg 
394aa0b96d0Sjoerg     case DW_OP_bra:
395aa0b96d0Sjoerg       svalue = (int16_t)addressSpace.get16(p);
396aa0b96d0Sjoerg       p += 2;
397aa0b96d0Sjoerg       if (*sp--)
398aa0b96d0Sjoerg         p += svalue;
399aa0b96d0Sjoerg       break;
400aa0b96d0Sjoerg 
401aa0b96d0Sjoerg     case DW_OP_eq:
402aa0b96d0Sjoerg       value = *sp--;
403aa0b96d0Sjoerg       *sp = (*sp == value);
404aa0b96d0Sjoerg       break;
405aa0b96d0Sjoerg 
406aa0b96d0Sjoerg     case DW_OP_ge:
407aa0b96d0Sjoerg       value = *sp--;
408aa0b96d0Sjoerg       *sp = (*sp >= value);
409aa0b96d0Sjoerg       break;
410aa0b96d0Sjoerg 
411aa0b96d0Sjoerg     case DW_OP_gt:
412aa0b96d0Sjoerg       value = *sp--;
413aa0b96d0Sjoerg       *sp = (*sp > value);
414aa0b96d0Sjoerg       break;
415aa0b96d0Sjoerg 
416aa0b96d0Sjoerg     case DW_OP_le:
417aa0b96d0Sjoerg       value = *sp--;
418aa0b96d0Sjoerg       *sp = (*sp <= value);
419aa0b96d0Sjoerg       break;
420aa0b96d0Sjoerg 
421aa0b96d0Sjoerg     case DW_OP_lt:
422aa0b96d0Sjoerg       value = *sp--;
423aa0b96d0Sjoerg       *sp = (*sp < value);
424aa0b96d0Sjoerg       break;
425aa0b96d0Sjoerg 
426aa0b96d0Sjoerg     case DW_OP_ne:
427aa0b96d0Sjoerg       value = *sp--;
428aa0b96d0Sjoerg       *sp = (*sp != value);
429aa0b96d0Sjoerg       break;
430aa0b96d0Sjoerg 
431aa0b96d0Sjoerg     case DW_OP_lit0:
432aa0b96d0Sjoerg     case DW_OP_lit1:
433aa0b96d0Sjoerg     case DW_OP_lit2:
434aa0b96d0Sjoerg     case DW_OP_lit3:
435aa0b96d0Sjoerg     case DW_OP_lit4:
436aa0b96d0Sjoerg     case DW_OP_lit5:
437aa0b96d0Sjoerg     case DW_OP_lit6:
438aa0b96d0Sjoerg     case DW_OP_lit7:
439aa0b96d0Sjoerg     case DW_OP_lit8:
440aa0b96d0Sjoerg     case DW_OP_lit9:
441aa0b96d0Sjoerg     case DW_OP_lit10:
442aa0b96d0Sjoerg     case DW_OP_lit11:
443aa0b96d0Sjoerg     case DW_OP_lit12:
444aa0b96d0Sjoerg     case DW_OP_lit13:
445aa0b96d0Sjoerg     case DW_OP_lit14:
446aa0b96d0Sjoerg     case DW_OP_lit15:
447aa0b96d0Sjoerg     case DW_OP_lit16:
448aa0b96d0Sjoerg     case DW_OP_lit17:
449aa0b96d0Sjoerg     case DW_OP_lit18:
450aa0b96d0Sjoerg     case DW_OP_lit19:
451aa0b96d0Sjoerg     case DW_OP_lit20:
452aa0b96d0Sjoerg     case DW_OP_lit21:
453aa0b96d0Sjoerg     case DW_OP_lit22:
454aa0b96d0Sjoerg     case DW_OP_lit23:
455aa0b96d0Sjoerg     case DW_OP_lit24:
456aa0b96d0Sjoerg     case DW_OP_lit25:
457aa0b96d0Sjoerg     case DW_OP_lit26:
458aa0b96d0Sjoerg     case DW_OP_lit27:
459aa0b96d0Sjoerg     case DW_OP_lit28:
460aa0b96d0Sjoerg     case DW_OP_lit29:
461aa0b96d0Sjoerg     case DW_OP_lit30:
462aa0b96d0Sjoerg     case DW_OP_lit31:
463aa0b96d0Sjoerg       value = opcode - DW_OP_lit0;
464aa0b96d0Sjoerg       *(++sp) = value;
465aa0b96d0Sjoerg       break;
466aa0b96d0Sjoerg 
467aa0b96d0Sjoerg     case DW_OP_reg0:
468aa0b96d0Sjoerg     case DW_OP_reg1:
469aa0b96d0Sjoerg     case DW_OP_reg2:
470aa0b96d0Sjoerg     case DW_OP_reg3:
471aa0b96d0Sjoerg     case DW_OP_reg4:
472aa0b96d0Sjoerg     case DW_OP_reg5:
473aa0b96d0Sjoerg     case DW_OP_reg6:
474aa0b96d0Sjoerg     case DW_OP_reg7:
475aa0b96d0Sjoerg     case DW_OP_reg8:
476aa0b96d0Sjoerg     case DW_OP_reg9:
477aa0b96d0Sjoerg     case DW_OP_reg10:
478aa0b96d0Sjoerg     case DW_OP_reg11:
479aa0b96d0Sjoerg     case DW_OP_reg12:
480aa0b96d0Sjoerg     case DW_OP_reg13:
481aa0b96d0Sjoerg     case DW_OP_reg14:
482aa0b96d0Sjoerg     case DW_OP_reg15:
483aa0b96d0Sjoerg     case DW_OP_reg16:
484aa0b96d0Sjoerg     case DW_OP_reg17:
485aa0b96d0Sjoerg     case DW_OP_reg18:
486aa0b96d0Sjoerg     case DW_OP_reg19:
487aa0b96d0Sjoerg     case DW_OP_reg20:
488aa0b96d0Sjoerg     case DW_OP_reg21:
489aa0b96d0Sjoerg     case DW_OP_reg22:
490aa0b96d0Sjoerg     case DW_OP_reg23:
491aa0b96d0Sjoerg     case DW_OP_reg24:
492aa0b96d0Sjoerg     case DW_OP_reg25:
493aa0b96d0Sjoerg     case DW_OP_reg26:
494aa0b96d0Sjoerg     case DW_OP_reg27:
495aa0b96d0Sjoerg     case DW_OP_reg28:
496aa0b96d0Sjoerg     case DW_OP_reg29:
497aa0b96d0Sjoerg     case DW_OP_reg30:
498aa0b96d0Sjoerg     case DW_OP_reg31:
499aa0b96d0Sjoerg       reg = opcode - DW_OP_reg0;
500aa0b96d0Sjoerg       *(++sp) = registers.getRegister(reg);
501aa0b96d0Sjoerg       break;
502aa0b96d0Sjoerg 
503aa0b96d0Sjoerg     case DW_OP_regx:
504aa0b96d0Sjoerg       reg = addressSpace.getULEB128(p, expressionEnd);
505aa0b96d0Sjoerg       *(++sp) = registers.getRegister(reg);
506aa0b96d0Sjoerg       break;
507aa0b96d0Sjoerg 
508aa0b96d0Sjoerg     case DW_OP_breg0:
509aa0b96d0Sjoerg     case DW_OP_breg1:
510aa0b96d0Sjoerg     case DW_OP_breg2:
511aa0b96d0Sjoerg     case DW_OP_breg3:
512aa0b96d0Sjoerg     case DW_OP_breg4:
513aa0b96d0Sjoerg     case DW_OP_breg5:
514aa0b96d0Sjoerg     case DW_OP_breg6:
515aa0b96d0Sjoerg     case DW_OP_breg7:
516aa0b96d0Sjoerg     case DW_OP_breg8:
517aa0b96d0Sjoerg     case DW_OP_breg9:
518aa0b96d0Sjoerg     case DW_OP_breg10:
519aa0b96d0Sjoerg     case DW_OP_breg11:
520aa0b96d0Sjoerg     case DW_OP_breg12:
521aa0b96d0Sjoerg     case DW_OP_breg13:
522aa0b96d0Sjoerg     case DW_OP_breg14:
523aa0b96d0Sjoerg     case DW_OP_breg15:
524aa0b96d0Sjoerg     case DW_OP_breg16:
525aa0b96d0Sjoerg     case DW_OP_breg17:
526aa0b96d0Sjoerg     case DW_OP_breg18:
527aa0b96d0Sjoerg     case DW_OP_breg19:
528aa0b96d0Sjoerg     case DW_OP_breg20:
529aa0b96d0Sjoerg     case DW_OP_breg21:
530aa0b96d0Sjoerg     case DW_OP_breg22:
531aa0b96d0Sjoerg     case DW_OP_breg23:
532aa0b96d0Sjoerg     case DW_OP_breg24:
533aa0b96d0Sjoerg     case DW_OP_breg25:
534aa0b96d0Sjoerg     case DW_OP_breg26:
535aa0b96d0Sjoerg     case DW_OP_breg27:
536aa0b96d0Sjoerg     case DW_OP_breg28:
537aa0b96d0Sjoerg     case DW_OP_breg29:
538aa0b96d0Sjoerg     case DW_OP_breg30:
539aa0b96d0Sjoerg     case DW_OP_breg31:
540aa0b96d0Sjoerg       reg = opcode - DW_OP_breg0;
541aa0b96d0Sjoerg       svalue = addressSpace.getSLEB128(p, expressionEnd);
542aa0b96d0Sjoerg       *(++sp) = registers.getRegister(reg) + svalue;
543aa0b96d0Sjoerg       break;
544aa0b96d0Sjoerg 
545aa0b96d0Sjoerg     case DW_OP_bregx:
546aa0b96d0Sjoerg       reg = addressSpace.getULEB128(p, expressionEnd);
547aa0b96d0Sjoerg       svalue = addressSpace.getSLEB128(p, expressionEnd);
548aa0b96d0Sjoerg       *(++sp) = registers.getRegister(reg) + svalue;
549aa0b96d0Sjoerg       break;
550aa0b96d0Sjoerg 
551aa0b96d0Sjoerg     case DW_OP_deref_size:
552aa0b96d0Sjoerg       // pop stack, dereference, push result
553aa0b96d0Sjoerg       value = *sp--;
554aa0b96d0Sjoerg       switch (addressSpace.get8(p++)) {
555aa0b96d0Sjoerg       case 1:
556aa0b96d0Sjoerg         value = addressSpace.get8(value);
557aa0b96d0Sjoerg         break;
558aa0b96d0Sjoerg       case 2:
559aa0b96d0Sjoerg         value = addressSpace.get16(value);
560aa0b96d0Sjoerg         break;
561aa0b96d0Sjoerg       case 4:
562aa0b96d0Sjoerg         value = addressSpace.get32(value);
563aa0b96d0Sjoerg         break;
564aa0b96d0Sjoerg       case 8:
565aa0b96d0Sjoerg         value = addressSpace.get64(value);
566aa0b96d0Sjoerg         break;
567aa0b96d0Sjoerg       default:
568aa0b96d0Sjoerg         assert(0 && "DW_OP_deref_size with bad size");
569aa0b96d0Sjoerg       }
570aa0b96d0Sjoerg       *(++sp) = value;
571aa0b96d0Sjoerg       break;
572aa0b96d0Sjoerg 
573aa0b96d0Sjoerg     case DW_OP_fbreg:
574aa0b96d0Sjoerg     case DW_OP_piece:
575aa0b96d0Sjoerg     case DW_OP_xderef_size:
576aa0b96d0Sjoerg     case DW_OP_nop:
577aa0b96d0Sjoerg     case DW_OP_push_object_addres:
578aa0b96d0Sjoerg     case DW_OP_call2:
579aa0b96d0Sjoerg     case DW_OP_call4:
580aa0b96d0Sjoerg     case DW_OP_call_ref:
581aa0b96d0Sjoerg     default:
582aa0b96d0Sjoerg       assert(0 && "dwarf opcode not implemented");
583aa0b96d0Sjoerg     }
584aa0b96d0Sjoerg   }
585aa0b96d0Sjoerg   return *sp;
586aa0b96d0Sjoerg }
587aa0b96d0Sjoerg 
588aa0b96d0Sjoerg } // namespace _Unwind
589aa0b96d0Sjoerg 
590aa0b96d0Sjoerg #endif // __DWARF_INSTRUCTIONS_HPP__
591