Fixing generation of arithmetic expressions:
[dyninst.git] / common / src / arch-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 // $Id: arch-power.h,v 1.45 2008/03/25 19:24:23 bernat Exp $
32
33 #ifndef _ARCH_AARCH64_H
34 #define _ARCH_AARCH64_H
35
36 // Code generation
37
38 #include "common/src/Types.h"
39 #include "common/src/Vector.h"
40 #include "common/h/dyn_regs.h"
41 class AddressSpace;
42
43 namespace NS_aarch64 {
44 /*
45  * Define arch64 instruction information.
46  *
47  */
48
49 //#define ATOMIC_MASK    (0x3f400000)
50 //#define ATOMIC_LD (0x08400000)
51 //#define ATOMIC_ST (0x08000000)
52 //
53 //#define UNCOND_BR_IMM_MASK  (0x7c000000)
54 //#define UNCOND_BR_IMM       (0x14000000)
55 //#define UNCOND_BR_REG_MASK  (0xfe000000)
56 //#define UNCOND_BR_REG       (0xd6000000)
57
58 #define BREAK_POINT_INSN 0xd4200000
59
60 #define BOp             0x05
61 #define BCondOp         0x2A
62 #define BRegOp          0xD61F
63 #define NOOP            0xD503201F
64
65 #define ADDShiftOp      0x2B
66 #define ADDImmOp        0x11
67 #define SUBShiftOp      0x6B
68 #define SUBImmOp        0x51
69 #define MULOp           0xD8
70 #define SDIVOp          0xD6
71
72 #define ORRShiftOp      0x2A
73 #define ANDShiftOp      0x0A
74 #define EORShiftOp      0x4A
75
76 #define STRImmOp        0x1C0
77 #define LDRImmOp        0x1C2
78 #define STRFPImmOp      0x1E0
79 #define LDRFPImmOp      0x1E2
80 #define STRImmUIOp      0xE4
81 #define LDRImmUIOp      0xE5
82 #define LDRSWImmUIOp    0xE6
83
84 #define MSROp           0xD51
85 #define MRSOp           0xD53
86 #define MSROp           0xD51
87 #define MOVSPOp         0x44000
88
89 #define MIN_IMM8    (-128)
90 #define MAX_IMM8    (127)
91 #define MIN_IMM16   (-32768)
92 #define MAX_IMM16   (32767)
93 #define MIN_IMM32   (-2147483647 - 1)
94 #define MAX_IMM32   (2147483647)
95 #define MAX_IMM48   ((long)(-1 >> 17))
96 #define MIN_IMM48   ((long)(~MAX_IMM48))
97 #define MAX_IMM52   ((long)(1 << 52))
98 #define MIN_IMM52   ((long)(~MAX_IMM52))
99
100 //Would probably want to use the register category as well (FPR/SPR/GPR), but for the uses of these macros, this should suffice
101 #define SPR_LR      (((Dyninst::aarch64::x29).val()) & 0x1F)
102 #define SPR_NZCV    (((Dyninst::aarch64::pstate).val()) & 0x1F)
103 #define SPR_FPCR    (((Dyninst::aarch64::fpcr).val()) & 0x1F)
104 #define SPR_FPSR    (((Dyninst::aarch64::fpsr).val()) & 0x1F)
105
106 #define INSN_SET(I, s, e, v)    ((I).setBits(s, e - s + 1, (v)))
107
108 #define INSN_GET_ISCALL(I)          ((unsigned int) ((I).asInt() & 0x80000000))
109 #define INSN_GET_CBRANCH_OFFSET(I)  ((unsigned int) (((I).asInt() >> 5) & 0x7ffff))
110
111 #define MAX_BRANCH_OFFSET      0x07ffffff  // 128MB  Used for B
112 #define MAX_CBRANCH_OFFSET     0x000fffff  //   1MB  Used for B.cond, CBZ and CBNZ
113 #define MAX_TBRANCH_OFFSET     0x0007ffff  //  32KB  Used for TBZ and TBNZ
114
115 #define CHECK_INST(isInst) \
116     !((insn_.raw&isInst##_MASK)^isInst)
117
118 #define GET_OFFSET32(thisInst) \
119     (((insn_.raw&thisInst##_OFFSET_MASK)>>thisInst##_OFFSHIFT)<<2)
120
121 typedef const unsigned int insn_mask;
122 class ATOMIC_t {
123 public:
124     static insn_mask LD_MASK =  (0x3f400000);
125     static insn_mask ST_MASK =  (0x3f400000);
126     static insn_mask LD =    (0x08400000);
127     static insn_mask ST =    (0x08000000);
128 };
129
130 class UNCOND_BR_t {
131 public:
132     static insn_mask IMM_MASK  =(0x7c000000);
133     static insn_mask IMM       =(0x14000000);
134     static insn_mask IMM_OFFSET_MASK   =(0x03ffffff);
135     static insn_mask IMM_OFFSHIFT   = 0;
136     static insn_mask REG_MASK  =(0xfe000000);
137     static insn_mask REG       =(0xd6000000);
138     static insn_mask REG_OFFSET_MASK   =(0x000001e0);
139     static insn_mask REG_OFFSHIFT   =5;
140 };
141
142
143 class COND_BR_t {
144 public:
145     static insn_mask BR_MASK = 0xfe000000; // conditional br mask
146     static insn_mask CB_MASK = 0x7e000000; // comp&B
147     static insn_mask TB_MASK = 0x7e000000; // test&B
148
149     static insn_mask BR =      0x54000000; // Conditional B
150     static insn_mask CB =      0x34000000; // Compare & B
151     static insn_mask TB =      0x36000000; // Test & B
152
153     static insn_mask CB_OFFSET_MASK = 0x07fffff0;
154     static insn_mask TB_OFFSET_MASK = 0x0007fff0;
155     static insn_mask BR_OFFSET_MASK = 0x07fffff0;
156
157     static insn_mask CB_OFFSHIFT = 4;
158     static insn_mask TB_OFFSHIFT = 4;
159     static insn_mask BR_OFFSHIFT = 4;
160 };
161
162 typedef union {
163     unsigned char byte[4];
164     unsigned int  raw;
165 } instructUnion;
166
167 typedef instructUnion codeBuf_t;
168 typedef unsigned codeBufIndex_t;
169
170 #define maxGPR 31           /* More space than is needed */
171 #define maxFPR 32           /* Save FPRs 0-13 */
172
173 // Helps to mitigate host/target endian mismatches
174 unsigned int swapBytesIfNeeded(unsigned int i);
175
176 class COMMON_EXPORT instruction {
177         private:
178     instructUnion insn_;
179
180         public:
181     instruction() { insn_.raw = 0; }
182     instruction(unsigned int raw) {
183         // Don't flip bits here.  Input is already in host byte order.
184         insn_.raw = raw;
185     }
186     // Pointer creation method
187     instruction(const void *ptr) {
188       insn_ = *((const instructUnion *)ptr);
189     }
190
191     instruction(const instruction &insn) :        insn_(insn.insn_) {};
192     instruction(instructUnion &insn) :
193         insn_(insn) {};
194
195     instruction *copy() const;
196
197     void clear() { insn_.raw = 0; }
198     void setInstruction(codeBuf_t *ptr, Address = 0);
199     void setBits(unsigned int pos, unsigned int len, unsigned int value) {
200         unsigned int mask;
201
202         mask = ~((unsigned int)(~0) << len);
203         value = value & mask;
204
205         mask = ~(mask << pos);
206         value = value << pos;
207
208         insn_.raw = insn_.raw & mask;
209         insn_.raw = insn_.raw | value;
210     }
211     unsigned int asInt() const { return insn_.raw; }
212     void setInstruction(unsigned char *ptr, Address = 0);
213
214
215     // To solve host/target endian mismatches
216     static int signExtend(unsigned int i, unsigned int pos);
217     static instructUnion &swapBytes(instructUnion &i);
218
219     // We need instruction::size() all _over_ the place.
220     static unsigned size() { return sizeof(instructUnion); }
221
222     Address getBranchOffset() const;
223     Address getBranchTargetAddress() const;
224     void setBranchOffset(Address newOffset);
225
226     // And tell us how much space we'll need...
227     // Returns -1 if we can't do a branch due to architecture limitations
228     static unsigned jumpSize(Address from, Address to, unsigned addr_width);
229     static unsigned jumpSize(Address disp, unsigned addr_width);
230     static unsigned maxJumpSize(unsigned addr_width);
231
232     static unsigned maxInterFunctionJumpSize(unsigned addr_width);
233
234     // return the type of the instruction
235     unsigned type() const;
236
237     // return a pointer to the instruction
238     const unsigned char *ptr() const { return (const unsigned char *)&insn_; }
239
240     // For external modification
241     // Don't allow external modification anymore.  Host byte order may differ
242     // from target byte order.
243     //instructUnion &operator* () { return insn_; }
244     //const instructUnion &operator* () const { return insn_; }
245     //const unsigned int &raw() const { return insn_.raw; }
246
247     unsigned opcode() const;
248
249     // Local version
250     bool isInsnType(const unsigned mask, const unsigned match) const {
251         return ((insn_.raw & mask) == match);
252     }
253
254     Address getTarget(Address insnAddr) const;
255
256     unsigned spaceToRelocate() const;
257     bool getUsedRegs(pdvector<int> &regs);
258
259     bool valid() const {
260                         assert(0);
261                         return false;
262                 }
263
264     bool isCall() const;
265
266     static bool isAligned(Address addr) {
267         return !(addr & 0x3);
268     }
269
270     bool isBranchReg() const;
271     bool isCondBranch() const;
272     bool isUncondBranch() const;
273     bool isThunk() const;
274
275
276         bool isCleaningRet() const {return false; }
277
278     bool isAtomicLoad( ) const;
279     bool isAtomicStore( ) const;
280
281     // inferface for being called outside this class
282     unsigned getTargetReg()const ;
283     unsigned getBranchTargetReg() const;
284 };
285
286 }
287 //end of NS_aarch64
288
289 #endif