Tracking commit: working in progress on dlopenDYNINSTlib()
[dyninst.git] / dyninstAPI / src / arch-ia64.C
1 /*
2  * Copyright (c) 1996 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: arch-ia64.C,v 1.3 2002/06/20 20:06:13 tlmiller Exp $
43 // ia64 instruction decoder
44
45 #include <assert.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include "dyninstAPI/src/arch-ia64.h"
49
50 #define TEMPLATE_MASK           0x000000000000001F      /* bits 00 - 04 */
51 #define INSTRUCTION0_MASK       0x00003FFFFFFFFFE0      /* bits 05 - 45 */
52 #define INSTRUCTION1_LOW_MASK   0xFFFFC00000000000      /* bits 45 - 63 */
53 #define INSTRUCTION1_HIGH_MASK  0x00000000007FFFFF      /* bits 00 - 20 */
54 #define INSTRUCTION2_MASK       0xFFFFFFFFFF800000      /* bits 21 - 63 */
55
56 #define MAJOR_OPCODE_MASK       0xF000000000000000      /* bits 37 - 40 */
57
58 #define MEMORY_X3_MASK          0x0700000000000000      /* bits 33 - 35 */
59 #define MEMORY_R1_MASK          0x0000000FE0000000      /* bits 06 - 12 */
60
61 #define ALLOC_SOR               0x003C000000000000      /* bits 27 - 30 */
62 #define ALLOC_SOL               0x0003F80000000000      /* bits 20 - 26 */
63 #define ALLOC_SOF               0x000007F000000000      /* bits 13 - 19 */
64
65 #define PREDICATE_MASK          0x000000001F800000      /* bits 00 - 05 */
66
67 #define ADDL_SIGN               0x0800000000000000      /* bit 36 */
68 #define ADDL_IMM9D              0x07FC000000000000      /* bits 27 - 35 */
69 #define ADDL_IMM5C              0x0003E00000000000      /* bits 22 - 26 */
70 #define ADDL_R3                 0x0000180000000000      /* bits 20 - 21 */
71 #define ADDL_IMM7B              0x000007F000000000      /* bits 13 - 19 */
72 #define ADDL_R1                 0x0000000FE0000000      /* bits 06 - 12 */
73
74 #define RIGHT_IMM5              0x00000000001F0000      /* bits 16 - 21 */
75 #define RIGHT_IMM9              0x000000000000FF80      /* bits 07 - 15 */
76 #define RIGHT_IMM7              0x000000000000007F      /* bits 00 - 06 */
77
78 #define ALIGN_RIGHT_SHIFT 23
79
80 IA64_instruction::IA64_instruction( uint64_t insn, uint8_t templ, IA64_bundle * mybl ) {
81         instruction = insn;
82         templateID = templ;
83         myBundle = mybl;
84         } /* end IA64_Instruction() */
85
86 IA64_bundle::IA64_bundle( ia64_bundle_t rawBundle ) {
87         /* FIXME: what's the Right Way to do this? */
88         * this = IA64_bundle( rawBundle.low, rawBundle.high );
89         } /* end IA64_bundle() */
90
91 IA64_bundle::IA64_bundle( uint8_t templateID, IA64_instruction & instruction0, IA64_instruction instruction1, IA64_instruction instruction2 ) {
92         /* FIXME: what's the Right Way to do this? */
93         * this = IA64_bundle( templateID, instruction0.getMachineCode(), instruction1.getMachineCode(), instruction2.getMachineCode() );
94         } /* end IA64_bundle() */
95
96 /* This handles the MLX template/long instructions. */
97 IA64_bundle::IA64_bundle( uint8_t templateID, IA64_instruction & instruction0, IA64_instruction & instructionLX ) {
98         if( templateID != 0x05 ) { fprintf( stderr, "Attempting to generate a bundle with a long instruction without using the MLX template, aborting.\n" ); abort(); }
99
100         /* FIXME */ * this = IA64_bundle( templateID, instruction0, 0, 0 );
101         } /* end IA64_bundle() */
102
103 IA64_bundle::IA64_bundle( uint8_t templateID, uint64_t instruction0, uint64_t instruction1, uint64_t instruction2 ) {
104         this->templateID = templateID;
105         this->instruction0 = instruction0;
106         this->instruction1 = instruction1;
107         this->instruction2 = instruction2;
108
109         myBundle.low =  ( templateID & TEMPLATE_MASK ) |
110                         ( (instruction0 >> (ALIGN_RIGHT_SHIFT - 5)) & INSTRUCTION0_MASK ) |
111                         ( (instruction1 << 23) & INSTRUCTION1_LOW_MASK );
112         myBundle.high = ( (instruction1 >> (ALIGN_RIGHT_SHIFT + 18)) & INSTRUCTION1_HIGH_MASK ) |
113                         ( instruction2 & INSTRUCTION2_MASK );
114         } /* end IA64_bundle() */
115
116 IA64_bundle::IA64_bundle( uint64_t lowHalfBundle, uint64_t highHalfBundle ) {
117         /* The template is right-aligned; the instructions are left-aligned. */
118         templateID = lowHalfBundle & TEMPLATE_MASK;
119         instruction0 = IA64_instruction( (lowHalfBundle & INSTRUCTION0_MASK) << 18, templateID, this );
120         instruction1 = IA64_instruction( ((lowHalfBundle & INSTRUCTION1_LOW_MASK) >> 23) +
121                                                 ((highHalfBundle & INSTRUCTION1_HIGH_MASK) << 41), templateID, this );
122         instruction2 = IA64_instruction( highHalfBundle & INSTRUCTION2_MASK, templateID, this );
123
124         myBundle.low = lowHalfBundle;
125         myBundle.high = highHalfBundle;
126         } /* end IA64_Bundle() */
127
128 IA64_instruction IA64_bundle::getInstruction( unsigned int slot ) {
129         switch( slot ) {
130                 case 0: return instruction0;
131                 case 1: return instruction1;
132                 case 2: return instruction2;
133                 default: fprintf( stderr, "Request of invalid instruction (%d), aborting.\n", slot ); abort();
134                 }
135         } /* end getInstruction() */
136
137 /* For linux-ia64.C */
138 IA64_instruction generateAlteredAlloc( InsnAddr & allocAddr, int deltaLocal, int deltaOutput, int deltaRotate ) {
139         uint64_t allocInsn = * allocAddr;
140
141         /* Verify that the given instruction is actually an alloc. */
142         // FIXME: check the template type and offset, too.
143         if( allocInsn & MAJOR_OPCODE_MASK != ((uint64_t)1) << 37 + ALIGN_RIGHT_SHIFT ||
144             allocInsn & MEMORY_X3_MASK != ((uint64_t)6) << 33 + ALIGN_RIGHT_SHIFT ) {
145                 fprintf( stderr, "Alleged alloc instruction is not, aborting.\n" );
146                 abort();
147                 }
148
149         /* Extract the local, output, and rotate sizes. */
150         uint64_t allocatedLocal = (allocInsn & ALLOC_SOL) >> (20 + ALIGN_RIGHT_SHIFT);
151         uint64_t allocatedOutput = ( (allocInsn & ALLOC_SOF) >> (13 + ALIGN_RIGHT_SHIFT) ) - allocatedLocal;
152         uint64_t allocatedRotate = (allocInsn & ALLOC_SOR) >> (27 + ALIGN_RIGHT_SHIFT + 3);             // SOR = r >> 3
153         
154         /* Calculate the new sizes. */
155         uint64_t generatedLocal = allocatedLocal + deltaLocal;
156         uint64_t generatedOutput = allocatedOutput + deltaOutput;
157         uint64_t generatedRotate = allocatedRotate + deltaRotate;
158
159         /* Finally, alter allocInsn. */
160         allocInsn = ( generatedLocal << (20 + ALIGN_RIGHT_SHIFT) ) | 
161                     ( ( generatedRotate >> 3) << (27 + ALIGN_RIGHT_SHIFT) ) |
162                     ( ( generatedLocal + generatedOutput ) << (13 + ALIGN_RIGHT_SHIFT) ) |
163                     allocInsn & (~ALLOC_SOF) & (~ALLOC_SOR) & (~ALLOC_SOL);
164         
165         /* We're done. */
166         return allocInsn;
167         } /* end generateAlteredAlloc() */
168
169 /* imm22 is assumed to be right-aligned, e.g., an actual value. :) */
170 IA64_instruction generateShortConstantInRegister( unsigned int registerN, int imm22 ) {
171         uint64_t sImm22 = (uint64_t)imm22;
172         uint64_t sRegisterN = (uint64_t)registerN;
173         /* Use addl (add long immediate). */
174         uint64_t rawInsn = 0x0000000000000000 | 
175                            ( ((uint64_t)9) << (37 + ALIGN_RIGHT_SHIFT)) |
176                            ( ((uint64_t)(imm22 < 0)) << (36 + ALIGN_RIGHT_SHIFT)) |
177                            ( (sImm22 & RIGHT_IMM7) << (13 + ALIGN_RIGHT_SHIFT)) |
178                            ( (sImm22 & RIGHT_IMM5) << (-16 + 22 + ALIGN_RIGHT_SHIFT)) |
179                            ( (sImm22 & RIGHT_IMM9) << (-7 + 27 + ALIGN_RIGHT_SHIFT)) |
180                            ( (sRegisterN & RIGHT_IMM7) << (6 + ALIGN_RIGHT_SHIFT) );
181
182         return IA64_instruction( rawInsn );
183         } /* end generateConstantInRegister( imm22 ) */
184
185 IA64_instruction generateLongConstantInRegister( unsigned int registerN, long long int imm64 ) {
186         /* FIXME */
187         return 0;
188         } /* end generateConstantInRegister( imm64 ) */
189
190 IA64_instruction generateLongBranchTo( long long int displacement64 ) {
191         long long int displacement60 = displacement64 >> 4;
192
193         /* FIXME */
194         return 0;
195         } /* end generatLongBranchTo( displacement64 ) */
196
197 /* --- FIXME LINE --- */
198
199 /* Required by func-reloc.C to calculate relative displacements. */
200 int get_disp( instruction *insn ) {
201         return 0;
202         } /* end get_disp() */
203                 
204 /* Required by func-reloc.C to correct relative displacements after relocation. */
205 int set_disp( bool setDisp, instruction * insn, int newOffset, bool outOfFunc ) {
206         return 0;
207         } /* end set_disp() */
208
209 /* Convience methods for func-reloc.C */
210 int sizeOfMachineInsn( instruction * insn ) {
211         return 0;
212         } /* end sizeOfMachineInsn() */
213
214 int addressOfMachineInsn( instruction * insn ) {
215         return 0;
216         } /* end addressOfMachineInsn */