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