Fixes Debian bug #350729
[cacao.git] / src / vm / jit / i386 / asmpart.S
1 /* src/vm/jit/i386/asmpart.S - Java-C interface functions for i386
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28             Reinhard Grafl
29             Christian Thalinger
30
31    Changes: Joseph Wenninger
32
33    $Id: asmpart.S 4392 2006-01-31 15:35:22Z twisti $
34
35 */
36
37
38 #include "config.h"
39
40 #include "vm/jit/abi.h"
41 #include "vm/jit/i386/md-abi.h"
42 #include "vm/jit/i386/md-asm.h"
43 #include "vm/jit/i386/offsets.h"
44
45 #include "vm/jit/methodheader.h"
46
47
48         .text
49
50
51 /* exported functions and variables *******************************************/
52
53         .globl asm_md_init
54
55         .globl asm_calljavafunction
56         .globl asm_calljavafunction_int
57
58         .globl asm_calljavafunction2
59         .globl asm_calljavafunction2int
60         .globl asm_calljavafunction2long
61         .globl asm_calljavafunction2float
62         .globl asm_calljavafunction2double
63
64         .globl asm_call_jit_compiler
65         .globl asm_handle_nat_exception
66         .globl asm_handle_exception
67
68         .globl asm_wrapper_patcher
69
70         .globl asm_builtin_f2i
71         .globl asm_builtin_f2l
72         .globl asm_builtin_d2i
73         .globl asm_builtin_d2l
74
75         .globl asm_perform_threadswitch
76         .globl asm_initialize_thread_stack
77         .globl asm_switchstackandcall
78         .globl asm_criticalsections
79         .globl asm_getclassvalues_atomic
80
81
82 /* asm_md_init *****************************************************************
83
84    Initialize machine dependent stuff.
85
86    See: http://www.srware.com/linux_numerics.txt
87
88    This puts the X86 FPU in 64-bit precision mode.  The default under
89    Linux is to use 80-bit mode, which produces subtle differences from
90    FreeBSD and other systems, eg, (int)(1000*atof("0.3")) is 300 in
91    64-bit mode, 299 in 80-bit mode.
92
93    Fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=350729
94
95 *******************************************************************************/
96
97 asm_md_init:
98         sub     $4,sp                       /* allocate space for the FPU state   */
99         fnstcw  (sp)                        /* get the FPU state                  */
100         mov     (sp),%eax
101         and     $0xfcff,%ax                 /* remove the extended mode flag      */
102         or      $0x0200,%ax                 /* put the double mode flag           */
103         mov     %eax,(sp)                   /* store new FPU state                */
104         fldcw   (sp)                        /* setup new FPU state                */
105         add     $4,sp
106         ret
107
108
109 /********************* function asm_calljavafunction ***************************
110 *                                                                              *
111 *   This function calls a Java-method (which possibly needs compilation)       *
112 *   with up to 4 address parameters.                                           *
113 *                                                                              *
114 *   This functions calls the JIT-compiler which eventually translates the      *
115 *   method into machine code.                                                  *
116 *                                                                              *
117 *   C-prototype:                                                               *
118 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
119 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
120 *                                                                              *
121 *******************************************************************************/
122
123         .align  8
124
125         .long   0                           /* catch type all                     */
126         .long   calljava_xhandler           /* handler pc                         */
127         .long   calljava_xhandler           /* end pc                             */
128         .long   asm_calljavafunction        /* start pc                           */
129         .long   1                           /* extable size                       */
130         .long   0                           /* line number table start            */
131         .long   0                           /* line number table size             */
132         .long   0                           /* fltsave                            */
133         .long   0                           /* intsave                            */
134         .long   0                           /* isleaf                             */
135         .long   0                           /* IsSync                             */
136         .long   0                           /* frame size                         */
137         .long   0                           /* method pointer (pointer to name)   */
138
139 asm_calljavafunction:
140 asm_calljavafunction_int:
141         push    bp                          /* allocate stack space               */
142         mov     sp,bp
143
144         push    %ebx                        /* save registers                     */
145         push    %esi
146         push    %edi
147
148         sub             $(4*4),sp                   /* 4 adress parameters * 4 Bytes      */
149         mov     5*4(bp),itmp1               /* copy adress parameters to new block*/
150         mov     itmp1,3*4(sp)
151                 
152         mov     5*4(bp),itmp1
153         mov     itmp1,2*4(sp)
154
155         mov     4*4(bp),itmp1
156         mov     itmp1,1*4(sp)
157
158         mov     3*4(bp),itmp1
159         mov     itmp1,0*4(sp)
160                 
161         mov     2*4(bp),itmp1               /* move function pointer to %eax      */
162
163         lea     asm_call_jit_compiler,itmp3
164         call    *itmp3                      /* call JIT compiler                  */
165
166 L_asm_calljavafunction_return:
167         add     $(4*4),sp
168         pop     %edi                        /* restore registers                  */
169         pop     %esi
170         pop     %ebx
171         leave
172         ret
173
174 calljava_xhandler:
175         push    xptr                        /* pass exception pointer             */
176         call    builtin_throw_exception
177         add     $4,sp
178         xor     v0,v0                       /* return NULL                        */
179         jmp     L_asm_calljavafunction_return
180
181
182 /********************* function asm_calljavafunction ***************************
183 *                                                                              *
184 *   This function calls a Java-method (which possibly needs compilation)       *
185 *   with up to 4 address parameters.                                           *
186 *                                                                              *
187 *   This functions calls the JIT-compiler which eventually translates the      *
188 *   method into machine code.                                                  *
189 *                                                                              *
190 *   C-prototype:                                                               *
191 *    javaobject_header *asm_calljavafunction2(methodinfo *m,                   *
192 *         u4 count, u4 size, void *callblock);                                 *
193 *                                                                              *
194 *******************************************************************************/
195
196         .align  8
197
198         .long   0                           /* catch type all                     */
199         .long   calljava_xhandler2          /* handler pc                         */
200         .long   calljava_xhandler2          /* end pc                             */
201         .long   asm_calljavafunction2       /* start pc                           */
202         .long   1                           /* extable size                       */
203         .long   0                           /* line number table start            */
204         .long   0                           /* line number table size             */
205         .long   0                           /* fltsave                            */
206         .long   0                           /* intsave                            */
207         .long   0                           /* isleaf                             */
208         .long   0                           /* IsSync                             */
209         .long   0                           /* frame size                         */
210         .long   0                           /* method pointer (pointer to name)   */
211
212 asm_calljavafunction2:
213 asm_calljavafunction2int:
214 asm_calljavafunction2long:
215 asm_calljavafunction2float:
216 asm_calljavafunction2double:
217         push    %ebp
218         mov     %esp,%ebp                 /* save stackptr                        */
219
220         push    %ebx                      /* save registers                       */
221         push    %esi
222         push    %edi
223
224         mov     20(%ebp),%eax             /* pointer to arg block (4(push)+4(return)+4+4+4)*/
225         mov     12(%ebp),%ecx             /* arg count            (4(push)+4(return)+4     */
226
227         xor     %esi,%esi                 /* clear stackframe size (MUST be       */
228                                           /* before args check, may be zero!!!)   */
229         test    %ecx,%ecx                 /* maybe we have no args                */
230         jle     calljava_copydone
231
232         mov     %ecx,%edx                 /* calculate stack size                 */
233         mov     %eax,%edi                 /* save pointer to arg block            */
234
235 calljava_calcstacksize:
236         mov     offjniitemtype(%eax),%ebx
237         test    $1,%ebx                   /* two word type?                       */
238         jz      calljava_onewordtype
239         add     $4,%esi                   /* add 1 slot to stackframe size        */
240
241 calljava_onewordtype:
242         add     $4,%esi                   /* add 1 slot to stackframe size        */
243         sub     $1,%edx
244         test    %edx,%edx                 /* any args left?                       */
245         jz      calljava_setstack
246         add     $sizejniblock,%eax        /* goto next argument block             */
247         jmp     calljava_calcstacksize
248                 
249 calljava_setstack:                              
250         mov     %edi,%eax                 /* restore pointer to arg block         */
251         sub     %esi,%esp                 /* create stackframe for arguments      */
252         mov     %esp,%edi                 /* move stackpointer into temp variable */
253
254 calljava_copyloop:
255         mov     offjniitem(%eax),%edx     /* copy 4 Byte of Argument              */
256         mov     %edx,(%edi)
257         add     $4,%edi                   /* increase sp to next argument         */
258         mov     offjniitemtype(%eax),%ebx /* type -> ebx                          */
259         test    $1,%ebx                   /* Two Word Type?                       */
260         jz      calljava_copynext
261
262         mov     offjniitem+4(%eax),%edx   /* copy upper 4 Byte of 2 Word Type     */
263         mov     %edx,(%edi)                     
264         add     $4,%edi                   /* increase sp to next argument         */
265
266 calljava_copynext:              
267         sub     $1,%ecx                   /* are there any args left?             */
268         test    %ecx,%ecx
269         jle     calljava_copydone
270
271         add     $sizejniblock,%eax        /* goto next argument block             */
272         jmp     calljava_copyloop
273
274 calljava_copydone:
275         mov     8(%ebp),%eax              /* move function pointer to %eax        */
276
277         lea     asm_call_jit_compiler,itmp3
278         call    *itmp3                      /* call JIT compiler                  */
279
280 L_asm_calljavafunction2_return:
281         add     %esi,%esp                   /* remove arg stack frame             */
282         pop     %edi                        /* restore registers                  */
283         pop     %esi
284         pop     %ebx
285         leave
286         ret
287
288 calljava_xhandler2:
289         push    xptr                        /* pass exception pointer             */
290         call    builtin_throw_exception
291         add     $4,sp
292         xor     v0,v0                       /* return NULL                        */
293         jmp     L_asm_calljavafunction2_return
294
295
296 /****************** function asm_call_jit_compiler *****************************
297 *                                                                              *
298 *   invokes the compiler for untranslated JavaVM methods.                      *
299 *                                                                              *
300 *   Register R0 contains a pointer to the method info structure (prepared      *
301 *   by createcompilerstub). Using the return address in R26 and the            *
302 *   offset in the LDA instruction or using the value in methodptr R28 the      *
303 *   patching address for storing the method address can be computed:           *
304 *                                                                              *
305 *   method address was either loaded using                                     *
306 *                                                                              *
307 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
308 *   i386_call_reg(REG_ITMP2)                                                   *
309 *                                                                              *
310 *   or                                                                         *
311 *                                                                              *
312 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP1)    ; invokevirtual/interface    *
313 *   i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)                *
314 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \                *
315 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
316 *   i386_call_reg(REG_ITMP1)                                                   *
317 *                                                                              *
318 *   in the static case the method pointer can be computed using the            *
319 *   return address and the lda function following the jmp instruction          *
320 *                                                                              *
321 *******************************************************************************/
322
323 asm_call_jit_compiler:
324         sub     $((4+2)*4+sizestackframeinfo),sp /* create stack frame            */
325         mov     itmp1,(4+0)*4(sp)           /* save method pointer                */
326                         
327         mov     (4+2)*4+sizestackframeinfo(sp),itmp3 /* get return address        */
328         mov     -1(itmp3),itmp1b            /* get function code                  */
329         cmp     $0xd1,itmp1b                /* called with `call *REG_ITMP2'?     */
330         jne             L_not_static_special
331
332         sub     $6,itmp3                    /* calculate address of immediate     */
333         jmp             L_call_jit_compile
334                 
335 L_not_static_special:
336         cmp     $0xd0,itmp1b                /* called with `call *REG_ITMP1'      */
337         jne             L_not_virtual_interface
338         
339         sub     $6,itmp3                    /* calculate address of offset        */
340         mov     (itmp3),itmp3               /* get offset                         */
341         add     itmp2,itmp3                 /* add base address to get method adr */
342         jmp             L_call_jit_compile
343
344 L_not_virtual_interface:
345         xor     itmp3,itmp3                 /* a call from asm_calljavafunction   */
346                 
347 L_call_jit_compile:
348         mov     itmp3,(4+1)*4(sp)           /* save address for method pointer    */
349
350         mov     sp,itmp1                    /* create stackframe info             */
351         add     $((4+2)*4),itmp1
352         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
353         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
354         mov     sp,itmp2
355         add     $((1+4+2)*4+sizestackframeinfo),itmp2 /* pass java sp             */
356         mov     itmp2,2*4(sp)
357         mov     ((0+4+2)*4+sizestackframeinfo)(sp),itmp3 /* pass java ra          */
358         mov     itmp3,3*4(sp)
359         call    stacktrace_create_inline_stackframeinfo
360
361         mov     (4+0)*4(sp),itmp1           /* pass method pointer                */
362         mov     itmp1,0*4(sp)
363         call    jit_compile
364         mov     v0,(4+0)*4(sp)              /* save return value                  */
365
366         mov     sp,itmp1                    /* remove stackframe info             */
367         add     $((4+2)*4),itmp1
368         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
369         call    stacktrace_remove_stackframeinfo
370
371         mov     (4+0)*4(sp),v0              /* restore return value               */
372         mov     (4+1)*4(sp),itmp3           /* restore address for method pointer */
373
374         add     $((4+2)*4+sizestackframeinfo),sp /* remove stack frame            */
375
376         test    v0,v0                       /* check for exception                */
377         je      L_asm_call_jit_compiler_exception
378
379         test    itmp3,itmp3                 /* was this a JIT call?               */
380         je              L_call_method
381         
382         mov     v0,(itmp3)                  /* save the new method pointer        */
383
384 L_call_method:
385         jmp             *v0                         /* ...and now call the new method     */
386
387 L_asm_call_jit_compiler_exception:
388 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
389         call    builtin_asm_get_exceptionptrptr
390         mov     v0,itmp2                    /* v0 == itmp1                        */
391 #else
392         lea     _exceptionptr,itmp2
393 #endif
394         mov     (itmp2),xptr                /* get the exception pointer          */
395         movl    $0,(itmp2)                  /* clear the exception pointer        */
396
397         pop     xpc                         /* get return address                 */
398         sub     $2,xpc                      /* faulting address is ra - 2         */
399         jmp     asm_handle_exception
400
401
402 /* asm_handle_exception ********************************************************
403 *                                                                              *
404 *   This function handles an exception. It does not use the usual calling      *
405 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
406 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
407 *   the local exception table for a handler. If no one is found, it unwinds    *
408 *   stacks and continues searching the callers.                                *
409 *                                                                              *
410 *******************************************************************************/
411
412 asm_handle_nat_exception:
413         add     $4,sp                       /* clear return address of native stub*/
414                 
415 asm_handle_exception:
416         sub     $((ARG_CNT+TMP_CNT)*4),sp   /* create maybe-leaf stackframe       */
417
418         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
419         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
420
421         mov     $((ARG_CNT+TMP_CNT)*4),itmp3/* prepare a3 for handle_exception    */
422         mov     $1,t0                       /* set maybe-leaf flag                */
423
424 L_asm_handle_exception_stack_loop:
425         sub     $(10*4),sp                  /* create stackframe                  */
426         mov     xptr,4*4(sp)                /* save exception pointer             */
427         mov     xpc,5*4(sp)                 /* save exception pc                  */
428         add     sp,itmp3                    /* calculate Java sp into a3...       */
429         add     $(10*4),itmp3
430         mov     itmp3,7*4(sp)               /* ...and save it                     */
431         mov     t0,8*4(sp)                  /* save maybe-leaf flag               */
432
433         mov     xpc,0*4(sp)                 /* pass exception pc                  */
434         call    codegen_findmethod
435         mov     v0,6*4(sp)                  /* save data segment pointer          */
436
437         mov     4*4(sp),itmp3               /* pass exception pointer             */
438         mov     itmp3,0*4(sp)
439         mov     5*4(sp),itmp3               /* pass exception pc                  */
440         mov     itmp3,1*4(sp)
441         mov     v0,2*4(sp)                  /* pass data segment pointer          */
442         mov     7*4(sp),itmp3               /* pass Java stack pointer            */
443         mov     itmp3,3*4(sp)
444         call    exceptions_handle_exception
445
446         test    v0,v0
447         jz      L_asm_handle_exception_not_catched
448
449         mov     v0,xpc                      /* move handlerpc into xpc            */
450         mov     4*4(sp),xptr                /* restore exception pointer          */
451         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
452         add     $(10*4),sp                  /* free stackframe                    */
453
454         test    t0,t0                       /* test for maybe-leaf flag           */
455         jz      L_asm_handle_exception_no_leaf
456
457         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
458         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
459
460         add     $((ARG_CNT+TMP_CNT)*4),sp   /* remove maybe-leaf stackframe       */
461
462 L_asm_handle_exception_no_leaf:
463         jmp     *xpc                        /* jump to exception handler          */
464
465 L_asm_handle_exception_not_catched:
466         mov     4*4(sp),xptr                /* restore exception pointer          */
467         mov     6*4(sp),itmp3               /* restore data segment pointer       */
468         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
469         add     $(10*4),sp                  /* free stackframe                    */
470
471         test    t0,t0
472         jz      L_asm_handle_exception_no_leaf_stack
473
474         add     $((ARG_CNT+TMP_CNT)*4),sp   /* remove maybe-leaf stackframe       */
475         xor     t0,t0                       /* clear the maybe-leaf flag          */
476
477 L_asm_handle_exception_no_leaf_stack:
478         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
479         add     sp,itmp2                    /* pointer to save area               */
480
481         push    xptr                        /* we are out of registers            */
482
483         mov     IntSave(itmp3),itmp1        /* itmp1 = saved int register count   */
484         test    itmp1,itmp1
485         je      noint
486
487         cmp     $1,itmp1
488         je      int1
489         cmp     $2,itmp1
490         je      int2
491
492         mov     -3*4(itmp2),s0
493 int2:   
494         mov     -2*4(itmp2),s1
495 int1:   
496         mov     -1*4(itmp2),s2
497
498         shl     $2,itmp1                    /* multiply by 4 bytes                */
499         sub     itmp1,itmp2
500                 
501 noint:
502 #if 0
503         mov     FltSave(itmp3),itmp1        /* itmp1 = saved flt register count   */
504         test    itmp1,itmp1
505         je      noflt
506
507         cmp     $1,itmp1
508         je      flt1
509         cmp     $2,itmp1
510         je      flt2
511         cmp     $3,itmp1
512         je      flt3
513                 
514         fldl    -4*8(itmp2)
515         fstp    %st(1)
516 flt3:
517         fldl    -3*8(itmp2)
518         fstp    %st(2)
519 flt2:
520         fldl    -2*8(itmp2)
521         fstp    %st(3)
522 flt1:
523         fldl    -1*8(itmp2)
524         fstp    %st(4)
525                 
526 noflt:
527 #endif
528         pop     xptr                        /* restore exception pointer          */
529         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
530         add     itmp2,sp                    /* unwind stack                       */
531
532         pop     xpc                         /* the new xpc is return address      */
533         sub     $2,xpc                      /* subtract 2-bytes for call          */
534
535         xor     itmp3,itmp3                 /* prepare a3 for handle_exception    */
536
537         jmp     L_asm_handle_exception_stack_loop
538                 
539
540 /* asm_wrapper_patcher *********************************************************
541
542    XXX
543
544    Stack layout:
545      20   return address
546      16   pointer to virtual java_objectheader
547      12   last byte of machine code (xmcode)
548       8   machine code (which is patched back later)
549       4   unresolved field reference
550       0   patcher function pointer to call
551
552 *******************************************************************************/
553
554 asm_wrapper_patcher:
555         sub     $((2+4)*4+sizestackframeinfo),sp /* create stack frame            */
556
557         mov     itmp1,(0+4)*4(sp)           /* save itmp1 and itmp2               */
558         mov     itmp2,(1+4)*4(sp)           /* may be used by some instructions   */
559
560         mov     sp,itmp1                    /* create stackframe info             */
561         add     $((2+4)*4),itmp1
562         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
563         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
564         mov     sp,itmp2
565         add     $((6+2+4)*4+sizestackframeinfo),itmp2
566         mov     itmp2,2*4(sp)
567         mov     ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
568         mov     itmp3,3*4(sp)
569         call    stacktrace_create_inline_stackframeinfo
570
571         mov     sp,itmp1                    /* pass stack pointer                 */
572         add     $((1+2+4)*4+sizestackframeinfo),itmp1  /* skip function pointer   */
573         mov     itmp1,0*4(sp)
574         mov     (0+2+4)*4+sizestackframeinfo(sp),itmp1 /* get function pointer    */
575         call    *itmp1                      /* call the patcher function          */
576         mov     v0,1*4(sp)                  /* save return value                  */
577
578         mov     sp,itmp1                    /* remove stackframe info             */
579         add     $((2+4)*4),itmp1
580         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
581         call    stacktrace_remove_stackframeinfo
582
583         mov     (0+4)*4(sp),itmp1           /* restore itmp1 and itmp2            */
584         mov     (1+4)*4(sp),itmp2           /* may be used by some instructions   */
585         mov     1*4(sp),itmp3               /* restore return value               */
586
587         add     $((5+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
588         test    itmp3,itmp3                 /* exception thrown?                  */
589         jz      L_asm_wrapper_patcher_exception
590         ret                                 /* call new patched code              */
591
592 L_asm_wrapper_patcher_exception:
593 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
594         call    builtin_asm_get_exceptionptrptr
595         mov     v0,itmp2
596 #else
597         lea     _exceptionptr,itmp2
598 #endif
599         mov     (itmp2),xptr                /* get the exception pointer          */
600         movl    $0,(itmp2)                  /* clear the exception pointer        */
601
602         pop     xpc                         /* get and remove return address      */
603         jmp     asm_handle_exception
604
605
606 /************************ function asm_builtin_x2x *****************************
607 *                                                                              *
608 *   Wrapper functions for corner cases                                         *
609 *                                                                              *
610 *******************************************************************************/
611
612 asm_builtin_f2i:
613         sub     $4,%esp
614         fsts    (%esp)
615         call    builtin_f2i
616         add     $4,%esp
617         ret
618
619 asm_builtin_d2i:
620         sub     $8,%esp
621         fstl    (%esp)
622         call    builtin_d2i
623         add     $8,%esp
624         ret
625
626 asm_builtin_f2l:
627         sub     $4,%esp
628         fsts    (%esp)
629         call    builtin_f2l
630         add     $4,%esp
631         ret
632
633 asm_builtin_d2l:
634         sub     $8,%esp
635         fstl    (%esp)
636         call    builtin_d2l
637         add     $8,%esp
638         ret
639
640
641 /******************* function asm_initialize_thread_stack **********************
642 *                                                                              *
643 * initialized a thread stack                                                   *
644 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
645 *                                                                              *
646 *******************************************************************************/
647
648 asm_initialize_thread_stack:
649                 mov             8(%esp),%eax            /* (to)->stackEnd                     */
650                 sub             $36,%eax                /* 4 bytes * 8 regs + 4 bytes func    */
651                                 
652                 xor             %edx,%edx
653                 mov             %edx,0(%eax)
654                 mov             %edx,4(%eax)
655                 mov             %edx,8(%eax)
656                 mov             %edx,12(%eax)
657                 mov             %edx,16(%eax)
658                 mov             %edx,20(%eax)
659                 mov     %edx,24(%eax)
660                 mov     %edx,28(%eax)
661                                 
662                 mov     4(%esp),%edx            /* save (u1*) (func)                  */
663                 mov     %edx,32(%eax)
664
665                 ret                             /* return restorepoint in %eax        */
666
667
668 /******************* function asm_perform_threadswitch *************************
669 *                                                                              *
670 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
671 *                                                                              *
672 *   performs a threadswitch                                                    *
673 *                                                                              *
674 *******************************************************************************/
675
676 asm_perform_threadswitch:
677         sub     $36,%esp
678            
679         mov     %eax,0(%esp)
680         mov     %ecx,4(%esp)
681         mov     %edx,8(%esp)
682         mov     %ebx,12(%esp)
683         mov     %esp,16(%esp)
684         mov     %ebp,20(%esp)
685         mov     %esi,24(%esp)
686         mov     %edi,28(%esp)
687            
688         mov     36(%esp),%eax         /* save current return address              */
689         mov     %eax,32(%esp)
690            
691         mov     40(%esp),%eax         /* first argument **from                    */
692         mov     %esp,0(%eax)
693            
694         mov     48(%esp),%eax         /* third argument **stackTop                */
695         mov     %esp,0(%eax)
696            
697         mov     44(%esp),%eax         /* second argument **to                     */
698         mov     0(%eax),%esp          /* load new stack pointer                   */
699            
700         mov     0(%esp),%eax
701         mov     4(%esp),%ecx
702         mov     8(%esp),%edx
703         mov     12(%esp),%ebx
704                                       /* skip stack pointer                       */
705         mov     20(%esp),%ebp
706         mov     24(%esp),%esi
707         mov     28(%esp),%edi
708            
709         add     $32,%esp              /* leave return address on stack            */
710         ret
711                 
712
713 /********************* function asm_switchstackandcall *************************
714 *                                                                              *
715 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
716 *                                      void *p);                                       *
717 *                                                                              *
718 *   Switches to a new stack, calls a function and switches back.               *
719 *       a0      new stack pointer                                              *
720 *       a1      function pointer                                               *
721 *               a2              pointer to variable where stack top should be stored           *
722 *       a3      pointer to user data, is passed to the function                *
723 *                                                                              *
724 *******************************************************************************/
725
726 asm_switchstackandcall:
727         mov     4(%esp),%edx          /* first argument *stack                    */
728         sub     $8,%edx               /* allocate new stack                       */
729
730         mov     (%esp),%eax           /* save return address on new stack         */
731         mov     %eax,(%edx)
732
733         mov     %esp,4(%edx)          /* save old stack pointer on new stack      */
734
735         mov     12(%esp),%eax         /* third argument **stacktopsave            */
736         mov     %esp,(%eax)           /* save old stack pointer to variable       */
737
738         mov     8(%esp),%eax          /* load function pointer                    */
739         mov     16(%esp),%ecx         /* fourth argument *p                       */
740         
741         mov     %edx,%esp             /* switch to new stack                      */
742
743         sub     $4,%esp
744         mov     %ecx,0(%esp)          /* pass pointer                             */
745         call    *%eax                 /* and call function                        */
746         add     $4,%esp
747
748         mov     (%esp),%edx           /* load return address                      */
749         mov     4(%esp),%esp          /* switch to old stack                      */
750         mov     %edx,(%esp)
751         ret
752
753                 
754 asm_getclassvalues_atomic:
755 _crit_restart2:
756         mov     4(%esp),%ecx        /* super */
757         mov     8(%esp),%edx        /* sub */
758 _crit_begin2:
759         mov     offbaseval(%ecx),%eax
760         mov     offdiffval(%ecx),%ecx
761         mov     offbaseval(%edx),%edx
762 _crit_end2:
763         push    %ebx
764         mov     16(%esp),%ebx      /* out */
765         mov     %eax,offcast_super_baseval(%ebx)
766         mov     %ecx,offcast_super_diffval(%ebx)
767         mov     %edx,offcast_sub_baseval(%ebx)
768         pop     %ebx
769         ret
770
771         .data
772
773 asm_criticalsections:
774 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
775 #if 0
776         .long   _crit_begin1
777         .long   _crit_end1
778         .long   _crit_restart1
779 #endif
780         .long   _crit_begin2
781         .long   _crit_end2
782         .long   _crit_restart2
783 #endif
784         .long 0
785
786
787 /*
788  * These are local overrides for various environment variables in Emacs.
789  * Please do not remove this and leave it at the end of the file, where
790  * Emacs will automagically detect them.
791  * ---------------------------------------------------------------------
792  * Local variables:
793  * mode: asm
794  * indent-tabs-mode: t
795  * c-basic-offset: 4
796  * tab-width: 4
797  * End:
798  */