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