3bac5562615bf8ddde4579bce58a18ebc9fb396e
[cacao.git] / src / vm / jit / m68k / asmpart.S
1 /* src/vm/jit/m68k/asmpart.S - Java-C interface functions for m68k
2
3    Copyright (C) 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    $Id: asmpart.S 8210 2007-07-18 12:51:00Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include "md-abi.h"
33
34 #include "vm/jit/methodheader.h"
35
36
37 .text
38
39 .globl asm_vm_call_method
40 .globl asm_vm_call_method_int
41 .globl asm_vm_call_method_long
42 .globl asm_vm_call_method_float
43 .globl asm_vm_call_method_double
44 .globl asm_vm_call_method_end
45 .globl asm_vm_call_method_exception_handler
46
47 .globl asm_call_jit_compiler
48
49 .globl asm_patcher_wrapper
50
51 .globl asm_abstractmethoderror
52
53 .globl asm_handle_exception
54 .globl asm_handle_nat_exception
55
56 /*
57  *      This functions implement the C prototyped funtion
58  *      java_objectheader *asm_vm_call_method(methodinfo *m, s4 vmargscount,vm_arg *vmargs);
59  *      the _int, _long, _float, _double are used for different return types
60  *
61  *      The function may still be uncompiled, so the jit compiler gets invoked.
62  *
63  *
64  */
65
66         /* this is the method header see src/vm/jit/methodheader.h */
67         .align  4
68         .long   0                           /* catch type all                     */
69         .long   0                           /* handler pc                         */
70         .long   0                           /* end pc                             */
71         .long   0                           /* start pc                           */
72         .long   1                           /* extable size                       */
73         .long   0                           /* line number table start            */
74         .long   0                           /* line number table size             */
75         .long   0                           /* fltsave                            */
76         .long   0                           /* intsave                            */
77         .long   0                           /* isleaf                             */
78         .long   0                           /* IsSync                             */
79         .long   0                           /* frame size                         */
80         .long   0                           /* codeinfo pointer                   */
81
82
83 /*
84         This method gets called with 3 arguments:
85         1st arg: addres of method to call (fake invokevirtual here)
86         2nd arg: uint64_t array of argument registers followed by stack 
87         3rd arg: number of 8 byte stack slots to be copied.
88
89         coldifire does not use any argument registers, so just the stack has to be copied
90 */
91 asm_vm_call_method:
92 asm_vm_call_method_int:
93 asm_vm_call_method_long:
94 asm_vm_call_method_float:
95 asm_vm_call_method_double:
96
97 #if defined(ENABLE_SOFTFLOAT)
98         addal   #(-12*4),%sp                                            /* create stackframe to save registers, and 1 slot for method invocation */
99         moveml  %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp,%sp@        /* save registers */
100
101         /* fetch arguments from vmargs data structure */
102         movel   %sp@(12*4+1*4),%a3                              /* method */
103         movel   %sp@(12*4+2*4),%a2                              /* arg array */
104         movel   %sp@(12*4+3*4),%d2                              /* arg count */
105
106         movel   %a3, %sp@(12*4)                                 /* copy method address to stackslot */
107         leal    %sp@(12*4), %a3                                 /* and store that address in %a3 */
108 #else
109         addal #(-12*4-6*8), %sp
110         moveml  %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp,%sp@        /* save registers */
111         fmovemd %fp2/%fp3/%fp4/%fp5/%fp6/%fp7,%sp@(11*4)                        /* save registers */
112
113         /* fetch arguments from vmargs data structure */
114         movel   %sp@(12*4+6*8+1*4),%a3                          /* method */
115         movel   %sp@(12*4+6*8+2*4),%a2                          /* arg array */
116         movel   %sp@(12*4+6*8+3*4),%d2                          /* arg count */
117
118         movel   %a3, %sp@(11*4+6*8)                                     /* copy method address to stackslot */
119         leal    %sp@(11*4+6*8), %a3                                     /* and store that address in %a3 */
120 #endif
121
122         moveal  %sp, %a5                                        /* memorize stack */
123
124         tstl    %d2                                                     /* do we have arguments ? */
125         beq     L_asm_vm_call_method_copy_done
126         movel   %d2, %d3                                                /* create stackframe */
127         asll    #3,  %d3                                                /* number args * 8 */
128         subal   %d3, %sp                        
129         moveal  %sp, %a4                                                /* %a4 is temp stack pointer */
130
131 L_asm_vm_call_method_copy_loop:
132         movel   %a2@(0), %d3
133         movel   %d3, %a4@(0)                                    /* copy 4 bytes */
134         movel   %a2@(4), %d3
135         movel   %d3, %a4@(4)                                    /* a whole stack slot has been copied */
136
137         addal   #8, %a2
138         addal   #8, %a4
139         addl    #-1, %d2
140         tstl    %d2                                                             /* do we have more arguments ? */
141         beq     L_asm_vm_call_method_copy_done
142         br      L_asm_vm_call_method_copy_loop
143
144
145 L_asm_vm_call_method_copy_done:
146         /* now we fake method invocation as it would happen from invokevirtual */
147         /* this is needed as we patch the caller site, so we need a writeable slot */
148         /* %a3 points to the address containing the method, %a3 == REG_METHODPTR */
149
150         moveal  %a3@(0), %a4
151         jsr     %a4@
152
153 L_asm_vm_call_method_return:
154         movel   %a5, %sp                                                /* pop arguments off stack */
155
156 #if defined(ENABLE_SOFTFLOAT)
157         moveml  %sp@, %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp       /* restore registers */
158         addal   #(12*4),%sp                                             /* restore stack */
159 #else
160         fmovemd %sp@(12*4), %fp2/%fp3/%fp4/%fp5/%fp6/%fp7                       /* restore registers */
161         moveml  %sp@, %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp       /* restore registers */
162         addal   #(12*4+6*8),%sp                                         /* restore stack */
163 #endif
164         moveal  %d0, %a0                                                /* XXX return value in %a0, too, gcc sometimes expects addresses in %a0, wired */
165 asm_vm_call_method_end:                                         /* symbol needed to insert method into avl tree */
166         rts                                                                             /* return to c code */
167
168 /* asm_vm_call_method_exception_handler ********************************************************************
169  *
170  * calls void *builtin_throw_exception(java_objectheader *xptr) when no other handler is appropiate
171  * this functions gets called indirectly from asm_handle_exception, which back then moved xptr to %a2
172  * clear software design is in the eye of the beholder.
173  ************************************************************************************************************/
174 asm_vm_call_method_exception_handler:
175         movel   %a2, %sp@-                      /* push xptr argument */
176         jsr     builtin_throw_exception
177         lea     %sp@(4), %sp                    /* pop arg off stack */
178         jmp     L_asm_vm_call_method_return
179
180
181 /* asm_call_jit_compiler ************************************************************************************
182  *      Invokes compiler for untranslated java methods.
183  *      C prototype: void asm_call_jit_compiler(void);
184  *      BUT: this does not match reality, arguments _ARE_ passed via createcompilerstub and asm_vm_call_method...
185  *      arguments passed via %a2(methodinfo) == REG_ATMP1
186  *                       %a3(mptr)       == REG_ATMP2
187  ************************************************************************************************************/
188 asm_call_jit_compiler:
189         addal   #(-4*4),%sp                                             /* create stackframe to save registers */
190         moveml  %a0/%a1/%d0/%d1,%sp@                    /* save volatile registers */
191 #if !defined(ENABLE_SOFTFLOAT)
192         addal   #-8*2, %sp
193         fmovemd %fp0/%fp1, %sp@
194         movel   %sp@(8*4), %sp@-
195         pea             %sp@(8*4+8)
196 #else
197         movel   %sp@(4*4), %sp@-                                /* push arguments onto stack (ra)*/
198         pea     %sp@(4*4+8)                                             /* the old stack pointer*/
199 #endif
200         movel   %a3,%sp@-                                               /* mptr */
201         movel   %a2,%sp@-                                               /* methodinfo */
202
203         /* C prototype: u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra); */
204         jsr     jit_asm_compile                                         /* invoke compiler */
205         addal   #(4*4),%sp                                              /* pop arguments off stack */
206         moveal  %d0, %a2                                                /* to tmp register */
207
208 #if !defined(ENABLE_SOFTFLOAT)
209         fmovemd %sp@, %fp0/%fp1
210         addal   #8*2, %sp
211 #endif
212
213         moveml %sp@,%a0/%a1/%d0/%d1                             /* restore volatile registers */
214         addal   #(4*4),%sp                                              /* remove stackframe */
215
216         tstl    %a2                                                             /* check for exception */
217         beq     L_asm_call_jit_compiler_exception
218
219         jmp     %a2@                                                            /* invoke java method */
220         jsr     0                                                               /* we should not ever return here */
221
222 L_asm_call_jit_compiler_exception:
223         jsr             exceptions_get_and_clear_exception              /* exception object in %d0 now */
224         moveal  %d0, %a2                                                                /* move exception object into sptr register */
225         moveal  %sp@+, %a3                                                              /* pop return address into exception address reg */
226         jmp asm_handle_exception                                                /* handle exception */
227
228
229 /* asm_patcher_wrapper ********************************************************
230         
231   prepares arguments on stack
232   calls patcher_wrapper signature: java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra);
233
234   Stack layout:
235      24   return address
236      20   REG_ITMP3
237      16   pointer to virtual java_objectheader
238      12   last byte of machine code (xmcode)
239       8   machine code (which is patched back later)
240       4   unresolved field reference
241       0   patcher function pointer to call
242 *******************************************************************************/
243 asm_patcher_wrapper:
244
245   /* save scratch registers */
246   movel %a0, %sp@-
247   movel %a1, %sp@-
248   movel %d0, %sp@-
249   movel %d1, %sp@-
250
251 #if defined(ENABLE_SOFTFLOAT)
252   /* calculate original value of sp */
253   movel %sp, %d0
254   addil #4*4, %d0
255 #else
256   addal #-8*2, %sp
257   fmovemd %fp0/%fp1, %sp@
258
259   movel %sp, %d0
260   addil #8*4, %d0
261 #endif
262
263   clrl  %sp@-                           /* pass ra */
264   clrl  %sp@-                           /* pass pv, if null use findmethod */
265   movel %d0, %sp@-                      /* pass sp of patcher stub */
266   jsr   patcher_wrapper         /* return value in %d0 */
267
268   lea   %sp@(3*4), %sp          /* pop arguments off stack */
269   tst   %d0                                     /* test if exception occured */
270   bne   L_asm_patcher_wrapper_exception
271
272 #if !defined(ENABLE_SOFTFLOAT)
273   fmovemd %sp@, %fp0/%fp1
274   addal #8*2, %sp
275 #endif
276   movel %sp@+, %d1
277   movel %sp@+, %d0
278   movel %sp@+, %a1
279   movel %sp@+, %a0
280
281   lea   %sp@(6*4), %sp                  /* restore stack and remove patcher stub*/
282   rts                                                   /* back to jit code */
283
284 L_asm_patcher_wrapper_exception:
285   /* WARNING: the stack is still disturbed, look at asm_patcher_wrapper for details */
286   /* we do not need to restore the content of the registers, I hope */
287 #if !defined(ENABLE_SOFTFLOAT)
288         lea             %sp@(8*4), %sp
289 #else
290         lea             %sp@(4*4), %sp
291 #endif
292
293   lea           %sp@(5*4), %sp                          /* restore stack and remove patcher stub*/
294   movel         %sp@+, %d4                                      /* restore REG_ITMP3, stored in emit_patcher_stubs */
295   moveal        %d0, %a2                                        /* xptr, pointer to exception object */
296   moveal        %sp@+, %a3                                      /* pop return address into exception address register */
297   jmp           asm_handle_exception            /* handle exception */
298   illegal                                                               /* XXX: we never come back */
299
300
301 asm_abstractmethoderror:
302
303 /* asm_handle_exception ********************************************************
304 *                                                                              *
305 *   This function handles an exception. It does not use the usual calling      *
306 *   conventions. The exception pointer is passed in REG_ATMP1 and the          *
307 *   pc from the exception raising position is passed in REG_ATMP2. It searches *
308 *   the local exception table for a handler. If no one is found, it unwinds    *
309 *   stacks and continues searching the callers.                                *
310 *                                                                              *
311 *   void asm_handle_exception (void);
312 *   exception object pointer...%a2   exception raising address...%a3           *
313 *                                                                              *
314 *******************************************************************************/
315 asm_handle_nat_exception:
316         lea     %sp@(4), %sp
317 asm_handle_exception:
318 L_asm_handle_exception_stack_loop:
319         /* save temporary registers */
320         movel   %d0, %sp@-
321         movel   %d1, %sp@-
322         movel   %a0, %sp@-
323         movel   %a1, %sp@-
324 #if !defined(ENABLE_SOFTFLOAT)
325         addal   #-8*2, %sp
326         fmovemd %fp0, %sp@(0)
327         fmovemd %fp1, %sp@(8)
328 #endif
329
330         /* we need the dseg, figure it out */
331         movel   %a3, %sp@-                              /* push ra argument */
332         jsr     md_codegen_get_pv_from_pc       /* pv in %d0 now */
333         movel   %d0, %d2                                /* move to safe register */
334         lea     %sp@(4), %sp                            /* pop args off stack */
335
336         /* now call the following c function */
337         /* u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp) */
338 #if !defined(ENABLE_SOFTFLOAT)
339         pea             %sp@(4*4 + 8*2)
340 #else
341         pea             %sp@(4*4)
342 #endif
343         movel   %d2,%sp@-
344         movel   %a3,%sp@-
345         movel   %a2,%sp@-
346         jsr     exceptions_handle_exception             /* %d0 is address of handler or 0 when not catched */
347         lea     %sp@(4*4), %sp                          /* pop args off stack */
348         tstl    %d0
349         beq     L_asm_handle_exception_not_catched
350
351         /* %d0 contains address of exception handler */
352         moveal  %d0, %a3
353
354         /* restore temporary registers */
355         moveal  %sp@+, %a1
356         moveal  %sp@+, %a0
357         movel   %sp@+, %d1
358         movel   %sp@+, %d0
359 #if !defined(ENABLE_SOFTFLOAT)
360         fmovemd %fp0, %sp@(0)
361         fmovemd %fp1, %sp@(8)
362         addal   #8*2, %sp
363 #endif
364
365         jmp     %a3@
366
367 L_asm_handle_exception_not_catched:
368         /* we did not find an exception handler in this stackframe */
369         /* remove this frame and search in the one above */
370         /* %a2 containts exception object ptr, %d2 the actual pv */
371
372         /* remove temporary registers stored */
373 #if !defined(ENABLE_SOFTFLOAT)
374         addal   #4*4 + 8*2, %sp
375 #else
376         addal   #4*4, %sp
377 #endif
378
379         moveal  %d2, %a3
380         movel   %a3@(FrameSize), %d2
381
382         moveal  %sp, %a0
383         addal   %d2, %a0        /* %a0 now points to top of stackframe, where saved regs are */
384
385         /* the saved registers have to be restored */
386         /* XXX ugly hack: intsave and adrsave share one field */
387         movel   %a3@(IntSave), %d0
388         andil   #0x0000ffff, %d0        /* this is IntSave */
389         cmpb    #0,%d0
390         beq     L_asm_handle_ex_int_done
391         movel   -(%a0), %d7
392
393         cmpb    #1,%d0
394         beq     L_asm_handle_ex_int_done
395         movel   -(%a0), %d6
396
397         cmpb    #2,%d0 
398         beq     L_asm_handle_ex_int_done
399         movel   -(%a0), %d5
400
401 L_asm_handle_ex_int_done:
402
403         movel   %a3@(IntSave), %d0
404         andil   #0xffff0000, %d0        /* this is AdrSave */
405         lsrl    #8, %d0
406         lsrl    #8, %d0
407
408 #if 0
409         cmpb    #0, %d0
410         beq     L_asm_handle_ex_adr_done
411         moveal  -(%a0), %a5
412 #else
413         cmpb    #0, %d0
414         beq     L_asm_handle_ex_adr_done
415         moveal  -(%a0), %fp
416
417         cmpb    #1,%d0
418         beq     L_asm_handle_ex_adr_done
419         moveal  -(%a0), %a5
420 #endif
421
422 L_asm_handle_ex_adr_done:
423
424 #if !defined(ENABLE_SOFTFLOAT)
425         movel   %a3@(FltSave), %d0
426         cmpb    #0,%d0
427         beq     L_asm_handle_ex_flt_done
428         fmovemd %a0@(-8), %fp7
429
430         cmpb    #1,%d0
431         beq     L_asm_handle_ex_flt_done
432         fdmoved %a0@(-16), %fp6
433         
434         cmpb    #2,%d0
435         beq     L_asm_handle_ex_flt_done
436         fdmoved %a0@(-24), %fp5
437
438 L_asm_handle_ex_flt_done:
439 #else
440         /* nothing to do */
441 #endif
442         addal   %d2, %sp                /* remove old stackframe */
443         moveal  %sp@+, %a3              /* make return address, new exception rasing address */
444         subal   #2, %a3                 /* it was a jsr %aX, which is 4 bytes long */
445         jmp     L_asm_handle_exception_stack_loop
446
447
448 illegal
449 .long 0x23234242
450
451
452 /*
453  * These are local overrides for various environment variables in Emacs.
454  * Please do not remove this and leave it at the end of the file, where
455  * Emacs will automagically detect them.
456  * ---------------------------------------------------------------------
457  * Local variables:
458  * mode: c
459  * indent-tabs-mode: t
460  * c-basic-offset: 4
461  * tab-width: 4
462  * End:
463  * vim:noexpandtab:sw=4:ts=4:
464  */