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