Commit | Line | Data |
---|---|---|
8f99e3f3 SJ |
1 | ;; i386.asm -- assembly support. |
2 | ||
3 | ;; | |
4 | ;; QuickThreads -- Threads-building toolkit. | |
6e7d5622 | 5 | ;; Copyright (c) 2001, 2006 Free Software Foundation, Inc. |
8f99e3f3 SJ |
6 | ;; |
7 | ;; Permission to use, copy, modify and distribute this software and | |
8 | ;; its documentation for any purpose and without fee is hereby | |
9 | ;; granted, provided that the above copyright notice and this notice | |
10 | ;; appear in all copies. This software is provided as a | |
11 | ;; proof-of-concept and for demonstration purposes; there is no | |
12 | ;; representation about the suitability of this software for any | |
13 | ;; purpose. | |
14 | ||
15 | ;; NOTE: double-labeled `_name' and `name' for System V compatability. | |
16 | ;; NOTE: Comment lines start like this one, or with '//' ONLY. Sorry! | |
17 | ||
18 | ;; Callee-save: %esi, %edi, %ebx, %ebp | |
19 | ;; Caller-save: %eax, %ecx | |
20 | ;; Can't tell: %edx (seems to work w/o saving it.) | |
21 | ;; | |
22 | ;; Assignment: | |
23 | ;; | |
24 | ;; See ``i386.h'' for the somewhat unconventional stack layout. | |
25 | ||
26 | ||
27 | .386p | |
28 | .model flat | |
29 | .code | |
30 | ||
31 | public _qt_abort | |
32 | public qt_abort | |
33 | public _qt_block | |
34 | public qt_block | |
35 | public _qt_blocki | |
36 | public qt_blocki | |
37 | ||
38 | ;; These all have the type signature | |
39 | ;; | |
40 | ;; void *blocking (helper, arg0, arg1, new) | |
41 | ;; | |
42 | ;; On procedure entry, the helper is at 4(sp), args at 8(sp) and | |
43 | ;; 12(sp) and the new thread's sp at 16(sp). It *appears* that the | |
44 | ;; calling convention for the 8X86 requires the caller to save all | |
45 | ;; floating-point registers, this makes our life easy. | |
46 | ||
47 | ;; Halt the currently-running thread. Save it's callee-save regs on | |
48 | ;; to the stack, 32 bytes. Switch to the new stack (next == 16+32(sp)) | |
49 | ;; and call the user function (f == 4+32(sp) with arguments: old sp | |
50 | ;; arg1 (8+32(sp)) and arg2 (12+32(sp)). When the user function is | |
51 | ;; done, restore the new thread's state and return. | |
52 | ;; | |
53 | ;; `qt_abort' is (currently) an alias for `qt_block' because most of | |
54 | ;; the work is shared. We could save the insns up to `qt_common' by | |
55 | ;; replicating, but w/o replicating we need an inital subtract (to | |
56 | ;; offset the stack as if it had been a qt_block) and then a jump | |
57 | ;; to qt_common. For the cost of a jump, we might as well just do | |
58 | ;; all the work. | |
59 | ;; | |
60 | ;; The helper function (4(sp)) can return a void* that is returned | |
61 | ;; by the call to `qt_blockk{,i}'. Since we don't touch %eax in | |
62 | ;; between, we get that ``for free''. | |
63 | ||
64 | _qt_abort: | |
65 | qt_abort: | |
66 | _qt_block: | |
67 | qt_block: | |
68 | _qt_blocki: | |
69 | qt_blocki: | |
70 | push ebp ; Save callee-save, sp-=4. | |
71 | push esi ; Save callee-save, sp-=4. | |
72 | push edi ; Save callee-save, sp-=4. | |
73 | push ebx ; Save callee-save, sp-=4. | |
74 | mov eax, esp ; Remember old stack pointer. | |
75 | ||
76 | qt_common: | |
77 | mov esp, [esp+32] ; Move to new thread. | |
78 | push [eax+28] ; Push arg 2. | |
79 | push [eax+24] ; Push arg 1. | |
80 | push eax ; Push arg 0. | |
81 | mov ebx, [eax+20] ; Get function to call. | |
82 | call ebx ; Call f. | |
83 | add esp, 12 ; Pop args. | |
84 | ||
85 | pop ebx ; Restore callee-save, sp+=4. | |
86 | pop edi ; Restore callee-save, sp+=4. | |
87 | pop esi ; Restore callee-save, sp+=4. | |
88 | pop ebp ; Restore callee-save, sp+=4. | |
89 | ret ; Resume the stopped function. | |
90 | hlt | |
91 | ||
92 | ||
93 | ;; Start a varargs thread. | |
94 | ||
95 | public _qt_vstart | |
96 | public qt_vstart | |
97 | ||
98 | _qt_vstart: | |
99 | qt_vstart: | |
100 | push edi ; Push `pt' arg to `startup'. | |
101 | call ebp ; Call `startup'. | |
102 | pop eax ; Clean up the stack. | |
103 | ||
104 | call ebx ; Call the user's function. | |
105 | ||
106 | push eax ; Push return from user's. | |
107 | push edi ; Push `pt' arg to `cleanup'. | |
108 | call esi ; Call `cleanup'. | |
109 | ||
110 | hlt ; `cleanup' never returns. | |
111 | ||
112 | end |