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