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