* src/vm/jit/m68k/md.c (md_codegen_patch_branch): Removed.
[cacao.git] / src / vm / jit / powerpc64 / md.c
1 /* src/vm/jit/powerpc64/md.c - machine dependent PowerPC functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <stdint.h>
32
33 #include "vm/types.h"
34
35 #include "md-abi.h"
36
37 #include "vm/jit/powerpc64/codegen.h"
38
39 #include "vm/exceptions.h"
40 #include "vm/global.h"
41
42 #include "vm/jit/asmpart.h"
43 #include "vm/jit/codegen-common.h"
44 #include "vm/jit/jit.h"
45 #include "vm/jit/md.h"
46
47
48 /* md_init *********************************************************************
49
50    Do some machine dependent initialization.
51
52 *******************************************************************************/
53
54 void md_init(void)
55 {
56         /* nothing to do */
57 }
58
59
60 /* md_stacktrace_get_returnaddress *********************************************
61
62    Returns the return address of the current stackframe, specified by
63    the passed stack pointer and the stack frame size.
64
65 *******************************************************************************/
66
67 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
68 {
69         u1 *ra;
70
71         /* on PowerPC the return address is located in the linkage area */
72
73         ra = *((u1 **) (sp + framesize + LA_LR_OFFSET));
74
75         return ra;
76 }
77
78
79 /* md_jit_method_patch_address *************************************************
80
81    Gets the patch address of the currently compiled method. The offset
82    is extracted from the load instruction(s) before the jump and added
83    to the right base address (PV or REG_METHODPTR).
84
85    INVOKESTATIC/SPECIAL:
86
87    e9ceffb8    ld      r14,-72(r14)     
88    7dc903a6    mtctr   r14              
89    4e800421    bctrl
90
91    INVOKEVIRTUAL:
92
93 FIXME   81830000    lwz     r12,0(r3)
94    e9cc0000     ld      r14,0(r12)
95    7dc903a6     mtctr   r14
96    4e800421     bctrl
97
98
99    INVOKEINTERFACE:
100
101 FIXME   81830000    lwz     r12,0(r3)
102 FIXME   818c0000    lwz     r12,0(r12)
103 FIXME   81ac0000    lwz     r13,0(r12)
104   7dc903a6    mtctr   r14
105   4e800421    bctrl
106
107 *******************************************************************************/
108
109 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
110 {
111         uint32_t *pc;
112         uint32_t  mcode;
113         int32_t   offset;
114         void     *pa;
115
116         /* Go back to the actual load instruction (3 instructions). */
117
118         pc = ((uint32_t *) ra) - 3;
119
120         /* get first instruction word (lwz) */
121
122         mcode = pc[0];
123
124         /* check if we have 2 instructions (addis, addi) */
125
126         if ((mcode >> 16) == 0x3c19) {
127                 /* XXX write a regression for this */
128                 pa = NULL;
129                 assert(0);
130
131                 /* get displacement of first instruction (addis) */
132
133                 offset = (int32_t) (mcode << 16);
134
135                 /* get displacement of second instruction (addi) */
136
137                 mcode = pc[1];
138
139                 assert((mcode >> 16) != 0x6739);
140
141                 offset += (int16_t) (mcode & 0x0000ffff);
142         }
143         else {
144                 /* get the offset from the instruction */
145
146                 offset = (int16_t) (mcode & 0x0000ffff);
147
148                 /* check for load from PV */
149
150                 if ((mcode >> 16) == 0xe9ce) {  
151                         /* get the final data segment address */
152
153                         pa = ((uint8_t *) pv) + offset;
154                 }
155                 else if ((mcode >> 16) == 0xe9cc) { 
156                         /* in this case we use the passed method pointer */
157
158                         /* return NULL if no mptr was specified (used for replacement) */
159
160                         if (mptr == NULL)
161                                 return NULL;
162
163                         pa = ((uint8_t *) mptr) + offset;
164                 }
165                 else {
166                         /* catch any problems */
167
168                         vm_abort("md_jit_method_patch_address: unknown instruction %x",
169                                          mcode);
170
171                         /* keep compiler happy */
172
173                         pa = NULL;
174                 }
175         }
176
177         return pa;
178 }
179
180
181 /* md_codegen_get_pv_from_pc ***************************************************
182
183    Machine code:
184
185    7d6802a6    mflr    r11
186    39cbffe0    addi    r14,r11,-32
187
188    or
189
190    7d6802a6    mflr    r11
191    3dcbffff    addis   r14,r11,-1
192    39ce68b0    addi    r14,r13,26800
193
194 *******************************************************************************/
195
196 u1 *md_codegen_get_pv_from_pc(u1 *ra)
197 {
198         u1 *pv;
199         u4  mcode;
200         s4  offset;
201
202         /* get first instruction word after jump */
203
204         mcode = *((u4 *) (ra + 1 * 4));
205
206         /* check if we have 2 instructions (addis, addi) */
207
208         if ((mcode >> 16) == 0x3dcb) {
209                 /* get displacement of first instruction (addis) */
210
211                 offset = (s4) (mcode << 16);
212
213                 /* get displacement of second instruction (addi) */
214
215                 mcode = *((u4 *) (ra + 2 * 4));
216
217                 /* check for addi instruction */
218
219                 assert((mcode >> 16) == 0x39ce);
220
221                 offset += (s2) (mcode & 0x0000ffff);
222         }
223         else if ((mcode >> 16) == 0x39cb) {
224                 /* get offset of first instruction (addi) */
225
226                 offset = (s2) (mcode & 0x0000ffff);
227         }
228         else {
229                 vm_abort("md_codegen_get_pv_from_pc: unknown instruction %x", mcode);
230
231                 /* keep compiler happy */
232
233                 offset = 0;
234         }
235
236         /* calculate PV via RA + offset */
237
238         pv = ra + offset;
239
240         return pv;
241 }
242
243
244 /* md_cacheflush ***************************************************************
245
246    Calls the system's function to flush the instruction and data
247    cache.
248
249 *******************************************************************************/
250
251 void md_cacheflush(u1 *addr, s4 nbytes)
252 {
253         asm_cacheflush(addr, nbytes);
254 }
255
256
257 /* md_icacheflush **************************************************************
258
259    Calls the system's function to flush the instruction cache.
260
261 *******************************************************************************/
262
263 void md_icacheflush(u1 *addr, s4 nbytes)
264 {
265         asm_cacheflush(addr, nbytes);
266 }
267
268
269 /* md_dcacheflush **************************************************************
270
271    Calls the system's function to flush the data cache.
272
273 *******************************************************************************/
274
275 void md_dcacheflush(u1 *addr, s4 nbytes)
276 {
277         asm_cacheflush(addr, nbytes);
278 }
279
280
281 /* md_patch_replacement_point **************************************************
282
283    Patch the given replacement point.
284
285 *******************************************************************************/
286
287 #if defined(ENABLE_REPLACEMENT)
288 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
289 {
290         u4 mcode;
291
292         if (revert) {
293                 /* restore the patched-over instruction */
294                 *(u4*)(pc) = *(u4*)(savedmcode);
295         }
296         else {
297                 /* save the current machine code */
298                 *(u4*)(savedmcode) = *(u4*)(pc);
299
300                 /* build the machine code for the patch */
301                 mcode = (0x80000000 | (EXCEPTION_HARDWARE_PATCHER));
302
303                 /* write the new machine code */
304                 *(u4*)(pc) = (u4) mcode;
305         }
306
307         /* flush instruction cache */
308     md_icacheflush(pc,4);
309 }
310 #endif /* defined(ENABLE_REPLACEMENT) */
311
312 /*
313  * These are local overrides for various environment variables in Emacs.
314  * Please do not remove this and leave it at the end of the file, where
315  * Emacs will automagically detect them.
316  * ---------------------------------------------------------------------
317  * Local variables:
318  * mode: c
319  * indent-tabs-mode: t
320  * c-basic-offset: 4
321  * tab-width: 4
322  * End:
323  * vim:noexpandtab:sw=4:ts=4:
324  */