source: release/1.9/source/lisp-kernel/x86-asmutils32.s @ 16083

Last change on this file since 16083 was 15500, checked in by gb, 7 years ago

Try to clean up code which uses CMPXCHG: imm0 should contain the expected
value (which may or may not be the current value, as of a few cycles before
the CMPXCHG ...). In general, we don't need or want to repeat the CMPXCHG
in order to do a conditional store (failures aren't transient). In cases
where we repeat a CMPXCHG in a loop, ensure that the loop contains a PAUSE
instruction to work correctly with hyperthreading.

Change the x86 pc_luser_xp() to account for changes in
_SPstore_node_conditional and _SPset_hash_key_conditional.

Introduce a WITH-EXCEPTION-LOCK macro; refactor
%LOCK-RECURSIVE-LOCK-OBJECT and friends so that we can lock/unlock a
kernel lock (with no lisp LOCK object around it) without having to
call into the kernel. RECURSIVE-LOCK-WHOSTATE allows its argument to
be a string. (WITH-EXCEPTION-LOCK isn't used anywhere yet; it may be
a better alternative to things like WITHOUT-GCING, where (a) it's
preferable to delay exception handing in other threads than to let
the heap grow and (b) the body is short and doesn't try to grab other
locks.)

This is all intended to fix ticket:1030 in the trunk.

File size: 8.5 KB
Line 
1/*   Copyright (C) 2005-2009 Clozure Associates */
2/*   This file is part of Clozure CL.   */
3 
4/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
5/*   License , known as the LLGPL and distributed with Clozure CL as the */
6/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
7/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
8/*   conflict, the preamble takes precedence.   */
9 
10/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
11 
12/*   The LLGPL is also available online at */
13/*   http://opensource.franz.com/preamble.html */
14
15
16       
17
18        include(lisp.s)
19
20        _beginfile
21
22_exportfn(C(current_stack_pointer))
23        __(movl %esp,%eax)
24        __(ret)
25_endfn
26                       
27_exportfn(C(count_leading_zeros))
28        __(bsr 4(%esp),%eax)
29        __(xor $31,%eax)
30        __(ret)
31_endfn
32
33_exportfn(C(noop))
34        __(ret)
35_endfn
36
37_exportfn(C(set_mxcsr))
38        __(ldmxcsr 4(%esp))
39        __(ret)
40_endfn
41       
42_exportfn(C(get_mxcsr))
43        __(push $0)
44        __(stmxcsr (%esp))
45        __(pop %eax)
46        __(ret)
47_endfn
48
49_exportfn(C(save_fp_context))
50_endfn
51       
52_exportfn(C(restore_fp_context))
53_endfn                       
54
55/*  Atomically store new in *p, if *p == old. */
56/*  Return actual old value. */
57/* natural store_conditional(natural *p, natural old, natural new) */
58_exportfn(C(store_conditional))
59        __(movl 12(%esp),%edx)  /* new */
60        __(movl 8(%esp),%eax)   /* old */
61        __(movl 4(%esp),%ecx)   /* ptr */
62        __(lock)
63        __(cmpxchgl %edx,(%ecx))
64        __(cmovne %edx,%eax)
65        __(ret)
66_endfn
67
68/*      Atomically store val in *p; return previous *p */
69/*      of *%rdi. */
70/* signed_natural atomic_swap(signed_natural *p, signed_natural val) */
71_exportfn(C(atomic_swap))
72        __(movl 8(%esp),%eax)
73        __(movl 4(%esp),%edx)
74        __(lock)
75        __(xchg %eax,(%edx))
76        __(ret)
77_endfn
78
79/*      Logior the value in *p with mask (presumably a */
80/*      bitmask with exactly 1 bit set.)  Return non-zero if any of */
81/*      the bits in that bitmask were already set. */
82/* natural atomic_ior(natural *p, natural mask) */
83_exportfn(C(atomic_ior))
84        __(movl 4(%esp),%edx)   /* ptr */
850:      __(movl (%edx),%eax)
86        __(movl %eax,%ecx)
87        __(orl 8(%esp),%ecx)
88        __(lock)
89        __(cmpxchg %ecx,(%edx))
90        __(jz 1f)
91        __(pause)
92        __(jmp 0b)
931:      __(andl 8(%esp),%eax)
94        __(ret)
95_endfn
96       
97       
98/* Logand the value in *p with mask (presumably a bitmask with exactly 1 */
99/* bit set.)  Return the value now in *p (for some value of "now"). */
100/* natural atomic_and(natural *p, natural mask) */
101_exportfn(C(atomic_and))
102        __(movl 4(%esp),%edx)
1030:      __(movl (%edx),%eax)
104        __(movl %eax,%ecx)
105        __(and 8(%esp),%ecx)
106        __(lock)
107        __(cmpxchg %ecx,(%edx))
108        __(jz 1f)
109        __(pause)
110        __(jmp 0b)
1111:      __(movl %ecx,%eax)
112        __(ret)
113_endfn
114
115
116
117/* int cpuid (int code, int *pebx, int *pecx, int *pedx)  */
118_exportfn(C(cpuid))
119        __(push %ebx)           /* %ebx is non-volatile */
120        __(push %esi)           /* ditto here */
121        __(movl 12(%esp),%eax)
122        __(xorl %ecx,%ecx)
123        __(cpuid)
124        __(movl 16(%esp),%esi)
125        __(movl %ebx,(%esi))
126        __(movl 20(%esp),%esi)
127        __(movl %ecx,(%esi))
128        __(movl 24(%esp),%esi)
129        __(movl %edx,(%esi))
130        __(pop %esi)
131        __(pop %ebx)
132        __(ret)
133_endfn
134
135/* switch_to_foreign_stack(new_sp, func, arg_0, arg_1, arg_2)  */
136/*   Not fully general, but should get us off of the signal stack */
137/* Beware: on Darwin, GDB can get very confused by this code, and
138   doesn't really get unconfused until the target function - the
139   handler - has built its stack frame
140   The lone caller of this function passes 3 arguments (besides
141   the new stack pointer and the handler address.)
142   On platforms where the C stack must be 16-byte aligned, pushing
143   a 4th word helps make the stack aligned before the return
144   address is (re-)pushed.
145   On Linux, there are severe constraints on what the top of stack
146   can look like when rt_sigreturn (the code at the return address)
147   runs, and there aren't any constraints on stack alignment, so
148   we don't push the extra word on the new stack.*/
149_exportfn(C(switch_to_foreign_stack))
150        __(addl $4,%esp)        /* discard return address, on wrong stack */
151        __(pop %edi)            /* new esp */
152        __(pop %esi)            /* handler */
153        __(pop %eax)            /* arg_0 */
154        __(pop %ebx)            /* arg_1 */
155        __(pop %ecx)            /* arg_2 */
156        __(mov %edi,%esp)
157        __(pop %edi)            /* Return address pushed by caller */
158        __ifndef(`LINUX')
159        __(push $0)             /* For alignment. See comment above */
160        __endif
161        __(push %ecx)           /* arg_2 */
162        __(push %ebx)           /* arg_1 */
163        __(push %eax)           /* arg_0 */
164        __(push %edi)           /* return address */
165        __(jmp *%esi)           /* On some platforms, we don't really return */
166_endfn
167
168        __ifdef(`FREEBSD')
169        .globl C(sigreturn)
170_exportfn(C(freebsd_sigreturn))
171        __(jmp C(sigreturn))
172_endfn
173        __endif
174
175        __ifdef(`DARWIN')
176_exportfn(C(darwin_sigreturn))
177        __(movl $0xb8,%eax)     /* SYS_sigreturn */
178        __(int $0x80)
179        __(ret)                 /* shouldn't return */
180
181_endfn
182        __endif       
183               
184_exportfn(C(get_vector_registers))
185        __(ret)
186_endfn
187
188_exportfn(C(put_vector_registers))
189        __(ret)
190_endfn                         
191
192        __ifdef(`WIN_32')
193_exportfn(C(restore_windows_context))
194Xrestore_windows_context_start:
195        __(movl 4(%esp),%ecx)   /* context */
196        __(movl 12(%esp),%edx)  /* old valence */
197        __(movl 8(%esp),%eax)   /* tcr */
198        __(movl %edx,rcontext(tcr.valence))
199        __(movl $0,rcontext(tcr.pending_exception_context))
200        __(frstor win32_context.FloatSave(%ecx))
201        /* Windows doesn't bother to align the context, so use
202          'movupd' here */
203        __(movupd win32_context.Xmm0(%ecx),%xmm0)
204        __(movupd win32_context.Xmm1(%ecx),%xmm1)
205        __(movupd win32_context.Xmm2(%ecx),%xmm2)
206        __(movupd win32_context.Xmm3(%ecx),%xmm3)
207        __(movupd win32_context.Xmm4(%ecx),%xmm4)
208        __(movupd win32_context.Xmm5(%ecx),%xmm5)
209        __(movupd win32_context.Xmm6(%ecx),%xmm6)
210        __(movupd win32_context.Xmm7(%ecx),%xmm7)
211        __(ldmxcsr win32_context.MXCSR(%ecx))
212        __(movl win32_context.Ebp(%ecx),%ebp)
213        __(movl win32_context.Edi(%ecx),%edi)
214        __(movl win32_context.Esi(%ecx),%esi)
215        __(movl win32_context.Edx(%ecx),%edx)
216        __(movl win32_context.Ebx(%ecx),%ebx)
217        __(movl win32_context.Eax(%ecx),%eax)
218        __(movl win32_context.Esp(%ecx),%esp)
219        __(pushl win32_context.EFlags(%ecx))
220        __(pushl %cs)
221        __(pushl win32_context.Eip(%ecx))       
222        /* This must be the last thing before the iret, e.g., if we're
223        interrupted before the iret, the context we're returning to here
224        is still in %ecx.  If we're interrupted -at- the iret, then
225        everything but that which the iret will restore has been restored. */
226        __(movl win32_context.Ecx(%ecx),%ecx)
227Xrestore_windows_context_iret:           
228        __(iret)
229Xrestore_windows_context_end:             
230        __(nop)
231_endfn
232       
233_exportfn(C(windows_switch_to_foreign_stack))
234        __(pop %eax)
235        __(pop %ebx)            /* new %esp */
236        __(pop %ecx)            /* handler */
237        __(pop %edx)            /* arg */
238        __(movl %ebx,%esp)
239        __(subl $0x10,%esp)
240        __(movl %edx,(%esp))
241        __(push %eax)
242        __(jmp *%ecx)
243_endfn       
244
245        .data
246        .globl C(restore_windows_context_start)
247        .globl C(restore_windows_context_end)
248        .globl C(restore_windows_context_iret)
249C(restore_windows_context_start):  .long Xrestore_windows_context_start
250C(restore_windows_context_end): .long Xrestore_windows_context_end
251C(restore_windows_context_iret): .long Xrestore_windows_context_iret
252        .text
253       
254/* Something that we shouldn't return to */
255_exportfn(C(windows_halt))
256        __(hlt)
257_endfn         
258
259_exportfn(C(ensure_safe_for_string_operations))
260        __ifdef(`WIN32_ES_HACK')
261        __(movw %es,%ax)
262        __(movw %ds,%dx)
263        __(cmpw %ax,%dx)
264        __(jne 9f)
2650:      __(movw %dx,%es)
266        __endif
267        __(cld)       
268        __(ret)
269        __ifdef(`WIN32_ES_HACK')
2709:      __(hlt)
271        __(jmp 0b)
272        __endif
273_endfn                                       
274        __endif
275
276/* zero arg1 dnodes,starting at the dnode-aligned address in arg0 */
277_exportfn(C(zero_dnodes)) 
278        __(xorl %eax,%eax)
279        __(mov 4(%esp),%edx)
280        __(mov 8(%esp),%ecx)
281        __(testl %ecx,%ecx)
282        __(jmp 1f)
2830:      __(mov %eax,0(%edx))
284        __(mov %eax,4(%edx))
285        __(lea dnode_size(%edx),%edx)
286        __(subl $1,%ecx)
2871:      __(jne 0b)
288        __(repret)
289_endfn       
290        _endfile
291
Note: See TracBrowser for help on using the repository browser.