exception back traces for i386
[cacao.git] / src / vm / jit / i386 / asmpart.S
1 /* jit/i386/asmpart.S - Java-C interface functions for i386
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    Institut f. Computersprachen, TU Wien
5    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6    S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
7    J. Wenninger
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Andreas Krall
29             Reinhard Grafl
30             Christian Thalinger
31
32    $Id: asmpart.S 963 2004-03-15 07:37:49Z jowenn $
33
34 */
35
36
37 #include "offsets.h"
38
39 /* data segment offsets */
40
41 #define MethodPointer           -4
42 #define FrameSize               -8
43 #define IsSync                  -12
44 #define IsLeaf                  -16
45 #define IntSave                 -20
46 #define FltSave                 -24
47 #define LineNumberTableSize     -28
48 #define LineNumberTableStart    -32
49 #define ExTableSize             -36
50 #define ExTableStart            -36
51
52 #define ExEntrySize     -16
53 #define ExStartPC       -4
54 #define ExEndPC         -8
55 #define ExHandlerPC     -12
56 #define ExCatchType     -16
57
58
59 #define LineEntrySize   -8
60 #define LinePC          0
61 #define LineLine        -4
62                 
63         .text
64
65
66 /********************* exported functions and variables ***********************/
67
68         .globl has_no_x_instr_set
69         .globl asm_calljavafunction
70         .globl asm_calljavafunction2
71         .globl asm_calljavafunction2long
72         .globl asm_calljavafunction2double
73
74         .globl asm_call_jit_compiler
75         .globl asm_dumpregistersandcall
76         .globl asm_handle_builtin_exception
77         .globl asm_handle_nat_exception
78         .globl asm_handle_exception
79         .globl asm_check_clinit
80         .globl asm_builtin_checkcast    
81         .globl asm_builtin_checkarraycast
82         .globl asm_builtin_newarray
83         .globl asm_builtin_anewarray
84         .globl asm_builtin_newarray_array
85         .globl asm_builtin_aastore
86         .globl asm_builtin_monitorenter
87         .globl asm_builtin_monitorexit
88         .globl asm_builtin_ldiv
89         .globl asm_builtin_lrem
90     .globl asm_builtin_f2i
91     .globl asm_builtin_f2l
92     .globl asm_builtin_d2i
93     .globl asm_builtin_d2l
94         .globl asm_builtin_arrayinstanceof
95         .globl asm_perform_threadswitch
96         .globl asm_initialize_thread_stack
97         .globl asm_switchstackandcall
98         .globl asm_getcallingmethod
99         .globl Java_java_lang_VMSecurityManager_getClassContext
100         .globl Java_java_lang_VMSecurityManager_currentClassLoader    
101         .globl asm_builtin_new
102         .globl asm_get_stackTrace
103
104 /*************************** imported functions *******************************/
105
106         .globl jit_compile
107         .globl builtin_monitorexit
108         .globl builtin_throw_exception
109         .globl builtin_trace_exception
110         .globl class_java_lang_Object
111         .globl findmethod
112         .globl builtin_asm_createclasscontextarray
113         .globl builtin_asm_getclassloader
114 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
115         .globl cast_lock
116         .globl cast_unlock
117 #endif
118
119
120 /*********************** function has_no_x_instr_set ***************************
121 *                                                                              *
122 *   determines if the byte support instruction set (21164a and higher)         *
123 *   is available.                                                              *
124 *                                                                              *
125 *   Use it on i386 architecture to init the fpu.                               *
126 *                                                                              *
127 *******************************************************************************/
128
129 has_no_x_instr_set:
130                 finit                         /* intitialize the fpu                  */
131
132                 pushl   $0x027f   /* Round to nearest, 53-bit mode, exceptions masked */
133                 fldcw   (%esp)
134                 addl    $4,%esp
135                 
136                 xor             %eax,%eax                               /* result code 0 (not used for i386)  */
137                 ret
138
139
140 /********************* function asm_calljavafunction ***************************
141 *                                                                              *
142 *   This function calls a Java-method (which possibly needs compilation)       *
143 *   with up to 4 address parameters.                                           *
144 *                                                                              *
145 *   This functions calls the JIT-compiler which eventually translates the      *
146 *   method into machine code.                                                  *
147 *                                                                              *
148 *   C-prototype:                                                               *
149 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
150 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
151 *                                                                              *
152 *******************************************************************************/
153
154 call_name:
155         .ascii  "calljavafunction\0\0"
156
157         .align  8
158         .long   0                         /* catch type all                       */
159         .long   calljava_xhandler         /* handler pc                           */
160         .long   calljava_xhandler         /* end pc                               */
161         .long   asm_calljavafunction      /* start pc                             */
162         .long   1                         /* extable size                         */
163         .long   0                         /* line number table  start             */
164         .long   0                         /* line number table  size              */
165         .long   0                         /* fltsave                              */
166         .long   0                         /* intsave                              */
167         .long   0                         /* isleaf                               */
168         .long   0                         /* IsSync                               */
169         .long   32                        /* frame size                           */
170         .long   0                         /* method pointer (pointer to name)     */
171
172 asm_calljavafunction:
173                 push    %ebp                  /* allocate stack space                 */
174                 mov             %esp, %ebp
175
176         push    %ebx                  /* save registers                       */
177         push    %esi
178         push    %edi
179         
180                 sub             $32,%esp              /* pass the remaining parameters        */
181                 xor             %edx,%edx
182
183                 mov             %edx,28(%esp)         /* convert parms to 8 byte              */
184                 mov             24(%ebp),%eax
185                 mov             %eax,24(%esp)
186                 
187                 mov             %edx,20(%esp)
188                 mov             20(%ebp),%eax
189                 mov             %eax,16(%esp)
190
191                 mov             %edx,12(%esp)
192                 mov             16(%ebp),%eax
193                 mov             %eax,8(%esp)
194
195                 mov             %edx,4(%esp)
196                 mov             12(%ebp),%eax
197                 mov             %eax,(%esp)
198
199                 mov             8(%ebp),%eax          /* move function pointer to %eax        */
200
201                 lea             asm_call_jit_compiler,%edx 
202                 call    *%edx                 /* call JIT compiler                    */
203         
204 calljava_return:
205         add     $32,%esp
206         pop     %edi                 /* restore registers                     */
207         pop     %esi
208         pop     %ebx
209                 leave
210                 ret
211
212 calljava_xhandler:
213                 push    %eax                              /* pass exception pointer               */
214                 call    builtin_throw_exception
215                 add     $4,%esp
216
217                 add     $32,%esp
218         pop     %edi                 /* restore registers                     */
219         pop     %esi
220         pop     %ebx
221         leave
222                 ret
223                                                 
224
225
226 /********************* function asm_calljavafunction ***************************
227 *                                                                              *
228 *   This function calls a Java-method (which possibly needs compilation)       *
229 *   with up to 4 address parameters.                                           *
230 *                                                                              *
231 *   This functions calls the JIT-compiler which eventually translates the      *
232 *   method into machine code.                                                  *
233 *                                                                              *
234 *   C-prototype:                                                               *
235 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
236 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
237 *                                                                              *
238 *******************************************************************************/
239
240 call_name2:
241         .ascii  "calljavafunction2\0\0"
242
243         .align  8
244         .long   0                         /* catch type all                       */
245         .long   calljava_xhandler2        /* handler pc                           */
246         .long   calljava_xhandler2        /* end pc                               */
247         .long   asm_calljavafunction2     /* start pc                             */
248         .long   1                         /* extable size                         */
249         .long   0                         /* line number table start              */
250         .long   0                         /* line number table size               */
251         .long   0                         /* fltsave                              */
252         .long   0                         /* intsave                              */
253         .long   0                         /* isleaf                               */
254         .long   0                         /* IsSync                               */
255         .long   32                        /* frame size                           */
256         .long   0                         /* method pointer (pointer to name)     */
257
258 asm_calljavafunction2:
259 asm_calljavafunction2double:
260 asm_calljavafunction2long:
261                 push    %ebp                  /* save ebp                             */
262
263                 mov     %esp,%eax             /* save stackptr                        */
264                 mov     20(%esp),%ebp
265
266         push    %ebx                  /* save registers                       */
267         push    %esi
268         push    %edi
269
270                 sub     $32,%esp
271
272         mov     sizejniblock*3+offjniitem+4(%ebp),%ebx
273         mov     %ebx,28(%esp)
274         mov     sizejniblock*3+offjniitem(%ebp),%ebx
275         mov     %ebx,24(%esp)
276
277         mov     sizejniblock*2+offjniitem+4(%ebp),%ebx
278         mov     %ebx,20(%esp)
279         mov     sizejniblock*2+offjniitem(%ebp),%ebx
280         mov     %ebx,16(%esp)
281
282
283         mov     sizejniblock+offjniitem+4(%ebp),%ebx
284         mov     %ebx,12(%esp)
285         mov     sizejniblock+offjniitem(%ebp),%ebx
286         mov     %ebx,8(%esp)
287
288         mov     offjniitem+4(%ebp),%ebx
289         mov     %ebx,4(%esp)
290         mov     offjniitem(%ebp),%ebx
291         mov     %ebx,0(%esp)
292
293                 mov     %eax,%ebp       
294                 mov     8(%ebp),%eax          /* move function pointer to %eax        */
295
296                 lea     asm_call_jit_compiler,%edx 
297                 call    *%edx                 /* call JIT compiler                    */
298         
299 calljava_return2:
300         add     $32,%esp
301         pop     %edi                  /* restore registers                    */
302         pop     %esi
303         pop     %ebx
304                 leave
305                 ret
306
307 calljava_xhandler2:
308                 push    %eax                              /* pass exception pointer               */
309                 call    builtin_throw_exception
310                 add     $4,%esp
311         
312                 add     $32,%esp
313         pop     %edi                  /* restore registers                    */
314         pop     %esi
315         pop     %ebx
316                 leave
317                 ret
318
319
320 /****************** function asm_call_jit_compiler *****************************
321 *                                                                              *
322 *   invokes the compiler for untranslated JavaVM methods.                      *
323 *                                                                              *
324 *   Register R0 contains a pointer to the method info structure (prepared      *
325 *   by createcompilerstub). Using the return address in R26 and the            *
326 *   offset in the LDA instruction or using the value in methodptr R28 the      *
327 *   patching address for storing the method address can be computed:           *
328 *                                                                              *
329 *   method address was either loaded using                                     *
330 *                                                                              *
331 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
332 *   i386_call_reg(REG_ITMP2)                                                   *
333 *                                                                              *
334 *   or                                                                         *
335 *                                                                              *
336 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP1)    ; invokevirtual/interface    *
337 *   i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)                *
338 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \                *
339 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
340 *   i386_call_reg(REG_ITMP1)                                                   *
341 *                                                                              *
342 *   in the static case the method pointer can be computed using the            *
343 *   return address and the lda function following the jmp instruction          *
344 *                                                                              *
345 *******************************************************************************/
346
347
348 asm_call_jit_compiler:
349                 push    %ebx            /* save register                              */
350         push    %ebp
351                                 
352                 mov     8(%esp),%ebp    /* get return address (2 push)                */
353                 mov     -1(%ebp),%bl    /* get function code                          */
354                 cmp     $0xd1,%bl               /* called with `call *REG_ITMP2' (%ecx)?      */
355                 jne             L_not_static_special
356
357                 sub     $6,%ebp                 /* calculate address of immediate             */
358                 jmp             L_call_jit_compile
359                 
360 L_not_static_special:
361                 cmp     $0xd0,%bl               /* called with `call *REG_ITMP1' (%eax)       */
362                 jne             L_not_virtual_interface
363                 
364                 sub     $6,%ebp         /* calculate address of offset                */
365                 mov     (%ebp),%ebp     /* get offset                                 */
366                 add     %ecx,%ebp       /* add base address to get method address     */
367                 jmp             L_call_jit_compile
368
369 L_not_virtual_interface:        /* a call from asm_calljavafunction           */
370                 xor     %ebp,%ebp
371                 
372 L_call_jit_compile:
373                 push    %ebp            /* save address for method pointer            */
374
375                 push    %eax                    /* push methodpointer on stack                */
376                 call    jit_compile
377                 add     $4,%esp
378
379                 pop     %ebp            /* restore address for method pointer         */
380                 test    %ebp,%ebp               /* is address == 0 (asm_calljavafunction)     */
381                 je              L_call_method
382                 
383                 mov     %eax,(%ebp)             /* and now save the new pointer               */
384
385 L_call_method:
386         pop     %ebp            /* restore registers                          */
387                 pop     %ebx
388                         
389                 jmp             *%eax                   /* ...and now call the new method             */
390
391
392
393 /****************** function asm_dumpregistersandcall **************************
394 *                                                                              *
395 *   This funtion saves all callee saved registers and calls the function       *
396 *   which is passed as parameter.                                              *
397 *                                                                              *
398 *   This function is needed by the garbage collector, which needs to access    *
399 *   all registers which are stored on the stack. Unused registers are          *
400 *   cleared to avoid interferances with the GC.                                *
401 *                                                                              *
402 *   void asm_dumpregistersandcall (functionptr f);                             *
403 *                                                                              *
404 *******************************************************************************/
405
406 asm_dumpregistersandcall:
407         xor     %eax,%eax
408         mov     %eax,(%eax)
409
410                 push    %ebp
411         push    %ecx
412         push    %edx
413                 push    %ebx
414                 push    %esi
415                 push    %edi
416                                 
417                 mov     4(%ebp),%eax            /* load function pointer */
418                 call    *%eax                           /* call function */
419
420                 pop             %edi
421                 pop             %esi
422                 pop             %ebx
423         pop     %edx
424                 pop     %ecx
425                 pop             %ebp
426         
427                 ret
428         
429
430 /********************* function asm_handle_exception ***************************
431 *                                                                              *
432 *   This function handles an exception. It does not use the usual calling      *
433 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
434 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
435 *   the local exception table for a handler. If no one is found, it unwinds    *
436 *   stacks and continues searching the callers.                                *
437 *                                                                              *
438 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
439 *                                                                              *
440 *******************************************************************************/
441
442 asm_handle_builtin_exception:
443         add     $4,%esp                                         /* clear return address of this call */
444         mov     (%esp),%eax                 /* get exceptionptr               */
445         leave                               /* leave builtin function         */
446         mov     (%esp),%edx                 /* get exceptionpc                */
447         sub     $2,%edx                     /* size of builtin call           */
448         jmp     asm_handle_exception
449         
450 asm_handle_nat_exception:
451                 add     $4,%esp                                         /* clear return address of native stub */
452                 
453 asm_handle_exception:
454 #if 0
455                 push %ebp
456                 mov %esp,%ebp
457                 push %eax       /* exception pointer */
458                 push %ecx       /* excepiton pc */
459
460                 call asm_get_stackTrace
461
462                 pop %ecx
463                 pop %eax
464                 pop %ebp
465 #endif
466 asm_handle_exception_loop:
467                 push    %ebp
468                 mov     %esp,%ebp
469         
470                 push    %eax                                            /* save exception pointer         */
471                 push    %ecx                        /* save exception pc              */
472
473 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
474                 call    cast_lock
475 #endif
476                 
477                 call    findmethod                  /* get the data segment ptr       */
478                 mov     %eax,%edx
479                         
480                 mov     -4(%ebp),%eax
481                 mov     -8(%ebp),%ecx               /* could be changed in findmethod */
482
483                 push    %edx                                            /* save data segment pointer      */
484                 push    %ebx
485                 push    %esi
486                 push    %edi
487                 
488 ex_stack_loop:
489                 sub     $20,%esp
490                 mov     %eax,(%esp)                                     /* exception pointer              */
491                 mov     MethodPointer(%edx),%eax        /* method pointer                 */
492                 mov     %eax,4(%esp)
493                 mov     %ecx,8(%esp)                            /* exception pc                   */
494
495                 movl    $0,12(%esp)             /* line number */
496
497                 movl    $1,16(%esp)                                     /* set no unwind flag             */
498                 call    builtin_trace_exception
499                 add     $20,%esp
500                 mov     -12(%ebp),%esi                          /* %esi = data segment pointer    */
501                 mov     ExTableSize(%esi),%ecx          /* %ecx = exception table size    */
502                 test    %ecx,%ecx                                       /* if empty table skip            */
503                 je      empty_table
504
505                 lea             ExTableStart(%esi),%edi         /* %edi = start of exception table*/
506                 mov     -4(%ebp),%eax               /* get xptr                       */
507                 
508 ex_table_loop:
509                 mov     -8(%ebp),%edx                           /* get xpc                        */
510
511                 mov     ExStartPC(%edi),%ebx            /* %ebx = exception start pc      */
512                 cmp     %edx,%ebx                                       /* %ebx = (startpc <= xpc)        */
513                 jg      ex_table_cont                           /* if (false) continue            */
514                 mov     ExEndPC(%edi),%ebx                      /* %ebx = exception end pc        */
515                 cmp     %ebx,%edx                                       /* %ebx = (xpc < endpc)           */
516                 jge     ex_table_cont                           /* if (false) continue            */
517                 mov     ExCatchType(%edi),%ebx          /* arg1 = exception catch type    */
518                 test    %ebx,%ebx                                       /* NULL catches everything        */
519                 je      ex_handle_it
520
521                 mov     offobjvftbl(%eax),%esi          /* %esi = vftblptr(xptr)          */
522                 mov     offclassvftbl(%ebx),%ebx    /* %ebx = vftblptr(catchtype) class (not obj) */
523                 mov     offbaseval(%esi),%esi           /* %esi = baseval(xptr)           */
524                 mov     offbaseval(%ebx),%edx           /* %edx = baseval(catchtype)      */
525                 mov     offdiffval(%ebx),%ebx           /* %ebx = diffval(catchtype)      */
526                 sub     %edx,%esi                                       /* %esi = baseval(xptr) - baseval(catchtype) */
527                 cmp     %ebx,%esi                                       /* xptr is instanceof catchtype   */
528                 ja      ex_table_cont
529                 
530 ex_handle_it:
531                 mov     ExHandlerPC(%edi),%edx
532                 
533                 pop     %edi                        /* restore registers              */
534                 pop     %esi
535                 pop     %ebx
536         add     $8,%esp                     /* suck %ecx, %edx                */
537         pop     %eax                        /* restore xptr                   */
538
539 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
540                 call cast_unlock
541 #endif
542         
543                 leave
544                 jmp             *%edx                       /* jump to exception handler      */
545
546 ex_table_cont:
547                 lea     ExEntrySize(%edi),%edi
548                 dec     %ecx
549                 test    %ecx,%ecx
550                 jg      ex_table_loop
551                 
552 empty_table:
553         pop     %edi
554         pop     %esi
555         pop     %ebx
556         pop     %edx                        /* restore data segment pointer   */
557         pop     %ecx
558         pop     %eax
559         pop     %ebp
560
561         push    %eax                        /* save exception pointer         */
562         
563 ex_already_cleared:
564                 mov     IsSync(%edx),%eax                       /* %eax = SyncOffset              */
565                 test    %eax,%eax                                       /* if zero no monitorexit         */
566                 je      no_monitor_exit
567
568         add     %esp,%eax
569         mov     -4(%eax),%eax               /* we have the xptr on the stack  */
570         push    %edx                        /* save regs                      */
571         push    %eax
572                 call    builtin_monitorexit
573                 add     $4,%esp
574         pop     %edx                        /* restore regs                   */
575         
576 no_monitor_exit:
577         mov     %esp,%eax
578         add     FrameSize(%edx),%eax        /* %eax = frame size              */
579         add     $4,%eax                     /* we have the xptr on the stack  */
580         
581                 mov     IntSave(%edx),%ecx          /* %ecx = saved int register count*/
582                 test    %ecx,%ecx
583                 je      noint
584                 cmp     $1,%ecx
585                 je      int1
586                 cmp     $2,%ecx
587                 je      int2
588                 cmp     $3,%ecx
589                 je      int3
590
591 int4:   
592                 mov     -32(%eax),%ebx
593
594 int3:   
595                 mov     -24(%eax),%ebp
596
597 int2:   
598                 mov     -16(%eax),%esi
599
600 int1:   
601                 mov     -8(%eax),%edi
602
603                 shl     $3,%ecx                                         /* multiply by 8 bytes             */
604                 sub     %ecx,%eax
605                 
606 noint:
607                 mov     FltSave(%edx),%ecx                      /* %ecx = saved flt register count */
608                 test    %ecx,%ecx
609                 je      noflt
610                 cmp     $1,%ecx
611                 je      flt1
612                 cmp     $2,%ecx
613                 je      flt2
614                 cmp     $3,%ecx
615                 je      flt3
616                 
617 flt4:   
618                 fldl    -32(%eax)
619                 fstp    %st(1)
620
621 flt3:   
622                 fldl    -24(%eax)
623                 fstp    %st(2)
624                 
625 flt2:   
626                 fldl    -16(%eax)
627                 fstp    %st(3)
628                 
629 flt1:   
630                 fldl    -8(%eax)
631                 fstp    %st(4)
632                 
633 noflt:
634         pop     %eax                        /* restore exception pointer      */
635         
636         mov     FrameSize(%edx),%ecx        /* %ecx = frame size              */
637         add     %ecx,%esp                   /* unwind stack                   */
638         
639                 pop     %ecx                        /* the new xpc is return address  */
640                 sub     $2,%ecx
641                 
642                 jmp             asm_handle_exception_loop
643                 
644
645 /********************* function asm_check_clinit *******************************
646 *                                                                              *
647 *   Does null check and calls monitorenter or throws an exception              *
648 *                                                                              *
649 *******************************************************************************/
650
651 asm_check_clinit:
652                 mov             offclassinit(%eax),%ecx     /* get initialized flag           */
653                 test    %ecx,%ecx
654                 jnz             L_is_initialized
655
656                 push    %eax                        /* pass classinfo pointer         */
657                 call    class_init                  /* call class_init function       */
658                 add             $4,%esp
659                                 
660 L_is_initialized:
661                 mov             (%esp),%eax                 /* get return address             */
662                 sub             $12,%eax                    /* asm_putstatic call code size   */
663                 movb    $0xeb,(%eax)                /* jmp rel8                       */
664                 movl    $10,1(%eax)                 /* 32-bit offset                  */
665                 ret
666
667                 
668 /********************* function asm_builtin_monitorenter ***********************
669 *                                                                              *
670 *   Does null check and calls monitorenter or throws an exception              *
671 *                                                                              *
672 *******************************************************************************/
673
674 asm_builtin_monitorenter:
675                 cmpl    $0,4(%esp)
676                 je              nb_monitorenter                 /* if (null) throw exception          */
677                 jmp             builtin_monitorenter    /* else call builtin_monitorenter     */
678
679 nb_monitorenter:
680                 popl    %ecx                                    /* delete return address */
681                 subl    $2,%ecx                                 /* faulting address is return adress - 2 */
682                 movl    proto_java_lang_NullPointerException,%eax
683                 jmp             asm_handle_exception
684                 
685
686 /********************* function asm_builtin_monitorexit ************************
687 *                                                                              *
688 *   Does null check and calls monitorexit or throws an exception               *
689 *                                                                              *
690 *******************************************************************************/
691
692 asm_builtin_monitorexit:
693                 mov     4(%esp),%eax
694         test    %eax,%eax
695                 je      nb_monitorexit                  /* if (null) throw exception          */
696         push    %ecx                    /* save registers which could be used */
697         push    %edx
698         push    %eax
699                 call    builtin_monitorexit             /* else call builtin_monitorenter     */
700         add     $4,%esp
701         pop     %edx                    /* restore registers which could be used */
702         pop     %ecx
703         ret
704
705 nb_monitorexit:
706                 popl    %ecx                                    /* delete return address */
707                 subl    $2,%ecx                                 /* faulting address is return adress - 2 */
708                 movl    proto_java_lang_NullPointerException,%eax
709                 jmp             asm_handle_exception
710
711
712 /************************ function asm_builtin_ldiv ****************************
713 *                                                                              *
714 *   Does null check and calls ldiv or throws an exception                      *
715 *                                                                              *
716 *******************************************************************************/
717
718 asm_builtin_ldiv:
719                 mov             12(%esp),%eax
720                 or              16(%esp),%eax
721                 test    %eax,%eax                               /* if (null) throw exception */
722                 je              nb_ldiv
723
724                 jmp             builtin_ldiv
725
726 nb_ldiv:
727                 pop             %ecx                                    /* delete return address */
728                 sub             $2,%ecx                                 /* faulting address is return adress - 2 */
729                 mov             proto_java_lang_ArithmeticException,%eax
730                 jmp             asm_handle_exception
731                                 
732
733 /************************ function asm_builtin_lrem ****************************
734 *                                                                              *
735 *   Does null check and calls lrem or throws an exception                      *
736 *                                                                              *
737 *******************************************************************************/
738
739 asm_builtin_lrem:
740                 mov             12(%esp),%eax
741                 or                      16(%esp),%eax
742                 test    %eax,%eax                               /* if (null) throw exception */
743                 je              nb_lrem
744
745                 jmp             builtin_lrem
746
747 nb_lrem:
748                 pop             %ecx                                    /* delete return address */
749                 sub             $2,%ecx                                 /* faulting address is return adress - 2 */
750                 mov             proto_java_lang_ArithmeticException,%eax
751                 jmp             asm_handle_exception
752                 
753
754 /************************ function asm_builtin_x2x *****************************
755 *                                                                              *
756 *   Wrapper functions for corner cases                                         *
757 *                                                                              *
758 *******************************************************************************/
759
760 asm_builtin_f2i:
761         sub     $4,%esp
762         fsts    (%esp)
763         call    builtin_f2i
764         add     $4,%esp
765         ret             
766
767 asm_builtin_d2i:
768         sub     $8,%esp
769         fstl    (%esp)
770         call    builtin_d2i
771         add     $8,%esp
772         ret             
773
774 asm_builtin_f2l:
775         sub     $4,%esp
776         fsts    (%esp)
777         call    builtin_f2l
778         add     $4,%esp
779         ret             
780
781 asm_builtin_d2l:
782         sub     $8,%esp
783         fstl    (%esp)
784         call    builtin_d2l
785         add     $8,%esp
786         ret             
787
788         
789 /*********************** function new_builtin_checkcast ************************
790 *                                                                              *
791 *   Does the cast check and eventually throws an exception                     *
792 *                                                                              *
793 *******************************************************************************/
794
795 asm_builtin_checkcast:
796                 xor             %eax,%eax
797                 mov             %eax,(%eax)
798                 ret
799
800                 
801 /******************* function asm_builtin_checkarraycast ***********************
802 *                                                                              *
803 *   Does the cast check and eventually throws an exception                     *
804 *                                                                              *
805 *******************************************************************************/
806
807 asm_builtin_checkarraycast:
808                 sub             $8,%esp                                 /* build stack frame (2 * 4 bytes)    */
809
810                 mov             12(%esp),%eax           /* 8 (frame) + 4 (return)             */
811                 mov             %eax,(%esp)                             /* save object pointer                */
812
813                 mov             20(%esp),%eax
814                 mov             %eax,4(%esp)
815
816                 call    builtin_checkarraycast  /* builtin_checkarraycast             */
817         
818                 test    %eax,%eax               /* if (false) throw exception         */
819                 je              nb_carray_throw
820
821                 mov             12(%esp),%eax                   /* return object pointer              */
822                 add             $8,%esp
823                 ret
824
825 nb_carray_throw:
826                 add             $8,%esp
827                 
828                 pop             %ecx                                    /* delete return address              */
829                 sub             $2,%ecx                                 /* faulting address is return adress - 2 */
830                 mov             proto_java_lang_ClassCastException,%eax
831                 jmp             asm_handle_exception
832
833                 
834 /******************* function asm_builtin_newarray *****************************
835 *                                                                              *
836 *   Does the cast check and eventually throws an exception                     *
837 *                                                                              *
838 *******************************************************************************/
839
840 asm_builtin_newarray:
841                 sub             $8,%esp                                 /* build stack frame (2 * 4 bytes) */
842
843                 mov             12(%esp),%eax
844                 mov             %eax,(%esp)
845
846                 mov             20(%esp),%eax
847                 mov             %eax,4(%esp)
848
849                 call    builtin_newarray
850         
851                 add             $8,%esp
852                 ret
853
854                 
855 /******************* function asm_builtin_aastore ******************************
856 *                                                                              *
857 *   Does the cast check and eventually throws an exception                     *
858 *                                                                              *
859 *******************************************************************************/
860
861 asm_builtin_aastore:
862                 subl    $12,%esp                                /* build stack frame (3 * 4 bytes)    */
863
864                 movl    16(%esp),%eax           /* 12 (frame) + 4 (return)            */
865                 test    %eax,%eax                               /* if null pointer throw exception    */
866                 je              nb_aastore_null
867
868                 movl    offarraysize(%eax),%edx /* load size                          */
869                 movl    24(%esp),%ecx                   /* index                              */
870                 cmpl    %edx,%ecx                               /* do bound check                     */
871                 ja              nb_aastore_bound                /* if out of bounds throw exception   */
872
873                 shll    $2,%ecx                                 /* index * 4                          */
874                 addl    %eax,%ecx                               /* add index * 4 to arrayref          */
875                 
876                 movl    %ecx,8(%esp)                    /* save store position                */
877                 
878                 movl    16(%esp),%eax           /* 12 (frame) + 4 (return)            */
879                 movl    %eax,(%esp)
880
881                 movl    32(%esp),%eax                   /* object is second argument          */
882                 movl    %eax,4(%esp)
883                 
884                 call    builtin_canstore                /* builtin_canstore(arrayref,object)  */
885
886                 test    %eax,%eax                               /* if (false) throw exception         */
887                 je              nb_aastore_throw
888
889                 movl    32(%esp),%eax
890                 movl    8(%esp),%ecx
891                 movl    %eax,offobjarrdata(%ecx)/* store objectptr in array           */
892                 
893                 addl    $12,%esp
894                 ret
895
896 nb_aastore_null:
897                 addl    $12,%esp
898                 popl    %ecx                                    /* delete return address */
899                 subl    $2,%ecx                                 /* faulting address is return adress - 2 */
900                 movl    proto_java_lang_NullPointerException,%eax
901                 jmp             asm_handle_exception
902
903 nb_aastore_bound:
904                 addl    $12,%esp
905                 popl    %ecx                                    /* delete return address */
906                 subl    $2,%ecx                                 /* faulting address is return adress - 2 */
907                 movl    proto_java_lang_ArrayIndexOutOfBoundsException,%eax
908                 jmp             asm_handle_exception
909                 
910 nb_aastore_throw:
911                 addl    $12,%esp
912                 popl    %ecx                                    /* delete return address */
913                 subl    $2,%ecx                                 /* faulting address is return adress - 2 */
914                 movl    proto_java_lang_ArrayStoreException,%eax
915                 jmp             asm_handle_exception
916
917                 
918 /******************* function asm_builtin_arrayinstanceof **********************
919 *                                                                              *
920 *   Does the instanceof check of arrays                                        *
921 *                                                                              *
922 *******************************************************************************/
923
924 asm_builtin_arrayinstanceof:
925                 subl    $8,%esp                                 /* build stack frame (2 * 4 bytes) */
926
927                 movl    12(%esp),%eax
928                 movl    %eax,(%esp)
929
930                 movl    20(%esp),%eax
931                 movl    %eax,4(%esp)
932
933                 call    builtin_arrayinstanceof
934         
935                 addl    $8,%esp
936                 ret
937
938                 
939 /******************* function asm_initialize_thread_stack **********************
940 *                                                                              *
941 * initialized a thread stack                                                   *
942 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
943 *                                                                              *
944 *******************************************************************************/
945
946 asm_initialize_thread_stack:
947                 movl    8(%esp),%eax            /* (to)->stackEnd                     */
948                 subl    $36,%eax                                /* 4 bytes * 8 regs + 4 bytes func    */
949
950                 xorl    %edx,%edx
951                 movl    %edx,0(%eax)
952                 movl    %edx,4(%eax)
953                 movl    %edx,8(%eax)
954                 movl    %edx,12(%eax)
955                 movl    %edx,16(%eax)
956                 movl    %edx,20(%eax)
957                 movl    %edx,24(%eax)
958                 movl    %edx,28(%eax)
959
960                 movl    4(%esp),%edx            /* save (u1*) (func)                  */
961                 movl    %edx,32(%eax)
962
963                 ret                             /* return restorepoint in %eax        */
964
965
966 /******************* function asm_perform_threadswitch *************************
967 *                                                                              *
968 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
969 *                                                                              *
970 *   performs a threadswitch                                                    *
971 *                                                                              *
972 *******************************************************************************/
973
974 asm_perform_threadswitch:
975                 subl    $36,%esp
976
977                 movl    %eax,0(%esp)
978                 movl    %ecx,4(%esp)
979                 movl    %edx,8(%esp)
980                 movl    %ebx,12(%esp)
981                 movl    %esp,16(%esp)
982                 movl    %ebp,20(%esp)
983                 movl    %esi,24(%esp)
984                 movl    %edi,28(%esp)
985
986                 movl    36(%esp),%eax                   /* save current return address */
987                 movl    %eax,32(%esp)
988
989                 movl    40(%esp),%eax                   /* first argument **from */
990                 movl    %esp,0(%eax)
991
992                 movl    48(%esp),%eax                   /* third argument **stackTop */
993                 movl    %esp,0(%eax)
994
995                 movl    44(%esp),%eax                   /* second argument **to */
996                 movl    0(%eax),%esp                    /* load new stack pointer */
997
998                 movl    0(%esp),%eax
999                 movl    4(%esp),%ecx
1000                 movl    8(%esp),%edx
1001                 movl    12(%esp),%ebx
1002                                                                                 /* skip stack pointer */
1003                 movl    20(%esp),%ebp
1004                 movl    24(%esp),%esi
1005                 movl    28(%esp),%edi
1006
1007                 addl    $32,%esp                /* leave return address on stack      */
1008                 ret
1009                 
1010
1011 /********************* function asm_switchstackandcall *************************
1012 *                                                                              *
1013 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
1014 *                                      void *p);                                       *
1015 *                                                                              *
1016 *   Switches to a new stack, calls a function and switches back.               *
1017 *       a0      new stack pointer                                              *
1018 *       a1      function pointer                                               *
1019 *               a2              pointer to variable where stack top should be stored           *
1020 *       a3      pointer to user data, is passed to the function                *
1021 *                                                                              *
1022 *******************************************************************************/
1023
1024 asm_switchstackandcall:
1025                 movl    4(%esp),%edx                    /* first argument *stack              */
1026                 subl    $8,%edx                                 /* allocate new stack                 */
1027
1028                 movl    (%esp),%eax                             /* save return address on new stack   */
1029                 movl    %eax,(%edx)
1030
1031                 movl    %esp,4(%edx)                    /* save old stack pointer on new stack*/
1032
1033                 movl    12(%esp),%eax                   /* third argument **stacktopsave      */
1034                 movl    %esp,(%eax)                             /* save old stack pointer to variable */
1035
1036                 movl    8(%esp),%eax                    /* load function pointer              */
1037                 movl    16(%esp),%ecx                   /* fourth argument *p                 */
1038                 
1039                 movl    %edx,%esp                               /* switch to new stack                */
1040
1041                 subl    $4,%esp
1042                 movl    %ecx,0(%esp)                    /* pass pointer                       */
1043                 call    *%eax                                   /* and call function                  */
1044                 addl    $4,%esp
1045
1046                 movl    (%esp),%edx                             /* load return address                */
1047                 movl    4(%esp),%esp                    /* switch to old stack                */
1048                 movl    %edx,(%esp)
1049                 ret
1050
1051                 
1052 /********************* function asm_getcallingmethod ***************************
1053 *                                                                              *
1054 *   classinfo *asm_getcallingmethod ();                                                                    *
1055 *                                                                                                                                                          *    
1056 *   goes back stack frames to get the calling method                                               *       
1057 *                                                                                                                                                          *    
1058 *                               t2 .. sp                                                                                                       *
1059 *                               t3 .. ra                                                                                                       *
1060 *                               t4 .. pv                                                                                                       *
1061 *                                                                              *
1062 *******************************************************************************/
1063
1064 asm_getcallingmethod:
1065                 xorl    %eax,%eax
1066 /*              movl    $0,(%eax) */
1067                 ret
1068
1069 Java_java_lang_VMSecurityManager_currentClassLoader:
1070         lea  builtin_asm_getclassloader,%eax 
1071         push %eax       /*store collector function pointer*/
1072         jmp getClassContext_begin
1073 Java_java_lang_VMSecurityManager_getClassContext:
1074         lea  builtin_asm_createclasscontextarray,%eax 
1075         push %eax /*store collector function pointer*/
1076 getClassContext_begin:  /*start the real work*/
1077
1078         mov %esp,%eax
1079         sub $4,%eax
1080         sub $68,%esp /*64 memory location without overwriting return adress and collector function adress*/
1081         mov %esp,%ebx   /*end of allocated memory block for classpointers is the adress of the working data block +4 */
1082         push $0 /*%esp+32 was native*/
1083         push %eax /*%esp+24 blkbegin*/
1084         push %eax /*%esp+20 currentpos*/
1085         push %ebx /*%esp+16 blkend*/
1086
1087         call builtin_asm_get_threadrootmethod
1088         push %eax /*%esp+12*/
1089         movl 104(%esp),%eax /*(stack contains: threadRootMethod,blkend,blkpos,blkbegin,was native, data(64kB),collector,ret,env,class,frame stack info of stub, we want the frame stack info  of thestub*/
1090         movl %esp,%edx
1091         addl $116, %edx
1092         push %edx /*esp+8*/ /*position of return address of native stub*/
1093         call builtin_asm_get_stackframeinfo
1094         movl (%eax),%eax /*comment ??*/
1095         push 0(%eax) /*esp+4*/ /*address of frame info block*/
1096         movl 124(%esp),%edx
1097
1098 /*DEBUG*/
1099 /*      mov %esp,%eax
1100         addl $116,%eax
1101         push %eax
1102         call i386_native_stub_debug
1103         pop %eax*/
1104
1105         push %edx /*esp+0*/ /*return adress out of native stub*/
1106         call findmethod /*find calling java method, this one is still to be skipped (==SecurityManager.getClassContext (or .currentClassLoader)*/
1107
1108 /*DEBUGGING*/
1109 /*      push %eax
1110         movl MethodPointer(%eax),%eax
1111         push %eax
1112         call temporaryGetClassContextHelper
1113         pop %eax
1114         call traverseStackInfo
1115         pop %eax
1116 */
1117
1118         movl 20(%esp),%edx
1119         movl MethodPointer(%eax),%ebx
1120         movl offclassmethodinfo(%ebx),%ecx
1121         movl %ecx,(%edx)
1122         subl $4,%edx
1123         movl %edx,20(%esp)
1124
1125         mov 8(%esp),%ebx /*pos of return adress */
1126         add FrameSize(%eax),%ebx
1127         add $4,%ebx     /*adress of new return adress (out of Securitymanager.*/
1128         mov %ebx,8(%esp) 
1129         mov %eax,(%esp)
1130
1131         /* by now we have skipped this method call*/
1132
1133 getClassContext_next:   
1134         movl 8(%esp),%eax
1135         movl (%eax),%eax
1136         movl %eax,(%esp) /*return adress*/
1137
1138         call findmethod
1139
1140         cmp $1,32(%esp)
1141         mov 8(%esp),%ebx
1142         add FrameSize(%eax),%ebx
1143         add $4,%ebx
1144         mov %ebx,8(%esp) /*store adress of next return adress*/
1145 getClassContext_nextRetStored:
1146
1147         mov MethodPointer(%eax),%ecx    /*get struct methodinfo*/
1148
1149         cmp $0,%ecx
1150         je getClassContext_nativeCall
1151         /*save class pointer*/
1152         movl $0,32(%esp)
1153 getClassContext_saveClassPointer:
1154         movl 20(%esp),%ebx      /*get temporary memory adress in stack*/
1155         movl offclassmethodinfo(%ecx),%edx /* get class pointer of method*/
1156         movl %edx,(%ebx) /*save */
1157         sub $4,%ebx     /*calculate next position */
1158         movl %ebx,20(%esp) /* check if the new adress would overwrite our working data */
1159         cmp %ebx,16(%esp)
1160         je getClassContext_incStack
1161 getClassContext_checkLeave:
1162         
1163         cmp 12(%esp),%ecx       /*check if we reached the toplevel method of our thread*/
1164         je  getClassContext_leave /*yes ->leave*/
1165
1166 /*DEBUGING*/
1167 /*      mov %ecx,(%esp)
1168         call temporaryGetClassContextHelper
1169 */
1170         
1171         
1172         jmp getClassContext_next /*continue*/
1173
1174
1175 getClassContext_nativeCall:
1176         movl $1,32(%esp)
1177         movl 4(%esp),%eax       /*get top most element on stackframe help information stack*/
1178         movl 0(%eax),%ecx 
1179         movl %ecx,4(%esp)
1180         addl $8,%eax
1181         movl (%eax),%ecx
1182         addl $4,%eax
1183         movl %eax,8(%esp)
1184         
1185         cmp $0,%ecx
1186         je getClassContext_checkLeave
1187         jmp getClassContext_saveClassPointer
1188
1189 getClassContext_incStack:
1190         /*make another 64 in our temporary storage free and store the workingdata */
1191         movl %esp,%edx
1192         subl $40,%esp /*should be 32*/
1193         push 32(%edx)
1194         push 28(%edx)
1195         push 24(%edx)
1196         push 20(%edx)
1197         push 16(%edx)
1198         push 12(%edx)
1199         push 8(%edx)
1200         push 4(%edx)
1201         push 0(%edx)
1202         subl $64,16(%esp)
1203
1204         jmp getClassContext_checkLeave /* continue */
1205
1206 getClassContext_leave:
1207 /*DEBUGING*/
1208 /*      mov %ecx,(%esp)
1209         call temporaryGetClassContextHelper*/
1210
1211         /*call collector function with begin/end of temporary classarray*/
1212         push 24(%esp)
1213         push 24(%esp)
1214         
1215         movl 32(%esp),%eax
1216         add $4,%eax
1217         movl (%eax),%ebx
1218         call *%ebx
1219
1220         /* free stack memory of this function*/
1221         mov 32(%esp),%esp
1222         add $8,%esp
1223         ret
1224
1225
1226 asm_builtin_new:
1227 /*optimize a littlebit */
1228                 mov %esp,%eax
1229 /*DEBUG*/
1230 /*              push %eax
1231                 call i386_native_stub_debug
1232                 pop %eax */
1233
1234                 sub             $16,%esp                                 /* build stack frame (4 * 4 bytes) */
1235
1236                 mov             20(%esp),%eax
1237                 mov             %eax,(%esp)
1238
1239                 call    builtin_asm_get_stackframeinfo
1240                 movl    $0,12(%esp)
1241                 mov     %eax,8(%esp)
1242                 mov     (%eax),%ebx
1243                 mov     %ebx,4(%esp)
1244                 mov     %esp,%ecx
1245                 add     $4,%ecx
1246                 mov     %ecx,(%eax)
1247
1248                 call    builtin_new
1249
1250                 mov     4(%esp),%ebx
1251                 mov     8(%esp),%ecx
1252                 mov     %ebx,(%ecx)
1253
1254                 add             $16,%esp
1255                 ret
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268 asm_get_stackTrace:
1269         push %ebp /*(%ebp-4)*/
1270         mov %esp,%ebp
1271         add $4,%ebp
1272         push %edi /*(%ebp-8)*/
1273         push %esi /*(%ebp-12)*/
1274         push %ebx /*(%ebp-16)*/
1275         call builtin_asm_get_stackframeinfo
1276         movl (%eax),%eax
1277         pushl 0(%eax) /*(%ebp-20)*/
1278         lea 12(%eax),%edi
1279         call builtin_asm_get_threadrootmethod
1280         pushl %eax /*(%ebp-24)*/
1281
1282         pushl (%edi)
1283 asm_get_stackTraceLoop:
1284         call findmethod
1285         mov %eax,%esi
1286         add $4,%esp
1287         pushl $1 /*no indent*/
1288
1289         mov (%edi),%edx
1290         sub $4,%edx
1291
1292 get_stackTrace_line:
1293         movl LineNumberTableSize(%esi),%ecx
1294         test    %ecx,%ecx /* skip if empty line table */
1295         je      get_stackTrace_noLineInfo
1296
1297         movl LineNumberTableStart(%esi),%ebx
1298         
1299 get_stackTrace_lineLoop:
1300         cmp %edx,LinePC(%ebx)
1301         jg get_stackTrace_nextLineInfo
1302
1303         pushl LineLine(%ebx)
1304         jmp get_stackTrace_cont
1305
1306 get_stackTrace_nextLineInfo:    
1307         lea LineEntrySize(%ebx),%ebx
1308         dec %ecx
1309         test %ecx,%ecx
1310
1311         jne get_stackTrace_lineLoop
1312
1313 get_stackTrace_noLineInfo:
1314         pushl $0
1315
1316
1317 get_stackTrace_cont:
1318         pushl (%edi) /*4*/
1319         pushl MethodPointer(%esi)
1320         pushl $0 /*8(%ebp)*/ /*exception ptr*/
1321         call builtin_trace_exception
1322         add $12,%esp
1323
1324         movl MethodPointer(%esi),%eax
1325         movl %eax,4(%esp)
1326         test %eax,%eax
1327         je get_stackTrace_nat
1328
1329         cmp %eax,-24(%ebp)
1330         je get_stackTrace_leave
1331
1332         mov FrameSize(%esi),%eax
1333         add $4,%edi
1334         add %eax,%edi
1335         pushl (%edi)
1336         jmp asm_get_stackTraceLoop
1337
1338 get_stackTrace_nat:
1339         add $8,%esp
1340         movl -20(%ebp),%eax
1341         cmp $0,%eax
1342         je get_stackTrace_leave
1343         movl  0(%eax),%ebx
1344         movl  %ebx,-20(%ebp)
1345         pushl 8(%eax)
1346         pushl $0
1347         lea 12(%eax),%edi
1348         pushl (%edi)
1349         jmp asm_get_stackTraceLoop
1350
1351 get_stackTrace_leave:
1352         mov %esp,%eax
1353         lea -24(%ebp),%ebx
1354         push %ebx
1355         push %eax
1356         push 4(%ebp)
1357         call builtin_stacktrace_copy
1358
1359         lea -16(%ebp),%esp
1360         pop %ebx
1361         pop %esi
1362         pop %edi
1363         pop %ebp
1364         ret
1365
1366 /*
1367  * These are local overrides for various environment variables in Emacs.
1368  * Please do not remove this and leave it at the end of the file, where
1369  * Emacs will automagically detect them.
1370  * ---------------------------------------------------------------------
1371  * Local variables:
1372  * mode: asm
1373  * indent-tabs-mode: t
1374  * c-basic-offset: 4
1375  * tab-width: 4
1376  * End:
1377  */