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