xref: /minix3/sys/lib/libunwind/DwarfInstructions.hpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1472758f3SLionel Sambuc //===-------------------------- DwarfInstructions.hpp ---------------------===//
2472758f3SLionel Sambuc //
3472758f3SLionel Sambuc //                     The LLVM Compiler Infrastructure
4472758f3SLionel Sambuc //
5472758f3SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6472758f3SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7472758f3SLionel Sambuc //
8472758f3SLionel Sambuc //
9472758f3SLionel Sambuc //  Processor specific interpretation of DWARF unwind info.
10472758f3SLionel Sambuc //
11472758f3SLionel Sambuc //===----------------------------------------------------------------------===//
12472758f3SLionel Sambuc 
13472758f3SLionel Sambuc #ifndef __DWARF_INSTRUCTIONS_HPP__
14472758f3SLionel Sambuc #define __DWARF_INSTRUCTIONS_HPP__
15472758f3SLionel Sambuc 
16472758f3SLionel Sambuc #include <cstdint>
17472758f3SLionel Sambuc #include <cstdlib>
18472758f3SLionel Sambuc 
19472758f3SLionel Sambuc #include "dwarf2.h"
20472758f3SLionel Sambuc #include "AddressSpace.hpp"
21472758f3SLionel Sambuc #include "Registers.hpp"
22472758f3SLionel Sambuc #include "DwarfParser.hpp"
23472758f3SLionel Sambuc 
24472758f3SLionel Sambuc namespace _Unwind {
25472758f3SLionel Sambuc 
26472758f3SLionel Sambuc enum step_result {
27472758f3SLionel Sambuc   UNW_STEP_SUCCESS,
28472758f3SLionel Sambuc   UNW_STEP_END,
29472758f3SLionel Sambuc   UNW_STEP_FAILED
30472758f3SLionel Sambuc };
31472758f3SLionel Sambuc 
32472758f3SLionel Sambuc /// DwarfInstructions maps abtract dwarf unwind instructions to a particular
33472758f3SLionel Sambuc /// architecture
34472758f3SLionel Sambuc template <typename A, typename R> class DwarfInstructions {
35472758f3SLionel Sambuc public:
36472758f3SLionel Sambuc   typedef typename A::pint_t pint_t;
37472758f3SLionel Sambuc   typedef typename A::sint_t sint_t;
38472758f3SLionel Sambuc 
39472758f3SLionel Sambuc   static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *);
40472758f3SLionel Sambuc 
41472758f3SLionel Sambuc private:
42472758f3SLionel Sambuc   static pint_t evaluateExpression(pint_t, A &, const R &, pint_t);
43472758f3SLionel Sambuc   static pint_t
44472758f3SLionel Sambuc   getSavedRegister(A &, const R &, pint_t,
45472758f3SLionel Sambuc                    const typename CFI_Parser<A, R>::RegisterLocation &);
46472758f3SLionel Sambuc   static pint_t
47472758f3SLionel Sambuc   computeRegisterLocation(A &, const R &, pint_t,
48472758f3SLionel Sambuc                           const typename CFI_Parser<A, R>::RegisterLocation &);
49472758f3SLionel Sambuc 
lastRestoreReg(const R &)50472758f3SLionel Sambuc   static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; }
51472758f3SLionel Sambuc 
getCFA(A & addressSpace,const typename CFI_Parser<A,R>::PrologInfo & prolog,const R & registers)52472758f3SLionel Sambuc   static pint_t getCFA(A &addressSpace,
53472758f3SLionel Sambuc                        const typename CFI_Parser<A, R>::PrologInfo &prolog,
54472758f3SLionel Sambuc                        const R &registers) {
55472758f3SLionel Sambuc     if (prolog.cfaRegister != 0)
56472758f3SLionel Sambuc       return registers.getRegister(prolog.cfaRegister) +
57472758f3SLionel Sambuc              prolog.cfaRegisterOffset;
58472758f3SLionel Sambuc     if (prolog.cfaExpression != 0)
59472758f3SLionel Sambuc       return evaluateExpression(prolog.cfaExpression, addressSpace, registers,
60472758f3SLionel Sambuc                                 0);
61472758f3SLionel Sambuc     assert(0 && "getCFA(): unknown location");
62472758f3SLionel Sambuc     __builtin_unreachable();
63472758f3SLionel Sambuc   }
64472758f3SLionel Sambuc };
65472758f3SLionel Sambuc 
66472758f3SLionel Sambuc template <typename A, typename R>
getSavedRegister(A & addressSpace,const R & registers,pint_t cfa,const typename CFI_Parser<A,R>::RegisterLocation & savedReg)67472758f3SLionel Sambuc typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
68472758f3SLionel Sambuc     A &addressSpace, const R &registers, pint_t cfa,
69472758f3SLionel Sambuc     const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
70472758f3SLionel Sambuc   switch (savedReg.location) {
71472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterInCFA:
72472758f3SLionel Sambuc     return addressSpace.getP(cfa + savedReg.value);
73472758f3SLionel Sambuc 
74472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterAtExpression:
75472758f3SLionel Sambuc     return addressSpace.getP(
76472758f3SLionel Sambuc         evaluateExpression(savedReg.value, addressSpace, registers, cfa));
77472758f3SLionel Sambuc 
78472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterIsExpression:
79472758f3SLionel Sambuc     return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
80472758f3SLionel Sambuc 
81472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterInRegister:
82472758f3SLionel Sambuc     return registers.getRegister(savedReg.value);
83472758f3SLionel Sambuc 
84472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterUnused:
85472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
86472758f3SLionel Sambuc     assert(0 && "unsupported restore location for register");
87472758f3SLionel Sambuc   }
88472758f3SLionel Sambuc   __builtin_unreachable();
89472758f3SLionel Sambuc }
90472758f3SLionel Sambuc 
91472758f3SLionel Sambuc template <typename A, typename R>
92472758f3SLionel Sambuc typename DwarfInstructions<A, R>::pint_t
computeRegisterLocation(A & addressSpace,const R & registers,pint_t cfa,const typename CFI_Parser<A,R>::RegisterLocation & savedReg)93472758f3SLionel Sambuc DwarfInstructions<A, R>::computeRegisterLocation(
94472758f3SLionel Sambuc     A &addressSpace, const R &registers, pint_t cfa,
95472758f3SLionel Sambuc     const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
96472758f3SLionel Sambuc   switch (savedReg.location) {
97472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterInCFA:
98472758f3SLionel Sambuc     return cfa + savedReg.value;
99472758f3SLionel Sambuc 
100472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterAtExpression:
101472758f3SLionel Sambuc     return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
102472758f3SLionel Sambuc 
103472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterIsExpression:
104472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterUnused:
105472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
106472758f3SLionel Sambuc   case CFI_Parser<A, R>::kRegisterInRegister:
107472758f3SLionel Sambuc     assert(0 && "unsupported restore location for float/vector register");
108472758f3SLionel Sambuc   }
109472758f3SLionel Sambuc   __builtin_unreachable();
110472758f3SLionel Sambuc }
111472758f3SLionel Sambuc 
112472758f3SLionel Sambuc template <typename A, typename R>
stepWithDwarf(A & addressSpace,pint_t pc,pint_t fdeStart,R & registers,unw_proc_info_t * ctx)113472758f3SLionel Sambuc step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
114472758f3SLionel Sambuc                                                    pint_t fdeStart,
115472758f3SLionel Sambuc                                                    R &registers,
116472758f3SLionel Sambuc                                                    unw_proc_info_t *ctx) {
117472758f3SLionel Sambuc   typename CFI_Parser<A, R>::FDE_Info fdeInfo;
118472758f3SLionel Sambuc   typename CFI_Parser<A, R>::CIE_Info cieInfo;
119472758f3SLionel Sambuc   if (!CFI_Parser<A, R>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo,
120472758f3SLionel Sambuc                                    ctx))
121472758f3SLionel Sambuc     return UNW_STEP_FAILED;
122472758f3SLionel Sambuc 
123472758f3SLionel Sambuc   typename CFI_Parser<A, R>::PrologInfo prolog;
124472758f3SLionel Sambuc   if (!CFI_Parser<A, R>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo,
125472758f3SLionel Sambuc                                               pc, &prolog, ctx))
126472758f3SLionel Sambuc     return UNW_STEP_FAILED;
127472758f3SLionel Sambuc 
128472758f3SLionel Sambuc   // Create working copy of the register set.
129472758f3SLionel Sambuc   R newRegisters = registers;
130472758f3SLionel Sambuc 
131472758f3SLionel Sambuc   // Get pointer to CFA by the architecture-specific code.
132472758f3SLionel Sambuc   pint_t cfa = getCFA(addressSpace, prolog, registers);
133472758f3SLionel Sambuc 
134472758f3SLionel Sambuc   // Restore registers according to DWARF instructions
135472758f3SLionel Sambuc   pint_t returnAddress = 0;
136472758f3SLionel Sambuc   for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
137472758f3SLionel Sambuc     if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused)
138472758f3SLionel Sambuc       continue;
139b029fb59SBen Gras     if (i == (int)cieInfo.returnAddressRegister)
140472758f3SLionel Sambuc       returnAddress = getSavedRegister(addressSpace, registers, cfa,
141472758f3SLionel Sambuc                                        prolog.savedRegisters[i]);
142472758f3SLionel Sambuc     else if (registers.validRegister(i))
143472758f3SLionel Sambuc       newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa,
144472758f3SLionel Sambuc                                                    prolog.savedRegisters[i]));
145472758f3SLionel Sambuc     else if (registers.validFloatVectorRegister(i))
146472758f3SLionel Sambuc       newRegisters.copyFloatVectorRegister(
147472758f3SLionel Sambuc           i, computeRegisterLocation(addressSpace, registers, cfa,
148472758f3SLionel Sambuc                                      prolog.savedRegisters[i]));
149472758f3SLionel Sambuc     else
150472758f3SLionel Sambuc       return UNW_STEP_FAILED;
151472758f3SLionel Sambuc   }
152472758f3SLionel Sambuc 
153472758f3SLionel Sambuc   // The CFA is defined as the stack pointer at the call site.
154472758f3SLionel Sambuc   // Therefore the SP is restored by setting it to the CFA.
155472758f3SLionel Sambuc   newRegisters.setSP(cfa);
156b029fb59SBen Gras   newRegisters.setIP(returnAddress + R::RETURN_OFFSET);
157*0a6a1f1dSLionel Sambuc   returnAddress += R::RETURN_OFFSET;
158*0a6a1f1dSLionel Sambuc   returnAddress &= ~R::RETURN_MASK;
159*0a6a1f1dSLionel Sambuc   newRegisters.setIP(returnAddress);
160472758f3SLionel Sambuc 
161472758f3SLionel Sambuc   // Now replace register set with the working copy.
162472758f3SLionel Sambuc   registers = newRegisters;
163472758f3SLionel Sambuc 
164472758f3SLionel Sambuc   return UNW_STEP_SUCCESS;
165472758f3SLionel Sambuc }
166472758f3SLionel Sambuc 
167472758f3SLionel Sambuc template <typename A, typename R>
168472758f3SLionel Sambuc typename A::pint_t
evaluateExpression(pint_t expression,A & addressSpace,const R & registers,pint_t initialStackValue)169472758f3SLionel Sambuc DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
170472758f3SLionel Sambuc                                             const R &registers,
171472758f3SLionel Sambuc                                             pint_t initialStackValue) {
172472758f3SLionel Sambuc   pint_t p = expression;
173472758f3SLionel Sambuc   pint_t expressionEnd = expression + 20; // Rough estimate
174472758f3SLionel Sambuc   uint64_t length = addressSpace.getULEB128(p, expressionEnd);
175472758f3SLionel Sambuc   expressionEnd = p + length;
176472758f3SLionel Sambuc   pint_t stack[100];
177472758f3SLionel Sambuc   pint_t *sp = stack;
178472758f3SLionel Sambuc   *(++sp) = initialStackValue;
179472758f3SLionel Sambuc 
180472758f3SLionel Sambuc   while (p < expressionEnd) {
181472758f3SLionel Sambuc     uint8_t opcode = addressSpace.get8(p++);
182472758f3SLionel Sambuc     sint_t svalue;
183472758f3SLionel Sambuc     pint_t value;
184472758f3SLionel Sambuc     uint32_t reg;
185472758f3SLionel Sambuc     switch (opcode) {
186472758f3SLionel Sambuc     case DW_OP_addr:
187472758f3SLionel Sambuc       // push immediate address sized value
188472758f3SLionel Sambuc       value = addressSpace.getP(p);
189472758f3SLionel Sambuc       p += sizeof(pint_t);
190472758f3SLionel Sambuc       *(++sp) = value;
191472758f3SLionel Sambuc       break;
192472758f3SLionel Sambuc 
193472758f3SLionel Sambuc     case DW_OP_deref:
194472758f3SLionel Sambuc       // pop stack, dereference, push result
195472758f3SLionel Sambuc       value = *sp--;
196472758f3SLionel Sambuc       *(++sp) = addressSpace.getP(value);
197472758f3SLionel Sambuc       break;
198472758f3SLionel Sambuc 
199472758f3SLionel Sambuc     case DW_OP_const1u:
200472758f3SLionel Sambuc       // push immediate 1 byte value
201472758f3SLionel Sambuc       value = addressSpace.get8(p);
202472758f3SLionel Sambuc       p += 1;
203472758f3SLionel Sambuc       *(++sp) = value;
204472758f3SLionel Sambuc       break;
205472758f3SLionel Sambuc 
206472758f3SLionel Sambuc     case DW_OP_const1s:
207472758f3SLionel Sambuc       // push immediate 1 byte signed value
208472758f3SLionel Sambuc       svalue = (int8_t)addressSpace.get8(p);
209472758f3SLionel Sambuc       p += 1;
210472758f3SLionel Sambuc       *(++sp) = svalue;
211472758f3SLionel Sambuc       break;
212472758f3SLionel Sambuc 
213472758f3SLionel Sambuc     case DW_OP_const2u:
214472758f3SLionel Sambuc       // push immediate 2 byte value
215472758f3SLionel Sambuc       value = addressSpace.get16(p);
216472758f3SLionel Sambuc       p += 2;
217472758f3SLionel Sambuc       *(++sp) = value;
218472758f3SLionel Sambuc       break;
219472758f3SLionel Sambuc 
220472758f3SLionel Sambuc     case DW_OP_const2s:
221472758f3SLionel Sambuc       // push immediate 2 byte signed value
222472758f3SLionel Sambuc       svalue = (int16_t)addressSpace.get16(p);
223472758f3SLionel Sambuc       p += 2;
224472758f3SLionel Sambuc       *(++sp) = svalue;
225472758f3SLionel Sambuc       break;
226472758f3SLionel Sambuc 
227472758f3SLionel Sambuc     case DW_OP_const4u:
228472758f3SLionel Sambuc       // push immediate 4 byte value
229472758f3SLionel Sambuc       value = addressSpace.get32(p);
230472758f3SLionel Sambuc       p += 4;
231472758f3SLionel Sambuc       *(++sp) = value;
232472758f3SLionel Sambuc       break;
233472758f3SLionel Sambuc 
234472758f3SLionel Sambuc     case DW_OP_const4s:
235472758f3SLionel Sambuc       // push immediate 4 byte signed value
236472758f3SLionel Sambuc       svalue = (int32_t)addressSpace.get32(p);
237472758f3SLionel Sambuc       p += 4;
238472758f3SLionel Sambuc       *(++sp) = svalue;
239472758f3SLionel Sambuc       break;
240472758f3SLionel Sambuc 
241472758f3SLionel Sambuc     case DW_OP_const8u:
242472758f3SLionel Sambuc       // push immediate 8 byte value
243472758f3SLionel Sambuc       value = addressSpace.get64(p);
244472758f3SLionel Sambuc       p += 8;
245472758f3SLionel Sambuc       *(++sp) = value;
246472758f3SLionel Sambuc       break;
247472758f3SLionel Sambuc 
248472758f3SLionel Sambuc     case DW_OP_const8s:
249472758f3SLionel Sambuc       // push immediate 8 byte signed value
250472758f3SLionel Sambuc       value = (int32_t)addressSpace.get64(p);
251472758f3SLionel Sambuc       p += 8;
252472758f3SLionel Sambuc       *(++sp) = value;
253472758f3SLionel Sambuc       break;
254472758f3SLionel Sambuc 
255472758f3SLionel Sambuc     case DW_OP_constu:
256472758f3SLionel Sambuc       // push immediate ULEB128 value
257472758f3SLionel Sambuc       value = addressSpace.getULEB128(p, expressionEnd);
258472758f3SLionel Sambuc       *(++sp) = value;
259472758f3SLionel Sambuc       break;
260472758f3SLionel Sambuc 
261472758f3SLionel Sambuc     case DW_OP_consts:
262472758f3SLionel Sambuc       // push immediate SLEB128 value
263472758f3SLionel Sambuc       svalue = addressSpace.getSLEB128(p, expressionEnd);
264472758f3SLionel Sambuc       *(++sp) = svalue;
265472758f3SLionel Sambuc       break;
266472758f3SLionel Sambuc 
267472758f3SLionel Sambuc     case DW_OP_dup:
268472758f3SLionel Sambuc       // push top of stack
269472758f3SLionel Sambuc       value = *sp;
270472758f3SLionel Sambuc       *(++sp) = value;
271472758f3SLionel Sambuc       break;
272472758f3SLionel Sambuc 
273472758f3SLionel Sambuc     case DW_OP_drop:
274472758f3SLionel Sambuc       // pop
275472758f3SLionel Sambuc       --sp;
276472758f3SLionel Sambuc       break;
277472758f3SLionel Sambuc 
278472758f3SLionel Sambuc     case DW_OP_over:
279472758f3SLionel Sambuc       // dup second
280472758f3SLionel Sambuc       value = sp[-1];
281472758f3SLionel Sambuc       *(++sp) = value;
282472758f3SLionel Sambuc       break;
283472758f3SLionel Sambuc 
284472758f3SLionel Sambuc     case DW_OP_pick:
285472758f3SLionel Sambuc       // pick from
286472758f3SLionel Sambuc       reg = addressSpace.get8(p);
287472758f3SLionel Sambuc       p += 1;
288472758f3SLionel Sambuc       value = sp[-reg];
289472758f3SLionel Sambuc       *(++sp) = value;
290472758f3SLionel Sambuc       break;
291472758f3SLionel Sambuc 
292472758f3SLionel Sambuc     case DW_OP_swap:
293472758f3SLionel Sambuc       // swap top two
294472758f3SLionel Sambuc       value = sp[0];
295472758f3SLionel Sambuc       sp[0] = sp[-1];
296472758f3SLionel Sambuc       sp[-1] = value;
297472758f3SLionel Sambuc       break;
298472758f3SLionel Sambuc 
299472758f3SLionel Sambuc     case DW_OP_rot:
300472758f3SLionel Sambuc       // rotate top three
301472758f3SLionel Sambuc       value = sp[0];
302472758f3SLionel Sambuc       sp[0] = sp[-1];
303472758f3SLionel Sambuc       sp[-1] = sp[-2];
304472758f3SLionel Sambuc       sp[-2] = value;
305472758f3SLionel Sambuc       break;
306472758f3SLionel Sambuc 
307472758f3SLionel Sambuc     case DW_OP_xderef:
308472758f3SLionel Sambuc       // pop stack, dereference, push result
309472758f3SLionel Sambuc       value = *sp--;
310472758f3SLionel Sambuc       *sp = *((uint64_t *)value);
311472758f3SLionel Sambuc       break;
312472758f3SLionel Sambuc 
313472758f3SLionel Sambuc     case DW_OP_abs:
314472758f3SLionel Sambuc       svalue = *sp;
315472758f3SLionel Sambuc       if (svalue < 0)
316472758f3SLionel Sambuc         *sp = -svalue;
317472758f3SLionel Sambuc       break;
318472758f3SLionel Sambuc 
319472758f3SLionel Sambuc     case DW_OP_and:
320472758f3SLionel Sambuc       value = *sp--;
321472758f3SLionel Sambuc       *sp &= value;
322472758f3SLionel Sambuc       break;
323472758f3SLionel Sambuc 
324472758f3SLionel Sambuc     case DW_OP_div:
325472758f3SLionel Sambuc       svalue = *sp--;
326472758f3SLionel Sambuc       *sp = *sp / svalue;
327472758f3SLionel Sambuc       break;
328472758f3SLionel Sambuc 
329472758f3SLionel Sambuc     case DW_OP_minus:
330472758f3SLionel Sambuc       svalue = *sp--;
331472758f3SLionel Sambuc       *sp = *sp - svalue;
332472758f3SLionel Sambuc       break;
333472758f3SLionel Sambuc 
334472758f3SLionel Sambuc     case DW_OP_mod:
335472758f3SLionel Sambuc       svalue = *sp--;
336472758f3SLionel Sambuc       *sp = *sp % svalue;
337472758f3SLionel Sambuc       break;
338472758f3SLionel Sambuc 
339472758f3SLionel Sambuc     case DW_OP_mul:
340472758f3SLionel Sambuc       svalue = *sp--;
341472758f3SLionel Sambuc       *sp = *sp * svalue;
342472758f3SLionel Sambuc       break;
343472758f3SLionel Sambuc 
344472758f3SLionel Sambuc     case DW_OP_neg:
345472758f3SLionel Sambuc       *sp = 0 - *sp;
346472758f3SLionel Sambuc       break;
347472758f3SLionel Sambuc 
348472758f3SLionel Sambuc     case DW_OP_not:
349472758f3SLionel Sambuc       svalue = *sp;
350472758f3SLionel Sambuc       *sp = ~svalue;
351472758f3SLionel Sambuc       break;
352472758f3SLionel Sambuc 
353472758f3SLionel Sambuc     case DW_OP_or:
354472758f3SLionel Sambuc       value = *sp--;
355472758f3SLionel Sambuc       *sp |= value;
356472758f3SLionel Sambuc       break;
357472758f3SLionel Sambuc 
358472758f3SLionel Sambuc     case DW_OP_plus:
359472758f3SLionel Sambuc       value = *sp--;
360472758f3SLionel Sambuc       *sp += value;
361472758f3SLionel Sambuc       break;
362472758f3SLionel Sambuc 
363472758f3SLionel Sambuc     case DW_OP_plus_uconst:
364472758f3SLionel Sambuc       // pop stack, add uelb128 constant, push result
365472758f3SLionel Sambuc       *sp += addressSpace.getULEB128(p, expressionEnd);
366472758f3SLionel Sambuc       break;
367472758f3SLionel Sambuc 
368472758f3SLionel Sambuc     case DW_OP_shl:
369472758f3SLionel Sambuc       value = *sp--;
370472758f3SLionel Sambuc       *sp = *sp << value;
371472758f3SLionel Sambuc       break;
372472758f3SLionel Sambuc 
373472758f3SLionel Sambuc     case DW_OP_shr:
374472758f3SLionel Sambuc       value = *sp--;
375472758f3SLionel Sambuc       *sp = *sp >> value;
376472758f3SLionel Sambuc       break;
377472758f3SLionel Sambuc 
378472758f3SLionel Sambuc     case DW_OP_shra:
379472758f3SLionel Sambuc       value = *sp--;
380472758f3SLionel Sambuc       svalue = *sp;
381472758f3SLionel Sambuc       *sp = svalue >> value;
382472758f3SLionel Sambuc       break;
383472758f3SLionel Sambuc 
384472758f3SLionel Sambuc     case DW_OP_xor:
385472758f3SLionel Sambuc       value = *sp--;
386472758f3SLionel Sambuc       *sp ^= value;
387472758f3SLionel Sambuc       break;
388472758f3SLionel Sambuc 
389472758f3SLionel Sambuc     case DW_OP_skip:
390472758f3SLionel Sambuc       svalue = (int16_t)addressSpace.get16(p);
391472758f3SLionel Sambuc       p += 2;
392472758f3SLionel Sambuc       p += svalue;
393472758f3SLionel Sambuc       break;
394472758f3SLionel Sambuc 
395472758f3SLionel Sambuc     case DW_OP_bra:
396472758f3SLionel Sambuc       svalue = (int16_t)addressSpace.get16(p);
397472758f3SLionel Sambuc       p += 2;
398472758f3SLionel Sambuc       if (*sp--)
399472758f3SLionel Sambuc         p += svalue;
400472758f3SLionel Sambuc       break;
401472758f3SLionel Sambuc 
402472758f3SLionel Sambuc     case DW_OP_eq:
403472758f3SLionel Sambuc       value = *sp--;
404472758f3SLionel Sambuc       *sp = (*sp == value);
405472758f3SLionel Sambuc       break;
406472758f3SLionel Sambuc 
407472758f3SLionel Sambuc     case DW_OP_ge:
408472758f3SLionel Sambuc       value = *sp--;
409472758f3SLionel Sambuc       *sp = (*sp >= value);
410472758f3SLionel Sambuc       break;
411472758f3SLionel Sambuc 
412472758f3SLionel Sambuc     case DW_OP_gt:
413472758f3SLionel Sambuc       value = *sp--;
414472758f3SLionel Sambuc       *sp = (*sp > value);
415472758f3SLionel Sambuc       break;
416472758f3SLionel Sambuc 
417472758f3SLionel Sambuc     case DW_OP_le:
418472758f3SLionel Sambuc       value = *sp--;
419472758f3SLionel Sambuc       *sp = (*sp <= value);
420472758f3SLionel Sambuc       break;
421472758f3SLionel Sambuc 
422472758f3SLionel Sambuc     case DW_OP_lt:
423472758f3SLionel Sambuc       value = *sp--;
424472758f3SLionel Sambuc       *sp = (*sp < value);
425472758f3SLionel Sambuc       break;
426472758f3SLionel Sambuc 
427472758f3SLionel Sambuc     case DW_OP_ne:
428472758f3SLionel Sambuc       value = *sp--;
429472758f3SLionel Sambuc       *sp = (*sp != value);
430472758f3SLionel Sambuc       break;
431472758f3SLionel Sambuc 
432472758f3SLionel Sambuc     case DW_OP_lit0:
433472758f3SLionel Sambuc     case DW_OP_lit1:
434472758f3SLionel Sambuc     case DW_OP_lit2:
435472758f3SLionel Sambuc     case DW_OP_lit3:
436472758f3SLionel Sambuc     case DW_OP_lit4:
437472758f3SLionel Sambuc     case DW_OP_lit5:
438472758f3SLionel Sambuc     case DW_OP_lit6:
439472758f3SLionel Sambuc     case DW_OP_lit7:
440472758f3SLionel Sambuc     case DW_OP_lit8:
441472758f3SLionel Sambuc     case DW_OP_lit9:
442472758f3SLionel Sambuc     case DW_OP_lit10:
443472758f3SLionel Sambuc     case DW_OP_lit11:
444472758f3SLionel Sambuc     case DW_OP_lit12:
445472758f3SLionel Sambuc     case DW_OP_lit13:
446472758f3SLionel Sambuc     case DW_OP_lit14:
447472758f3SLionel Sambuc     case DW_OP_lit15:
448472758f3SLionel Sambuc     case DW_OP_lit16:
449472758f3SLionel Sambuc     case DW_OP_lit17:
450472758f3SLionel Sambuc     case DW_OP_lit18:
451472758f3SLionel Sambuc     case DW_OP_lit19:
452472758f3SLionel Sambuc     case DW_OP_lit20:
453472758f3SLionel Sambuc     case DW_OP_lit21:
454472758f3SLionel Sambuc     case DW_OP_lit22:
455472758f3SLionel Sambuc     case DW_OP_lit23:
456472758f3SLionel Sambuc     case DW_OP_lit24:
457472758f3SLionel Sambuc     case DW_OP_lit25:
458472758f3SLionel Sambuc     case DW_OP_lit26:
459472758f3SLionel Sambuc     case DW_OP_lit27:
460472758f3SLionel Sambuc     case DW_OP_lit28:
461472758f3SLionel Sambuc     case DW_OP_lit29:
462472758f3SLionel Sambuc     case DW_OP_lit30:
463472758f3SLionel Sambuc     case DW_OP_lit31:
464472758f3SLionel Sambuc       value = opcode - DW_OP_lit0;
465472758f3SLionel Sambuc       *(++sp) = value;
466472758f3SLionel Sambuc       break;
467472758f3SLionel Sambuc 
468472758f3SLionel Sambuc     case DW_OP_reg0:
469472758f3SLionel Sambuc     case DW_OP_reg1:
470472758f3SLionel Sambuc     case DW_OP_reg2:
471472758f3SLionel Sambuc     case DW_OP_reg3:
472472758f3SLionel Sambuc     case DW_OP_reg4:
473472758f3SLionel Sambuc     case DW_OP_reg5:
474472758f3SLionel Sambuc     case DW_OP_reg6:
475472758f3SLionel Sambuc     case DW_OP_reg7:
476472758f3SLionel Sambuc     case DW_OP_reg8:
477472758f3SLionel Sambuc     case DW_OP_reg9:
478472758f3SLionel Sambuc     case DW_OP_reg10:
479472758f3SLionel Sambuc     case DW_OP_reg11:
480472758f3SLionel Sambuc     case DW_OP_reg12:
481472758f3SLionel Sambuc     case DW_OP_reg13:
482472758f3SLionel Sambuc     case DW_OP_reg14:
483472758f3SLionel Sambuc     case DW_OP_reg15:
484472758f3SLionel Sambuc     case DW_OP_reg16:
485472758f3SLionel Sambuc     case DW_OP_reg17:
486472758f3SLionel Sambuc     case DW_OP_reg18:
487472758f3SLionel Sambuc     case DW_OP_reg19:
488472758f3SLionel Sambuc     case DW_OP_reg20:
489472758f3SLionel Sambuc     case DW_OP_reg21:
490472758f3SLionel Sambuc     case DW_OP_reg22:
491472758f3SLionel Sambuc     case DW_OP_reg23:
492472758f3SLionel Sambuc     case DW_OP_reg24:
493472758f3SLionel Sambuc     case DW_OP_reg25:
494472758f3SLionel Sambuc     case DW_OP_reg26:
495472758f3SLionel Sambuc     case DW_OP_reg27:
496472758f3SLionel Sambuc     case DW_OP_reg28:
497472758f3SLionel Sambuc     case DW_OP_reg29:
498472758f3SLionel Sambuc     case DW_OP_reg30:
499472758f3SLionel Sambuc     case DW_OP_reg31:
500472758f3SLionel Sambuc       reg = opcode - DW_OP_reg0;
501472758f3SLionel Sambuc       *(++sp) = registers.getRegister(reg);
502472758f3SLionel Sambuc       break;
503472758f3SLionel Sambuc 
504472758f3SLionel Sambuc     case DW_OP_regx:
505472758f3SLionel Sambuc       reg = addressSpace.getULEB128(p, expressionEnd);
506472758f3SLionel Sambuc       *(++sp) = registers.getRegister(reg);
507472758f3SLionel Sambuc       break;
508472758f3SLionel Sambuc 
509472758f3SLionel Sambuc     case DW_OP_breg0:
510472758f3SLionel Sambuc     case DW_OP_breg1:
511472758f3SLionel Sambuc     case DW_OP_breg2:
512472758f3SLionel Sambuc     case DW_OP_breg3:
513472758f3SLionel Sambuc     case DW_OP_breg4:
514472758f3SLionel Sambuc     case DW_OP_breg5:
515472758f3SLionel Sambuc     case DW_OP_breg6:
516472758f3SLionel Sambuc     case DW_OP_breg7:
517472758f3SLionel Sambuc     case DW_OP_breg8:
518472758f3SLionel Sambuc     case DW_OP_breg9:
519472758f3SLionel Sambuc     case DW_OP_breg10:
520472758f3SLionel Sambuc     case DW_OP_breg11:
521472758f3SLionel Sambuc     case DW_OP_breg12:
522472758f3SLionel Sambuc     case DW_OP_breg13:
523472758f3SLionel Sambuc     case DW_OP_breg14:
524472758f3SLionel Sambuc     case DW_OP_breg15:
525472758f3SLionel Sambuc     case DW_OP_breg16:
526472758f3SLionel Sambuc     case DW_OP_breg17:
527472758f3SLionel Sambuc     case DW_OP_breg18:
528472758f3SLionel Sambuc     case DW_OP_breg19:
529472758f3SLionel Sambuc     case DW_OP_breg20:
530472758f3SLionel Sambuc     case DW_OP_breg21:
531472758f3SLionel Sambuc     case DW_OP_breg22:
532472758f3SLionel Sambuc     case DW_OP_breg23:
533472758f3SLionel Sambuc     case DW_OP_breg24:
534472758f3SLionel Sambuc     case DW_OP_breg25:
535472758f3SLionel Sambuc     case DW_OP_breg26:
536472758f3SLionel Sambuc     case DW_OP_breg27:
537472758f3SLionel Sambuc     case DW_OP_breg28:
538472758f3SLionel Sambuc     case DW_OP_breg29:
539472758f3SLionel Sambuc     case DW_OP_breg30:
540472758f3SLionel Sambuc     case DW_OP_breg31:
541472758f3SLionel Sambuc       reg = opcode - DW_OP_breg0;
542472758f3SLionel Sambuc       svalue = addressSpace.getSLEB128(p, expressionEnd);
543472758f3SLionel Sambuc       *(++sp) = registers.getRegister(reg) + svalue;
544472758f3SLionel Sambuc       break;
545472758f3SLionel Sambuc 
546472758f3SLionel Sambuc     case DW_OP_bregx:
547472758f3SLionel Sambuc       reg = addressSpace.getULEB128(p, expressionEnd);
548472758f3SLionel Sambuc       svalue = addressSpace.getSLEB128(p, expressionEnd);
549472758f3SLionel Sambuc       *(++sp) = registers.getRegister(reg) + svalue;
550472758f3SLionel Sambuc       break;
551472758f3SLionel Sambuc 
552472758f3SLionel Sambuc     case DW_OP_deref_size:
553472758f3SLionel Sambuc       // pop stack, dereference, push result
554472758f3SLionel Sambuc       value = *sp--;
555472758f3SLionel Sambuc       switch (addressSpace.get8(p++)) {
556472758f3SLionel Sambuc       case 1:
557472758f3SLionel Sambuc         value = addressSpace.get8(value);
558472758f3SLionel Sambuc         break;
559472758f3SLionel Sambuc       case 2:
560472758f3SLionel Sambuc         value = addressSpace.get16(value);
561472758f3SLionel Sambuc         break;
562472758f3SLionel Sambuc       case 4:
563472758f3SLionel Sambuc         value = addressSpace.get32(value);
564472758f3SLionel Sambuc         break;
565472758f3SLionel Sambuc       case 8:
566472758f3SLionel Sambuc         value = addressSpace.get64(value);
567472758f3SLionel Sambuc         break;
568472758f3SLionel Sambuc       default:
569472758f3SLionel Sambuc         assert(0 && "DW_OP_deref_size with bad size");
570472758f3SLionel Sambuc       }
571472758f3SLionel Sambuc       *(++sp) = value;
572472758f3SLionel Sambuc       break;
573472758f3SLionel Sambuc 
574472758f3SLionel Sambuc     case DW_OP_fbreg:
575472758f3SLionel Sambuc     case DW_OP_piece:
576472758f3SLionel Sambuc     case DW_OP_xderef_size:
577472758f3SLionel Sambuc     case DW_OP_nop:
578472758f3SLionel Sambuc     case DW_OP_push_object_addres:
579472758f3SLionel Sambuc     case DW_OP_call2:
580472758f3SLionel Sambuc     case DW_OP_call4:
581472758f3SLionel Sambuc     case DW_OP_call_ref:
582472758f3SLionel Sambuc     default:
583472758f3SLionel Sambuc       assert(0 && "dwarf opcode not implemented");
584472758f3SLionel Sambuc     }
585472758f3SLionel Sambuc   }
586472758f3SLionel Sambuc   return *sp;
587472758f3SLionel Sambuc }
588472758f3SLionel Sambuc 
589472758f3SLionel Sambuc } // namespace _Unwind
590472758f3SLionel Sambuc 
591472758f3SLionel Sambuc #endif // __DWARF_INSTRUCTIONS_HPP__
592