Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / inst-power.h
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 /*
33  * inst-power.h - Common definitions to the POWER specific instrumentation code.
34  * $Id: inst-power.h,v 1.35 2008/02/19 13:37:44 rchen Exp $
35  */
36
37 #ifndef INST_POWER_H
38 #define INST_POWER_H
39
40
41 /* "pseudo" instructions that are placed in the tramp code for the inst funcs
42  *   to patch up.   This must be invalid instructions (any instruction with
43  *   its top 10 bits as 0 is invalid (technically UNIMP).
44  *
45  */
46
47 #define DEAD_REG              0
48 #define LIVE_REG              1
49 #define LIVE_UNCLOBBERED_REG  2
50 #define LIVE_CLOBBERED_REG    3
51
52 #define GPRSIZE_32            4
53 #define GPRSIZE_64            8
54 #define FPRSIZE               8
55
56 #define REG_SP                1         
57 #define REG_TOC               2   /* TOC anchor                            */
58 // REG_GUARD_OFFSET and REG_GUARD_VALUE could overlap.
59 #define REG_GUARD_ADDR        5   /* Arbitrary                             */
60 #define REG_GUARD_VALUE       6
61 #define REG_GUARD_OFFSET      6
62
63 #define REG_COST_ADDR         5
64 #define REG_COST_VALUE        6
65
66 #define REG_SCRATCH          10
67
68 #define REG_MT_POS           12   /* Register to reserve for MT implementation */
69 #define NUM_INSN_MT_PREAMBLE 26   /* number of instructions required for   */
70                                   /* the MT preamble.                      */ 
71
72 // The stack grows down from high addresses toward low addresses.
73 // There is a maximum number of bytes on the stack below the current
74 // value of the stack frame pointer that a function can use without
75 // first establishing a new stack frame.  When our instrumentation
76 // needs to use the stack, we make sure not to write into this
77 // potentially used area.  AIX documentation stated 220 bytes as
78 // the maximum size of this area.  64-bit PowerPC ELF ABI Supplement,
79 // Version 1.9, 2004-10-23, used by Linux, stated 288 bytes for this
80 // area.  We skip the larger number of bytes (288) to be safe on both
81 // AIX and Linux, 32-bit and 64-bit.
82 #define STACKSKIP          288
83
84 // Both 32-bit and 64-bit PowerPC ELF ABI documents for Linux state
85 // that the stack frame pointer value must always be 16-byte (quadword)
86 // aligned.  Use the following macro on all quantities used to
87 // increment or decrement the stack frame pointer.
88 #define ALIGN_QUADWORD(x)  ( ((x) + 0xf) & ~0xf )  //x is positive or unsigned
89
90 #define GPRSAVE_32 (14*4)
91 #define GPRSAVE_64 (14*8)
92 #define FPRSAVE    (14*8)
93 #define SPRSAVE_32 (6*4+8)
94 #define SPRSAVE_64 (6*8+8)
95 #define PDYNSAVE   (8)
96 #define FUNCSAVE   (14*4)
97 #define FUNCARGS   64
98 #define LINKAREA   24
99
100 #if defined(os_aix)
101 // The offset values for AIX are pretty fragile, AFAIK.  Things change
102 // when there are parameters of different sizes involved (or floats).
103 // We should probably do some mapping back to variable, and determine
104 // location by debug information.
105 #define PARAM_OFFSET(mutatee_address_width)                         \
106         (                                                           \
107             ((mutatee_address_width) == sizeof(uint64_t))           \
108             ? (   /* 64-bit XCOFF AIX */                            \
109                   112                                               \
110               )                                                     \
111             : (   /* 32-bit XCOFF AIX */                            \
112                   56                                                \
113               )                                                     \
114         )
115
116 #elif defined(os_linux)
117 #define PARAM_OFFSET(mutatee_address_width)                         \
118         (                                                           \
119             ((mutatee_address_width) == sizeof(uint64_t))           \
120             ? (   /* 64-bit ELF PowerPC Linux                   */  \
121                   sizeof(uint64_t) +  /* TOC save               */  \
122                   sizeof(uint64_t) +  /* link editor doubleword */  \
123                   sizeof(uint64_t) +  /* compiler doubleword    */  \
124                   sizeof(uint64_t) +  /* LR save                */  \
125                   sizeof(uint64_t) +  /* CR save                */  \
126                   sizeof(uint64_t)    /* Stack frame back chain */  \
127               )                                                     \
128             : (   /* 32-bit ELF PowerPC Linux                   */  \
129                   sizeof(uint32_t) +  /* LR save                */  \
130                   sizeof(uint32_t)    /* Stack frame back chain */  \
131               )                                                     \
132         )
133 #else
134 #error "Unknown operating system in inst-power.h"
135 #endif
136
137 // The number of registers (general and floating point) that aren't
138 // used in the base tramp explicitly 
139 #define NUM_LO_REGISTERS 18
140
141
142 // Okay, now that we have those defined, let's define the offsets upwards
143 #define TRAMP_FRAME_SIZE_32 ALIGN_QUADWORD(STACKSKIP + GPRSAVE_32 + FPRSAVE \
144                                            + SPRSAVE_32 + PDYNSAVE \
145                                            + FUNCSAVE + FUNCARGS + LINKAREA)
146 #define TRAMP_FRAME_SIZE_64 ALIGN_QUADWORD(STACKSKIP + GPRSAVE_64 + FPRSAVE \
147                                            + SPRSAVE_64 + PDYNSAVE \
148                                            + FUNCSAVE + FUNCARGS + LINKAREA)
149 #define PDYN_RESERVED (LINKAREA + FUNCARGS + FUNCSAVE)
150 #define TRAMP_SPR_OFFSET (PDYN_RESERVED + PDYNSAVE) /* 4 for LR */
151 #define STK_GUARD (PDYN_RESERVED)
152 #define STK_LR       (              0)
153 #define STK_CR_32    (STK_LR      + 4)
154 #define STK_CTR_32   (STK_CR_32   + 4)
155 #define STK_XER_32   (STK_CTR_32  + 4)
156 #define STK_SPR0_32  (STK_XER_32  + 4)
157 #define STK_FP_CR_32 (STK_SPR0_32 + 4)
158
159 #define STK_CR_64    (STK_LR      + 8)
160 #define STK_CTR_64   (STK_CR_64   + 8)
161 #define STK_XER_64   (STK_CTR_64  + 8)
162 #define STK_SPR0_64  (STK_XER_64  + 8)
163 #define STK_FP_CR_64 (STK_SPR0_64 + 8)
164
165 #define TRAMP_FPR_OFFSET_32 (TRAMP_SPR_OFFSET + SPRSAVE_32)
166 #define TRAMP_GPR_OFFSET_32 (TRAMP_FPR_OFFSET_32 + FPRSAVE)
167
168 #define TRAMP_FPR_OFFSET_64 (TRAMP_SPR_OFFSET + SPRSAVE_64)
169 #define TRAMP_GPR_OFFSET_64 (TRAMP_FPR_OFFSET_64 + FPRSAVE)
170
171 #define FUNC_CALL_SAVE (LINKAREA + FUNCARGS)
172                
173
174 ///////////////////////////// Multi-instruction sequences
175 class codeGen;
176
177 void saveSPR(codeGen &gen,
178              Register scratchReg,
179              int sprnum,
180              int stkOffset);
181 void restoreSPR(codeGen &gen,
182                 Register scratchReg,
183                 int sprnum,
184                 int stkOffset);
185 void saveLR(codeGen &gen,
186             Register scratchReg,
187             int stkOffset);
188 void restoreLR(codeGen &gen,
189                Register scratchReg,
190                int stkOffset);
191 void setBRL(codeGen &gen,
192             Register scratchReg,
193             long val,
194             unsigned ti); // We're lazy and hand in the next insn
195 void saveCR(codeGen &gen,
196             Register scratchReg,
197             int stkOffset);
198 void restoreCR(codeGen &gen,
199                Register scratchReg,
200                int stkOffset);
201 void saveFPSCR(codeGen &gen,
202                Register scratchReg,
203                int stkOffset);
204 void restoreFPSCR(codeGen &gen,
205                   Register scratchReg,
206                   int stkOffset);
207 void saveRegister(codeGen &gen,
208                   Register reg,
209                   int save_off);
210 // We may want to restore a _logical_ register N
211 // (that is, the save slot for N) into a different reg.
212 // This avoids using a temporary
213 void restoreRegister(codeGen &gen,
214                      Register source,
215                      Register dest,
216                      int save_off);
217 // Much more common case
218 void restoreRegister(codeGen &gen,
219                      Register reg,
220                      int save_off);
221 void saveFPRegister(codeGen &gen,
222                     Register reg,
223                     int save_off);
224 // See above...
225 void restoreFPRegister(codeGen &gen,
226                        Register source,
227                        Register dest,
228                        int save_off);
229 void restoreFPRegister(codeGen &gen,
230                        Register reg,
231                        int save_off);
232 void pushStack(codeGen &gen);
233 void popStack(codeGen &gen);
234 unsigned saveGPRegisters(codeGen &gen, 
235                          registerSpace *theRegSpace,
236                          int save_off);
237 unsigned restoreGPRegisters(codeGen &gen, 
238                             registerSpace *theRegSpace,
239                             int save_off);
240 unsigned saveFPRegisters(codeGen &gen, 
241                          registerSpace *theRegSpace,
242                          int save_off);
243 unsigned restoreFPRegisters(codeGen &gen,
244                             registerSpace *theRegSpace,
245                             int save_off);
246 unsigned saveSPRegisters(codeGen &gen, 
247                          int save_off);
248 unsigned restoreSPRegisters(codeGen &gen, 
249                             int save_off);
250
251 #endif