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