source: trunk/source/lisp-kernel/x86-spentry32.s @ 15816

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

Start new scheme: maintain a second bitmap with 1 bit for every 256
in the global ephemeral refmap. (According too my calculations, this
should be ... 256X smaller than the refmap and should be easier to
traverse on machines with relatively small caches.

So far, we just allocate it (at overestimated maximum size) and map
it all read/write. Maintain this in the write barrier on x86 (so far)
and in pc_luser_xp's emulation of the write barrier

Todo: map at correct size and associate with managed_static
and tenured areas, and actually traverse this.

Last commit added a kernel global to support this.

File size: 161.4 KB
Line 
1/*
2   Copyright (C) 2006-2012 Clozure Associates
3   This file is part of Clozure CL. 
4
5   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
6   License , known as the LLGPL and distributed with Clozure CL as the
7   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
8   which is distributed with Clozure CL as the file "LGPL".  Where these
9   conflict, the preamble takes precedence. 
10
11   Clozure CL is referenced in the preamble as the "LIBRARY."
12
13   The LLGPL is also available online at
14   http://opensource.franz.com/preamble.html
15*/
16        include(lisp.s)
17        _beginfile
18
19        .align 2
20define(`_spentry',`ifdef(`__func_name',`_endfn',`')
21        .p2align 3
22        _exportfn(_SP$1)
23')
24
25define(`_endsubp',`
26        _endfn(_SP$1)
27')
28
29define(`jump_builtin',`
30        ref_nrs_value(builtin_functions,%fname)
31        set_nargs($2)
32        vrefr(%fname,%fname,$1)
33        jump_fname()
34')
35
36_spentry(bad_funcall)
37Xspentry_start:                 
38        .globl C(bad_funcall)
39__(tra(C(bad_funcall)))
40        __(uuo_error_not_callable)
41_endsubp(bad_funcall)
42
43/* %arg_z has overflowed by one bit.  Make a bignum with 1 (32-bit) digit. */
44_spentry(fix_overflow)
45C(fix_one_bit_overflow):
46        __(movl $one_digit_bignum_header,%imm0)
47        __(movd %imm0,%mm0)
48        __(Misc_Alloc_Fixed(`',aligned_bignum_size(1)))
49        __(unbox_fixnum(%arg_z,%imm0))
50        __(xor $0xc0000000,%imm0)
51        __(mov %temp0,%arg_z)
52        __(movl %imm0,misc_data_offset(%arg_z))
53        __(ret)
54_endsubp(fix_overflow)
55
56/* %arg_y = vector, %arg_z = unscaled-idx */
57_spentry(misc_ref)
58        __(mov %arg_y,%imm0)
59        __(andb $tagmask,%imm0_b)
60        __(cmpb $tag_misc,%imm0_b)
61        __(jne 0f)
62        __(testb $fixnummask,%arg_z_b)
63        __(jne 1f)
64        __(movl misc_header_offset(%arg_y),%imm0)
65        __(xorb %imm0_b,%imm0_b)
66        __(shrl $num_subtag_bits-fixnumshift,%imm0)
67        __(cmpl %imm0,%arg_z)
68        __(jae 2f)
69        __(movb misc_subtag_offset(%arg_y),%imm0_b)
70        __(jmp C(misc_ref_common))
71
720:      __(uuo_error_reg_not_tag(Rarg_y,tag_misc))
731:      __(uuo_error_reg_not_fixnum(Rarg_z))
742:      __(uuo_error_vector_bounds(Rarg_z,Rarg_y))
75_endsubp(misc_ref)
76
77/* %imm0_b = subtag, %arg_y = vector, %arg_z = index. */
78/* Bounds/type-checking done in caller. */
79_startfn(C(misc_ref_common))
80        __(movzbl %imm0_b,%imm0)
81        __(leal local_label(misc_ref_jmp)(,%imm0,4),%imm0)
82        __(jmp *(%imm0))
83        .p2align 2
84local_label(misc_ref_jmp):
85        /* 00-0f */
86        .long local_label(misc_ref_invalid) /* 00 even_fixnum  */
87        .long local_label(misc_ref_invalid) /* 01 cons  */
88        .long local_label(misc_ref_invalid) /* 02 nodeheader  */
89        .long local_label(misc_ref_invalid) /* 03 imm  */
90        .long local_label(misc_ref_invalid) /* 04 odd_fixnum  */
91        .long local_label(misc_ref_invalid) /* 05 tra  */
92        .long local_label(misc_ref_invalid) /* 06 misc  */
93        .long local_label(misc_ref_u32) /* 07 bignum  */
94        .long local_label(misc_ref_invalid) /* 08 even_fixnum  */
95        .long local_label(misc_ref_invalid) /* 09 cons  */
96        .long local_label(misc_ref_node) /* 0a ratio  */
97        .long local_label(misc_ref_invalid) /* 0b imm  */
98        .long local_label(misc_ref_invalid) /* 0c odd_fixnum  */
99        .long local_label(misc_ref_invalid) /* 0d tra  */
100        .long local_label(misc_ref_invalid) /* 0e misc  */
101        .long local_label(misc_ref_u32) /* 0f single_float  */
102        /* 10-1*/
103        .long local_label(misc_ref_invalid) /* 10 even_fixnum  */
104        .long local_label(misc_ref_invalid) /* 11 cons  */
105        .long local_label(misc_ref_invalid) /* 12 nodeheader  */
106        .long local_label(misc_ref_invalid) /* 13 imm  */
107        .long local_label(misc_ref_invalid) /* 14 odd_fixnum  */
108        .long local_label(misc_ref_invalid) /* 15 tra  */
109        .long local_label(misc_ref_invalid) /* 16 misc  */
110        .long local_label(misc_ref_u32) /* 17 double_float  */
111        .long local_label(misc_ref_invalid) /* 18 even_fixnum  */
112        .long local_label(misc_ref_invalid) /* 19 cons  */
113        .long local_label(misc_ref_node) /* 1a complex  */
114        .long local_label(misc_ref_invalid) /* 1b imm  */
115        .long local_label(misc_ref_invalid) /* 1c odd_fixnum  */
116        .long local_label(misc_ref_invalid) /* 1d tra  */
117        .long local_label(misc_ref_invalid) /* 1e misc  */
118        .long local_label(misc_ref_u32) /* 1f macptr  */
119        /* 20-2*/
120        .long local_label(misc_ref_invalid) /* 20 even_fixnum  */
121        .long local_label(misc_ref_invalid) /* 21 cons  */
122        .long local_label(misc_ref_node) /* 22 catch_frame  */
123        .long local_label(misc_ref_invalid) /* 23 imm  */
124        .long local_label(misc_ref_invalid) /* 24 odd_fixnum  */
125        .long local_label(misc_ref_invalid) /* 25 tra  */
126        .long local_label(misc_ref_invalid) /* 26 misc  */
127        .long local_label(misc_ref_u32) /* 27 dead_macptr  */
128        .long local_label(misc_ref_invalid) /* 28 even_fixnum  */
129        .long local_label(misc_ref_invalid) /* 29 cons  */
130        .long local_label(misc_ref_function) /* 2a function  */
131        .long local_label(misc_ref_invalid) /* 2b imm  */
132        .long local_label(misc_ref_invalid) /* 2c odd_fixnum  */
133        .long local_label(misc_ref_invalid) /* 2d tra  */
134        .long local_label(misc_ref_invalid) /* 2e misc  */
135        .long local_label(misc_ref_invalid) /* 2f immheader  */
136        /* 30-3*/
137        .long local_label(misc_ref_invalid) /* 30 even_fixnum  */
138        .long local_label(misc_ref_invalid) /* 31 cons  */
139        .long local_label(misc_ref_node) /* 32 basic_stream  */
140        .long local_label(misc_ref_invalid) /* 33 imm  */
141        .long local_label(misc_ref_invalid) /* 34 odd_fixnum  */
142        .long local_label(misc_ref_invalid) /* 35 tra  */
143        .long local_label(misc_ref_invalid) /* 36 misc  */
144        .long local_label(misc_ref_invalid) /* 37 immheader  */
145        .long local_label(misc_ref_invalid) /* 38 even_fixnum  */
146        .long local_label(misc_ref_invalid) /* 39 cons  */
147        .long local_label(misc_ref_node) /* 3a symbol  */
148        .long local_label(misc_ref_invalid) /* 3b imm  */
149        .long local_label(misc_ref_invalid) /* 3c odd_fixnum  */
150        .long local_label(misc_ref_invalid) /* 3d tra  */
151        .long local_label(misc_ref_invalid) /* 3e misc  */
152        .long local_label(misc_ref_u32) /* 3f xcode_vector  */
153        /* 40-4*/
154        .long local_label(misc_ref_invalid) /* 40 even_fixnum  */
155        .long local_label(misc_ref_invalid) /* 41 cons  */
156        .long local_label(misc_ref_node) /* 42 lock  */
157        .long local_label(misc_ref_invalid) /* 43 imm  */
158        .long local_label(misc_ref_invalid) /* 44 odd_fixnum  */
159        .long local_label(misc_ref_invalid) /* 45 tra  */
160        .long local_label(misc_ref_invalid) /* 46 misc  */
161        .long local_label(misc_ref_invalid) /* 47 immheader  */
162        .long local_label(misc_ref_invalid) /* 48 even_fixnum  */
163        .long local_label(misc_ref_invalid) /* 49 cons  */
164        .long local_label(misc_ref_node) /* 4a hash_vector  */
165        .long local_label(misc_ref_invalid) /* 4b imm  */
166        .long local_label(misc_ref_invalid) /* 4c odd_fixnum  */
167        .long local_label(misc_ref_invalid) /* 4d tra  */
168        .long local_label(misc_ref_invalid) /* 4e misc  */
169        .long local_label(misc_ref_invalid) /* 4f immheader  */
170        /* 50-5*/
171        .long local_label(misc_ref_invalid) /* 50 even_fixnum  */
172        .long local_label(misc_ref_invalid) /* 51 cons  */
173        .long local_label(misc_ref_node) /* 52 pool  */
174        .long local_label(misc_ref_invalid) /* 53 imm  */
175        .long local_label(misc_ref_invalid) /* 54 odd_fixnum  */
176        .long local_label(misc_ref_invalid) /* 55 tra  */
177        .long local_label(misc_ref_invalid) /* 56 misc  */
178        .long local_label(misc_ref_invalid) /* 57 immheader  */
179        .long local_label(misc_ref_invalid) /* 58 even_fixnum  */
180        .long local_label(misc_ref_invalid) /* 59 cons  */
181        .long local_label(misc_ref_node) /* 5a weak  */
182        .long local_label(misc_ref_invalid) /* 5b imm  */
183        .long local_label(misc_ref_invalid) /* 5c odd_fixnum  */
184        .long local_label(misc_ref_invalid) /* 5d tra  */
185        .long local_label(misc_ref_invalid) /* 5e misc  */
186        .long local_label(misc_ref_invalid) /* 5f immheader  */
187        /* 60-6*/
188        .long local_label(misc_ref_invalid) /* 60 even_fixnum  */
189        .long local_label(misc_ref_invalid) /* 61 cons  */
190        .long local_label(misc_ref_node) /* 62 package  */
191        .long local_label(misc_ref_invalid) /* 63 imm  */
192        .long local_label(misc_ref_invalid) /* 64 odd_fixnum  */
193        .long local_label(misc_ref_invalid) /* 65 tra  */
194        .long local_label(misc_ref_invalid) /* 66 misc  */
195        .long local_label(misc_ref_invalid) /* 67 immheader  */
196        .long local_label(misc_ref_invalid) /* 68 even_fixnum  */
197        .long local_label(misc_ref_invalid) /* 69 cons  */
198        .long local_label(misc_ref_node) /* 6a slot_vector  */
199        .long local_label(misc_ref_invalid) /* 6b imm  */
200        .long local_label(misc_ref_invalid) /* 6c odd_fixnum  */
201        .long local_label(misc_ref_invalid) /* 6d tra  */
202        .long local_label(misc_ref_invalid) /* 6e misc  */
203        .long local_label(misc_ref_invalid) /* 6f immheader  */
204        /* 70-7*/
205        .long local_label(misc_ref_invalid) /* 70 even_fixnum  */
206        .long local_label(misc_ref_invalid) /* 71 cons  */
207        .long local_label(misc_ref_node) /* 72 instance  */
208        .long local_label(misc_ref_invalid) /* 73 imm  */
209        .long local_label(misc_ref_invalid) /* 74 odd_fixnum  */
210        .long local_label(misc_ref_invalid) /* 75 tra  */
211        .long local_label(misc_ref_invalid) /* 76 misc  */
212        .long local_label(misc_ref_invalid) /* 77 immheader  */
213        .long local_label(misc_ref_invalid) /* 78 even_fixnum  */
214        .long local_label(misc_ref_invalid) /* 79 cons  */
215        .long local_label(misc_ref_node) /* 7a struct  */
216        .long local_label(misc_ref_invalid) /* 7b imm  */
217        .long local_label(misc_ref_invalid) /* 7c odd_fixnum  */
218        .long local_label(misc_ref_invalid) /* 7d tra  */
219        .long local_label(misc_ref_invalid) /* 7e misc  */
220        .long local_label(misc_ref_invalid) /* 7f immheader  */
221        /* 80-8*/
222        .long local_label(misc_ref_invalid) /* 80 even_fixnum  */
223        .long local_label(misc_ref_invalid) /* 81 cons  */
224        .long local_label(misc_ref_node) /* 82 istruct  */
225        .long local_label(misc_ref_invalid) /* 83 imm  */
226        .long local_label(misc_ref_invalid) /* 84 odd_fixnum  */
227        .long local_label(misc_ref_invalid) /* 85 tra  */
228        .long local_label(misc_ref_invalid) /* 86 misc  */
229        .long local_label(misc_ref_invalid) /* 87 immheader  */
230        .long local_label(misc_ref_invalid) /* 88 even_fixnum  */
231        .long local_label(misc_ref_invalid) /* 89 cons  */
232        .long local_label(misc_ref_node) /* 8a value_cell  */
233        .long local_label(misc_ref_invalid) /* 8b imm  */
234        .long local_label(misc_ref_invalid) /* 8c odd_fixnum  */
235        .long local_label(misc_ref_invalid) /* 8d tra  */
236        .long local_label(misc_ref_invalid) /* 8e misc  */
237        .long local_label(misc_ref_invalid) /* 8f immheader  */
238        /* 90-9*/
239        .long local_label(misc_ref_invalid) /* 90 even_fixnum  */
240        .long local_label(misc_ref_invalid) /* 91 cons  */
241        .long local_label(misc_ref_node) /* 92 xfunction  */
242        .long local_label(misc_ref_invalid) /* 93 imm  */
243        .long local_label(misc_ref_invalid) /* 94 odd_fixnum  */
244        .long local_label(misc_ref_invalid) /* 95 tra  */
245        .long local_label(misc_ref_invalid) /* 96 misc  */
246        .long local_label(misc_ref_invalid) /* 97 immheader  */
247        .long local_label(misc_ref_invalid) /* 98 even_fixnum  */
248        .long local_label(misc_ref_invalid) /* 99 cons  */
249        .long local_label(misc_ref_node) /* 9a arrayH  */
250        .long local_label(misc_ref_invalid) /* 9b imm  */
251        .long local_label(misc_ref_invalid) /* 9c odd_fixnum  */
252        .long local_label(misc_ref_invalid) /* 9d tra  */
253        .long local_label(misc_ref_invalid) /* 9e misc  */
254        .long local_label(misc_ref_invalid) /* 9f immheader  */
255        /* a0-af  */
256        .long local_label(misc_ref_invalid) /* a0 even_fixnum  */
257        .long local_label(misc_ref_invalid) /* a1 cons  */
258        .long local_label(misc_ref_node) /* a2 vectorH  */
259        .long local_label(misc_ref_invalid) /* a3 imm  */
260        .long local_label(misc_ref_invalid) /* a4 odd_fixnum  */
261        .long local_label(misc_ref_invalid) /* a5 tra  */
262        .long local_label(misc_ref_invalid) /* a6 misc  */
263        .long local_label(misc_ref_single_float_vector) /* a7 sf_vector  */
264        .long local_label(misc_ref_invalid) /* a8 even_fixnum  */
265        .long local_label(misc_ref_invalid) /* a9 cons  */
266        .long local_label(misc_ref_node) /* aa simple_vector  */
267        .long local_label(misc_ref_invalid) /* ab imm  */
268        .long local_label(misc_ref_invalid) /* ac odd_fixnum  */
269        .long local_label(misc_ref_invalid) /* ad tra  */
270        .long local_label(misc_ref_invalid) /* ae misc  */
271        .long local_label(misc_ref_u32) /* af u32  */
272        /* b0-bf  */
273        .long local_label(misc_ref_invalid) /* b0 even_fixnum  */
274        .long local_label(misc_ref_invalid) /* b1 cons  */
275        .long local_label(misc_ref_invalid) /* b2 nodeheader  */
276        .long local_label(misc_ref_invalid) /* b3 imm  */
277        .long local_label(misc_ref_invalid) /* b4 odd_fixnum  */
278        .long local_label(misc_ref_invalid) /* b5 tra  */
279        .long local_label(misc_ref_invalid) /* b6 misc  */
280        .long local_label(misc_ref_s32) /* b7 s32  */
281        .long local_label(misc_ref_invalid) /* b8 even_fixnum  */
282        .long local_label(misc_ref_invalid) /* b9 cons  */
283        .long local_label(misc_ref_invalid) /* ba nodeheader  */
284        .long local_label(misc_ref_invalid) /* bb imm  */
285        .long local_label(misc_ref_invalid) /* bc odd_fixnum  */
286        .long local_label(misc_ref_invalid) /* bd tra  */
287        .long local_label(misc_ref_invalid) /* be misc  */
288        .long local_label(misc_ref_fixnum_vector) /* bf fixnum_vector  */
289        /* c0-cf  */
290        .long local_label(misc_ref_invalid) /* c0 even_fixnum  */
291        .long local_label(misc_ref_invalid) /* c1 cons  */
292        .long local_label(misc_ref_invalid) /* c2 nodeheader  */
293        .long local_label(misc_ref_invalid) /* c3 imm  */
294        .long local_label(misc_ref_invalid) /* c4 odd_fixnum  */
295        .long local_label(misc_ref_invalid) /* c5 tra  */
296        .long local_label(misc_ref_invalid) /* c6 misc  */
297        .long local_label(misc_ref_string) /* c7 simple_base_string  */
298        .long local_label(misc_ref_invalid) /* c8 even_fixnum  */
299        .long local_label(misc_ref_invalid) /* c9 cons  */
300        .long local_label(misc_ref_invalid) /* ca nodeheader  */
301        .long local_label(misc_ref_invalid) /* cb imm  */
302        .long local_label(misc_ref_invalid) /* cc odd_fixnum  */
303        .long local_label(misc_ref_invalid) /* cd tra  */
304        .long local_label(misc_ref_invalid) /* ce misc  */
305        .long local_label(misc_ref_u8) /* cf u8  */
306        /* d0-df  */
307        .long local_label(misc_ref_invalid) /* d0 even_fixnum  */
308        .long local_label(misc_ref_invalid) /* d1 cons  */
309        .long local_label(misc_ref_invalid) /* d2 nodeheader  */
310        .long local_label(misc_ref_invalid) /* d3 imm  */
311        .long local_label(misc_ref_invalid) /* d4 odd_fixnum  */
312        .long local_label(misc_ref_invalid) /* d5 tra  */
313        .long local_label(misc_ref_invalid) /* d6 misc  */
314        .long local_label(misc_ref_s8)      /* d7 s8  */
315        .long local_label(misc_ref_invalid) /* d8 even_fixnum  */
316        .long local_label(misc_ref_invalid) /* d9 cons  */
317        .long local_label(misc_ref_invalid) /* da nodeheader  */
318        .long local_label(misc_ref_invalid) /* db imm  */
319        .long local_label(misc_ref_invalid) /* dc odd_fixnum  */
320        .long local_label(misc_ref_invalid) /* dd tra  */
321        .long local_label(misc_ref_invalid) /* de misc  */
322        .long local_label(misc_ref_invalid) /* df immheader  */
323        /* e0-ef  */
324        .long local_label(misc_ref_invalid) /* e0 even_fixnum  */
325        .long local_label(misc_ref_invalid) /* e1 cons  */
326        .long local_label(misc_ref_invalid) /* e2 nodeheader  */
327        .long local_label(misc_ref_invalid) /* e3 imm  */
328        .long local_label(misc_ref_invalid) /* e4 odd_fixnum  */
329        .long local_label(misc_ref_invalid) /* e5 tra  */
330        .long local_label(misc_ref_invalid) /* e6 misc  */
331        .long local_label(misc_ref_u16) /* e7 u16  */
332        .long local_label(misc_ref_invalid) /* e8 even_fixnum  */
333        .long local_label(misc_ref_invalid) /* e9 cons  */
334        .long local_label(misc_ref_invalid) /* ea nodeheader  */
335        .long local_label(misc_ref_invalid) /* eb imm  */
336        .long local_label(misc_ref_invalid) /* ec odd_fixnum  */
337        .long local_label(misc_ref_invalid) /* ed tra  */
338        .long local_label(misc_ref_invalid) /* ee misc  */
339        .long local_label(misc_ref_s16) /* ef s16  */
340        /* f0-ff  */
341        .long local_label(misc_ref_invalid) /* f0 even_fixnum  */
342        .long local_label(misc_ref_invalid) /* f1 cons  */
343        .long local_label(misc_ref_invalid) /* f2 nodeheader  */
344        .long local_label(misc_ref_invalid) /* f3 imm  */
345        .long local_label(misc_ref_invalid) /* f4 odd_fixnum  */
346        .long local_label(misc_ref_invalid) /* f5 tra  */
347        .long local_label(misc_ref_invalid) /* f6 misc  */
348        .long local_label(misc_ref_double_float_vector) /* f7 df vector  */
349        .long local_label(misc_ref_invalid) /* f8 even_fixnum  */
350        .long local_label(misc_ref_invalid) /* f9 cons  */
351        .long local_label(misc_ref_invalid) /* fa nodeheader  */
352        .long local_label(misc_ref_invalid) /* fb imm  */
353        .long local_label(misc_ref_invalid) /* fc odd_fixnum  */
354        .long local_label(misc_ref_invalid) /* fd tra  */
355        .long local_label(misc_ref_invalid) /* fe misc  */
356        .long local_label(misc_ref_bit_vector) /* ff bit_vector  */
357
358/* Functions are funny.  The first N words are treated as */
359/* (UNSIGNED-BYTE 32), where N is the low 16 bits of the first word. */
360
361local_label(misc_ref_function):
362        __(movzwl misc_data_offset(%arg_y), %imm0)
363        /* XXX bootstrapping */
364        __(btr $15,%imm0)
365        __(jnc 0f)
366        __(movl $0xffffff00,%temp0)
367        __(andl misc_header_offset(%arg_y),%temp0)
368        __(shr $num_subtag_bits-fixnumshift,%temp0)
369        __(shl $fixnumshift,%imm0)
370        __(subl %imm0,%temp0)
371        __(movl %temp0,%imm0)
372        __(shr $fixnumshift,%imm0)
3730:     
374        __(shl $fixnumshift,%imm0)
375        __(rcmpl(%arg_z,%imm0))
376        __(jb local_label(misc_ref_u32))
377local_label(misc_ref_node):
378        __(movl misc_data_offset(%arg_y,%arg_z),%arg_z)
379        __(ret)
380local_label(misc_ref_u32):
381        __(movl misc_data_offset(%arg_y,%arg_z),%imm0)
382        __(jmp _SPmakeu32)
383local_label(misc_ref_s32):
384        __(movl misc_data_offset(%arg_y,%arg_z),%imm0)
385        __(jmp _SPmakes32)
386local_label(misc_ref_single_float_vector):
387        __(movss misc_data_offset(%arg_y,%arg_z),%fp1)
388        __(movl $single_float_header,%imm0)
389        __(movd %imm0,%mm0)
390        __(Misc_Alloc_Fixed(%arg_z,single_float.size))
391        __(movss %fp1,single_float.value(%arg_z))
392        __(ret)
393local_label(misc_ref_double_float_vector):
394        __(movsd misc_dfloat_offset(%arg_y,%arg_z,2),%fp1)
395        __(movl $double_float_header,%imm0)
396        __(movd %imm0,%mm0)
397        __(Misc_Alloc_Fixed(%arg_z,double_float.size))
398        __(movsd %fp1,double_float.value(%arg_z))
399        __(ret)
400local_label(misc_ref_fixnum_vector):
401        __(movl misc_data_offset(%arg_y,%arg_z),%imm0)
402        __(box_fixnum(%imm0,%arg_z))
403        __(ret)
404local_label(misc_ref_u8):
405        __(movl %arg_z,%imm0)
406        __(shr $2,%imm0)
407        __(movzbl misc_data_offset(%arg_y,%imm0),%imm0)
408        __(box_fixnum(%imm0,%arg_z))
409        __(ret)
410local_label(misc_ref_s8):
411        __(movl %arg_z,%imm0)
412        __(shr $2,%imm0)
413        __(movsbl misc_data_offset(%arg_y,%imm0),%imm0)
414        __(box_fixnum(%imm0,%arg_z))
415        __(ret)
416local_label(misc_ref_string):
417        __(movl %arg_z,%imm0)
418        __(movl misc_data_offset(%arg_y,%imm0),%imm0)
419        __(shll $charcode_shift,%imm0)
420        __(leal subtag_character(%imm0),%arg_z)
421        __(ret)
422local_label(misc_ref_u16):
423        __(movl %arg_z,%imm0)
424        __(shrl $1,%imm0)
425        __(movzwl misc_data_offset(%arg_y,%imm0),%imm0)
426        __(box_fixnum(%imm0,%arg_z))
427        __(ret)
428local_label(misc_ref_s16):
429        __(movl %arg_z,%imm0)
430        __(shrl $1,%imm0)
431        __(movswl misc_data_offset(%arg_y,%imm0),%imm0)
432        __(box_fixnum(%imm0,%arg_z))
433        __(ret)
434local_label(misc_ref_bit_vector):
435        __(unbox_fixnum(%arg_z,%imm0))
436        __(btl %imm0,misc_data_offset(%arg_y))
437        __(setc %imm0_b)
438        __(movzbl %imm0_b,%imm0)
439        __(box_fixnum(%imm0,%arg_z))
440        __(ret)
441local_label(misc_ref_invalid):
442        __(pop %temp1)  /* return addr */
443        __(push $reserved_frame_marker)
444        __(push $reserved_frame_marker)
445        __(push $XBADVEC)
446        __(push %temp1)
447        __(set_nargs(3))
448        __(jmp _SPksignalerr)
449_endfn(C(misc_ref_common))
450
451/* Like misc_ref, only the boxed subtag is in temp0. */
452_spentry(subtag_misc_ref)
453        __(mov %arg_y,%imm0)
454        __(and $tagmask,%imm0)
455        __(cmp $tag_misc,%imm0)
456        __(jne 0f)
457        __(testb $fixnummask,%arg_z_b)
458        __(jne 1f)
459        __(movl misc_header_offset(%arg_y),%imm0)
460        __(xorb %imm0_b,%imm0_b)
461        __(shrl $num_subtag_bits-fixnumshift,%imm0)
462        __(cmp %imm0,%arg_z)
463        __(jae 2f)
464        __(unbox_fixnum(%temp0,%imm0))
465        __(jmp C(misc_ref_common))
4660:      __(uuo_error_reg_not_tag(Rarg_y,tag_misc))
4671:      __(uuo_error_reg_not_fixnum(Rarg_z))
4682:      __(uuo_error_vector_bounds(Rarg_z,Rarg_y))
469_endsubp(subtag_misc_ref)
470
471/* Like misc_set, only the boxed subtag is in temp1. */
472_spentry(subtag_misc_set)
473        __(mov %temp0,%imm0)
474        __(andb $tagmask,%imm0_b)
475        __(cmpb $tag_misc,%imm0_b)
476        __(jne 0f)
477        __(mov %arg_y,%imm0)
478        __(testb $fixnummask,%imm0_b)
479        __(jne 1f)
480        __(movl misc_header_offset(%temp0),%imm0)
481        __(xorb %imm0_b,%imm0_b)
482        __(shrl $num_subtag_bits-fixnumshift,%imm0)
483        __(cmpl %imm0,%arg_y)
484        __(jae 2f)
485        __(unbox_fixnum(%temp1,%imm0))
486        __(jmp C(misc_set_common))
4870:      __(uuo_error_reg_not_tag(Rtemp0,tag_misc))
4881:      __(uuo_error_reg_not_fixnum(Rarg_y))
4892:      __(uuo_error_vector_bounds(Rarg_y,Rtemp0))
490_endsubp(subtag_misc_set)
491
492/* %temp0 = vector, %arg_y = unscaled-idx, %arg_z = val */
493_spentry(misc_set)
494        __(mov %temp0,%imm0)
495        __(andb $tagmask,%imm0_b)
496        __(cmpb $tag_misc,%imm0_b)
497        __(jne 0f)
498        __(test $fixnummask,%arg_y)
499        __(jne 1f)
500        __(movl misc_header_offset(%temp0),%imm0)
501        __(xorb %imm0_b,%imm0_b)
502        __(shrl $num_subtag_bits-fixnumshift,%imm0)
503        __(cmpl %imm0,%arg_y)
504        __(jae 2f)
505        __(xorl %imm0,%imm0)
506        __(movb misc_subtag_offset(%temp0),%imm0_b)
507        __(jmp C(misc_set_common))
5080:      __(uuo_error_reg_not_tag(Rtemp0,tag_misc))
5091:      __(uuo_error_reg_not_fixnum(Rarg_y))
5102:      __(uuo_error_vector_bounds(Rarg_y,Rtemp0))
511_endsubp(misc_set)
512
513/* imm0_b = subtag, %temp0 = vector, %arg_y = index, %arg_z = value */
514_startfn(C(misc_set_common))
515        __(movzbl %imm0_b,%imm0)
516        __(leal local_label(misc_set_jmp)(,%imm0,4),%imm0)
517        __(jmp *(%imm0))
518        .p2align 2
519local_label(misc_set_jmp):
520        /* 00-0f */
521        .long local_label(misc_set_invalid) /* 00 even_fixnum  */
522        .long local_label(misc_set_invalid) /* 01 cons  */
523        .long local_label(misc_set_invalid) /* 02 nodeheader  */
524        .long local_label(misc_set_invalid) /* 03 imm  */
525        .long local_label(misc_set_invalid) /* 04 odd_fixnum  */
526        .long local_label(misc_set_invalid) /* 05 tra  */
527        .long local_label(misc_set_invalid) /* 06 misc  */
528        .long local_label(misc_set_u32) /* 07 bignum  */
529        .long local_label(misc_set_invalid) /* 08 even_fixnum  */
530        .long local_label(misc_set_invalid) /* 09 cons  */
531        .long _SPgvset /* 0a ratio  */
532        .long local_label(misc_set_invalid) /* 0b imm  */
533        .long local_label(misc_set_invalid) /* 0c odd_fixnum  */
534        .long local_label(misc_set_invalid) /* 0d tra  */
535        .long local_label(misc_set_invalid) /* 0e misc  */
536        .long local_label(misc_set_u32) /* 0f single_float  */
537        /* 10-1*/
538        .long local_label(misc_set_invalid) /* 10 even_fixnum  */
539        .long local_label(misc_set_invalid) /* 11 cons  */
540        .long local_label(misc_set_invalid) /* 12 nodeheader  */
541        .long local_label(misc_set_invalid) /* 13 imm  */
542        .long local_label(misc_set_invalid) /* 14 odd_fixnum  */
543        .long local_label(misc_set_invalid) /* 15 tra  */
544        .long local_label(misc_set_invalid) /* 16 misc  */
545        .long local_label(misc_set_u32) /* 17 double_float  */
546        .long local_label(misc_set_invalid) /* 18 even_fixnum  */
547        .long local_label(misc_set_invalid) /* 19 cons  */
548        .long _SPgvset /* 1a complex  */
549        .long local_label(misc_set_invalid) /* 1b imm  */
550        .long local_label(misc_set_invalid) /* 1c odd_fixnum  */
551        .long local_label(misc_set_invalid) /* 1d tra  */
552        .long local_label(misc_set_invalid) /* 1e misc  */
553        .long local_label(misc_set_u32) /* 1f macptr  */
554        /* 20-2*/
555        .long local_label(misc_set_invalid) /* 20 even_fixnum  */
556        .long local_label(misc_set_invalid) /* 21 cons  */
557        .long _SPgvset /* 22 catch_frame  */
558        .long local_label(misc_set_invalid) /* 23 imm  */
559        .long local_label(misc_set_invalid) /* 24 odd_fixnum  */
560        .long local_label(misc_set_invalid) /* 25 tra  */
561        .long local_label(misc_set_invalid) /* 26 misc  */
562        .long local_label(misc_set_u32) /* 27 dead_macptr  */
563        .long local_label(misc_set_invalid) /* 28 even_fixnum  */
564        .long local_label(misc_set_invalid) /* 29 cons  */
565        .long local_label(misc_set_function) /* 2a function  */
566        .long local_label(misc_set_invalid) /* 2b imm  */
567        .long local_label(misc_set_invalid) /* 2c odd_fixnum  */
568        .long local_label(misc_set_invalid) /* 2d tra  */
569        .long local_label(misc_set_invalid) /* 2e misc  */
570        .long local_label(misc_set_invalid) /* 2f immheader  */
571        /* 30-3*/
572        .long local_label(misc_set_invalid) /* 30 even_fixnum  */
573        .long local_label(misc_set_invalid) /* 31 cons  */
574        .long _SPgvset /* 32 basic_stream  */
575        .long local_label(misc_set_invalid) /* 33 imm  */
576        .long local_label(misc_set_invalid) /* 34 odd_fixnum  */
577        .long local_label(misc_set_invalid) /* 35 tra  */
578        .long local_label(misc_set_invalid) /* 36 misc  */
579        .long local_label(misc_set_invalid) /* 37 immheader  */
580        .long local_label(misc_set_invalid) /* 38 even_fixnum  */
581        .long local_label(misc_set_invalid) /* 39 cons  */
582        .long _SPgvset /* 3a symbol  */
583        .long local_label(misc_set_invalid) /* 3b imm  */
584        .long local_label(misc_set_invalid) /* 3c odd_fixnum  */
585        .long local_label(misc_set_invalid) /* 3d tra  */
586        .long local_label(misc_set_invalid) /* 3e misc  */
587        .long local_label(misc_set_u32) /* 3f xcode_vector  */
588        /* 40-4*/
589        .long local_label(misc_set_invalid) /* 40 even_fixnum  */
590        .long local_label(misc_set_invalid) /* 41 cons  */
591        .long _SPgvset /* 42 lock  */
592        .long local_label(misc_set_invalid) /* 43 imm  */
593        .long local_label(misc_set_invalid) /* 44 odd_fixnum  */
594        .long local_label(misc_set_invalid) /* 45 tra  */
595        .long local_label(misc_set_invalid) /* 46 misc  */
596        .long local_label(misc_set_invalid) /* 47 immheader  */
597        .long local_label(misc_set_invalid) /* 48 even_fixnum  */
598        .long local_label(misc_set_invalid) /* 49 cons  */
599        .long _SPgvset /* 4a hash_vector  */
600        .long local_label(misc_set_invalid) /* 4b imm  */
601        .long local_label(misc_set_invalid) /* 4c odd_fixnum  */
602        .long local_label(misc_set_invalid) /* 4d tra  */
603        .long local_label(misc_set_invalid) /* 4e misc  */
604        .long local_label(misc_set_invalid) /* 4f immheader  */
605        /* 50-5*/
606        .long local_label(misc_set_invalid) /* 50 even_fixnum  */
607        .long local_label(misc_set_invalid) /* 51 cons  */
608        .long _SPgvset /* 52 pool  */
609        .long local_label(misc_set_invalid) /* 53 imm  */
610        .long local_label(misc_set_invalid) /* 54 odd_fixnum  */
611        .long local_label(misc_set_invalid) /* 55 tra  */
612        .long local_label(misc_set_invalid) /* 56 misc  */
613        .long local_label(misc_set_invalid) /* 57 immheader  */
614        .long local_label(misc_set_invalid) /* 58 even_fixnum  */
615        .long local_label(misc_set_invalid) /* 59 cons  */
616        .long _SPgvset /* 5a weak  */
617        .long local_label(misc_set_invalid) /* 5b imm  */
618        .long local_label(misc_set_invalid) /* 5c odd_fixnum  */
619        .long local_label(misc_set_invalid) /* 5d tra  */
620        .long local_label(misc_set_invalid) /* 5e misc  */
621        .long local_label(misc_set_invalid) /* 5f immheader  */
622        /* 60-6*/
623        .long local_label(misc_set_invalid) /* 60 even_fixnum  */
624        .long local_label(misc_set_invalid) /* 61 cons  */
625        .long _SPgvset /* 62 package  */
626        .long local_label(misc_set_invalid) /* 63 imm  */
627        .long local_label(misc_set_invalid) /* 64 odd_fixnum  */
628        .long local_label(misc_set_invalid) /* 65 tra  */
629        .long local_label(misc_set_invalid) /* 66 misc  */
630        .long local_label(misc_set_invalid) /* 67 immheader  */
631        .long local_label(misc_set_invalid) /* 68 even_fixnum  */
632        .long local_label(misc_set_invalid) /* 69 cons  */
633        .long _SPgvset /* 6a slot_vector  */
634        .long local_label(misc_set_invalid) /* 6b imm  */
635        .long local_label(misc_set_invalid) /* 6c odd_fixnum  */
636        .long local_label(misc_set_invalid) /* 6d tra  */
637        .long local_label(misc_set_invalid) /* 6e misc  */
638        .long local_label(misc_set_invalid) /* 6f immheader  */
639        /* 70-7*/
640        .long local_label(misc_set_invalid) /* 70 even_fixnum  */
641        .long local_label(misc_set_invalid) /* 71 cons  */
642        .long _SPgvset /* 72 instance  */
643        .long local_label(misc_set_invalid) /* 73 imm  */
644        .long local_label(misc_set_invalid) /* 74 odd_fixnum  */
645        .long local_label(misc_set_invalid) /* 75 tra  */
646        .long local_label(misc_set_invalid) /* 76 misc  */
647        .long local_label(misc_set_invalid) /* 77 immheader  */
648        .long local_label(misc_set_invalid) /* 78 even_fixnum  */
649        .long local_label(misc_set_invalid) /* 79 cons  */
650        .long _SPgvset /* 7a struct  */
651        .long local_label(misc_set_invalid) /* 7b imm  */
652        .long local_label(misc_set_invalid) /* 7c odd_fixnum  */
653        .long local_label(misc_set_invalid) /* 7d tra  */
654        .long local_label(misc_set_invalid) /* 7e misc  */
655        .long local_label(misc_set_invalid) /* 7f immheader  */
656        /* 80-8*/
657        .long local_label(misc_set_invalid) /* 80 even_fixnum  */
658        .long local_label(misc_set_invalid) /* 81 cons  */
659        .long _SPgvset /* 82 istruct  */
660        .long local_label(misc_set_invalid) /* 83 imm  */
661        .long local_label(misc_set_invalid) /* 84 odd_fixnum  */
662        .long local_label(misc_set_invalid) /* 85 tra  */
663        .long local_label(misc_set_invalid) /* 86 misc  */
664        .long local_label(misc_set_invalid) /* 87 immheader  */
665        .long local_label(misc_set_invalid) /* 88 even_fixnum  */
666        .long local_label(misc_set_invalid) /* 89 cons  */
667        .long _SPgvset /* 8a value_cell  */
668        .long local_label(misc_set_invalid) /* 8b imm  */
669        .long local_label(misc_set_invalid) /* 8c odd_fixnum  */
670        .long local_label(misc_set_invalid) /* 8d tra  */
671        .long local_label(misc_set_invalid) /* 8e misc  */
672        .long local_label(misc_set_invalid) /* 8f immheader  */
673        /* 90-9*/
674        .long local_label(misc_set_invalid) /* 90 even_fixnum  */
675        .long local_label(misc_set_invalid) /* 91 cons  */
676        .long _SPgvset /* 92 xfunction  */
677        .long local_label(misc_set_invalid) /* 93 imm  */
678        .long local_label(misc_set_invalid) /* 94 odd_fixnum  */
679        .long local_label(misc_set_invalid) /* 95 tra  */
680        .long local_label(misc_set_invalid) /* 96 misc  */
681        .long local_label(misc_set_invalid) /* 97 immheader  */
682        .long local_label(misc_set_invalid) /* 98 even_fixnum  */
683        .long local_label(misc_set_invalid) /* 99 cons  */
684        .long _SPgvset /* 9a arrayH  */
685        .long local_label(misc_set_invalid) /* 9b imm  */
686        .long local_label(misc_set_invalid) /* 9c odd_fixnum  */
687        .long local_label(misc_set_invalid) /* 9d tra  */
688        .long local_label(misc_set_invalid) /* 9e misc  */
689        .long local_label(misc_set_invalid) /* 9f immheader  */
690        /* a0-af  */
691        .long local_label(misc_set_invalid) /* a0 even_fixnum  */
692        .long local_label(misc_set_invalid) /* a1 cons  */
693        .long _SPgvset /* a2 vectorH  */
694        .long local_label(misc_set_invalid) /* a3 imm  */
695        .long local_label(misc_set_invalid) /* a4 odd_fixnum  */
696        .long local_label(misc_set_invalid) /* a5 tra  */
697        .long local_label(misc_set_invalid) /* a6 misc  */
698        .long local_label(misc_set_single_float_vector) /* a7 sf_vector  */
699        .long local_label(misc_set_invalid) /* a8 even_fixnum  */
700        .long local_label(misc_set_invalid) /* a9 cons  */
701        .long _SPgvset /* aa simple_vector  */
702        .long local_label(misc_set_invalid) /* ab imm  */
703        .long local_label(misc_set_invalid) /* ac odd_fixnum  */
704        .long local_label(misc_set_invalid) /* ad tra  */
705        .long local_label(misc_set_invalid) /* ae misc  */
706        .long local_label(misc_set_u32) /* af u32  */
707        /* b0-bf  */
708        .long local_label(misc_set_invalid) /* b0 even_fixnum  */
709        .long local_label(misc_set_invalid) /* b1 cons  */
710        .long local_label(misc_set_invalid) /* b2 nodeheader  */
711        .long local_label(misc_set_invalid) /* b3 imm  */
712        .long local_label(misc_set_invalid) /* b4 odd_fixnum  */
713        .long local_label(misc_set_invalid) /* b5 tra  */
714        .long local_label(misc_set_invalid) /* b6 misc  */
715        .long local_label(misc_set_s32) /* b7 s32  */
716        .long local_label(misc_set_invalid) /* b8 even_fixnum  */
717        .long local_label(misc_set_invalid) /* b9 cons  */
718        .long local_label(misc_set_invalid) /* ba nodeheader  */
719        .long local_label(misc_set_invalid) /* bb imm  */
720        .long local_label(misc_set_invalid) /* bc odd_fixnum  */
721        .long local_label(misc_set_invalid) /* bd tra  */
722        .long local_label(misc_set_invalid) /* be misc  */
723        .long local_label(misc_set_fixnum_vector) /* bf fixnum_vector  */
724        /* c0-cf  */
725        .long local_label(misc_set_invalid) /* c0 even_fixnum  */
726        .long local_label(misc_set_invalid) /* c1 cons  */
727        .long local_label(misc_set_invalid) /* c2 nodeheader  */
728        .long local_label(misc_set_invalid) /* c3 imm  */
729        .long local_label(misc_set_invalid) /* c4 odd_fixnum  */
730        .long local_label(misc_set_invalid) /* c5 tra  */
731        .long local_label(misc_set_invalid) /* c6 misc  */
732        .long local_label(misc_set_string) /* c7 simple_base_string  */
733        .long local_label(misc_set_invalid) /* c8 even_fixnum  */
734        .long local_label(misc_set_invalid) /* c9 cons  */
735        .long local_label(misc_set_invalid) /* ca nodeheader  */
736        .long local_label(misc_set_invalid) /* cb imm  */
737        .long local_label(misc_set_invalid) /* cc odd_fixnum  */
738        .long local_label(misc_set_invalid) /* cd tra  */
739        .long local_label(misc_set_invalid) /* ce misc  */
740        .long local_label(misc_set_u8) /* cf u8  */
741        /* d0-df  */
742        .long local_label(misc_set_invalid) /* d0 even_fixnum  */
743        .long local_label(misc_set_invalid) /* d1 cons  */
744        .long local_label(misc_set_invalid) /* d2 nodeheader  */
745        .long local_label(misc_set_invalid) /* d3 imm  */
746        .long local_label(misc_set_invalid) /* d4 odd_fixnum  */
747        .long local_label(misc_set_invalid) /* d5 tra  */
748        .long local_label(misc_set_invalid) /* d6 misc  */
749        .long local_label(misc_set_s8)      /* d7 s8  */
750        .long local_label(misc_set_invalid) /* d8 even_fixnum  */
751        .long local_label(misc_set_invalid) /* d9 cons  */
752        .long local_label(misc_set_invalid) /* da nodeheader  */
753        .long local_label(misc_set_invalid) /* db imm  */
754        .long local_label(misc_set_invalid) /* dc odd_fixnum  */
755        .long local_label(misc_set_invalid) /* dd tra  */
756        .long local_label(misc_set_invalid) /* de misc  */
757        .long local_label(misc_set_invalid) /* df immheader  */
758        /* e0-ef  */
759        .long local_label(misc_set_invalid) /* e0 even_fixnum  */
760        .long local_label(misc_set_invalid) /* e1 cons  */
761        .long local_label(misc_set_invalid) /* e2 nodeheader  */
762        .long local_label(misc_set_invalid) /* e3 imm  */
763        .long local_label(misc_set_invalid) /* e4 odd_fixnum  */
764        .long local_label(misc_set_invalid) /* e5 tra  */
765        .long local_label(misc_set_invalid) /* e6 misc  */
766        .long local_label(misc_set_u16) /* e7 u16  */
767        .long local_label(misc_set_invalid) /* e8 even_fixnum  */
768        .long local_label(misc_set_invalid) /* e9 cons  */
769        .long local_label(misc_set_invalid) /* ea nodeheader  */
770        .long local_label(misc_set_invalid) /* eb imm  */
771        .long local_label(misc_set_invalid) /* ec odd_fixnum  */
772        .long local_label(misc_set_invalid) /* ed tra  */
773        .long local_label(misc_set_invalid) /* ee misc  */
774        .long local_label(misc_set_s16) /* ef s16  */
775        /* f0-ff  */
776        .long local_label(misc_set_invalid) /* f0 even_fixnum  */
777        .long local_label(misc_set_invalid) /* f1 cons  */
778        .long local_label(misc_set_invalid) /* f2 nodeheader  */
779        .long local_label(misc_set_invalid) /* f3 imm  */
780        .long local_label(misc_set_invalid) /* f4 odd_fixnum  */
781        .long local_label(misc_set_invalid) /* f5 tra  */
782        .long local_label(misc_set_invalid) /* f6 misc  */
783        .long local_label(misc_set_double_float_vector) /* f7 df vector  */
784        .long local_label(misc_set_invalid) /* f8 even_fixnum  */
785        .long local_label(misc_set_invalid) /* f9 cons  */
786        .long local_label(misc_set_invalid) /* fa nodeheader  */
787        .long local_label(misc_set_invalid) /* fb imm  */
788        .long local_label(misc_set_invalid) /* fc odd_fixnum  */
789        .long local_label(misc_set_invalid) /* fd tra  */
790        .long local_label(misc_set_invalid) /* fe misc  */
791        .long local_label(misc_set_bit_vector) /* ff bit_vector  */
792
793local_label(misc_set_function):
794        /* Functions are funny: the first N words are treated as */
795        /* (UNSIGNED-BYTE 32), where N is the low 16 bits of the first word. */
796        __(movzwl misc_data_offset(%temp0),%imm0)
797        /* XXX bootstrapping */
798        __(btr $15,%imm0)
799        __(jnc 0f)
800        __(movl $0xffffff00,%temp1)
801        __(andl misc_header_offset(%temp0),%temp1)
802        __(shr $num_subtag_bits-fixnumshift,%temp1)
803        __(shl $fixnumshift,%imm0)
804        __(subl %imm0,%temp1)
805        __(movl %temp1,%imm0)
806        __(shr $fixnumshift,%imm0)
8070:
808        __(shl $fixnumshift,%imm0)
809        __(rcmpl(%arg_y,%imm0))
810        __(jae _SPgvset)
811local_label(misc_set_u32):
812        /* Either a non-negative fixnum, a positive one-digit bignum, or */
813        /* a two-digit bignum whose sign-digit is 0 is OK. */
814        __(movl $~(target_most_positive_fixnum <<fixnumshift),%imm0)
815        __(test %arg_z,%imm0)
816        __(movl %arg_z,%imm0)
817        __(jne 1f)
818        __(sarl $fixnumshift,%imm0)
819        __(jmp 9f)
8201:      __(andb $tagmask,%imm0_b)
821        __(cmpb $tag_misc,%imm0_b)
822        __(jne local_label(misc_set_bad))
823        __(movb misc_subtag_offset(%arg_z),%imm0_b)
824        __(cmpb $subtag_bignum,%imm0_b)
825        __(jne local_label(misc_set_bad))
826        __(movl misc_header_offset(%arg_z),%imm0)
827        __(cmpl $two_digit_bignum_header,%imm0)
828        __(je 3f)
829        __(cmpl $one_digit_bignum_header,%imm0)
830        __(jne local_label(misc_set_bad))
831        __(movl misc_data_offset(%arg_z),%imm0)
832        __(testl %imm0,%imm0)
833        __(js local_label(misc_set_bad))
834        __(jmp 9f)
8353:      __(movl misc_data_offset(%arg_z),%imm0)
836        __(cmpl $0,misc_data_offset+4(%arg_z))
837        __(jne local_label(misc_set_bad))
8389:      __(movl %imm0,misc_data_offset(%temp0,%arg_y))
839        __(ret)
840local_label(misc_set_s32):
841        __(unbox_fixnum(%arg_z,%imm0))
842        __(testb $fixnummask,%arg_z_b)
843        __(je 9f)
8441:      __(movb %arg_z_b,%imm0_b)
845        __(andb $tagmask,%imm0_b)
846        __(cmpb $tag_misc,%imm0_b)
847        __(jne local_label(misc_set_bad))
848        __(movl misc_header_offset(%arg_z),%imm0)
849        __(cmpl $one_digit_bignum_header,%imm0)
850        __(jne local_label(misc_set_bad))
851        __(movl misc_data_offset(%arg_z),%imm0)
8529:      __(movl %imm0,misc_data_offset(%temp0,%arg_y))
853        __(ret)
854local_label(misc_set_bad):
855        __(movl %arg_z,%arg_y)
856        __(movl %temp0,%arg_z)
857        __(pop %temp1)  /* return addr */
858        __(push $reserved_frame_marker)
859        __(push $reserved_frame_marker)
860        __(push $XNOTELT)
861        __(push %temp1)
862        __(set_nargs(3))
863        __(jmp _SPksignalerr)
864local_label(misc_set_single_float_vector):
865        __(extract_lisptag(%arg_z,%imm0))
866        __(cmpb $tag_misc,%imm0_b)
867        __(jne local_label(misc_set_bad))
868        __(movb misc_subtag_offset(%arg_z),%imm0_b)
869        __(cmpb $subtag_single_float,%imm0_b)
870        __(jne local_label(misc_set_bad))
871        __(movl single_float.value(%arg_z),%imm0)
872        __(movl %imm0,misc_data_offset(%temp0,%arg_y))
873        __(ret)
874local_label(misc_set_double_float_vector):
875        __(extract_lisptag(%arg_z,%imm0))
876        __(cmpb $tag_misc,%imm0_b)
877        __(jne local_label(misc_set_bad))
878        __(movb misc_subtag_offset(%arg_z),%imm0_b)
879        __(cmpb $subtag_double_float,%imm0_b)
880        __(jne local_label(misc_set_bad))
881        __(movsd double_float.value(%arg_z),%fp0)
882        __(movsd %fp0,misc_dfloat_offset(%temp0,%arg_y,2))
883        __(ret)
884local_label(misc_set_fixnum_vector):
885        __(unbox_fixnum(%arg_z,%imm0))
886        __(testb $fixnummask,%arg_z_b)
887        __(jne local_label(misc_set_bad))
888        __(movl %imm0,misc_data_offset(%temp0,%arg_y))
889        __(ret)
890local_label(misc_set_u8):
891        __(testl $~(0xff<<fixnumshift),%arg_z)
892        __(jne local_label(misc_set_bad))
893        __(unbox_fixnum(%arg_y,%imm0))
894        __(movl %arg_z,%arg_y)
895        __(shll $8-fixnumshift,%arg_z)
896        __(movb %arg_z_bh,misc_data_offset(%temp0,%imm0))
897        __(movl %arg_y,%arg_z)
898        __(ret)
899local_label(misc_set_s8):
900        __(movl %arg_z,%imm0)
901        __(shll $32-(8+fixnumshift),%imm0)
902        __(sarl $32-(8+fixnumshift),%imm0)
903        __(cmpl %arg_z,%imm0)
904        __(jne local_label(misc_set_bad))
905        __(testb $fixnummask,%arg_z_b)
906        __(jne local_label(misc_set_bad))
907        __(unbox_fixnum(%arg_y,%imm0))
908        __(movl %arg_z,%arg_z)
909        __(shll $8-fixnumshift,%arg_z)
910        __(movb %arg_z_bh,misc_data_offset(%temp0,%imm0))
911        __(movl %arg_y,%arg_z)
912        __(ret)
913local_label(misc_set_string):
914        __(cmpb $subtag_character,%arg_z_b)
915        __(jne local_label(misc_set_bad))
916        __(movl %arg_z,%imm0)
917        __(shrl $charcode_shift,%imm0)
918        __(movl %imm0,misc_data_offset(%temp0,%arg_y))
919        __(ret)
920local_label(misc_set_u16):
921        __(testl $~(0xffff<<fixnumshift),%arg_z)
922        __(jne local_label(misc_set_bad))
923        __(movl %arg_y,%imm0)
924        __(shrl $1,%imm0)
925        __(mark_as_imm(%temp1))
926        __(unbox_fixnum(%arg_z,%temp1))
927        __(movw %temp1_w,misc_data_offset(%temp0,%imm0))
928        __(mark_as_node(%temp1))
929        __(ret)
930local_label(misc_set_s16):
931        __(movl %arg_z,%imm0)
932        __(shll $32-(16+fixnumshift),%imm0)
933        __(sarl $32-(16+fixnumshift),%imm0)
934        __(cmpl %arg_z,%imm0)
935        __(jne local_label(misc_set_bad))
936        __(testb $fixnummask,%arg_z_b)
937        __(jne local_label(misc_set_bad))
938        __(movl %arg_y,%imm0)
939        __(shrl $1,%imm0)
940        __(mark_as_imm(%temp1))
941        __(unbox_fixnum(%arg_z,%temp1))
942        __(movw %temp1_w,misc_data_offset(%temp0,%imm0))
943        __(mark_as_node(%temp1))
944        __(ret)
945local_label(misc_set_bit_vector):
946        __(testl $~fixnumone,%arg_z)
947        __(jne local_label(misc_set_bad))
948        __(unbox_fixnum(%arg_y,%imm0))
949        __(testb %arg_z_b,%arg_z_b)
950        __(je local_label(misc_set_clr_bit))
951local_label(misc_set_set_bit):
952        __(btsl %imm0,misc_data_offset(%temp0))
953        __(ret)
954local_label(misc_set_clr_bit):
955        __(btrl %imm0,misc_data_offset(%temp0))
956        __(ret)
957local_label(misc_set_invalid):
958        __(pop %temp1)  /* return addr */
959        __(push $reserved_frame_marker)
960        __(push $reserved_frame_marker)
961        __(push $XSETBADVEC)
962        __(push %temp0)
963        __(push %temp1)
964        __(set_nargs(4))
965        __(jmp _SPksignalerr)
966_endfn(C(misc_set_common))
967
968_spentry(Fret1valn)
969        .globl C(ret1valn)
970__(tra(C(ret1valn)))
971        __(mov (%esp),%ra0)
972        __(mov %arg_z,(%esp))
973        __(set_nargs(1))
974        __(jmp *%ra0)
975_endsubp(Fret1valn)
976
977_spentry(nvalret)
978        .globl C(nvalret)
979C(nvalret):
980        __(ref_global(ret1val_addr,%temp0))
981        __(cmpl lisp_frame.savera0(%ebp),%temp0)
982        __(je 1f)
983        __(test %nargs,%nargs)
984        __(movl $nil_value,%arg_z)
985        __(cmovnel -node_size(%esp,%nargs),%arg_z)
986        __(leave)
987        __(ret)
988
989/* actually need to return values; always need to copy. */
9901:      __(lea 2*node_size(%ebp),%imm0)
991        __(pushl (%imm0))
992        __(movl 0(%ebp),%ebp)
993        __(addl $node_size,%imm0)
994        __(lea node_size(%esp,%nargs),%temp0)
995        __(xorl %arg_y,%arg_y)
996        __(jmp 3f)
9972:      __(movl -node_size(%temp0),%arg_z)
998        __(subl $node_size,%temp0)
999        __(addl $node_size,%arg_y)
1000        __(movl %arg_z,-node_size(%imm0))
1001        __(subl $node_size,%imm0)
10023:      __(cmpl %arg_y,%nargs)
1003        __(jne 2b)
1004        __(pop %ra0)
1005        __(movl %imm0,%esp)
1006        __(jmp *%ra0)
1007_endsubp(nvalret)
1008
1009_spentry(jmpsym)
1010        __(jump_fname())
1011_endsubp(jmpsym)
1012
1013_spentry(jmpnfn)
1014        __(mov %temp0,%fn)
1015        __(jmp *%fn)
1016_endsubp(jmpnfn)
1017
1018_spentry(funcall)
1019        __(do_funcall())
1020_endsubp(funcall)
1021
1022/* Make a lisp integer (fixnum or one-digit bignum) from the value in %imm0 */
1023_spentry(makes32)
1024        __(imull $fixnumone,%imm0,%arg_z)       /* result is fixnum-tagged */
1025        __(jno 0f)                              /* but may have overflowed */
1026        __(movd %imm0,%mm1)
1027        __(movl $one_digit_bignum_header,%imm0)
1028        __(movd %imm0,%mm0)
1029        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
1030        __(movd %mm1,misc_data_offset(%arg_z))
10310:      __(repret)
1032_endsubp(makes32)
1033
1034/* Make a lisp integer out of the unboxed 64-bit word in %mm0. */
1035/* This is a little clumsy, but the alternative requires callers to */
1036/* have already marked %edx as an imm reg (or else store it in memory
1037/* somewhere), and I'm nervous about */
1038/* splitting up the mark-as-imm/mark-as-node between two separate */
1039/* pieces of code. */
1040_spentry(makes64)
1041        __(movq %mm0,%mm2)
1042        __(pshufw $0x4e,%mm0,%mm1)      /* swap hi/lo halves */
1043        __(psrad $31,%mm0)      /* propagate sign */
1044        __(pcmpeqd %mm0,%mm1)   /* all ones if equal */
1045        __(movd %mm1,%imm0)
1046        __(cmpb $-1,%imm0_b)    /* upper half just sign extension? */
1047        __(jne 1f)
1048        __(movd %mm2,%imm0)
1049        __(jmp _SPmakes32)
10501:      __(movl $two_digit_bignum_header,%imm0)
1051        __(movd %imm0,%mm0)
1052        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
1053        __(movq %mm2,misc_data_offset(%arg_z))
1054        __(ret)
1055_endsubp(makes64)
1056
1057_spentry(syscall)
1058        /* Save lisp registers */
1059        __(push %ebp)
1060        __(movl %esp,%ebp)
1061        __(push %temp0)
1062        __(push %temp1)
1063        __(push %arg_y)
1064        __(push %arg_z)
1065        __(push %fn)
1066        __(movl %esp,rcontext(tcr.save_vsp))
1067        __(movl %ebp,rcontext(tcr.save_ebp))
1068        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
1069        __(movl rcontext(tcr.foreign_sp),%esp)
1070        __(emms)
1071        __(pop %ebp)            /* backlink */
1072        __(lea 15(%esp),%edx)
1073        __(andl $-16,%edx)
1074        __(movl %edx,%esp)
1075        __(unbox_fixnum(%arg_z,%eax))   /* syscall number */
1076        __(movl $local_label(back_from_sysenter),%edx)
1077        __(push %edx)
1078        __(movl %esp,%ecx)
1079        __(sysenter)
1080local_label(back_from_sysenter):
1081        __(jnc 0f)
1082        __(neg %eax)
10830:     
1084        __(movl %ebp,%esp)
1085        __(movl %esp,rcontext(tcr.foreign_sp))
1086        __(clr %arg_z)
1087        __(clr %arg_y)
1088        __(clr %temp1)
1089        __(clr %temp0)
1090        __(clr %fn)
1091        __(pxor %fpzero,%fpzero)
1092        __(movl rcontext(tcr.save_vsp),%esp)
1093        __(movl rcontext(tcr.save_ebp),%ebp)
1094        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
1095        __(pop %fn)
1096        __(pop %arg_z)
1097        __(pop %arg_y)
1098        __(pop %temp1)
1099        __(check_pending_interrupt(%temp0))
1100        __(pop %temp0)
1101        __(leave)
1102        __(ret)
1103_endsubp(syscall)
1104
1105/* Make system call that returns a doubleword result in %edx:%eax and */
1106/* copy the result into %mm0. */
1107_spentry(syscall2)
1108        /* Save lisp registers */
1109        __(push %ebp)
1110        __(movl %esp,%ebp)
1111        __(push %temp0)
1112        __(push %temp1)
1113        __(push %arg_y)
1114        __(push %arg_z)
1115        __(push %fn)
1116        __(movl %esp,rcontext(tcr.save_vsp))
1117        __(movl %ebp,rcontext(tcr.save_ebp))
1118        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
1119        __(movl rcontext(tcr.foreign_sp),%esp)
1120        __(emms)
1121        __(pop %ebp)            /* backlink */
1122        __(lea 15(%esp),%edx)
1123        __(andl $-16,%edx)
1124        __(movl %edx,%esp)
1125        __(unbox_fixnum(%arg_z,%eax))   /* syscall number */
1126        __(pushl $local_label(back_from_syscall))
1127        __(int $0x80)
1128local_label(back_from_syscall):
1129        __(jnc 0f)
1130        __(neg %eax)
1131        __(movl $-1,%edx)
11320:
1133        /* just use memory rather than screwing around with */
1134        /* movd %eax,%mm0, movd %edx,%mm1, psllq $32,%mm1, por %mm1,%mm0 */
1135        __(push %edx)
1136        __(push %eax)
1137        __(movq (%esp),%mm0)
1138        __(movl %ebp,%esp)
1139        __(movl %esp,rcontext(tcr.foreign_sp))
1140        __(clr %arg_z)
1141        __(clr %arg_y)
1142        __(clr %temp1)
1143        __(clr %temp0)
1144        __(clr %fn)
1145        __(pxor %fpzero,%fpzero)
1146        __(movl rcontext(tcr.save_vsp),%esp)
1147        __(movl rcontext(tcr.save_ebp),%ebp)
1148        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
1149        __(pop %fn)
1150        __(pop %arg_z)
1151        __(pop %arg_y)
1152        __(pop %temp1)
1153        __(check_pending_interrupt(%temp0))
1154        __(pop %temp0)
1155        __(leave)
1156        __(ret)
1157_endsubp(syscall2)
1158
1159
1160_spentry(mkcatch1v)
1161        __(nMake_Catch(0))
1162        __(ret)
1163_endsubp(mkcatch1v)
1164
1165_spentry(mkunwind)
1166        __(movl $undefined,%arg_z)
1167        __(Make_Catch(fixnumone))
1168        __(jmp *%ra0)
1169_endsubp(mkunwind)
1170
1171/* this takes a return address in %ra0; it's "new" in that it does the */
1172/*   double binding of *interrupt-level* out-of-line */
1173_spentry(nmkunwind)
1174        __(movl rcontext(tcr.tlb_pointer),%arg_z)
1175        __(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_z),%arg_y)
1176        __(push %arg_y)
1177        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
1178        __(push rcontext(tcr.db_link))
1179        __(movl %esp,rcontext(tcr.db_link))
1180        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_z))
1181        __(movl $undefined,%arg_z)
1182        /* %arg_z = tag, %xfn (%temp1) = pc */
1183        __(Make_Catch(fixnumone))
1184        __(movl %arg_y,%arg_z)
1185        __(jmp _SPbind_interrupt_level)
1186_endsubp(nmkunwind)
1187
1188_spentry(mkcatchmv)
1189        __(nMake_Catch(fixnumone))
1190        __(ret)
1191_endsubp(mkcatchmv)
1192
1193_spentry(throw)
1194        __(movl rcontext(tcr.catch_top),%imm0)
1195        __(movl (%esp,%nargs),%arg_y)   /* arg_y = tag   */
1196        __(movd %nargs,%mm0)
1197        __(xorl %temp1,%temp1)
1198        __(jmp local_label(_throw_test))
1199local_label(_throw_loop):
1200        __(cmpl %arg_y,catch_frame.catch_tag(%imm0))
1201        __(je local_label(_throw_found))
1202        __(movl catch_frame.link(%imm0),%imm0)
1203        __(addl $fixnum_one,%temp1)
1204local_label(_throw_test):
1205        __(test %imm0,%imm0)
1206        __(jne local_label(_throw_loop))
1207        __(push %ra0)
1208        __(uuo_error_reg_not_tag(Rarg_y,subtag_catch_frame))
1209        __(pop %ra0)
1210        __(jmp _SPthrow)
1211local_label(_throw_found):
1212        __(testb $fulltagmask,catch_frame.mvflag(%imm0))
1213        __(movl %temp1,%imm0)
1214        __(movd %mm0,%nargs)
1215        __(jne local_label(_throw_multiple))
1216        __(movl $nil_value,%arg_z)
1217        __(test %nargs,%nargs)
1218        __(je local_label(_throw_one_value))
1219        __(movl -node_size(%esp,%nargs),%arg_z)
1220        __(add %nargs,%esp)
1221local_label(_throw_one_value):
1222        __(movl $local_label(_threw_one_value),%ra0)
1223        __(jmp _SPnthrow1value)
1224__(tra(local_label(_threw_one_value)))
1225        __(movl rcontext(tcr.catch_top),%arg_y)
1226        __(movl catch_frame.db_link(%arg_y),%imm0)
1227        __(cmpl %imm0,rcontext(tcr.db_link))
1228        __(jz local_label(_threw_one_value_dont_unbind))
1229        __(push $local_label(_threw_one_value_dont_unbind))
1230        __(jmp _SPunbind_to)    /* preserves registers */
1231__(tra(local_label(_threw_one_value_dont_unbind)))
1232        __(movl catch_frame.ebp(%arg_y),%ebp)
1233        __(movl catch_frame.foreign_sp(%arg_y),%imm0)
1234        __(movl %imm0,rcontext(tcr.foreign_sp))
1235        __(movl catch_frame.xframe(%arg_y),%imm0)
1236        __(movl %imm0,rcontext(tcr.xframe))
1237        __(movl catch_frame.esp(%arg_y),%esp)
1238        __(movl catch_frame.link(%arg_y),%imm0)
1239        __(movl %imm0,rcontext(tcr.catch_top))
1240        __(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%arg_y),%imm0)
1241        __(movl (%imm0),%imm0)
1242        __(movl %imm0,rcontext(tcr.save_tsp))
1243        __(movl %imm0,rcontext(tcr.next_tsp))
1244        __(movl catch_frame.pc(%arg_y),%ra0)
1245        __(jmp *%ra0)
1246local_label(_throw_multiple):
1247        __(movl $local_label(_threw_multiple),%ra0)
1248        __(jmp _SPnthrowvalues)
1249__(tra(local_label(_threw_multiple)))
1250        __(movl rcontext(tcr.catch_top),%arg_y)
1251        __(movl catch_frame.db_link(%arg_y),%imm0)
1252        __(cmpl %imm0,rcontext(tcr.db_link))
1253        __(je local_label(_threw_multiple_dont_unbind))
1254        __(push $local_label(_threw_multiple_dont_unbind))
1255        __(jmp _SPunbind_to)    /* preserves registers */
1256__(tra(local_label(_threw_multiple_dont_unbind)))
1257        /* Copy multiple values from the current %esp to the target %esp   */
1258        __(lea (%esp,%nargs),%imm0)
1259        __(movd %nargs,%mm0)    /* nargs is aka temp1 */
1260        __(movl catch_frame.esp(%arg_y),%temp1)
1261        __(jmp local_label(_threw_multiple_push_test))
1262local_label(_threw_multiple_push_loop):
1263        __(subl $node_size,%imm0)
1264        __(subl $node_size,%temp1)
1265        __(movl (%imm0),%arg_z)
1266        __(movl %arg_z,(%temp1))
1267local_label(_threw_multiple_push_test):
1268        __(cmpl %imm0,%esp)
1269        __(jne local_label(_threw_multiple_push_loop))
1270        /* target %esp is now in %temp1   */
1271        __(movl catch_frame.ebp(%arg_y),%ebp)
1272        __(movl catch_frame.foreign_sp(%arg_y),%imm0)
1273        __(movl %imm0,rcontext(tcr.foreign_sp))       
1274        __(movl catch_frame.xframe(%arg_y),%imm0)
1275        __(movl %imm0,rcontext(tcr.xframe))
1276        __(movl %temp1,%esp)
1277        __(movl catch_frame.link(%arg_y),%temp1)
1278        __(movl %temp1,rcontext(tcr.catch_top))
1279        __(movd %mm0,%nargs)
1280        __(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%arg_y),%imm0)
1281        __(movl catch_frame.pc(%arg_y),%ra0)
1282        __(movl (%imm0),%imm0)
1283        __(movl %imm0,rcontext(tcr.save_tsp))
1284        __(movl %imm0,rcontext(tcr.next_tsp))
1285        __(jmp *%ra0)
1286_endsubp(throw)
1287
1288        /* This takes N multiple values atop the vstack.   */
1289_spentry(nthrowvalues)
1290        __(movb $1,rcontext(tcr.unwinding))
1291        __(movl %ra0,rcontext(tcr.save0)) /* %ra0 (aka %temp0) to spill area */
1292local_label(_nthrowv_nextframe):
1293        __(subl $fixnumone,%imm0)
1294        __(js local_label(_nthrowv_done))
1295        __(movd %imm0,%mm1)
1296        __(movl rcontext(tcr.catch_top),%temp0)
1297        __(movl catch_frame.link(%temp0),%imm0)
1298        __(movl %imm0,rcontext(tcr.catch_top))
1299        __(movl catch_frame.db_link(%temp0),%imm0)
1300        __(cmpl %imm0,rcontext(tcr.db_link))
1301        __(jz local_label(_nthrowv_dont_unbind))
1302        __(push %temp1)
1303        __(push %temp0)
1304        __(push $local_label(_nthrowv_back_from_unbind))
1305        __(jmp _SPunbind_to)
1306__(tra(local_label(_nthrowv_back_from_unbind)))
1307        __(pop %temp0)
1308        __(pop %temp1)
1309local_label(_nthrowv_dont_unbind):
1310        __(cmpb $unbound_marker,catch_frame.catch_tag(%temp0))
1311        __(je local_label(_nthrowv_do_unwind))
1312/* A catch frame.  If the last one, restore context from there.   */
1313        __(movd %mm1,%imm0)
1314        __(test %imm0,%imm0)    /* last catch frame ?   */
1315        __(jne local_label(_nthrowv_skip))
1316        __(movl catch_frame.xframe(%temp0),%arg_y)
1317        __(movl %arg_y,rcontext(tcr.xframe))
1318        __(lea (%esp,%nargs),%arg_y)
1319        __(movl catch_frame.esp(%temp0),%arg_z)
1320        __(movd %nargs,%mm2)
1321        __(jmp local_label(_nthrowv_push_test))
1322local_label(_nthrowv_push_loop):
1323        __(subl $node_size,%arg_y)
1324        __(subl $node_size,%arg_z)
1325        __(movd (%arg_y),%mm0)
1326        __(movd %mm0,(%arg_z))
1327local_label(_nthrowv_push_test):
1328        __(subl $node_size,%nargs)
1329        __(jns local_label(_nthrowv_push_loop))
1330        __(movd %mm2,%nargs)
1331        __(movl catch_frame.xframe(%temp0),%arg_y)
1332        __(movl %arg_y,rcontext(tcr.xframe))
1333        __(movl %arg_z,%esp)
1334        __(movl catch_frame.ebp(%temp0),%ebp)
1335        __(movd catch_frame.foreign_sp(%temp0),%stack_temp)
1336        __(movd %stack_temp,rcontext(tcr.foreign_sp))       
1337local_label(_nthrowv_skip):     
1338        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm0)
1339        __(movl %imm0,rcontext(tcr.save_tsp))
1340        __(movl %imm0,rcontext(tcr.next_tsp))
1341        __(movd %mm1,%imm0)
1342        __(jmp local_label(_nthrowv_nextframe))
1343local_label(_nthrowv_do_unwind):       
1344/* This is harder.  Call the cleanup code with the multiple values and   */
1345/* nargs, the throw count, and the caller's return address in a temp  */
1346/* stack frame.   */
1347        __(leal (%esp,%nargs),%arg_y)
1348        __(push catch_frame.pc(%temp0))
1349        __(movl catch_frame.ebp(%temp0),%ebp)
1350        __(movd catch_frame.xframe(%temp0),%stack_temp)
1351        __(movd %stack_temp,rcontext(tcr.xframe))
1352        __(movl catch_frame.esp(%temp0),%arg_z)
1353        __(movd catch_frame.foreign_sp(%temp0),%stack_temp)
1354        __(movd %stack_temp,rcontext(tcr.foreign_sp))       
1355        /* Discard the catch frame, so we can build a temp frame   */
1356        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm0)
1357        __(movl %imm0,rcontext(tcr.save_tsp))
1358        __(movl %imm0,rcontext(tcr.next_tsp))
1359        __(movd %temp1,%mm2) /* save %nargs */
1360        /* tsp overhead, nargs, throw count, ra0   */
1361        __(dnode_align(%nargs,(tsp_frame.fixed_overhead+(3*node_size)),%imm0))
1362        __(movl %imm0,%temp1)
1363        __(TSP_Alloc_Var(%temp1,%imm0))
1364        __(movd %mm2,%temp1) /* aka %nargs */
1365
1366        __(movl %nargs,(%imm0))
1367        __(movl rcontext(tcr.save0),%ra0)
1368        __(movl %ra0,node_size(%imm0))
1369        __(movd %mm1,node_size*2(%imm0))
1370        __(leal node_size*3(%imm0),%imm0)
1371        __(jmp local_label(_nthrowv_tpushtest))
1372local_label(_nthrowv_tpushloop):
1373        __(movl -node_size(%arg_y),%temp0)
1374        __(subl $node_size,%arg_y)
1375        __(movl %temp0,(%imm0))
1376        __(addl $node_size,%imm0)
1377local_label(_nthrowv_tpushtest):
1378        __(subl $node_size,%nargs)
1379        __(jns local_label(_nthrowv_tpushloop))
1380        __(pop %xfn)    /* aka %temp1/%nargs */
1381        __(movl %arg_z,%esp)
1382/* Ready to call cleanup code. set up tra, jmp to %xfn   */
1383        __(push $local_label(_nthrowv_called_cleanup))
1384        __(movb $0,rcontext(tcr.unwinding))
1385        __(jmp *%xfn)
1386__(tra(local_label(_nthrowv_called_cleanup)))
1387
1388        __(movb $1,rcontext(tcr.unwinding))
1389        __(movl rcontext(tcr.save_tsp),%imm0)
1390        __(movl tsp_frame.data_offset+(0*node_size)(%imm0),%nargs)
1391        __(movl tsp_frame.data_offset+(1*node_size)(%imm0),%ra0)
1392        __(movl %ra0,rcontext(tcr.save0))
1393        __(movd tsp_frame.data_offset+(2*node_size)(%imm0),%mm1)
1394        __(movd %nargs,%mm2)
1395        __(addl $tsp_frame.fixed_overhead+(node_size*3),%imm0)
1396        __(jmp local_label(_nthrowv_tpoptest))
1397local_label(_nthrowv_tpoploop):
1398        __(push (%imm0))
1399        __(addl $node_size,%imm0)
1400local_label(_nthrowv_tpoptest):
1401        __(subl $node_size,%nargs)
1402        __(jns local_label(_nthrowv_tpoploop))
1403        __(movd %mm2,%nargs)
1404        __(movl rcontext(tcr.save_tsp),%imm0)
1405        __(movl (%imm0),%imm0)
1406        __(movl %imm0,rcontext(tcr.save_tsp))
1407        __(movl %imm0,rcontext(tcr.next_tsp))
1408        __(movd %mm1,%imm0)
1409        __(jmp local_label(_nthrowv_nextframe))
1410local_label(_nthrowv_done):
1411        __(movb $0,rcontext(tcr.unwinding))
1412        __(check_pending_interrupt(%imm0))
1413local_label(_nthrowv_return):
1414        __(movl rcontext(tcr.save0),%ra0)
1415        __(movss %fpzero,rcontext(tcr.save0))
1416        __(jmp *%ra0)   
1417_endsubp(nthrowvalues)
1418
1419/* This is a (slight) optimization.  When running an unwind-protect,  */
1420/* save the single value and the throw count in the tstack frame.  */
1421/* Note that this takes a single value in arg_z.  */
1422
1423_spentry(nthrow1value)
1424        __(movb $1,rcontext(tcr.unwinding))
1425local_label(_nthrow1v_nextframe):
1426        __(subl $fixnumone,%imm0)
1427        __(js local_label(_nthrow1v_done))
1428        __(movd %imm0,%mm0)
1429        __(movl rcontext(tcr.catch_top),%temp1)
1430        __(movl catch_frame.link(%temp1),%imm0)
1431        __(movl %imm0,rcontext(tcr.catch_top))
1432        __(movl catch_frame.db_link(%temp1),%imm0)
1433        __(cmpl %imm0,rcontext(tcr.db_link))
1434        __(jz local_label(_nthrow1v_dont_unbind))
1435        __(push %temp1)
1436        __(push %temp0)
1437        __(push %arg_z)
1438        __(push `$'local_label(_nthrow1v_back_from_unbind))
1439        __(jmp _SPunbind_to)
1440__(tra(local_label(_nthrow1v_back_from_unbind)))
1441        __(pop %arg_z)
1442        __(pop %temp0)
1443        __(pop %temp1)
1444local_label(_nthrow1v_dont_unbind):
1445        __(cmpb $unbound_marker,catch_frame.catch_tag(%temp1))
1446        __(je local_label(_nthrow1v_do_unwind))
1447/* A catch frame.  If the last one, restore context from there. */
1448        __(movd %mm0,%imm0)
1449        __(test %imm0,%imm0)    /* last catch frame? */
1450        __(jne local_label(_nthrow1v_skip))
1451        __(movl catch_frame.xframe(%temp1),%arg_y)
1452        __(movl %arg_y,rcontext(tcr.xframe))
1453        __(movl catch_frame.esp(%temp1),%esp)
1454        __(movl catch_frame.ebp(%temp1),%ebp)
1455        __(movd catch_frame.foreign_sp(%temp1),%stack_temp)
1456        __(movd %stack_temp,rcontext(tcr.foreign_sp))
1457local_label(_nthrow1v_skip):
1458        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp1),%imm0)
1459        __(movl %imm0,rcontext(tcr.save_tsp))
1460        __(movl %imm0,rcontext(tcr.next_tsp))
1461        __(movd %mm0,%imm0)
1462        __(jmp local_label(_nthrow1v_nextframe))
1463local_label(_nthrow1v_do_unwind):
1464/* This is harder, but not as hard (not as much BLTing) as the */
1465/* multiple-value case. */
1466        __(movl catch_frame.xframe(%temp1),%arg_y)
1467        __(movl %arg_y,rcontext(tcr.xframe))
1468        __(movl catch_frame.ebp(%temp1),%ebp)
1469        __(movl catch_frame.esp(%temp1),%esp)
1470        __(movd catch_frame.foreign_sp(%temp1),%stack_temp)
1471        __(movd %stack_temp,rcontext(tcr.foreign_sp))
1472        /* Discard the catch frame so we can build a temp frame. */
1473        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp1),%imm0)
1474        __(movl %imm0,rcontext(tcr.save_tsp))
1475        __(movl %imm0,rcontext(tcr.next_tsp))
1476        __(movl catch_frame.pc(%temp1),%xfn) /* xfn is temp1 */
1477        __(TSP_Alloc_Fixed((3*node_size),%imm0))
1478        __(addl $tsp_frame.fixed_overhead,%imm0)
1479        __(movl %ra0,(%imm0))
1480        __(movd %mm0,node_size*1(%imm0))
1481        __(movl %arg_z,node_size*2(%imm0))
1482/* Ready to call cleanup code.  Set up tra, jmp to %xfn. */
1483        __(push $local_label(_nthrow1v_called_cleanup))
1484        __(movb $0,rcontext(tcr.unwinding))
1485        __(jmp *%xfn)
1486__(tra(local_label(_nthrow1v_called_cleanup)))
1487        __(movb $1,rcontext(tcr.unwinding))
1488        __(movl rcontext(tcr.save_tsp),%imm0)
1489        __(movl tsp_frame.data_offset+(0*node_size)(%imm0),%ra0)
1490        __(movd tsp_frame.data_offset+(1*node_size)(%imm0),%mm0)
1491        __(movl tsp_frame.data_offset+(2*node_size)(%imm0),%arg_z)
1492        __(movl (%imm0),%imm0)
1493        __(movl %imm0,rcontext(tcr.save_tsp))
1494        __(movl %imm0,rcontext(tcr.next_tsp))
1495        __(movd %mm0,%imm0)
1496        __(jmp local_label(_nthrow1v_nextframe))
1497local_label(_nthrow1v_done):
1498        __(movb $0,rcontext(tcr.unwinding))
1499        __(check_pending_interrupt(%imm0))
1500local_label(_nthrow1v_return):
1501        __(jmp *%ra0)
1502_endsubp(nthrow1value)
1503
1504/* This never affects the symbol's vcell   */
1505/* Non-null symbol in arg_y, new value in arg_z           */
1506
1507_spentry(bind)
1508        __(movl symbol.binding_index(%arg_y),%imm0)
1509        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1510        __(jb 0f)
1511        __(push %imm0)
1512        __(tlb_too_small())
15130:      __(test %imm0,%imm0)
1514        __(jz 9f)
1515        __(movl rcontext(tcr.tlb_pointer),%temp1)
1516        __(push (%temp1,%imm0))
1517        __(push %imm0)
1518        __(push rcontext(tcr.db_link))
1519        __(movl %esp,rcontext(tcr.db_link))
1520        __(movl %arg_z,(%temp1,%imm0))
1521        __(jmp *%ra0)
15229:     
1523        __(movl %arg_y,%arg_z)
1524        __(movl $XSYMNOBIND,%arg_y)
1525        __(set_nargs(2))
1526        __(push %ra0)
1527        __(jmp _SPksignalerr)
1528_endsubp(bind)
1529
1530/* arg_z = symbol: bind it to its current value  */
1531
1532_spentry(bind_self)
1533        __(movl symbol.binding_index(%arg_z),%imm0)
1534        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1535        __(jb 0f)
1536        __(push %imm0)
1537        __(tlb_too_small())
15380:      __(test %imm0,%imm0)
1539        __(jz 9f)
1540        __(movl rcontext(tcr.tlb_pointer),%temp1)
1541        __(cmpb $no_thread_local_binding_marker,(%temp1,%imm0))
1542        __(jz 2f)
1543        __(push (%temp1,%imm0))
1544        __(push %imm0)
1545        __(push rcontext(tcr.db_link))
1546        __(movl %esp,rcontext(tcr.db_link))
1547        __(jmp *%ra0)
15482:      __(movl symbol.vcell(%arg_z),%arg_y)
1549        __(push (%temp1,%imm0))
1550        __(push %imm0)
1551        __(push rcontext(tcr.db_link))
1552        __(movl %arg_y,(%temp1,%imm0))
1553        __(movl %esp,rcontext(tcr.db_link))
1554        __(jmp *%ra0)
15559:      __(movl $XSYMNOBIND,%arg_y)
1556        __(set_nargs(2))
1557        __(push %ra0)
1558        __(jmp _SPksignalerr)
1559_endsubp(bind_self)
1560
1561_spentry(bind_nil)
1562        __(movl symbol.binding_index(%arg_z),%imm0)
1563        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1564        __(jb 0f)
1565        __(push %imm0)
1566        __(tlb_too_small())
15670:      __(test %imm0,%imm0)
1568        __(jz 9f)
1569        __(movl rcontext(tcr.tlb_pointer),%temp1)
1570        __(push (%temp1,%imm0))
1571        __(push %imm0)
1572        __(push rcontext(tcr.db_link))
1573        __(movl %esp,rcontext(tcr.db_link))
1574        __(movl $nil_value,(%temp1,%imm0))
1575        __(jmp *%ra0)
15769:      __(movl $XSYMNOBIND,%arg_y)
1577        __(set_nargs(2))
1578        __(push %ra0)
1579        __(jmp _SPksignalerr)
1580_endsubp(bind_nil)
1581
1582_spentry(bind_self_boundp_check)
1583        __(movl symbol.binding_index(%arg_z),%imm0)
1584        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1585        __(jb 0f)
1586        __(push %imm0)
1587        __(tlb_too_small())
15880:      __(test %imm0,%imm0)
1589        __(jz 9f)
1590        __(movl rcontext(tcr.tlb_pointer),%temp1)
1591        __(cmpb $no_thread_local_binding_marker,(%temp1,%imm0))
1592        __(je 2f)
1593        __(cmpb $unbound_marker,(%temp1,%imm0))
1594        __(je 8f)
1595        __(push (%temp1,%imm0))
1596        __(push %imm0)
1597        __(push rcontext(tcr.db_link))
1598        __(movl %esp,rcontext(tcr.db_link))
1599        __(jmp *%ra0)
16002:      __(movl symbol.vcell(%arg_z),%arg_y)
1601        __(cmpl $unbound_marker,%arg_y)
1602        __(jz 8f)
1603        __(push (%temp1,%imm0))
1604        __(push %imm0)
1605        __(push rcontext(tcr.db_link))
1606        __(movl %esp,rcontext(tcr.db_link))
1607        __(movl %arg_y,(%temp1,%imm0))
1608        __(jmp *%ra0)
16098:      __(push %ra0)
1610        __(uuo_error_reg_unbound(Rarg_z))
1611       
16129:      __(movl $XSYMNOBIND,%arg_y)
1613        __(set_nargs(2))
1614        __(push %ra0)
1615        __(jmp _SPksignalerr)
1616_endsubp(bind_self_boundp_check)
1617
1618_spentry(conslist)
1619        __(movl %nargs,%imm0)
1620        __(movl %temp0,%temp1)  /* have to use temp0 for consing */
1621        __(movl $nil_value,%arg_z)
1622        __(test %imm0,%imm0)
1623        __(jmp 2f)
16241:      __(pop %arg_y)
1625        __(Cons(%arg_y,%arg_z,%arg_z))
1626        __(subl $node_size,%imm0)
16272:      __(jnz 1b)
1628        __(jmp *%temp1)
1629_endsubp(conslist)
1630
1631/* do list*: last arg in arg_z, all others pushed, nargs set to #args pushed.  */
1632/* Cons, one cons cell at at time.  Maybe optimize this later.  */
1633
1634_spentry(conslist_star)
1635        __(movl %nargs,%imm0)
1636        __(test %imm0,%imm0)
1637        __(movl %ra0,%temp1)
1638        __(jmp 2f)
16391:      __(pop %arg_y)
1640        __(Cons(%arg_y,%arg_z,%arg_z))
1641        __(subl $node_size,%imm0)
16422:      __(jnz 1b)
1643        __(jmp *%temp1)
1644_endsubp(conslist_star)
1645
1646/* We always have to create a tsp frame (even if nargs is 0), so the compiler */
1647/* doesn't get confused. */
1648_spentry(stkconslist)
1649        __(movl $nil_value,%arg_z)
1650C(stkconslist_common):               
1651        __(movl %ra0,rcontext(tcr.save0))
1652        __(movd %nargs,%mm0)
1653        __(movl %nargs,%temp0)
1654        __(addl %temp0,%temp0)
1655        __(dnode_align(%temp0,tsp_frame.fixed_overhead,%temp0))
1656        __(TSP_Alloc_Var(%temp0,%imm0))
1657        __(addl $fulltag_cons,%imm0)
1658        __(test %nargs,%nargs)
1659        __(jmp 2f)
16601:      __(pop %arg_y)
1661        __(_rplaca(%imm0,%arg_y))
1662        __(_rplacd(%imm0,%arg_z))
1663        __(movl %imm0,%arg_z)
1664        __(add $cons.size,%imm0)
1665        __(subl $node_size,%nargs)
16662:      __(jne 1b)
1667        __(movl rcontext(tcr.save0),%ra0)
1668        __(movl $0,rcontext(tcr.save0))
1669        __(jmp *%ra0)
1670_endsubp(stkconslist)
1671
1672/* do list*: last arg in arg_z, all others vpushed,   */
1673/*      nargs set to #args vpushed.  */
1674
1675_spentry(stkconslist_star)
1676        __(jmp C(stkconslist_common))
1677_endsubp(stkconslist_star)
1678
1679
1680/* Make a stack-consed simple-vector out of the NARGS objects   */
1681/*      on top of the vstack; return it in arg_z.  */
1682
1683_spentry(mkstackv)
1684        __(dnode_align(%nargs,tsp_frame.fixed_overhead+node_size,%imm0))
1685        __(TSP_Alloc_Var(%imm0,%arg_y))
1686        __(movl %nargs,%imm0)
1687        __(shll $(num_subtag_bits-fixnumshift),%imm0)
1688        __(movb $subtag_simple_vector,%imm0_b)
1689        __(movl %imm0,(%arg_y))
1690        __(leal fulltag_misc(%arg_y),%arg_z)
1691        __(test %nargs,%nargs)
1692        __(leal misc_data_offset(%arg_z,%nargs),%imm0)
1693        __(jmp 2f)
16941:      __(pop -node_size(%imm0))
1695        __(subl $node_size,%nargs)
1696        __(leal -node_size(%imm0),%imm0)
16972:      __(jne 1b)
1698        __(jmp *%ra0)   
1699_endsubp(mkstackv)
1700
1701        .globl C(egc_write_barrier_start)
1702C(egc_write_barrier_start):
1703/*  */
1704/* The function pc_luser_xp() - which is used to ensure that suspended threads  */
1705/* are suspended in a GC-safe way - has to treat these subprims (which implement  */
1706/* the EGC write-barrier) specially.  Specifically, a store that might introduce  */
1707/* an intergenerational reference (a young pointer stored in an old object) has  */
1708/* to "memoize" that reference by setting a bit in the global "refbits" bitmap.  */
1709/* This has to happen atomically, and has to happen atomically wrt GC.  */
1710
1711/* Note that updating a word in a bitmap is itself not atomic, unless we use  */
1712/* interlocked loads and stores.  */
1713
1714/* For RPLACA and RPLACD, things are fairly simple: regardless of where we are  */
1715/* in the function, we can do the store (even if it's already been done) and  */
1716/* calculate whether or not we need to set the bit out-of-line.  (Actually  */
1717/* setting the bit needs to be done atomically, unless we're sure that other  */
1718/* threads are suspended.)  */
1719/* We can unconditionally set the suspended thread's RIP to the return address.  */
1720
1721_spentry(rplaca)
1722        .globl C(egc_rplaca)
1723C(egc_rplaca):
1724        /* pc_luser_xp() expects the store to be the first instruction here */
1725        __(_rplaca(%arg_y,%arg_z))
1726        __(rcmpl(%arg_z,%arg_y))
1727        __(ja 1f)
17280:      __(repret)
17291:      __(movl %arg_y,%imm0)
1730        __(subl lisp_global(ref_base),%imm0)
1731        __(shrl $dnode_shift,%imm0)
1732        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1733        __(jae 2f)
1734        __(movd %imm0,%mm0)
1735        __(ref_global(refbits,%temp0))
1736        __(xorb $31,%imm0_b)
1737        __(lock)
1738        __(btsl %imm0,(%temp0))
1739        __(shrl $8,%imm0)
1740        __(xorb $31,%imm0_b)
1741        __(ref_global(ephemeral_refidx,%temp0))
1742        __(lock)
1743        __(btsl %imm0,(%temp0))
1744        __(movd %mm0,%imm0)
17452:      __(cmpl lisp_global(managed_static_dnodes),%imm0)
1746        __(jae 0b)
1747        __(ref_global(managed_static_refbits,%temp0))
1748        __(xorb $31,%imm0_b)
1749        __(lock)
1750        __(btsl %imm0,(%temp0))       
1751        __(ret)
1752_endsubp(rplaca)
1753
1754_spentry(rplacd)
1755        .globl C(egc_rplacd)
1756C(egc_rplacd):
1757        /* pc_luser_xp() expects the store to be the first instruction here */
1758        __(_rplacd(%arg_y,%arg_z))
1759        __(rcmpl(%arg_z,%arg_y))
1760        __(ja 1f)
17610:      __(repret)
17621:      __(movl %arg_y,%imm0)
1763        __(subl lisp_global(ref_base),%imm0)
1764        __(shrl $dnode_shift,%imm0)
1765        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1766        __(jae 2f)
1767        __(movd %imm0,%mm0)
1768        __(ref_global(refbits,%temp0))
1769        __(xorb $31,%imm0_b)
1770        __(lock)
1771        __(btsl %imm0,(%temp0))
1772        __(shrl $8,%imm0)
1773        __(xorb $31,%imm0_b)
1774        __(ref_global(ephemeral_refidx,%temp0))
1775        __(lock)
1776        __(btsl %imm0,(%temp0))
1777        __(movd %mm0,%imm0)
17782:      __(cmpl lisp_global(managed_static_dnodes),%imm0)
1779        __(jae 0b)
1780        __(ref_global(managed_static_refbits,%temp0))
1781        __(xorb $31,%imm0_b)
1782        __(lock)
1783        __(btsl %imm0,(%temp0))       
1784        __(ret)
1785_endsubp(rplacd)
1786
1787/* Storing into a gvector can be handled the same way as storing into a CONS. */
1788/* args (src, unscaled-idx, val) in temp0, arg_y, arg_z */
1789_spentry(gvset)
1790        .globl C(egc_gvset)
1791C(egc_gvset):
1792        /* pc_luser_xp() expects the store to be the first instruction here */
1793        __(movl %arg_z,misc_data_offset(%temp0,%arg_y))
1794        __(rcmpl(%arg_z,%temp0))
1795        __(ja 1f)
17960:      __(repret)
17971:      __(lea misc_data_offset(%temp0,%arg_y),%imm0)
1798        __(subl lisp_global(ref_base),%imm0)
1799        __(shrl $dnode_shift,%imm0)
1800        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1801        __(jae 2f)
1802        __(movd %imm0,%mm0)
1803        __(ref_global(refbits,%temp1))
1804        __(xorb $31,%imm0_b)
1805        __(lock)
1806        __(btsl %imm0,(%temp1))
1807        __(shrl $8,%imm0)
1808        __(xorb $31,%imm0_b)
1809        __(ref_global(ephemeral_refidx,%temp1))
1810        __(lock)
1811        __(btsl %imm0,(%temp1))
1812        __(movd %mm0,%imm0)
18132:      __(cmpl lisp_global(managed_static_dnodes),%imm0)
1814        __(jae 0b)
1815        __(ref_global(managed_static_refbits,%temp1))
1816        __(xorb $31,%imm0_b)
1817        __(lock)
1818        __(btsl %imm0,(%temp1))
1819        __(ret)
1820_endsubp(gvset)
1821
1822/* This is a special case of storing into a gvector: if we need to  */
1823/* memoize the store, record the address of the hash-table vector  */
1824/* in the refmap, as well.  */
1825
1826_spentry(set_hash_key)
1827        .globl C(egc_set_hash_key)
1828C(egc_set_hash_key):
1829        /* pc_luser_xp() expects the store to be the first instruction here */
1830        __(movl %arg_z,misc_data_offset(%temp0,%arg_y))
1831        __(rcmpl(%arg_z,%temp0))
1832        __(ja 1f)
18330:      __(repret)
18341:      __(lea misc_data_offset(%temp0,%arg_y),%imm0)
1835        __(subl lisp_global(ref_base),%imm0)
1836        __(shrl $dnode_shift,%imm0)
1837        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1838        __(jae 2f)
1839        __(ref_global(refbits,%temp1))
1840        __(xorb $31,%imm0_b)
1841        __(lock)
1842        __(btsl %imm0,(%temp1))
1843        __(shrl $8,%imm0)
1844        __(xorb $31,%imm0_b)
1845        __(ref_global(ephemeral_refidx,%temp1))
1846        __(lock)
1847        __(btsl %imm0,(%temp1))
1848        /* Now memoize the address of the hash vector */
1849        __(ref_global(refbits,%temp1))
1850        __(movl %temp0,%imm0)
1851        __(subl lisp_global(ref_base),%imm0)
1852        __(shrl $dnode_shift,%imm0)
1853        __(xorb $31,%imm0_b)
1854        __(lock)
1855        __(btsl %imm0,(%temp1))
1856        __(shrl $8,%imm0)
1857        __(xorb $31,%imm0_b)
1858        __(ref_global(ephemeral_refidx,%temp1))
1859        __(lock)
1860        __(btsl %imm0,(%temp1))
1861        __(lea misc_data_offset(%temp0,%arg_y),%imm0)
1862        __(subl lisp_global(ref_base),%imm0)
1863        __(shrl $dnode_shift,%imm0)
18642:      __(cmpl lisp_global(managed_static_dnodes),%imm0)
1865        __(jae 0b)
1866        __(ref_global(managed_static_refbits,%temp1))
1867        __(xorb $31,%imm0_b)
1868        __(lock)
1869        __(btsl %imm0,(%temp1))
1870        /* Now memoize the address of the hash vector */
1871        __(movl %temp0,%imm0)
1872        __(subl lisp_global(ref_base),%imm0)
1873        __(shrl $dnode_shift,%imm0)
1874        __(xorb $31,%imm0_b)
1875        __(lock)
1876        __(btsl %imm0,(%temp1))               
1877        __(ret)
1878_endsubp(set_hash_key)
1879
1880/* This is a little trickier: if this is interrupted, we need to know  */
1881/* whether or not the STORE-CONDITIONAL (cmpxchgl) has won or not.    */
1882/* If we're interrupted   before the PC has reached the "success_test" label, */
1883/* repeat (luser the PC back to store_node_conditional_retry.)  If
1884        we're at that */
1885/* label with the Z flag set, we won and (may) need to memoize.  */
1886
1887/* %temp0 = offset, %temp1 = object, %arg_y = old, %arg_z = new */
1888_spentry(store_node_conditional)
1889        .globl C(egc_store_node_conditional)
1890C(egc_store_node_conditional):
1891        __(subl $misc_data_offset*fixnumone,%temp0) /* undo pre-added offset */
1892        __(sarl $fixnumshift,%temp0)    /* will be fixnum-tagged */
1893        .globl C(egc_store_node_conditional_retry)
1894C(egc_store_node_conditional_retry):     
18950:      __(movl %arg_y,%imm0)
1896        __(lock)
1897        __(cmpxchgl %arg_z,misc_data_offset(%temp1,%temp0))
1898        .globl C(egc_store_node_conditional_success_test)
1899C(egc_store_node_conditional_success_test):
1900        __(jne 9f)
1901        __(leal misc_data_offset(%temp1,%temp0),%imm0)
1902        __(subl lisp_global(ref_base),%imm0)
1903        __(shrl $dnode_shift,%imm0)
1904        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1905        __(jae 2f)
1906        __(movd %imm0,%mm0)
1907        __(ref_global(refbits,%arg_y))
1908        __(xorb $31,%imm0_b)
1909        __(lock)
1910        __(btsl %imm0,(%arg_y))
1911        __(shrl $8,%imm0)
1912        __(xorb $31,%imm0_b)
1913        __(ref_global(ephemeral_refidx,%arg_y))
1914        __(lock)
1915        __(btsl %imm0,(%arg_y))
1916        __(movd %mm0,%imm0)
19172:      __(cmpl lisp_global(managed_static_dnodes),%imm0)
1918        __(jae 8f)
1919        __(ref_global(managed_static_refbits,%arg_y))
1920        __(xorb $31,%imm0_b)
1921        __(lock)
1922        __(btsl %imm0,(%arg_y))
1923        .globl C(egc_store_node_conditional_success_end)
1924C(egc_store_node_conditional_success_end):
19258:      __(movl $t_value,%arg_z)
1926        __(ret)
19279:      __(movl $nil_value,%arg_z)
1928        __(ret)
1929_endsubp(store_node_conditional)
1930
1931        /* %temp0 = offset, %temp1 = object, %arg_y = old, %arg_z = new */
1932_spentry(set_hash_key_conditional)
1933        .globl C(egc_set_hash_key_conditional)
1934C(egc_set_hash_key_conditional):
1935        __(subl $misc_data_offset*fixnumone,%temp0) /* undo pre-added offset */
1936        __(sarl $fixnumshift,%temp0)    /* will be fixnum-tagged */
1937        .globl C(egc_set_hash_key_conditional_retry)
1938C(egc_set_hash_key_conditional_retry):         
19390:      __(movl %arg_y,%imm0)
1940        __(lock)
1941        __(cmpxchgl %arg_z,misc_data_offset(%temp1,%temp0))
1942        .globl C(egc_set_hash_key_conditional_success_test)
1943C(egc_set_hash_key_conditional_success_test):
1944        __(jne 9f)
1945        __(leal misc_data_offset(%temp1,%temp0),%imm0)
1946        __(subl lisp_global(ref_base),%imm0)
1947        __(shrl $dnode_shift,%imm0)
1948        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1949        __(jae 2f)
1950        __(ref_global(refbits,%arg_y))
1951        __(xorb $31,%imm0_b)
1952        __(lock)
1953        __(btsl %imm0,(%arg_y))
1954        __(shrl $8,%imm0)
1955        __(xorb $31,%imm0_b)
1956        __(ref_global(ephemeral_refidx,%arg_y))
1957        __(lock)
1958        __(btsl %imm0,(%arg_y))
1959        /* Now memoize the address of the hash vector */
1960        __(ref_global(refbits,%arg_y))
1961        __(movl %temp1,%imm0)
1962        __(subl lisp_global(ref_base),%imm0)
1963        __(shrl $dnode_shift,%imm0)
1964        __(xorb $31,%imm0_b)
1965        __(lock)
1966        __(btsl %imm0,(%arg_y))
1967        __(ref_global(ephemeral_refidx,%arg_y))
1968        __(shrl $8,%imm0)
1969        __(xorb $31,%imm0_b)
1970        __(lock)
1971        __(btsl %imm0,(%arg_y))
1972        __(leal misc_data_offset(%temp1,%temp0),%imm0)
1973        __(subl lisp_global(ref_base),%imm0)
1974        __(shrl $dnode_shift,%imm0)
19752:      __(cmpl lisp_global(managed_static_dnodes),%imm0)
1976        __(jae 8f)
1977        __(ref_global(managed_static_refbits,%arg_y))
1978        __(xorb $31,%imm0_b)
1979        __(lock)
1980        __(btsl %imm0,(%arg_y))
1981        /* Now memoize the address of the hash vector */
1982        __(movl %temp1,%imm0)
1983        __(subl lisp_global(ref_base),%imm0)
1984        __(shrl $dnode_shift,%imm0)
1985        __(xorb $31,%imm0_b)
1986        __(lock)
1987        __(btsl %imm0,(%arg_y))
1988        .globl C(egc_write_barrier_end)
1989C(egc_write_barrier_end):
19908:      __(movl $t_value,%arg_z)
1991        __(ret)
19929:      __(movl $nil_value,%arg_z)
1993        __(ret)
1994_endsubp(store_node_conditional)
1995
1996_spentry(setqsym)
1997        __(bt $sym_vbit_const,symbol.flags(%arg_y))
1998        __(jae _SPspecset)
1999        __(mov %arg_y,%arg_z)
2000        __(mov $XCONST,%arg_y)
2001        __(set_nargs(2))
2002        __(jmp _SPksignalerr)
2003_endsubp(setqsym)
2004
2005_spentry(progvsave)
2006        __(push %arg_y)
2007       
2008        /* Error if arg_z isn't a proper list.  That's unlikely,  */
2009        /* but it's better to check now than to crash later.  */
2010       
2011        __(compare_reg_to_nil(%arg_z))
2012        __(movl %arg_z,%temp0)  /* fast   */
2013        __(movl %arg_z,%temp1)  /* slow   */
2014        __(je 9f)               /* Null list is proper   */
20150:
2016        __(extract_lisptag(%temp0,%imm0))
2017        __(cmpb $tag_list,%imm0_b)
2018        __(jne 8f)
2019        __(compare_reg_to_nil(%temp0))
2020        __(je 9f)
2021        __(_cdr(%temp0,%arg_y)) /* (null (cdr fast)) ?   */
2022        __(compare_reg_to_nil(%arg_y))
2023        __(je 9f)
2024        __(extract_lisptag(%arg_y,%imm0))
2025        __(cmpb $tag_list,%imm0_b)
2026        __(jne 8f)
2027        __(_cdr(%arg_y,%temp0))
2028        __(_cdr(%temp1,%temp1))
2029        __(cmpl %temp1,%temp0)
2030        __(jne 0b)
2031
20328:      __(add $node_size,%esp) /* discard pushed arg_y */
2033        __(movl $XIMPROPERLIST,%arg_y)
2034        __(set_nargs(2))
2035        __(jmp _SPksignalerr)
20369:      /* Whew           */
2037
2038        /* Next, determine the length of arg_y.  We   */
2039        /* know that it's a proper list.   */
2040        __(pop %arg_y)
2041       
2042        __(movl $-fixnumone,%imm0)
2043        __(movl %arg_y,%temp0)
20441:      __(compare_reg_to_nil(%temp0))
2045        __(_cdr(%temp0,%temp0))
2046        __(leal fixnumone(%imm0),%imm0)
2047        __(jne 1b)
2048       
2049        /* imm0 is now (boxed) triplet count.  */
2050        /* Determine word count, add 1 (to align), and make room.  */
2051        /*  if count is 0, make an empty tsp frame and exit   */
2052        __(testl %imm0,%imm0)
2053        __(jne 2f)
2054        __(TSP_Alloc_Fixed(2*node_size,%imm0))
2055        __(ret)
20562:      __(movl %imm0,%temp1)
2057        __(add %imm0,%imm0)
2058        __(add %temp1,%imm0)
2059        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
2060        __(TSP_Alloc_Var(%imm0,%temp0))
2061        __(movl %temp1,(%temp0))
2062        __(movd rcontext(tcr.db_link),%mm0)
20633:      __(movl $unbound_marker,%temp0)
2064        __(compare_reg_to_nil(%arg_z))
2065        __(cmovnel cons.car(%arg_z),%temp0)
2066        __(cmovnel cons.cdr(%arg_z),%arg_z)
2067        __(_car(%arg_y,%temp1))
2068        __(_cdr(%arg_y,%arg_y))
2069        __(movl symbol.binding_index(%temp1),%temp1)
2070        __(cmp rcontext(tcr.tlb_limit),%temp1)
2071        __(jb 4f)
2072        __(push %temp1)
2073        __(tlb_too_small())
20744:      __(push %arg_z)
2075        __(movl rcontext(tcr.tlb_pointer),%arg_z)
2076        __(subl $binding.size,%imm0)
2077        __(movl %temp1,binding.sym(%imm0))
2078        __(push (%arg_z,%temp1))
2079        __(pop binding.val(%imm0))
2080        __(movl %temp0,(%arg_z,%temp1))
2081        __(pop %arg_z)
2082        __(movd %mm0,binding.link(%imm0))
2083        __(movd %imm0,%mm0)
2084        __(compare_reg_to_nil(%arg_y))
2085        __(jne 3b)
2086        __(movd %mm0,rcontext(tcr.db_link))
2087        __(ret)
2088_endsubp(progvsave)
2089
2090/* Allocate node objects on the temp stack, immediate objects on the foreign  */
2091/* stack. (The caller has to know which stack to discard a frame from.)  */
2092/* %arg_y = boxed element-count, %arg_z = boxed subtype  */
2093
2094_spentry(stack_misc_alloc)
2095        __(testl $~(((1<<24)-1)<<fixnumshift),%arg_y)
2096        __(jne local_label(stack_misc_alloc_not_u24))
2097        __(unbox_fixnum(%arg_z,%imm0))
2098        __(mov %arg_y,%temp0)
2099        __(shl $num_subtag_bits-fixnumshift,%temp0)
2100        __(or %temp0,%imm0)     /* %imm0 now = header */
2101        __(movd %imm0,%mm0)     /* cache header in %mm0 */
2102        __(andb $fulltagmask,%imm0_b)
2103        __(cmpb $fulltag_nodeheader,%imm0_b)
2104        __(je local_label(stack_misc_alloc_node))
2105        __(movd %mm0,%imm0)
2106        __(cmpb $max_32_bit_ivector_subtag,%imm0_b)
2107        __(jbe local_label(stack_misc_alloc_32))
2108        __(cmpb $max_8_bit_ivector_subtag,%imm0_b)
2109        __(jbe local_label(stack_misc_alloc_8))
2110        __(cmpb $max_16_bit_ivector_subtag,%imm0_b)
2111        __(jbe local_label(stack_misc_alloc_16))
2112        __(cmpb $subtag_double_float_vector,%imm0_b)
2113        __(jne local_label(stack_misc_alloc_1))
2114        /* double-float vector case */
2115        __(imul $2,%arg_y,%imm0)
2116        __(jmp local_label(stack_misc_alloc_alloc_ivector))
2117local_label(stack_misc_alloc_1):
2118        __(unbox_fixnum(%arg_y,%imm0))
2119        __(addl $7,%imm0)
2120        __(shrl $3,%imm0)
2121        __(jmp local_label(stack_misc_alloc_alloc_ivector))
2122local_label(stack_misc_alloc_8):
2123        __(unbox_fixnum(%arg_y,%imm0))
2124        __(jmp local_label(stack_misc_alloc_alloc_ivector))
2125local_label(stack_misc_alloc_16):
2126        __(unbox_fixnum(%arg_y,%imm0))
2127        __(shl $1,%imm0)
2128        __(jmp local_label(stack_misc_alloc_alloc_ivector))
2129local_label(stack_misc_alloc_32):
2130        __(mov %arg_y,%imm0)
2131local_label(stack_misc_alloc_alloc_ivector):
2132        /* byte count in %imm0 */
2133        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
2134        __(cmpl $tstack_alloc_limit,%imm0)
2135        __(ja local_label(stack_misc_alloc_heap_alloc_ivector))
2136        __ifdef(`WINDOWS')
2137         __(windows_cstack_probe(%imm0,%temp1))
2138        __endif
2139        __(movd rcontext(tcr.foreign_sp),%stack_temp)
2140        __(movd %stack_temp,%temp1)
2141        __(subl %imm0,rcontext(tcr.foreign_sp))
2142        __(movl rcontext(tcr.foreign_sp),%temp0)
21430:      __(movsd %fpzero,-dnode_size(%temp1))
2144        __(subl $dnode_size,%temp1)
2145        __(cmpl %temp1,%temp0)
2146        __(jnz 0b)
2147        __(movd %stack_temp,(%temp0))
2148        __(movl %ebp,csp_frame.save_ebp(%temp0))
2149        __(movd %mm0,csp_frame.fixed_overhead(%temp0))
2150        __(lea csp_frame.fixed_overhead+fulltag_misc(%temp0),%arg_z)
2151        __(ret)
2152local_label(stack_misc_alloc_heap_alloc_ivector):
2153        __(movd rcontext(tcr.foreign_sp),%stack_temp)
2154        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2155        __(movl rcontext(tcr.foreign_sp),%imm0)
2156        __(movd %stack_temp,(%imm0))
2157        __(jmp _SPmisc_alloc)
2158local_label(stack_misc_alloc_node):
2159        __(movl %arg_y,%imm0)
2160        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
2161        __(cmpl $tstack_alloc_limit,%imm0)
2162        __(ja local_label(stack_misc_alloc_heap_alloc_gvector))
2163        __(TSP_Alloc_Var(%imm0,%temp1))
2164        __(movd %mm0,(%temp1))
2165        __(leal fulltag_misc(%temp1),%arg_z)
2166        __(ret)
2167local_label(stack_misc_alloc_heap_alloc_gvector):
2168        __(TSP_Alloc_Fixed(0,%imm0))
2169        __(jmp _SPmisc_alloc)
2170
2171local_label(stack_misc_alloc_not_u24):
2172        __(popl %temp0)
2173        __(pushl $reserved_frame_marker)
2174        __(pushl $reserved_frame_marker)
2175        __(pushl $XARRLIMIT)
2176        __(pushl %temp0)
2177        __(set_nargs(3))
2178        __(jmp _SPksignalerr)       
2179_endsubp(stack_misc_alloc)
2180
2181/* subtype (boxed, of course) is pushed, followed by nargs bytes worth of */
2182/* initial-contents.  Note that this can be used to cons any type of */
2183/* initialized node-header'ed misc object (symbols, closures, ...) */
2184/* as well as vector-like objects. */
2185_spentry(gvector)
2186        __(subl $node_size,%nargs)      /* off by one in x862-%gvector */
2187        __(movl (%esp,%nargs),%imm0)    /* boxed subtype */
2188        __(sarl $fixnumshift,%imm0)
2189        __(movl %nargs,%arg_z)
2190        __(shll $num_subtag_bits-word_shift,%arg_z)
2191        __(orl %arg_z,%imm0)
2192        __(movd %imm0,%mm0)
2193        __(dnode_align(%nargs,node_size,%imm0))
2194        __(push %ra0)   /* aka %temp0, can't be live while consing */
2195        __(Misc_Alloc(%arg_z))
2196        __(pop %ra0)
2197        __(movl %nargs,%imm0)
2198        __(jmp 2f)
21991:      __(movl %arg_y,misc_data_offset(%arg_z,%imm0))
22002:      __(subl $node_size,%imm0)
2201        __(pop %arg_y)  /* Note the intentional fencepost: */
2202                        /* discard the subtype as well. */
2203        __(jge 1b)
2204        __(jmp *%ra0)
2205_endsubp(gvector)
2206
2207_spentry(mvpass)
2208        __(hlt)
2209_endsubp(mvpass)
2210
2211_spentry(nthvalue)
2212        __(hlt)
2213_endsubp(nthvalue)
2214
2215_spentry(values)
2216        __(movl (%temp0),%arg_y)        /* return address */
2217        __(ref_global(ret1val_addr,%imm0))
2218        __(movl $nil_value,%arg_z)
2219        __(cmpl %imm0,%arg_y)
2220        __(je 0f)
2221        __(test %nargs,%nargs)
2222        __(cmovne -node_size(%esp,%nargs),%arg_z)
2223        __(movl %temp0,%esp)
2224        __(ret)
22250:      __(movl 4(%temp0),%arg_y)
2226        __(addl $2*node_size,%temp0)
2227        __(lea (%esp,%nargs),%imm0)
2228        __(movd %nargs,%mm0)
2229        __(jmp 2f)
22301:      __(subl $node_size,%imm0)
2231        __(movl (%imm0),%temp1)
2232        __(subl $node_size,%temp0)
2233        __(movl %temp1,(%temp0))
22342:      __(cmp %imm0,%esp)
2235        __(jne 1b)
2236        __(movl %temp0,%esp)
2237        __(movd %mm0,%nargs)
2238        __(jmp *%arg_y)
2239
2240_endsubp(values)
2241
2242_spentry(default_optional_args)
2243        __(hlt)
2244_endsubp(default_optional_args)
2245
2246_spentry(opt_supplied_p)
2247        __(hlt)
2248_endsubp(opt_supplied_p)
2249
2250_spentry(lexpr_entry)
2251        __(hlt)
2252_endsubp(lexpr_entry)
2253
2254_spentry(heap_rest_arg)
2255        __(push_argregs())
2256        __(movl %temp0,%arg_y)
2257        __(movl %nargs,%imm0)
2258        __(testl %imm0,%imm0)
2259        __(movl $nil_value,%arg_z)
2260        __(jmp 2f)
2261        .p2align 4
22621:      __(pop %temp1)
2263        __(Cons(%temp1,%arg_z,%arg_z))
2264        __(subl $node_size,%imm0)
22652:      __(jg 1b)
2266        __(push %arg_z)
2267        __(movl %arg_y,%temp0)
2268        __(jmp *%ra0)
2269
2270_endsubp(heap_rest_arg)
2271
2272/* %imm0 contains the number of fixed args; make an &rest arg out of */
2273/* the others. */
2274_spentry(req_heap_rest_arg)
2275        __(push_argregs())
2276        __(movd %nargs,%mm0)
2277        __(subl %imm0,%nargs)
2278        __(movl %nargs,%imm0)
2279        __(movl %temp0,%temp1)
2280        __(movl $nil_value,%arg_z)
2281        __(jmp 2f)
2282        .p2align 4
22831:      __(pop %arg_y)
2284        __(Cons(%arg_y,%arg_z,%arg_z))
2285        __(subl $node_size,%imm0)
22862:      __(jg 1b)
2287        __(push %arg_z)
2288        __(movl %temp1,%temp0)
2289        __(movd %mm0,%nargs)
2290        __(jmp *%ra0)
2291_endsubp(req_heap_rest_arg)
2292
2293/* %imm0 bytes of stuff has already been pushed   */
2294/* make an &rest arg out of any others   */
2295_spentry(heap_cons_rest_arg)
2296        __(movd %nargs,%mm0)
2297        __(subl %imm0,%nargs)
2298        __(movl %nargs,%imm0)
2299        __(movl $nil_value,%arg_z)
2300        __(movl %ra0,%arg_y)    /* temp0 can't be live while consing */
2301        __(jmp 2f)              /* (did I mention that already?) */
2302        .p2align 4
23031:      __(pop %temp1)
2304        __(Cons(%temp1,%arg_z,%arg_z))
2305        __(subl $node_size,%imm0)
23062:      __(jg 1b)
2307        __(push %arg_z)
2308        __(movd %mm0,%nargs)
2309        __(jmp *%arg_y)
2310_endsubp(heap_cons_rest_arg)
2311
2312_spentry(simple_keywords)
2313        __(xor %imm0,%imm0)
2314        __(push_argregs())
2315        __(jmp _SPkeyword_bind)
2316_endsubp(simple_keywords)
2317
2318_spentry(keyword_args)
2319        __(push_argregs())
2320        __(jmp _SPkeyword_bind)
2321_endsubp(keyword_args)
2322
2323/* There are %nargs words of arguments on the stack; %imm0 contains the */
2324/* number of non-keyword args pushed.  It's possible that we never actually */
2325/* got any keyword args, which would make things much simpler. */
2326
2327/* On entry, the upper half of %temp1 (aka %nargs) contains some bits */
2328/* indicating whether &allow-other-keys and/or &rest was present in the */
2329/* lambda list. */
2330
2331/* Once we get here, we can use the arg registers. */
2332
2333/* N.B.: %ra0 is %temp0, and must not be clobbered. */
2334
2335define(`keyword_flags_aok_bit',`16')
2336define(`keyword_flags_unknown_keys_bit',`17')
2337define(`keyword_flags_rest_bit',`18')
2338define(`keyword_flags_seen_aok_bit',`19')
2339
2340_spentry(keyword_bind)
2341        __(movl %temp1,rcontext(tcr.unboxed0))  /* save keyword flags */
2342        __(movzwl %nargs_w,%nargs)
2343        __(movl %nargs,%arg_z)
2344        __(subl %imm0,%arg_z)
2345        __(jbe local_label(no_keyword_values))
2346        __(btl $word_shift,%arg_z)
2347        __(jnc local_label(even))
2348        __(movl $nil_value,%arg_y)
2349        __(movl %arg_z,%nargs)
2350        __(test %nargs,%nargs)
2351        __(movl %ra0,rcontext(tcr.save0))       /* save temp0 while consing */
2352        __(jmp 1f)
23530:      __(pop %arg_z)
2354        __(Cons(%arg_z,%arg_y,%arg_y))
2355        __(subl $node_size,%nargs)
23561:      __(jnz 0b)
2357        __(movl rcontext(tcr.save0),%ra0)
2358        __(movapd %fpzero,rcontext(tcr.save0))
2359        __(movl %arg_y,%arg_z)
2360        __(movl $XBADKEYS,%arg_y)
2361        __(set_nargs(2))
2362        __(jmp _SPksignalerr)
2363
2364        /* Now that we're sure that we have an even number of */
2365        /* keywords and values (in %arg_z), move the pairs over */
2366        /* to the temp stack. */
2367local_label(even):
2368        __(lea tsp_frame.fixed_overhead(%arg_z),%arg_y)
2369        __(TSP_Alloc_Var(%arg_y,%imm0))
23702:      __(subl $node_size,%arg_y)
2371        __(pop (%arg_y))
2372        __(cmpl %arg_y,%imm0)
2373        __(jne 2b)
2374
2375        /* Get the keyword vector into %arg_y, and its length into %imm0. */
2376        /* Push %imm0 pairs of NILs (representing value, supplied-p) */
2377        /* for each declared keyword. */
2378        __(movzwl misc_data_offset(%fn),%imm0)
2379        /* XXX bootstrapping */
2380        __(btr $15,%imm0)
2381        __(jnc 0f)
2382        __(vector_length(%fn,%arg_y))
2383        __(box_fixnum(%imm0,%imm0))
2384        __(subl %imm0,%arg_y)
2385        __(movl %arg_y,%imm0)
2386        __(shrl $fixnumshift,%imm0)
23870:
2388        __(movl misc_data_offset(%fn,%imm0,node_size),%arg_y)
2389        __(vector_length(%arg_y,%imm0))
2390        __(jmp 4f)
23913:      __(push $nil_value)
2392        __(push $nil_value)
23934:      __(subl $fixnumone,%imm0)
2394        __(jge 3b)
2395
2396        /* We can now push %ra0 (aka %temp0) and %nargs (aka %temp1) */
2397        /* in order to get a couple more registers to work with. */
2398        __(push %ra0)
2399        __(push %nargs)
2400
2401        /* At this point we have: */
2402        /* number of supplied keywords and values in %arg_z */
2403        /* keyword vector in %arg_y */
2404        __(vector_length(%arg_y,%imm0))
2405        __(push %imm0)          /* count of declared keywords */
2406        __(push %arg_z)         /* count of supplied keys and values */
2407
2408        /* For each declared keyword, iterate over the supplied k/v pairs */
2409        /* to see if it's supplied and what the value is. */
2410        /* checking to see if any */
2411        /* key-value pairs were unexpectedly supplied. */
2412
2413        __(movl rcontext(tcr.save_tsp),%temp0)
2414        __(addl $2*node_size,%temp0) /* skip frame overhead */
2415        /* %temp0: top of tstack (skipping frame overhead) */
2416        __(lea 4*node_size(%esp,%imm0,2),%temp1)
2417        /* %temp1: word above 0th value/supplied-p pair on vstack */
2418        /* %arg_y: keyword vector */
2419        __(xorl %imm0,%imm0)
2420        /* %imm0: index */
2421        /* %arg_z: temporary */
2422
2423        /* Iterate over supplied k/v pairs on tstack.  See if key is */
2424        /* in the keyword vector.  Copy value and set supplied-p on */
2425        /* vstack if found. */
2426
2427local_label(tstack_loop):
2428        __(movl (%temp0,%imm0,2),%arg_z)        /* keyword */
2429        __(push %imm0)
2430        __(xorl %imm0,%imm0)
2431        __(cmpl $nrs.kallowotherkeys,%arg_z)
2432        __(jne local_label(next_keyvect_entry))
2433        __(btsl $keyword_flags_seen_aok_bit,rcontext(tcr.unboxed0))
2434        __(jc local_label(next_keyvect_entry))
2435        __(push %imm0)
2436        __(movl 4(%esp),%imm0)
2437        __(cmpl $nil_value,node_size(%temp0,%imm0,2))
2438        __(pop %imm0)
2439        __(je local_label(next_keyvect_entry))
2440        __(btsl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2441        __(jmp local_label(next_keyvect_entry))
2442        /* loop through keyword vector */
24436:      __(cmpl misc_data_offset(%arg_y,%imm0),%arg_z)
2444        __(jne 7f)
2445        /* Got a match; have we already seen this keyword? */
2446        __(negl %imm0)
2447        __(cmpl $nil_value,-node_size*2(%temp1,%imm0,2))
2448        __(jne 9f)      /* seen it, ignore this value */
2449        __(movl (%esp),%arg_z)
2450        __(lea (%temp0,%arg_z,2),%arg_z)
2451        __(movl node_size(%arg_z),%arg_z) /* value for this key */
2452        __(movl %arg_z,-node_size(%temp1,%imm0,2))
2453        __(movl $t_value,-node_size*2(%temp1,%imm0,2))
2454        __(jmp 9f)
24557:      __(addl $node_size,%imm0)
2456local_label(next_keyvect_entry):
2457        __(cmpl %imm0,8(%esp))
2458        __(jne 6b)
2459        /* Didn't match anything in the keyword vector.  Is the keyword */
2460        /* :allow-other-keys? */
2461        __(cmpl $nrs.kallowotherkeys,%arg_z)
2462        __(je 9f)       /* :allow-other-keys is never "unknown" */
24638:      __(btsl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
24649:      __(pop %imm0)
2465        __(addl $fixnumone,%imm0)
2466        __(movl %imm0,%arg_z)
2467        __(shll $1,%arg_z)      /* pairs of tstack words */
2468        __(cmpl %arg_z,0(%esp))
2469        __(jne local_label(tstack_loop))
2470
2471        __(pop %imm0)   /* count of supplied keys and values */
2472        __(addl $node_size,%esp)
2473        __(pop %nargs)
2474        __(pop %ra0)
2475
2476        /* If the function takes an &rest arg, or if we got an unrecognized */
2477        /* keyword and don't allow that, copy the incoming k/v pairs from */
2478        /* the temp stack back to the value stack. */
2479        __(btl $keyword_flags_rest_bit,rcontext(tcr.unboxed0))
2480        __(jc 1f)
2481        __(btl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
2482        __(jnc 0f)
2483        __(btl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2484        __(jnc 1f)
2485        /* pop the tstack frame */
24860:      __(discard_temp_frame(%imm0))
2487        __(jmp *%ra0)
2488
2489        /* Copy the k/v pairs from the tstack back to the value stack, */
2490        /* either because the function takes an &rest arg or because */
2491        /* we need to signal an "unknown keywords" error. */
24921:      __(movl rcontext(tcr.save_tsp),%arg_z)
2493        __(mov (%arg_z),%arg_y)
2494        __(jmp 3f)
24952:      __(push (%arg_z))
2496        __(push node_size(%arg_z))
24973:      __(addl $dnode_size,%arg_z)
2498        __(cmpl %arg_z,%arg_y)
2499        __(jne 2b)
2500        __(discard_temp_frame(%arg_z))
2501        __(btl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
2502        __(jnc 9f)
2503        __(btl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2504        __(jc 9f)
2505        /* Signal an "unknown keywords" error */
2506        __(movl %imm0,%nargs)
2507        __(movl $nil_value,%arg_z)
2508        __(test %nargs,%nargs)
2509        __(movl %ra0,rcontext(tcr.save0))
2510        __(jmp 5f)
25114:      __(pop %arg_y)
2512        __(Cons(%arg_y,%arg_z,%arg_z))
2513        __(subl $node_size,%nargs)
25145:      __(jnz 4b)
2515        __(movl $XBADKEYS,%arg_y)
2516        __(set_nargs(2))
2517        __(movl rcontext(tcr.save0),%ra0)
2518        __(movl $0,rcontext(tcr.save0))
2519        __(jmp _SPksignalerr)
25209:      __(jmp *%ra0)
2521
2522/* No keyword value were provided.  Access the keyword vector (which is the */
2523/* 0th constant in %fn), determine its length N, and push N pairs of NILs. */
2524/* N could be 0... */
2525
2526local_label(no_keyword_values):
2527        __(movzwl misc_data_offset(%fn),%imm0)
2528        /* XXX bootstrapping */
2529        __(btr $15,%imm0)
2530        __(jnc 9f)
2531        __(vector_length(%fn,%arg_y))
2532        __(box_fixnum(%imm0,%imm0))
2533        __(subl %imm0,%arg_y)
2534        __(movl %arg_y,%imm0)
2535        __(shrl $fixnumshift,%imm0)
25369:
2537        __(movl misc_data_offset(%fn,%imm0,node_size),%arg_y)
2538        __(vector_length(%arg_y,%arg_z))
2539        __(movl $nil_value,%imm0)
2540        __(jmp 1f)
25410:      __(push %imm0)
2542        __(push %imm0)
25431:      __(subl $fixnumone,%arg_z)
2544        __(jge 0b)
2545        __(jmp *%ra0)
2546_endsubp(keyword_bind)
2547
2548/* Normally, we'd just set %fname (aka %temp0) and do */
2549/* jump_fname().  Sometimes, though, %temp0 is being used */
2550/* as %ra0, and I'm not sure that it's going to be safe to */
2551/* clobber that.  (Note that nil-relative symbols aren't going */
2552/* get moved around by the GC, so we can get away with putting */
2553/* '%err-disp in %imm0.) */
2554_spentry(ksignalerr)
2555        __(mov $nrs.errdisp,%imm0)
2556        __(mov symbol.fcell(%imm0),%fn)
2557        __(jump_fn)
2558_endsubp(ksignalerr)
2559
2560_spentry(stack_rest_arg)
2561        __(xorl %imm0,%imm0)
2562        __(push_argregs())
2563        __(jmp _SPstack_cons_rest_arg)
2564_endsubp(stack_rest_arg)
2565
2566_spentry(req_stack_rest_arg)
2567        __(push_argregs())
2568        __(jmp _SPstack_cons_rest_arg)
2569_endsubp(req_stack_rest_arg)
2570
2571_spentry(stack_cons_rest_arg)
2572        __(movd %nargs,%mm2)
2573        __(movl %temp0,rcontext(tcr.save0))
2574        __(subl %imm0,%temp1)
2575        __(movl $nil_value,%arg_z)
2576        __(jle 2f)      /* empty list; make an empty TSP frame */
2577        __(addl %temp1,%temp1)
2578        __(cmpl $(tstack_alloc_limit-dnode_size),%temp1)
2579        __(ja 3f)       /* make empty frame, then heap-cons */
2580        __(dnode_align(%temp1,tsp_frame.fixed_overhead,%imm0))
2581        __(TSP_Alloc_Var(%imm0,%temp0))
2582        __(addl $fulltag_cons,%temp0)
25831:      __(pop %arg_y)
2584        __(_rplacd(%temp0,%arg_z))
2585        __(_rplaca(%temp0,%arg_y))
2586        __(movl %temp0,%arg_z)
2587        __(addl $cons.size,%temp0)
2588        __(subl $dnode_size,%temp1)
2589        __(jne 1b)
2590        __(push %arg_z)
2591        __(movd %mm2,%nargs)
2592        __(movl rcontext(tcr.save0),%temp0)
2593        __(movss %fpzero,rcontext(tcr.save0))
2594        __(jmp *%temp0)
2595/* Length 0, make empty frame */
25962:
2597        __(TSP_Alloc_Fixed(0,%temp0))
2598        __(push %arg_z)
2599        __(movd %mm2,%nargs)
2600        __(movl rcontext(tcr.save0),%temp0)
2601        __(movss %fpzero,rcontext(tcr.save0))
2602        __(jmp *%temp0)
2603/* Too big to stack-cons, but make an empty frame before heap-consing */
2604        __(TSP_Alloc_Fixed(0,%temp0))
2605        __(movd %mm2,%nargs)
2606        __(movl rcontext(tcr.save0),%temp0)
2607        __(movss %fpzero,rcontext(tcr.save0))
2608        __(jmp _SPheap_cons_rest_arg)
2609_endsubp(stack_cons_rest_arg)
2610
2611_spentry(getxlong)
2612        __(hlt)
2613_endsubp(getxlong)
2614
2615/* Have to be a little careful here: the caller may or may not have pushed  */
2616/* an empty frame, and we may or may not have needed one.  We can't easily  */
2617/* tell whether or not a frame will be needed (if the caller didn't reserve  */
2618/* a frame, whether or not we need one depends on the length of the list  */
2619/* in arg_z.  So, if the caller didn't push a frame, we do so; once */
2620/* everything's been spread, we discard the reserved frame (regardless of
2621/* who pushed it) if all args fit in registers.   */
2622
2623/* xxx preserve temp1 somehow? cf. comment in x862-invoke-fn */
2624_spentry(spreadargz)
2625        __(test %nargs,%nargs)
2626        __(jne 0f)
2627        __(push $reserved_frame_marker)
2628        __(push $reserved_frame_marker)
26290:      __(movl %arg_z,rcontext(tcr.save0))     /* save in case of error */
2630        __(movd %nargs,%mm0)    /* now we can use %temp1 */
2631        __(xorl %nargs,%nargs)
2632        __(cmpl $nil_value,%arg_z)
2633        __(je 2f)
26341:      __(extract_fulltag(%arg_z,%imm0))
2635        __(cmpb $fulltag_cons,%imm0_b)
2636        __(jne 9f)
2637        __(_car(%arg_z,%arg_y))
2638        __(_cdr(%arg_z,%arg_z))
2639        __(add $node_size,%nargs)
2640        __(cmpl $call_arguments_limit<<fixnumshift,%nargs)
2641        __(jae 8f)
2642        __(push %arg_y)
2643        __(cmpl $nil_value,%arg_z)
2644        __(jne 1b)
26452:      __(movd %mm0,%imm0)
2646        __(addl %imm0,%nargs)
2647        __(jne 4f)
26483:      __(addl $2*node_size,%esp)
2649        __(movl $0,rcontext(tcr.save0))
2650        __(jmp *%ra0)
26514:      __(pop %arg_z)
2652        __(cmp $1*node_size,%nargs)
2653        __(je 3b)
2654        __(pop %arg_y)
2655        __(cmp $2*node_size,%nargs)
2656        __(je 3b)
2657        __(movl $0,rcontext(tcr.save0))
2658        __(jmp *%ra0)
2659/* Discard everything that's been pushed already, complain */
26608:      __(lea (%esp,%nargs),%esp)
2661        __(movl rcontext(tcr.save0),%arg_z) /* recover original */
2662        __(movl $0,rcontext(tcr.save0))
2663        __(movl $XTMINPS,%arg_y)
2664        __(set_nargs(2))
2665        __(push %ra0)
2666        __(jmp _SPksignalerr)
26679:      __(lea (%esp,%nargs),%esp)
2668        __(movl rcontext(tcr.save0),%arg_z) /* recover original */
2669        __(movl $0,rcontext(tcr.save0))
2670        __(movl $XNOSPREAD,%arg_y)
2671        __(set_nargs(2))
2672        __(push %ra0)
2673        __(jmp _SPksignalerr)
2674_endsubp(spreadargz)
2675
2676
2677/* Caller built its own frame when it was entered.  If all outgoing args  */
2678/* are in registers, we can discard that frame; otherwise, we copy outgoing  */
2679/* relative to it and restore %rbp/%ra0   */
2680_spentry(tfuncallgen)
2681        __(cmpl $nargregs*node_size,%nargs)
2682        __(jbe 9f)
2683        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2684        __(movl %temp0,rcontext(tcr.save0))
2685        __(movd %nargs,%mm0)
2686        __(xorl %temp1,%temp1)
2687        /* We can use %ra0 as a temporary here, since the real return address */
2688        /* is on the stack   */
26890:      __(movl -node_size(%imm0),%ra0)
2690        __(movl %ra0,-node_size(%ebp,%temp1))
2691        __(subl $node_size,%imm0)
2692        __(subl $node_size,%temp1)
2693        __(cmpl %imm0,%esp)
2694        __(jne 0b)
2695        __(lea (%ebp,%temp1),%esp)
2696        __(movl 4(%ebp),%ra0)
2697        __(movl (%ebp),%ebp)
2698        __(pushl %ra0)
2699        __(movd %mm0,%nargs)
2700        __(movl rcontext(tcr.save0),%temp0)
2701        __(movss %fpzero,rcontext(tcr.save0))
2702        __(do_funcall())
2703        /* All args in regs; exactly the same as the tfuncallvsp case   */
27049:             
2705        __(leave)
2706        __(do_funcall())
2707
2708_endsubp(tfuncallgen)
2709
2710/* Some args were pushed; move them down in the frame   */
2711_spentry(tfuncallslide)
2712        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2713        __(movd %nargs,%mm0)
2714        __(xorl %temp1,%temp1)
2715        __(movl %temp0,rcontext(tcr.save0))
27160:      __(movl -node_size(%imm0),%temp0)
2717        __(movl %temp0,-node_size(%ebp,%temp1))
2718        __(subl $node_size,%imm0)
2719        __(subl $node_size,%temp1)
2720        __(cmpl %imm0,%esp)
2721        __(jne 0b)
2722        __(lea (%ebp,%temp1),%esp)
2723        __(push 4(%ebp))        /* return address */
2724        __(movl (%ebp),%ebp)
2725        __(movd %mm0,%nargs)
2726        __(movl rcontext(tcr.save0),%temp0)
2727        __(movss %fpzero,rcontext(tcr.save0))
2728        __(do_funcall())
2729_endsubp(tfuncallslide)
2730
2731/* No args were pushed; recover saved context & do funcall        */
2732_spentry(tfuncallvsp)
2733        __(leave)
2734        __(do_funcall())
2735_endsubp(tfuncallvsp)
2736
2737_spentry(tcallsymgen)
2738        __(cmpl $nargregs*node_size,%nargs)
2739        __(jbe 9f)
2740        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2741        __(movd %nargs,%mm0)
2742        __(movl %temp0,rcontext(tcr.save0))
2743        __(xorl %temp1,%temp1)  /* aka nargs */
27440:      __(movl -node_size(%imm0),%temp0)
2745        __(movl %temp0,-node_size(%ebp,%temp1))
2746        __(subl $node_size,%imm0)
2747        __(subl $node_size,%temp1)
2748        __(cmpl %imm0,%esp)
2749        __(jne 0b)
2750        __(lea (%ebp,%temp1),%esp)
2751        __(movl 4(%ebp),%temp0)
2752        __(movl (%ebp),%ebp)
2753        __(push %temp0)
2754        __(movl rcontext(tcr.save0),%temp0)
2755        __(movss %fpzero,rcontext(tcr.save0))
2756        __(movd %mm0,%nargs)
2757        __(jump_fname())
2758/* All args in regs; exactly the same as the tcallsymvsp case. */
27599:
2760        __(leave)
2761        __(jump_fname())
2762_endsubp(tcallsymgen)
2763
2764_spentry(tcallsymslide)
2765        __(movl %ebp,%imm0)
2766        __(subl %nargs,%imm0)
2767        __(addl $nargregs*node_size,%imm0)      /* new tos */
2768        __(push %imm0)
2769        __(push %arg_y)
2770        __(push %arg_z)
2771        __(push %nargs)
2772        __(lea (4-nargregs)*node_size(%esp,%nargs),%arg_y) /* src ptr */
2773        __(movl %ebp,%imm0) /* dst ptr */
2774        __(subl $fixnumone*nargregs,%nargs)
2775        __(jmp 1f)
27760:      __(subl $node_size,%arg_y)
2777        __(movl (%arg_y),%arg_z)
2778        __(subl $node_size,%imm0)
2779        __(movl %arg_z,(%imm0))
27801:      __(subl $fixnumone,%nargs)
2781        __(jge 0b)
2782        __(pop %nargs)
2783        __(pop %arg_z)
2784        __(pop %arg_y)
2785        __(pop %esp)
2786        __(push node_size(%ebp))
2787        __(movl 0(%ebp),%ebp)
2788        __(jump_fname)
2789_endsubp(tcallsymslide)
2790
2791_spentry(tcallsymvsp)
2792        __(leave)
2793        __(jump_fname())
2794_endsubp(tcallsymvsp)
2795
2796_spentry(tcallnfngen)
2797        __(cmpl $nargregs*node_size,%nargs)
2798        __(jbe 9f)
2799        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2800        __(movd %nargs,%mm0)    /* stash nargs aka temp1 */
2801        __(xorl %temp1,%temp1)
2802        __(movl %temp0,rcontext(tcr.save0))
2803        /* It's OK to use %ra0 (%temp0) as an temp here, since the */
2804        /* real return address is on the stack. */
28050:      __(movl -node_size(%imm0),%ra0)
2806        __(movl %ra0,-node_size(%ebp,%temp1))
2807        __(subl $node_size,%imm0)
2808        __(subl $node_size,%temp1)
2809        __(cmpl %imm0,%esp)
2810        __(jne 0b)
2811        __(movl rcontext(tcr.save0),%fn)
2812        __(movss %fpzero,rcontext(tcr.save0))
2813        __(lea (%ebp,%temp1),%esp)
2814        __(movl lisp_frame.savera0(%ebp),%ra0)
2815        __(movl lisp_frame.backlink(%ebp),%ebp)
2816        __(push %ra0)
2817        __(movd %mm0,%nargs)
2818        __(jmp *%fn)
28199:      /* All args in regs; exactly the same as the tcallnfnvsp case */
2820        __(movl %temp0,%fn)
2821        __(leave)
2822        __(jmp *%fn)
2823_endsubp(tcallnfngen)
2824
2825_spentry(tcallnfnslide)
2826        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2827        __(movd %nargs,%mm0)    /* save nargs aka temp1 */
2828        __(xorl %temp1,%temp1)
2829        __(movl %temp0,rcontext(tcr.save0))
2830        /* We can use %ra0 as a temporary here, since the real return address */
2831        /* is on the stack   */
28320:      __(movl -node_size(%imm0),%ra0)
2833        __(movl %ra0,-node_size(%ebp,%temp1))
2834        __(subl $node_size,%imm0)
2835        __(subl $node_size,%temp1)
2836        __(cmpl %imm0,%esp)
2837        __(jne 0b)
2838        __(movl rcontext(tcr.save0),%fn)
2839        __(lea (%ebp,%temp1),%esp)
2840        __(movl lisp_frame.savera0(%ebp),%ra0)
2841        __(movl lisp_frame.backlink(%ebp),%ebp)
2842        __(push %ra0)
2843        __(movapd %fpzero,rcontext(tcr.save0))
2844        __(movd %mm0,%nargs)
2845        __(jmp *%fn)
2846_endsubp(tcallnfnslide)
2847
2848_spentry(tcallnfnvsp)
2849        __(mov %temp0,%fn)
2850        __(leave)
2851        __(jmp *%fn)
2852_endsubp(tcallnfnvsp)
2853
2854/* Make a "raw" area on the foreign stack, stack-cons a macptr to point */
2855/* to it, and return the macptr.  Size (in bytes, boxed) is in arg_z */
2856/* on entry; macptr in arg_z on exit. */
2857_spentry(makestackblock)
2858        __(check_cstack_alignment())
2859        __(unbox_fixnum(%arg_z,%imm0))
2860        __(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
2861        __(cmpl $tstack_alloc_limit,%imm0)
2862        __(jae 1f)
2863        __ifdef(`WINDOWS')
2864         __(windows_cstack_probe(%imm0,%arg_z))
2865        __endif
2866        __(movd rcontext(tcr.foreign_sp),%mm0)
2867        __(subl %imm0,rcontext(tcr.foreign_sp))
2868        __(movl rcontext(tcr.foreign_sp),%arg_z)
2869        __(movd %mm0,(%arg_z))
2870        __(movl %ebp,csp_frame.save_ebp(%arg_z))
2871        __(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
2872        __(movl $macptr_header,tsp_frame.fixed_overhead(%arg_z))
2873        __(addl $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
2874        __(movl %imm0,macptr.address(%arg_z))
2875        __(movss %fpzero,macptr.domain(%arg_z))
2876        __(movss %fpzero,macptr.type(%arg_z))
2877        __(ret)
28781:      __(movd rcontext(tcr.foreign_sp),%mm0)
2879        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2880        __(movl rcontext(tcr.foreign_sp),%imm0)
2881        __(movd %mm0,(%imm0))
2882        __(movl %ebp,csp_frame.save_ebp(%imm0))
2883        __(set_nargs(1))
2884        __(movl $nrs.new_gcable_ptr,%fname)
2885        __(jump_fname())
2886_endsubp(makestackblock)
2887
2888_spentry(makestackblock0)
2889        __(unbox_fixnum(%arg_z,%imm0))
2890        __(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
2891        __(cmpl $tstack_alloc_limit,%imm0)
2892        __(jae 9f)
2893        __ifdef(`WINDOWS')
2894         __(windows_cstack_probe(%imm0,%temp0))
2895        __endif
2896        __(movl rcontext(tcr.foreign_sp),%temp0)
2897        __(subl %imm0,rcontext(tcr.foreign_sp))
2898        __(movl rcontext(tcr.foreign_sp),%arg_z)
2899        __(movl %temp0,(%arg_z))
2900        __(movl %ebp,csp_frame.save_ebp(%arg_z))
2901        __(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
2902        __(movl $macptr_header,tsp_frame.fixed_overhead(%arg_z))
2903        __(addl $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
2904        __(movl %imm0,macptr.address(%arg_z))
2905        __(movss %fpzero,macptr.domain(%arg_z))
2906        __(movss %fpzero,macptr.type(%arg_z))
2907        __(jmp 2f)
29081:      __(movsd %fpzero,(%imm0))
2909        __(addl $dnode_size,%imm0)
29102:      __(cmpl %imm0,%temp0)
2911        __(jne 1b)
2912        __(repret)
29139:      __(movd rcontext(tcr.foreign_sp),%mm0)
2914        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2915        __(movl rcontext(tcr.foreign_sp),%imm0)
2916        __(movd %mm0,(%imm0))
2917        __(movl %ebp,csp_frame.save_ebp(%imm0))
2918        __(set_nargs(1))
2919        __(movl $nrs.new_gcable_ptr,%fname)
2920        __(jump_fname())
2921_endsubp(makestackblock0)
2922
2923_spentry(makestacklist)
2924        __(test %arg_y,%arg_y)
2925        __(js 9f)
2926        __(movl %arg_y,%imm0)
2927        __(testb $fixnummask,%imm0_b)
2928        __(jne 9f)
2929        __(addl %imm0,%imm0)
2930        __(rcmpl(%imm0,$tstack_alloc_limit))
2931        __(movl $nil_value,%temp1)
2932        __(jae 2f)
2933        __(addl $tsp_frame.fixed_overhead,%imm0)
2934        __(TSP_Alloc_Var(%imm0,%temp0))
2935        __(addl $fulltag_cons,%temp0)
2936        __(jmp 1f)
29370:      __(_rplaca(%temp0,%arg_z))
2938        __(_rplacd(%temp0,%temp1))
2939        __(movl %temp0,%temp1)
2940        __(addl $cons.size,%temp0)
29411:      __(subl $fixnumone,%arg_y)
2942        __(jge 0b)
2943        __(movl %temp1,%arg_z)
2944        __(ret)
29452:      __(TSP_Alloc_Fixed(0,%imm0))
2946        __(jmp 4f)
29473:      __(Cons(%arg_z,%temp1,%temp1))
29484:      __(subl $fixnumone,%arg_y)                             
2949        __(jge 3b)
2950        __(movl %temp1,%arg_z)
2951        __(ret)
29529:      __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte))
2953_endsubp(makestacklist)
2954
2955/* subtype (boxed) vpushed before initial values. (Had better be a */
2956/* node header subtag.)  Nargs set to count of things vpushed. */
2957_spentry(stkgvector)
2958        __(movl -fixnumone(%esp,%nargs),%imm0)  /* boxed subtag */
2959        __(shrl $fixnumshift,%imm0)
2960        __(leal -fixnumone(%nargs),%arg_z)
2961        __(movl %arg_z,%arg_y)
2962        __(shll $num_subtag_bits-fixnumshift,%arg_z)
2963        __(orl %arg_z,%imm0)    /* imm0 = header, %arg_y = unaligned size */
2964        __(movd %imm0,%mm0)
2965        __(dnode_align(%arg_y,(tsp_frame.fixed_overhead+node_size),%imm0))
2966        __(TSP_Alloc_Var(%imm0,%arg_z))
2967        __(movd %mm0,(%arg_z))
2968        __(addl $fulltag_misc,%arg_z)
2969        __(lea -node_size(%nargs),%imm0)
2970        __(jmp 2f)
29711:      __(pop misc_data_offset(%arg_z,%imm0))
29722:      __(subl $node_size,%imm0)
2973        __(jge 1b)
2974        __(addl $node_size,%esp)
2975        __(jmp *%ra0)
2976_endsubp(stkgvector)
2977
2978/* Allocate a fulltag-misc object. */
2979/* arg_y = boxed element count, arg_z = subtag (boxed, of course) */
2980_spentry(misc_alloc)
2981        __(testl $~(((1<<24)-1)<<fixnumshift),%arg_y)
2982        __(jne local_label(misc_alloc_not_u24))
2983        __(unbox_fixnum(%arg_z,%imm0))
2984        __(mov %arg_y,%temp0)
2985        __(shl $num_subtag_bits-fixnumshift,%temp0)
2986        __(or %temp0,%imm0)     /* %imm0 now = header */
2987        __(movd %imm0,%mm0)     /* Misc_Alloc wants header in %mm0 */
2988        __(andb $fulltagmask,%imm0_b)
2989        __(cmpb $fulltag_nodeheader,%imm0_b)
2990        __(je local_label(misc_alloc_32))
2991        __(movd %mm0,%imm0)
2992        __(cmpb $max_32_bit_ivector_subtag,%imm0_b)
2993        __(jbe local_label(misc_alloc_32))
2994        __(cmpb $max_8_bit_ivector_subtag,%imm0_b)
2995        __(jbe local_label(misc_alloc_8))
2996        __(cmpb $max_16_bit_ivector_subtag,%imm0_b)
2997        __(jbe local_label(misc_alloc_16))
2998        __(cmpb $subtag_double_float_vector,%imm0_b)
2999        __(jne local_label(misc_alloc_1))
3000        /* double-float vector case */
3001        __(imul $2,%arg_y,%imm0)
3002        __(jmp local_label(misc_alloc_alloc_vector))
3003local_label(misc_alloc_1):
3004        __(unbox_fixnum(%arg_y,%imm0))
3005        __(addl $7,%imm0)
3006        __(shrl $3,%imm0)
3007        __(jmp local_label(misc_alloc_alloc_vector))
3008local_label(misc_alloc_8):
3009        __(unbox_fixnum(%arg_y,%imm0))
3010        __(jmp local_label(misc_alloc_alloc_vector))
3011local_label(misc_alloc_16):
3012        __(unbox_fixnum(%arg_y,%imm0))
3013        __(shl $1,%imm0)
3014        __(jmp local_label(misc_alloc_alloc_vector))
3015local_label(misc_alloc_32):
3016        __(movl %arg_y,%imm0)
3017local_label(misc_alloc_alloc_vector):
3018        __(dnode_align(%imm0,node_size,%imm0))
3019        __(Misc_Alloc(%arg_z))
3020        __(ret)
3021local_label(misc_alloc_not_u24):
3022        __(popl %temp0)
3023        __(pushl $reserved_frame_marker)
3024        __(pushl $reserved_frame_marker)
3025        __(pushl $XARRLIMIT)
3026        __(pushl %temp0)
3027        __(set_nargs(3))
3028        __(jmp _SPksignalerr)       
3029_endsubp(misc_alloc)
3030
3031/* N.B. arg count word in %imm0, not %nargs */
3032/* no %whole_reg;  it's in rcontext(tcr.save0) */
3033/* %arg_reg is %temp1, key vector in %arg_y */
3034_startfn(C(destbind1))
3035        __(movl %ra0,rcontext(tcr.save1))
3036        /* Save entry %esp in case of error   */
3037        __(movd %esp,%mm0)
3038        /* Save arg count word */
3039        __(movd %imm0,%mm1)
3040        /* Extract required arg count.   */
3041        __(testb %imm0_b,%imm0_b)
3042        __(je local_label(opt))         /* skip if no required args   */
3043        __(movzbl %imm0_b,%imm0)
3044local_label(req_loop): 
3045        __(compare_reg_to_nil(%arg_reg))
3046        __(je local_label(toofew))
3047        __(movb $fulltagmask,%imm0_bh)
3048        __(andb %arg_reg_b,%imm0_bh)
3049        __(cmpb $fulltag_cons,%imm0_bh)
3050        __(jne local_label(badlist))
3051        __(subb $1,%imm0_b)
3052        __(pushl cons.car(%arg_reg))
3053        __(_cdr(%arg_reg,%arg_reg))
3054        __(jne local_label(req_loop))
3055        __(movd %mm1,%imm0)
3056local_label(opt):
3057        __(movb %imm0_bh,%imm0_b)
3058        __(testb %imm0_b,%imm0_b)
3059        __(je local_label(rest_keys))
3060        __(btl $initopt_bit,%imm0)
3061        __(jc local_label(opt_supp))
3062        /* 'simple' &optionals:  no supplied-p, default to nil.   */
3063local_label(simple_opt_loop):
3064        __(compare_reg_to_nil(%arg_reg))
3065        __(je local_label(default_simple_opt))
3066        __(movb $fulltagmask,%imm0_bh)
3067        __(andb %arg_reg_b,%imm0_bh)
3068        __(cmpb $fulltag_cons,%imm0_bh)
3069        __(jne local_label(badlist))
3070        __(subb $1,%imm0_b)
3071        __(pushl cons.car(%arg_reg))
3072        __(_cdr(%arg_reg,%arg_reg))
3073        __(jne local_label(simple_opt_loop))
3074        __(jmp local_label(rest_keys))
3075local_label(default_simple_opt):
3076        __(subb $1,%imm0_b)
3077        __(pushl $nil_value)
3078        __(jne local_label(default_simple_opt))
3079        __(jmp local_label(rest_keys))
3080local_label(opt_supp):
3081        __(movb $fulltagmask,%imm0_bh)
3082        __(andb %arg_reg_b,%imm0_bh)
3083        __(compare_reg_to_nil(%arg_reg))
3084        __(je local_label(default_hard_opt))
3085        __(cmpb $fulltag_cons,%imm0_bh)
3086        __(jne local_label(badlist))
3087        __(subb $1,%imm0_b)
3088        __(pushl cons.car(%arg_reg))
3089        __(_cdr(%arg_reg,%arg_reg))
3090        __(push $t_value)
3091        __(jne local_label(opt_supp))
3092        __(jmp local_label(rest_keys))
3093local_label(default_hard_opt):
3094        __(subb $1,%imm0_b)
3095        __(push $nil_value)
3096        __(push $nil_value)
3097        __(jne local_label(default_hard_opt))
3098local_label(rest_keys):
3099        __(btl $restp_bit,%imm0)
3100        __(jc local_label(have_rest))
3101        __(btl $keyp_bit,%imm0)
3102        __(jc local_label(have_keys))
3103        __(compare_reg_to_nil(%arg_reg))
3104        __(jne local_label(toomany))
3105        __(movss %fpzero,rcontext(tcr.save0))
3106        __(jmp *%ra0)
3107local_label(have_rest):
3108        __(pushl %arg_reg)
3109        __(btl $keyp_bit,%imm0)
3110        __(jc local_label(have_keys))
3111        __(movss %fpzero,rcontext(tcr.save0))
3112        __(jmp *%ra0)
3113        /* Ensure that arg_reg contains a proper,even-length list.  */
3114        /* Insist that its length is <= 512 (as a cheap circularity check.)   */
3115local_label(have_keys):
3116        __(movb $255,%imm0_b)
3117        __(push %arg_reg)
3118        __(push %arg_z)
3119        __(xorl %arg_z,%arg_z)
3120local_label(count_keys_loop):
3121        __(compare_reg_to_nil(%arg_reg))
3122        __(je local_label(counted_keys))
3123        __(subb $1,%imm0_b)
3124        __(jb local_label(toomany))
3125        __(movb $fulltagmask,%arg_z_bh)
3126        __(andb %arg_reg_b,%arg_z_bh)
3127        __(cmpb $fulltag_cons,%arg_z_bh)
3128        __(jne local_label(badlist))
3129        __(_cdr(%arg_reg,%arg_reg))
3130        __(compare_reg_to_nil(%arg_reg))
3131        __(je local_label(badlist))
3132        __(movb $fulltagmask,%arg_z_bh)
3133        __(andb %arg_reg_b,%arg_z_bh)
3134        __(cmpb $fulltag_cons,%arg_z_bh)
3135        __(jne local_label(badlist))
3136        __(_cdr(%arg_reg,%arg_reg))
3137        __(jmp local_label(count_keys_loop))
3138local_label(counted_keys):             
3139        /* We've got a proper, even-length list of key/value pairs in  */
3140        /* arg_reg. For each keyword var in the lambda-list, push a pair  */
3141        /* of NILs on the vstack.   */
3142        __(pop %arg_z)
3143        __(pop %arg_reg)
3144        __(movd %mm1,%imm0)
3145        __(shrl $16,%imm0)
3146        __(movzbl %imm0_b,%imm0)
3147        __(movl %esp,rcontext(tcr.unboxed0))    /* 0th value/supplied-p pair */
3148        __(jmp local_label(push_pair_test))
3149local_label(push_pair_loop):
3150        __(push $nil_value)
3151        __(push $nil_value)
3152local_label(push_pair_test):   
3153        __(subb $1,%imm0_b)
3154        __(jge local_label(push_pair_loop))
3155        __(push %temp0) /* keyword */
3156        __(push %arg_z) /* value */
3157        __(vector_length(%arg_y,%imm0))
3158        __(push %arg_reg)
3159        __(push %imm0)  /* keyword vector length */
3160        __(movd %mm1,%imm0)
3161        __(movl $0,rcontext(tcr.unboxed1)) /* count of unknown keywords seen */
3162local_label(match_keys_loop):
3163        __(movl 4(%esp),%arg_reg)
3164        __(compare_reg_to_nil(%arg_reg))
3165        __(je local_label(matched_keys))
3166        __(_car(%arg_reg,%temp0))
3167        __(_cdr(%arg_reg,%arg_reg))
3168        __(_car(%arg_reg,%arg_z))
3169        __(_cdr(%arg_reg,%arg_reg))
3170        __(movl %arg_reg,4(%esp))
3171        __(xorl %temp1,%temp1)
3172        __(jmp local_label(match_test))
3173local_label(match_loop):
3174        __(cmpl misc_data_offset(%arg_y,%temp1),%temp0)
3175        __(je local_label(matched))
3176        __(addl $node_size,%temp1)
3177local_label(match_test):
3178        __(cmpl %temp1,(%esp))  /* compare index, keyword vector length */
3179        __(jne local_label(match_loop))
3180        /* No match.  Note unknown keyword, check for :allow-other-keys   */
3181        __(addl $1,rcontext(tcr.unboxed1))
3182        __(cmpl $nrs.kallowotherkeys,%temp0)
3183        __(jne local_label(match_keys_loop))
3184        __(subl $1,rcontext(tcr.unboxed1))
3185        __(btsl $seen_aok_bit,%imm0)
3186        __(jc local_label(match_keys_loop))
3187        /* First time we've seen :allow-other-keys.  Maybe set aok_bit.   */
3188        __(compare_reg_to_nil(%arg_z))
3189        __(je local_label(match_keys_loop))
3190        __(btsl $aok_bit,%imm0)
3191        __(jmp local_label(match_keys_loop))
3192        /* Got a match.  Worry about :allow-other-keys here, too.   */
3193local_label(matched):
3194        __(negl %temp1)
3195        __(shll $1,%temp1)
3196        __(addl rcontext(tcr.unboxed0),%temp1)
3197        __(cmpl $nil_value,-node_size*2(%temp1))
3198        __(jne local_label(match_keys_loop))
3199        __(movl %arg_z,-node_size(%temp1))
3200        __(movl $t_value,-node_size*2(%temp1))
3201        __(cmpl $nrs.kallowotherkeys,%temp0)
3202        __(jne local_label(match_keys_loop))
3203        __(btsl $seen_aok_bit,%imm0)
3204        __(jnc local_label(match_keys_loop))
3205        __(compare_reg_to_nil(%arg_z))
3206        __(je local_label(match_keys_loop))
3207        __(btsl $aok_bit,%imm0)
3208        __(jmp local_label(match_keys_loop))
3209local_label(matched_keys):     
3210        __(cmpl $0,rcontext(tcr.unboxed1))      /* any unknown keys seen? */
3211        __(je local_label(keys_ok))
3212        __(btl $aok_bit,%imm0)
3213        __(jnc local_label(badkeys))
3214local_label(keys_ok):
3215        __(addl $(3*node_size),%esp)
3216        __(pop %ra0)
3217        __(movss %fpzero,rcontext(tcr.save0))
3218        __(jmp *%ra0)
3219        /* Some unrecognized keywords.  Complain generically about   */
3220        /* invalid keywords.   */
3221local_label(badkeys):
3222        __(movl $XBADKEYS,%arg_y)
3223        __(jmp local_label(destructure_error))
3224local_label(toomany):
3225        __(movl $XCALLTOOMANY,%arg_y)
3226        __(jmp local_label(destructure_error))
3227local_label(toofew):
3228        __(movl $XCALLTOOFEW,%arg_y)
3229        __(jmp local_label(destructure_error))
3230local_label(badlist):
3231        __(movl $XCALLNOMATCH,%arg_y)
3232local_label(destructure_error):
3233        __(movd %mm0,%esp)              /* undo everything done to the stack */
3234        __(movl rcontext(tcr.save0),%arg_z)     /* %whole_reg */
3235        __(movss %fpzero,rcontext(tcr.save0))
3236        __(set_nargs(2))
3237        __(push %ra0)
3238        __(jmp _SPksignalerr)
3239_endfn(C(destbind1))
3240
3241_spentry(macro_bind)
3242        __(movl %arg_reg,rcontext(tcr.save0))   /* %whole_reg */
3243        __(extract_fulltag(%arg_reg,%imm0))
3244        __(cmpb $fulltag_cons,%imm0_b)
3245        __(jne 1f)
3246        __(_cdr(%arg_reg,%arg_reg))
3247        __(jmp C(destbind1))
32481:      __(movl $XCALLNOMATCH,%arg_y)
3249        __(movl rcontext(tcr.save0),%arg_z)
3250        __(movss %fpzero,rcontext(tcr.save0))
3251        __(set_nargs(2))
3252        __(push %ra0)       
3253        __(jmp _SPksignalerr)
3254
3255_endsubp(macro_bind)
3256
3257_spentry(destructuring_bind)
3258        __(movl %arg_reg,rcontext(tcr.save0))   /* %whole_reg */
3259        __(jmp C(destbind1))
3260_endsubp(destructuring_bind)
3261
3262_spentry(destructuring_bind_inner)
3263        __(movl %arg_z,rcontext(tcr.save0))     /* %whole_reg */
3264        __(jmp C(destbind1))
3265_endsubp(destructuring_bind_inner)
3266
3267_spentry(vpopargregs)
3268        __(hlt)
3269_endsubp(vpopargregs)
3270
3271/* If arg_z is an integer, return in imm0 something whose sign  */
3272/* is the same as arg_z's.  If not an integer, error.   */
3273_spentry(integer_sign)
3274        __(mov %arg_z,%imm0)
3275        __(testb $tagmask,%arg_z_b)
3276        __(je 8f)
3277        __(extract_typecode(%arg_z,%imm0))
3278        __(cmpb $subtag_bignum,%imm0_b)
3279        __(jne 9f)
3280        __(getvheader(%arg_z,%imm0))
3281        __(shr $num_subtag_bits,%imm0)
3282        __(movl misc_data_offset-4(%arg_z,%imm0,4),%imm0)
32838:      __(repret)
32849:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_integer))
3285_endsubp(integer_sign)
3286
3287/* "slide" nargs worth of values up the stack.  imm0 contains */
3288/* the difference between the current stack pointer and the target. */
3289_spentry(mvslide)
3290        __(movd %nargs,%mm0)
3291        __(lea (%esp,%nargs),%arg_y)
3292        __(lea (%arg_y,%imm0),%imm0)
3293        __(test %nargs,%nargs)
3294        __(je 2f)
32951:
3296        __(subl $node_size,%arg_y)
3297        __(movl (%arg_y),%arg_z)
3298        __(subl $node_size,%imm0)
3299        __(movl %arg_z,(%imm0))
3300        __(subl $node_size,%nargs)
3301        __(jne 1b)
33022:      __(movl %imm0,%esp)
3303        __(movd %mm0,%nargs)
3304        __(jmp *%ra0)
3305_endsubp(mvslide)
3306
3307_spentry(save_values)
3308        __(movd rcontext(tcr.save_tsp),%mm1)
3309/* common exit: nargs = values in this set, mm1 = ptr to tsp before call to save_values   */
3310local_label(save_values_to_tsp):
3311        __(movl %ra0,rcontext(tcr.save0))
3312        __(movl rcontext(tcr.save_tsp),%temp0)
3313        __(dnode_align(%nargs,tsp_frame.fixed_overhead+(2*node_size),%imm0)) /* count, link   */
3314        __(TSP_Alloc_Var(%imm0,%arg_z))
3315        __(movl rcontext(tcr.save_tsp),%imm0)
3316        __(movd %mm1,(%imm0))
3317        __(movl %nargs,(%arg_z))
3318        __(movl %temp0,node_size(%arg_z))
3319        __(leal 2*node_size(%arg_z,%nargs),%arg_y)
3320        __(leal (%esp,%nargs),%imm0)
3321        __(cmpl %imm0,%esp)
3322        __(jmp 2f)
33231:      __(subl $node_size,%imm0)
3324        __(movl (%imm0),%arg_z)
3325        __(subl $node_size,%arg_y)
3326        __(cmpl %imm0,%esp)
3327        __(movl %arg_z,(%arg_y))
33282:      __(jne 1b)
3329        __(addl %nargs,%esp)
3330        __(movl rcontext(tcr.save0),%ra0)
3331        __(movl $0,rcontext(tcr.save0))
3332        __(jmp *%ra0)
3333_endsubp(save_values)
3334
3335/* Add the multiple values that are on top of the vstack to the set  */
3336/* saved in the top tsp frame, popping them off of the vstack in the  */
3337/* process.  It is an error (a bad one) if the TSP contains something  */
3338/* other than a previously saved set of multiple-values.  */
3339/* Since adding to the TSP may cause a new TSP segment to be allocated,  */
3340/* each add_values call adds another linked element to the list of  */
3341/* values. This makes recover_values harder.   */
3342_spentry(add_values)
3343        /* do we need to preserve imm0? */
3344        __(test %nargs,%nargs)
3345        __(movl rcontext(tcr.save_tsp),%imm0)
3346        __(movl (%imm0),%imm0)
3347        __(movd %imm0,%mm1)     /* for the benefit of save_values_to_tsp */
3348        __(jne local_label(save_values_to_tsp))
3349        __(jmp *%ra0)
3350_endsubp(add_values)
3351
3352/* push the values in the value set atop the sp, incrementing nargs.  */
3353/* Discard the tsp frame; leave values atop the sp.   */
3354_spentry(recover_values)
3355        __(movl %ra0,rcontext(tcr.save0)) /* temp0 */
3356        __(movd %nargs,%mm0)              /* temp1 */
3357        /* First, walk the segments reversing the pointer to previous  */
3358        /* segment pointers Can tell the end because that previous  */
3359        /* segment pointer is the prev tsp pointer   */
3360        __(movl rcontext(tcr.save_tsp),%temp1)
3361        __(movl %temp1,%temp0)  /* current segment   */
3362        __(movl %temp1,%arg_y)  /* last segment   */
3363        __(movl tsp_frame.backlink(%temp1),%arg_z)      /* previous tsp   */
3364local_label(walkloop):
3365        __(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
3366        __(cmpl %imm0,%arg_z)   /* last segment ?   */
3367        __(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
3368        __(movl %temp0,%arg_y)  /* last segment <- current segment   */
3369        __(movl %imm0,%temp0)   /* current segment <- next segment   */
3370        __(jne local_label(walkloop))
3371
3372        __(movl %temp1,%arg_z)
3373        __(movd %mm0,%nargs)
3374        /* the final segment pointer is now in %arg_y  */
3375        /* walk backwards, pushing values on the stack and incrementing %nargs   */
3376local_label(pushloop):
3377        __(movl tsp_frame.data_offset(%arg_y),%imm0)    /* nargs in segment   */
3378        __(test %imm0,%imm0)
3379        __(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
3380        __(leal (%nargs,%imm0),%nargs)
3381        __(jmp 2f)
33821:      __(push -node_size(%temp0))
3383        __(subl $node_size,%temp0)
3384        __(subl $fixnum_one,%imm0)
33852:      __(jne 1b)
3386        __(cmpl %arg_y,%arg_z)
3387        __(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
3388        __(jne local_label(pushloop))
3389        __(movl (%arg_z),%arg_z)
3390        __(movl %arg_z,rcontext(tcr.save_tsp))
3391        __(movl %arg_z,rcontext(tcr.next_tsp))
3392        __(movl rcontext(tcr.save0),%ra0)
3393        __(movl $0,rcontext(tcr.save0))
3394        __(jmp *%ra0)           
3395_endsubp(recover_values)
3396
3397/* Exactly like recover_values, but it's necessary to reserve an outgoing  */
3398/* frame if any values (which will be used as outgoing arguments) will  */
3399/* wind up on the stack.  We can assume that %nargs contains 0 (and  */
3400/* that no other arguments have been pushed) on entry.   */
3401
3402_spentry(recover_values_for_mvcall)
3403        __(movl %ra0,rcontext(tcr.save0)) /* temp0 */
3404        /* First, walk the segments reversing the pointer to previous  */
3405        /* segment pointers Can tell the end because that previous  */
3406        /* segment pointer is the prev tsp pointer   */
3407        __(xorl %nargs,%nargs)
3408        __(push %nargs)
3409        __(movl rcontext(tcr.save_tsp),%temp1)
3410        __(movl %temp1,%temp0)  /* current segment   */
3411        __(movl %temp1,%arg_y)  /* last segment   */
3412        __(movl tsp_frame.backlink(%temp1),%arg_z)      /* previous tsp   */
3413local_label(walkloop_mvcall):
3414        __(movl tsp_frame.data_offset(%temp0),%imm0)
3415        __(addl %imm0,(%esp))
3416        __(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
3417        __(cmpl %imm0,%arg_z)   /* last segment ?   */
3418        __(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
3419        __(movl %temp0,%arg_y)  /* last segment <- current segment   */
3420        __(movl %imm0,%temp0)   /* current segment <- next segment   */
3421        __(jne local_label(walkloop_mvcall))
3422
3423        __(movl %temp1,%arg_z)
3424        __(pop %nargs)
3425
3426        __(cmpl $nargregs*node_size,%nargs)
3427        __(jbe local_label(pushloop_mvcall))
3428        __(push $reserved_frame_marker)
3429        __(push $reserved_frame_marker)
3430
3431        /* the final segment pointer is now in %arg_y  */
3432        /* walk backwards, pushing values on the stack and incrementing %nargs*/
3433local_label(pushloop_mvcall):
3434        __(movl tsp_frame.data_offset(%arg_y),%imm0)    /* nargs in segment */
3435        __(test %imm0,%imm0)
3436        __(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
3437        __(jmp 2f)
34381:      __(push -node_size(%temp0))
3439        __(subl $node_size,%temp0)
3440        __(subl $fixnum_one,%imm0)
34412:      __(jne 1b)
3442        __(cmpl %arg_y,%arg_z)
3443        __(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
3444        __(jne local_label(pushloop_mvcall))
3445        __(movl (%arg_z),%arg_z)
3446        __(movl %arg_z,rcontext(tcr.save_tsp))
3447        __(movl %arg_z,rcontext(tcr.next_tsp))
3448        __(movl rcontext(tcr.save0),%ra0)
3449        __(movl $0,rcontext(tcr.save0))
3450        __(jmp *%ra0)           
3451_endsubp(recover_values_for_mvcall)
3452
3453_spentry(reset)
3454        __(hlt)
3455_endsubp(reset)
3456
3457/* temp0 = element-count, arg_y = subtag, arg_z = initval */
3458_spentry(misc_alloc_init)
3459        __(push %ebp)
3460        __(movl %esp,%ebp)
3461        __(push %arg_z)
3462        __(movl %arg_y,%arg_z)
3463        __(movl %temp0,%arg_y)
3464        __(push $local_label(misc_alloc_init_back))
3465        __(jmp _SPmisc_alloc)
3466__(tra(local_label(misc_alloc_init_back)))
3467        __(pop %arg_y)
3468        __(leave)
3469        __(movl $nrs.init_misc,%fname)
3470        __(set_nargs(2))
3471        __(jump_fname())
3472_endsubp(misc_alloc_init)
3473
3474/* %temp1 = element-count, %arg_y = subtag, %arg_z = initial-value */       
3475_spentry(stack_misc_alloc_init)
3476        __(push %ebp)
3477        __(movl %esp,%ebp)
3478        __(push %arg_z)
3479        __(movl %arg_y,%arg_z)
3480        __(movl %temp1,%arg_y)
3481        __(pushl $local_label(stack_misc_alloc_init_back))
3482        __(jmp _SPstack_misc_alloc)
3483__(tra(local_label(stack_misc_alloc_init_back)))
3484        __(popl %arg_y)
3485        __(leave)
3486        __(movl $nrs.init_misc,%fname)
3487        __(set_nargs(2))
3488        __(jump_fname())
3489_endsubp(stack_misc_alloc_init)
3490
3491        .globl C(popj)
3492_spentry(popj)
3493C(popj):
3494        __(leave)
3495        __(ret)
3496_endsubp(popj)
3497
3498/* arg_z should be of type (signed-byte 64) */
3499/* return unboxed value in mm0 */
3500_spentry(gets64)
3501        __(testb $fixnummask,%arg_z_b)
3502        __(jne 1f)
3503        __(unbox_fixnum(%arg_z,%imm0))
3504        __(movd %imm0,%mm0)
3505        __(jns 8f)
3506        /* get sign into upper half of %mm0 */
3507        __(pcmpeqd %mm1,%mm1)   /* all ones */
3508        __(psllq $32,%mm1)
3509        __(por %mm1,%mm0)
3510        __(ret)
35111:      __(movb %arg_z_b,%imm0_b)
3512        __(andb $tagmask,%imm0_b)
3513        __(cmpb $tag_misc,%imm0_b)
3514        __(jne 9f)
3515        __(movl misc_header_offset(%arg_z),%imm0)
3516        __(cmpb $subtag_bignum,%imm0_b)
3517        __(jne 9f)
3518        __(cmpl $two_digit_bignum_header,%imm0)
3519        __(ja 9f)
3520        __(movd misc_data_offset(%arg_z),%mm0)
3521        __(jne 8f)
3522        __(movq misc_data_offset(%arg_z),%mm0)
35238:      __(repret)
35249:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_s64))
3525_endsubp(gets64)
3526
3527/* arg_z should be of type (unsigned-byte 64) */
3528/* return unboxed value in mm0 */
3529_spentry(getu64)
3530        __(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
3531        __(testl %arg_z,%imm0)
3532        __(movl %arg_z,%imm0)
3533        __(jne 1f)
3534        __(sarl $fixnumshift,%imm0)
3535        __(movd %imm0,%mm0)
3536        __(ret)
35371:      __(andb $tagmask,%imm0_b)
3538        __(cmpb $tag_misc,%imm0_b)
3539        __(jne 9f)
3540        __(movl misc_header_offset(%arg_z),%imm0)
3541        __(cmpb $subtag_bignum,%imm0_b)
3542        __(jne 9f)
3543        __(cmpl $three_digit_bignum_header,%imm0)
3544        __(ja 9f)
3545        __(je 3f)
3546        __(cmpl $two_digit_bignum_header,%imm0)
3547        __(je 2f)
3548        /* must be a one digit bignum */
3549        __(movl misc_data_offset(%arg_z),%imm0)
3550        __(test %imm0,%imm0)
3551        __(js 9f)
3552        __(movd %imm0,%mm0)
3553        __(ret)
35542:      __(movl misc_data_offset+4(%arg_z),%imm0)
3555        __(testl %imm0,%imm0)
3556        __(js 9f)
3557        __(movq misc_data_offset(%arg_z),%mm0)
3558        __(ret)
35593:      __(movl misc_data_offset(%arg_z),%imm0)
3560        __(cmpl $0,misc_data_offset+8(%arg_z))
3561        __(jne 9f)
3562        __(movq misc_data_offset(%arg_z),%mm0)
3563        __(repret)
35649:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_u64))
3565_endsubp(getu64)
3566
3567/* Make unsigned integer from value in mm0 */
3568_spentry(makeu64)
3569        __(movq %mm0,%mm1)
3570        __(psrlq $32,%mm0)
3571        __(movd %mm0,%imm0)
3572        __(test %imm0,%imm0)
3573        __(js 3f)
3574        __(jnz 2f)
3575        __(movd %mm1,%imm0)
3576        __(cmpl $target_most_positive_fixnum,%imm0)
3577        __(ja 1f)
3578        __(box_fixnum(%imm0,%arg_z))
3579        __(ret)
35801:      /* maybe make a 1 digit bignum */
3581        __(test %imm0,%imm0)
3582        __(js 2f)
3583        __(movl $one_digit_bignum_header,%imm0)
3584        __(movd %imm0,%mm0)
3585        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
3586        __(movd %mm1,misc_data_offset(%arg_z))
3587        __(ret)
3588        /* make a 2 digit bignum */
35892:      __(movl $two_digit_bignum_header,%imm0)
3590        __(movd %imm0,%mm0)
3591        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
3592        __(movq %mm1,misc_data_offset(%arg_z))
3593        __(ret)
3594        /* make a 3 digit bignum */
35953:      __(movl $three_digit_bignum_header,%imm0)
3596        __(movd %imm0,%mm0)
3597        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(3)))
3598        __(movq %mm1,misc_data_offset(%arg_z))
3599        __(ret)
3600_endsubp(makeu64)
3601
3602/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly */
3603/* unbound_marker), arg_y = symbol */
3604_spentry(specref)
3605        __(movl symbol.binding_index(%arg_z),%imm0)
3606        __(cmp rcontext(tcr.tlb_limit),%imm0)
3607        __(movl rcontext(tcr.tlb_pointer),%temp1)
3608        __(movl %arg_z,%arg_y)
3609        __(jae 1f)
3610        __(movl (%temp1,%imm0),%arg_z)
3611        __(cmpb $no_thread_local_binding_marker,%arg_z_b)
3612        __(cmovel symbol.vcell(%arg_y),%arg_z)
3613        __(ret)
36141:      __(movl symbol.vcell(%arg_y),%arg_z)
3615        __(ret)
3616_endsubp(specref)
3617
3618/* arg_y = special symbol, arg_z = new value. */
3619_spentry(specset)
3620        __(movl symbol.binding_index(%arg_y),%imm0)
3621        __(cmp rcontext(tcr.tlb_limit),%imm0)
3622        __(movl rcontext(tcr.tlb_pointer),%temp1)
3623        __(jae 1f)
3624        __(movl (%temp1,%imm0),%temp0)
3625        __(cmpb $no_thread_local_binding_marker,%temp0_b)
3626        __(je 1f)
3627        __(movl %arg_z,(%temp1,%imm0))
3628        __(ret)
36291:      __(movl %arg_y,%temp0)
3630        __(movl $1<<fixnumshift,%arg_y)
3631        __(jmp _SPgvset)
3632_endsubp(specset)
3633
3634_spentry(specrefcheck)
3635        __(mov %arg_z,%arg_y)
3636        __(movl symbol.binding_index(%arg_z),%imm0)
3637        __(cmp rcontext(tcr.tlb_limit),%imm0)
3638        __(jae 7f)
3639        __(movl rcontext(tcr.tlb_pointer),%temp1)
3640        __(movl (%temp1,%imm0),%arg_z)
3641        __(cmpb $no_thread_local_binding_marker,%arg_z_b)
3642        __(cmovel symbol.vcell(%arg_y),%arg_z)
3643        __(cmpb $unbound_marker,%arg_z_b)
3644        __(je 9f)
36458:      __(repret)
36467:      __(movl symbol.vcell(%arg_y),%arg_z)
3647        __(cmpb $unbound_marker,symbol.vcell(%arg_y))
3648        __(je 9f)
3649        __(repret)
36509:      __(uuo_error_reg_unbound(Rarg_y))
3651_endsubp(specrefcheck)
3652
3653_spentry(restoreintlevel)
3654        __(hlt)
3655_endsubp(restoreintlevel)
3656
3657/* Make a lisp integer from the unsigned value in imm0 */
3658_spentry(makeu32)
3659        __(cmpl $target_most_positive_fixnum,%imm0)
3660        __(ja 0f)       /* need to make a bignum */
3661        __(box_fixnum(%imm0,%arg_z))
3662        __(ret)
36630:      __(movd %imm0,%mm1)
3664        __(test %imm0,%imm0)
3665        __(js 1f)
3666        __(movl $one_digit_bignum_header,%imm0)
3667        __(movd %imm0,%mm0)
3668        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
3669        __(movd %mm1,misc_data_offset(%arg_z))
3670        __(ret)
36711:      __(movl $two_digit_bignum_header,%imm0)
3672        __(movd %imm0,%mm0)
3673        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
3674        __(movd %mm1,misc_data_offset(%arg_z))
3675        __(ret)
3676_endsubp(makeu32)
3677
3678/* arg_z is of type (signed-byte 32) */
3679/* return unboxed value in %imm0 */
3680_spentry(gets32)
3681        __(testb $fixnummask,%arg_z_b)
3682        __(jne 1f)
3683        __(unbox_fixnum(%arg_z,%imm0))
3684        __(ret)
36851:      __(movb %arg_z_b,%imm0_b)
3686        __(andb $tagmask,%imm0_b)
3687        __(cmpb $tag_misc,%imm0_b)
3688        __(jne 9f)
3689        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3690        __(cmpb $subtag_bignum,%imm0_b)
3691        __(jne 9f)
3692        __(movl misc_header_offset(%arg_z),%imm0)
3693        __(cmpl $one_digit_bignum_header,%imm0)
3694        __(jne 9f)
3695        __(movl misc_data_offset(%arg_z),%imm0)
3696        __(ret)
36979:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_signed_byte_32))
3698_endsubp(gets32)
3699
3700/* arg_z is of type (unsigned-byte 32) */
3701/* return unboxed value in %imm0 */
3702_spentry(getu32)
3703        __(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
3704        __(testl %arg_z,%imm0)
3705        __(movl %arg_z,%imm0)
3706        __(jne 1f)
3707        __(sarl $fixnumshift,%imm0)
3708        __(ret)
37091:      __(andb $tagmask,%imm0_b)
3710        __(cmpb $tag_misc,%imm0_b)
3711        __(jne 9f)
3712        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3713        __(cmpb $subtag_bignum,%imm0_b)
3714        __(jne 9f)
3715        __(movl misc_header_offset(%arg_z),%imm0)
3716        __(cmpl $two_digit_bignum_header,%imm0)
3717        __(je 2f)
3718        __(cmpl $one_digit_bignum_header,%imm0)
3719        __(jne 9f)
3720        __(movl misc_data_offset(%arg_z),%imm0)
3721        __(ret)
37222:      __(movl misc_data_offset(%arg_z),%imm0)
3723        __(cmpl $0,misc_data_offset+4(%arg_z))
3724        __(jne 9f)
3725        __(ret)
37269:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_unsigned_byte_32))
3727_endsubp(getu32)
3728
3729_spentry(mvpasssym)
3730        __(hlt)
3731_endsubp(mvpasssym)
3732
3733/* don't smash arg_z */
3734_spentry(unbind)
3735        __(push %arg_z)
3736        __(movl rcontext(tcr.db_link),%imm0)
3737        __(movl rcontext(tcr.tlb_pointer),%arg_z)
3738        __(movl binding.sym(%imm0),%temp0)
3739        __(movl binding.val(%imm0),%arg_y)
3740        __(movl binding.link(%imm0),%imm0)
3741        __(movl %arg_y,(%arg_z,%temp0))
3742        __(movl %imm0,rcontext(tcr.db_link))
3743        __(pop %arg_z)
3744        __(ret)
3745_endsubp(unbind)
3746
3747_spentry(unbind_n)
3748        __(push %temp1)         /* preserve temp1/nargs */
3749        __(push %arg_z)
3750        __(xorl %arg_z,%arg_z)
3751        __(movl rcontext(tcr.db_link),%temp1)
3752        __(movl rcontext(tcr.tlb_pointer),%arg_z)
37531:             
3754        __(movl binding.sym(%temp1),%temp0)
3755        __(movl binding.val(%temp1),%arg_y)
3756        __(movl binding.link(%temp1),%temp1)
3757        __(movl %arg_y,(%arg_z,%temp0))
3758        __(decl %imm0)
3759        __(jne 1b)
3760        __(movl %temp1,rcontext(tcr.db_link))
3761        __(pop %arg_z)
3762        __(pop %temp1)
3763        __(ret)
3764_endsubp(unbind_n)
3765
3766_spentry(unbind_to)
3767        __(push %arg_y)
3768        __(push %arg_z)
3769        __(push %temp0)
3770        __(push %temp1)
3771       
3772        __(movl rcontext(tcr.db_link),%temp0)
3773        __(movl rcontext(tcr.tlb_pointer),%arg_z)
37741:
3775        __(movl binding.sym(%temp0),%temp1)
3776        __(movl binding.val(%temp0),%arg_y)
3777        __(movl binding.link(%temp0),%temp0)
3778        __(movl %arg_y,(%arg_z,%temp1))
3779        __(cmpl %temp0,%imm0)
3780        __(jne 1b)
3781        __(movl %temp0,rcontext(tcr.db_link))
3782
3783        __(pop %temp1)
3784        __(pop %temp0)
3785        __(pop %arg_z)
3786        __(pop %arg_y)
3787        __(ret)
3788_endsubp(unbind_to)
3789
3790_spentry(bind_interrupt_level_0)
3791        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3792        __(cmpl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3793        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3794        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3795        __(push rcontext(tcr.db_link))
3796        __(movl %esp,rcontext(tcr.db_link))
3797        __(movl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3798        __(js 1f)
37990:      __(jmp *%ra0)
3800        /* Interrupt level was negative; interrupt may be pending */
38011:      __(check_pending_enabled_interrupt(2f))
38022:      __(jmp *%ra0)
3803_endsubp(bind_interrupt_level_0)
3804
3805/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect  */
3806/* of disabling interrupts.)   */
3807_spentry(bind_interrupt_level_m1)
3808        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3809        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3810        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3811        __(push rcontext(tcr.db_link))
3812        __(movl %esp,rcontext(tcr.db_link))
3813        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3814        __(jmp *%ra0)
3815_endsubp(bind_interrupt_level_m1)
3816
3817/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0, */
3818/* do what _SPbind_interrupt_level_0 does. */
3819_spentry(bind_interrupt_level)
3820        __(test %arg_z,%arg_z)
3821        __(jz _SPbind_interrupt_level_0)
3822        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3823        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3824        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3825        __(push rcontext(tcr.db_link))
3826        __(movl %esp,rcontext(tcr.db_link))
3827        __(movl %arg_z,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3828        __(jmp *%ra0)
3829_endsubp(bind_interrupt_level)
3830
3831/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to */
3832/* non-negative, check for pending interrupts. */
3833_spentry(unbind_interrupt_level)
3834        __(btl $TCR_FLAG_BIT_PENDING_SUSPEND,rcontext(tcr.flags))
3835        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3836        __(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_y),%imm0)
3837        __(jc 5f)
38380:      __(test %imm0,%imm0)
3839        __(movl rcontext(tcr.db_link),%imm0)
3840        __(movl binding.val(%imm0),%temp0)
3841        __(movl binding.link(%imm0),%imm0)
3842        __(movl %temp0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3843        __(movl %imm0,rcontext(tcr.db_link))
3844        __(js 3f)
38452:      __(repret)
38463:      __(test %temp0,%temp0)
3847        __(js 2b)
3848        __(check_pending_enabled_interrupt(4f))
38494:      __(repret)
38505:       /* Missed a suspend request; force suspend now if we're restoring
3851          interrupt level to -1 or greater */
3852        __(cmpl $-2<<fixnumshift,%imm0)
3853        __(jne 0b)
3854        __(movl rcontext(tcr.db_link),%temp0)
3855        __(movl binding.val(%temp0),%temp0)
3856        __(cmpl %imm0,%temp0)
3857        __(je 0b)
3858        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3859        __(suspend_now())
3860        __(jmp 0b)
3861_endsubp(unbind_interrupt_level)
3862
3863_spentry(progvrestore)
3864        __(movl rcontext(tcr.save_tsp),%imm0)
3865        __(movl tsp_frame.backlink(%imm0),%imm0) /* ignore .SPnthrowXXX values frame   */
3866        __(movl tsp_frame.data_offset(%imm0),%imm0)
3867        __(shrl $fixnumshift,%imm0)
3868        __(jne _SPunbind_n)
3869        __(repret)
3870_endsubp(progvrestore)
3871
3872/* %arg_z <- %arg_y + %arg_z.  Do the fixnum case - including overflow -  */
3873/* inline.  Call out otherwise.   */
3874_spentry(builtin_plus)
3875        __(movl %arg_y,%imm0)
3876        __(orl %arg_z,%imm0)
3877        __(testb $fixnummask,%imm0_b)
3878        __(jne 1f)
3879        __(addl %arg_y,%arg_z)
3880        __(jo C(fix_one_bit_overflow))
3881        __(repret)
38821:      __(jump_builtin(_builtin_plus,2))
3883_endsubp(builtin_plus)
3884
3885/* %arg_z <- %arg_y - %arg_z.  Do the fixnum case - including overflow -  */
3886/*  inline.  Call out otherwise.   */
3887_spentry(builtin_minus)
3888        __(movl %arg_y,%imm0)
3889        __(orl %arg_z,%imm0)
3890        __(testb $fixnummask,%imm0_b)
3891        __(jne 1f)
3892        __(xchgl %arg_y,%arg_z)
3893        __(subl %arg_y,%arg_z)
3894        __(jo C(fix_one_bit_overflow))
3895        __(repret)
38961:      __(jump_builtin(_builtin_minus,2))
3897_endsubp(builtin_minus)
3898
3899/* %arg_z -< arg_y * arg_z. */
3900/* Do the fixnum case---including overflow---inline.  Call out otherwise. */
3901_spentry(builtin_times)
3902        __(movl %arg_y,%imm0)
3903        __(orb %arg_z_b,%imm0_b)
3904        __(testb $fixnummask,%imm0_b)
3905        __(jne 2f)
3906        __(unbox_fixnum(%arg_z,%imm0))
3907        /* 32-bit fixnum result in %imm0.  Overflow set if it doesn't fit. */
3908        __(imul %arg_y,%imm0)
3909        __(jo 1f)
3910        __(movl %imm0,%arg_z)
3911        __(ret)
39121:      __(unbox_fixnum(%arg_z,%eax))
3913        __(mark_as_imm(%edx))
3914        __(unbox_fixnum(%arg_y,%edx))
3915        __(imul %edx)
3916        __(movd %eax,%mm0)
3917        __(movd %edx,%mm1)
3918        __(mark_as_node(%edx))
3919        __(psllq $32,%mm1)
3920        __(por %mm1,%mm0)
3921        __(jmp _SPmakes64)
39222:      __(jump_builtin(_builtin_times,2))
3923_endsubp(builtin_times)
3924
3925_spentry(builtin_div)
3926        __(jump_builtin(_builtin_div,2))
3927
3928/* %arg_z <- (= %arg_y %arg_z).   */
3929_spentry(builtin_eq)
3930        __(movl %arg_y,%imm0)
3931        __(orb %arg_z_b,%imm0_b)
3932        __(testb $fixnummask,%imm0_b)
3933        __(jne 1f)
3934        __(rcmpl(%arg_z,%arg_y))
3935        __(condition_to_boolean(e,%imm0,%arg_z))
3936        __(ret)
39371:      __(jump_builtin(_builtin_eq,2))
3938_endsubp(builtin_eq)
3939
3940/* %arg_z <- (/= %arg_y %arg_z).          */
3941_spentry(builtin_ne)
3942        __(movl %arg_y,%imm0)
3943        __(orb %arg_z_b,%imm0_b)
3944        __(testb $fixnummask,%imm0_b)
3945        __(jne 1f)
3946        __(rcmpl(%arg_z,%arg_y))
3947        __(condition_to_boolean(ne,%imm0,%arg_z))
3948        __(ret)
39491:      __(jump_builtin(_builtin_ne,2))
3950_endsubp(builtin_ne)
3951
3952/* %arg_z <- (> %arg_y %arg_z).   */
3953_spentry(builtin_gt)
3954        __(movl %arg_y,%imm0)
3955        __(orb %arg_z_b,%imm0_b)
3956        __(testb $fixnummask,%imm0_b)
3957        __(jne 1f)
3958        __(rcmpl(%arg_y,%arg_z))
3959        __(condition_to_boolean(g,%imm0,%arg_z))
3960        __(ret)
39611:      __(jump_builtin(_builtin_gt,2))
3962_endsubp(builtin_gt)
3963
3964/* %arg_z <- (>= %arg_y %arg_z).          */
3965_spentry(builtin_ge)
3966        __(movl %arg_y,%imm0)
3967        __(orb %arg_z_b,%imm0_b)
3968        __(testb $fixnummask,%imm0_b)
3969        __(jne 1f)
3970        __(rcmpl(%arg_y,%arg_z))
3971        __(condition_to_boolean(ge,%imm0,%arg_z))
3972        __(ret)
39731:      __(jump_builtin(_builtin_ge,2))
3974_endsubp(builtin_ge)
3975
3976/* %arg_z <- (< %arg_y %arg_z).   */
3977_spentry(builtin_lt)
3978        __(movl %arg_y,%imm0)
3979        __(orb %arg_z_b,%imm0_b)
3980        __(testb $fixnummask,%imm0_b)
3981        __(jne 1f)
3982        __(rcmpl(%arg_y,%arg_z))
3983        __(condition_to_boolean(l,%imm0,%arg_z))
3984        __(ret)
39851:      __(jump_builtin(_builtin_lt,2))
3986_endsubp(builtin_lt)
3987
3988/* %arg_z <- (<= %arg_y %arg_z).   */
3989_spentry(builtin_le)
3990        __(movl %arg_y,%imm0)
3991        __(orb %arg_z_b,%imm0_b)
3992        __(testb $fixnummask,%imm0_b)
3993        __(jne 1f)
3994        __(rcmpl(%arg_y,%arg_z))
3995        __(condition_to_boolean(le,%imm0,%arg_z))
3996        __(ret)
39971:      __(jump_builtin(_builtin_le,2))
3998_endsubp(builtin_le)
3999
4000_spentry(builtin_eql)
40010:      __(cmpl %arg_y,%arg_z)
4002        __(je 8f)
4003        /* Not EQ.  Could only possibly be EQL if both are tag-misc  */
4004        /* and both have the same subtag. */
4005        __(movl %arg_y,%imm0)
4006        __(andb $tagmask,%imm0_b)
4007        __(cmpb $tag_misc,%imm0_b)
4008        __(jne 9f)
4009        __(movb %arg_z_b,%imm0_bh)
4010        __(andb $tagmask,%imm0_bh)
4011        __(cmpb %imm0_bh,%imm0_b)
4012        __(jne 9f)
4013        __(extract_subtag(%arg_y,%imm0_b))
4014        __(extract_subtag(%arg_z,%imm0_bh))
4015        __(cmpb %imm0_b,%imm0_bh)
4016        __(jne 9f)
4017        __(cmpb $subtag_macptr,%imm0_b)
4018        __(je 1f)
4019        __(cmpb $subtag_single_float,%imm0_b)
4020        __(jne 2f)
40211:      __(movl misc_data_offset(%arg_y),%imm0)
4022        __(cmpl misc_data_offset(%arg_z),%imm0)
4023        __(movl $t_value,%arg_z)
4024        __(movl $nil_value,%imm0)
4025        __(cmovnel %imm0,%arg_z)
4026        __(ret)
40272:      __(cmpb $subtag_double_float,%imm0_b)
4028        __(jne 3f)
4029        __(movl double_float.value(%arg_y),%imm0)
4030        __(cmpl double_float.value(%arg_z),%imm0)
4031        __(jne 9f)
4032        __(movl double_float.value+node_size(%arg_y),%imm0)
4033        __(cmpl double_float.value+node_size(%arg_z),%imm0)
4034        __(movl $t_value,%arg_z)
4035        __(movl $nil_value,%imm0)
4036        __(cmovnel %imm0,%arg_z)
4037        __(ret)
40383:      __(cmpb $subtag_ratio,%imm0_b)
4039        __(je 4f)
4040        __(cmpb $subtag_complex,%imm0_b)
4041        __(jne 6f)
40424:      __(pushl %ebp)
4043        __(pushl ratio.denom(%arg_y))
4044        __(pushl ratio.denom(%arg_z))
4045        __(movl ratio.numer(%arg_y),%arg_y)                       
4046        __(movl ratio.numer(%arg_z),%arg_z)
4047        __(pushl $5f)
4048        __(jmp 0b)
4049__(tra(5))
4050        __(compare_reg_to_nil(%arg_z))
4051        __(popl %arg_z)
4052        __(popl %arg_y)
4053        __(popl %ebp)
4054        __(je 9f)
4055        __(jmp 0b)
40566:      __(cmpb $subtag_bignum,%imm0_b)
4057        __(jne 9f)
4058        __(getvheader(%arg_y,%imm0))
4059        __(cmpl misc_header_offset(%arg_z),%imm0)
4060        __(jne 9f)
4061        __(header_length(%imm0,%temp0))
40627:      __(movl misc_data_offset-node_size(%arg_y,%temp0),%imm0)
4063        __(cmpl misc_data_offset-node_size(%arg_z,%temp0),%imm0)
4064        __(jne 9f)
4065        __(subl $node_size,%temp0)
4066        __(jne 7b)
40678:      __(movl $t_value,%arg_z)
4068        __(ret)
40699:      __(movl $nil_value,%arg_z)
4070        __(ret)
4071_endsubp(builtin_eql)
4072
4073_spentry(builtin_length)
4074        __(extract_fulltag(%arg_z,%imm0))
4075        __(cmpl $tag_list,%imm0)
4076        __(jz 2f)
4077        __(andl $tagmask,%imm0)
4078        __(cmpl $tag_misc,%imm0)
4079        __(jnz 8f)
4080        __(extract_subtag(%arg_z,%imm0_b))
4081        __(rcmpb(%imm0_b,$min_vector_subtag))
4082        __(jb 8f)
4083        __(je 1f)
4084        /* (simple-array * (*)) */
4085        __(movl %arg_z,%arg_y)
4086        __(vector_length(%arg_y,%arg_z))
4087        __(ret)
40881:      /* vector header */
4089        __(movl vectorH.logsize(%arg_z),%arg_z)
4090        __(ret)
40912:      /* list.  Maybe null, maybe dotted or circular. */
4092        __(movl $-fixnumone,%arg_y)
4093        __(movl %arg_z,%temp0)  /* fast pointer */
4094        __(movl %arg_z,%temp1)  /* slow pointer */
40953:      __(movb %temp0_b,%al)
4096        __(andb $fulltagmask,%al)
4097        __(addl $fixnumone,%arg_y)
4098        __(compare_reg_to_nil(%temp0))
4099        __(je 9f)
4100        __(cmpb $fulltag_cons,%al)
4101        __(jne 8f)
4102        __(movb %temp1_b,%ah)
4103        __(andb $fulltagmask,%ah)
4104        __(_cdr(%temp0,%temp0))
4105        __(testl $fixnumone,%arg_y)
4106        __(je 3b)
4107        __(cmpb $fulltag_cons,%ah)
4108        __(jne 8f)
4109        __(_cdr(%temp1,%temp1))
4110        __(cmpl %temp0,%temp1)
4111        __(jne 3b)
41128:
4113        __(jump_builtin(_builtin_length,1))
41149:
4115        __(movl %arg_y,%arg_z)
4116        __(ret)
4117_endsubp(builtin_length)
4118
4119_spentry(builtin_seqtype)
4120        __(extract_fulltag(%arg_z,%imm0))
4121        __(cmpb $fulltag_cons,%imm0_b)
4122        __(jz 1f)
4123        __(cmpb $tag_misc,%imm0_b)
4124        __(jne 2f)
4125        __(movb misc_subtag_offset(%arg_z),%imm0_b)
4126        __(rcmpb(%imm0_b,$min_vector_subtag))
4127        __(jb 2f)
4128        __(movl $nil_value,%arg_z)
4129        __(ret)
41301:      __(movl $t_value,%arg_z)
4131        __(ret)
41322:
4133        __(jump_builtin(_builtin_seqtype,1))
4134_endsubp(builtin_seqtype)
4135
4136_spentry(builtin_assq)
4137        __(cmpl $nil_value,%arg_z)
4138        __(je 5f)
41391:      __(movl %arg_z,%imm0)
4140        __(andb $fulltagmask,%imm0_b)
4141        __(cmpb $fulltag_cons,%imm0_b)
4142        __(jne 2f)
4143        __(_car(%arg_z,%temp0))
4144        __(_cdr(%arg_z,%arg_z))
4145        __(cmpl $nil_value,%temp0)
4146        __(je 4f)
4147        __(movl %temp0,%imm0)
4148        __(andb $fulltagmask,%imm0_b)
4149        __(cmpb $fulltag_cons,%imm0_b)
4150        __(jne 3f)
4151        __(_car(%temp0,%temp1))
4152        __(cmpl %temp1,%arg_y)
4153        __(jne 4f)
4154        __(movl %temp0,%arg_z)
4155        __(ret)
41564:      __(cmpl $nil_value,%arg_z)
41575:      __(jnz 1b)
4158        __(repret)
41592:      __(uuo_error_reg_not_list(Rarg_z))
41603:      __(uuo_error_reg_not_list(Rtemp0))
4161_endsubp(builtin_assq)
4162
4163_spentry(builtin_memq)
4164        __(cmpl $nil_value,%arg_z)
4165        __(jmp 3f)
41661:      __(movb $fulltagmask,%imm0_b)
4167        __(andb %arg_z_b,%imm0_b)
4168        __(cmpb $fulltag_cons,%imm0_b)
4169        __(jne 2f)
4170        __(_car(%arg_z,%temp1))
4171        __(_cdr(%arg_z,%temp0))
4172        __(cmpl %temp1,%arg_y)
4173        __(jz 4f)
4174        __(cmpl $nil_value,%temp0)
4175        __(movl %temp0,%arg_z)
41763:      __(jnz 1b)
41774:      __(repret)
41782:      __(uuo_error_reg_not_list(Rarg_z))
4179_endsubp(builtin_memq)
4180
4181logbitp_max_bit = 30
4182
4183_spentry(builtin_logbitp)
4184        /* Call out unless: both args fixnums, arg_y in `0, logbitp_max_bit) */
4185        __(movl %arg_z,%imm0)
4186        __(orl %arg_y,%imm0)
4187        __(testb $fixnummask,%imm0_b)
4188        __(jnz 1f)
4189        __(unbox_fixnum(%arg_y,%imm0))
4190        __(js 1f)       /* bit number negative */
4191        __(addb $fixnumshift,%imm0_b)
4192        __(cmpl $logbitp_max_bit<<fixnumshift,%arg_y)
4193        __(jb 2f)
4194        __(movl $logbitp_max_bit-1+fixnumshift,%imm0)
41952:      __(bt %imm0,%arg_z)
4196        __(condition_to_boolean(b,%imm0,%arg_z))
4197        __(ret)
41981:      __(jump_builtin(_builtin_logbitp,2))
4199_endsubp(builtin_logbitp)
4200
4201_spentry(builtin_logior)
4202        __(movl %arg_y,%imm0)
4203        __(orb %arg_z_b,%imm0_b)
4204        __(testb $fixnummask,%imm0_b)
4205        __(jne 1f)
4206        __(orl %arg_y,%arg_z)
4207        __(ret)
42081:
4209        __(jump_builtin(_builtin_logior,2))
4210_endsubp(builtin_logior)
4211
4212_spentry(builtin_logand)
4213        __(movl %arg_y,%imm0)
4214        __(orb %arg_z_b,%imm0_b)
4215        __(testb $fixnummask,%imm0_b)
4216        __(jne 1f)
4217        __(andl %arg_y,%arg_z)
4218        __(ret)
42191:
4220        __(jump_builtin(_builtin_logand,2))
4221_endsubp(builtin_logand)
4222
4223_spentry(builtin_negate)
4224        __(testb $fixnummask,%arg_z_b)
4225        __(jne 1f)
4226        __(negl %arg_z)
4227        __(jo C(fix_one_bit_overflow))
4228        __(repret)
42291:
4230        __(jump_builtin(_builtin_negate,1))
4231_endsubp(builtin_negate)
4232
4233_spentry(builtin_logxor)
4234        __(movl %arg_y,%imm0)
4235        __(orb %arg_z_b,%imm0_b)
4236        __(testb $fixnummask,%imm0_b)
4237        __(jne 1f)
4238        __(xorl %arg_y,%arg_z)
4239        __(ret)
42401:
4241        __(jump_builtin(_builtin_logxor,2))
4242_endsubp(builtin_logxor)
4243
4244/* temp0 = vector, arg_y = index, arg_z = newval */
4245_spentry(aset1)
4246        __(extract_typecode(%temp0,%imm0))
4247        __(box_fixnum(%imm0,%temp1))
4248        __(cmpb $min_vector_subtag,%imm0_b)
4249        __(ja _SPsubtag_misc_set)
4250        /* push frame... */
4251        __(pop %temp1)
4252        __(push $reserved_frame_marker)
4253        __(push $reserved_frame_marker)
4254        __(push %temp0)
4255        __(push %temp1)
4256        /* and fall through... */
4257_endsubp(aset1)
4258
4259_spentry(builtin_aset1)
4260        __(jump_builtin(_builtin_aset1,3))
4261_endsubp(builtin_aset1)
4262
4263_spentry(builtin_ash)
4264        __(movl %arg_y,%imm0)
4265        __(orb %arg_z_b,%imm0_b)
4266        __(testb $fixnummask,%imm0_b)
4267        __(jne 9f)
4268        __(unbox_fixnum(%arg_z,%imm0))
4269        /* Z flag set if zero ASH shift count */
4270        __(jnz 1f)
4271        __(movl %arg_y,%arg_z) /* shift by 0 */
4272        __(ret)
42731:      __(jns 3f)
4274        __(rcmpl(%imm0,$-31))
4275        __(jg 2f)
4276        __(unbox_fixnum(%arg_y,%imm0))
4277        __(sar $31,%imm0)
4278        __(box_fixnum(%imm0,%arg_z))
4279        __(ret)
42802:      /* Right-shift by small fixnum */
4281        __(negb %imm0_b)
4282        __(movzbl %imm0_b,%ecx)
4283        __(unbox_fixnum(%arg_y,%imm0))
4284        __(sar %cl,%imm0)
4285        __(box_fixnum(%imm0,%arg_z))
4286        __(ret)
42873:      /* Left shift by fixnum.  We can't shift by more than 31 bits, */
4288        /* though shifting by 32 is actually easy. */
4289        __(rcmpl(%imm0,$32))
4290        __(jg 9f)
4291        __(jne 4f)
4292        /* left-shift by 32 bits exactly */
4293        __(unbox_fixnum(%arg_y,%imm0))
4294        __(movd %imm0,%mm0)
4295        __(psllq $32,%mm0)
4296        __(jmp _SPmakes64)
42974:      /* left-shift by 1..31 bits. Safe to move shift count to %cl */
4298        __(movd %imm0,%mm1)     /* shift count */
4299        __(unbox_fixnum(%arg_y,%imm0))
4300        __(movd %imm0,%mm0)
4301        __(sarl $31,%imm0)      /* propagate sign */
4302        __(movd %imm0,%mm2)
4303        __(pshufw $0x4e,%mm2,%mm2) /* swap hi/lo halves */
4304        __(por %mm2,%mm0)
4305        __(psllq %mm1,%mm0)
4306        __(jmp _SPmakes64)
43079:
4308        __(jump_builtin(_builtin_ash,2))
4309_endsubp(builtin_ash)
4310
4311_spentry(builtin_aref1)
4312        __(extract_typecode(%arg_y,%imm0))
4313        __(box_fixnum_no_flags(%imm0,%temp0))
4314        __(cmpb $min_vector_subtag,%imm0_b)
4315        __(ja _SPsubtag_misc_ref)
4316        __(jump_builtin(_builtin_aref1,2))
4317_endsubp(builtin_aref1)
4318
4319/* Maybe check the x87 tag word to see if st(0) is valid and pop it */
4320/* if so.  This might allow us to avoid having to have a priori */
4321/* knowledge of whether a foreign function returns a floating-point result. */
4322/* backlink to saved %esp, below */
4323/* arg n-1 */
4324/* arg n-2 */
4325/* ... */
4326/* arg 0 */
4327/* space for alignment */
4328/* previous %esp */
4329
4330/*
4331 * Note that we assume that the lisp registers are in the default
4332 * state here:  that is, tcr.node_regs_mask has its default value,
4333 * and the DF is clear.
4334 */
4335        .globl C(ffcall_return)           
4336_spentry(ffcall)
4337LocalLabelPrefix`'ffcall:
4338        __(unbox_fixnum(%arg_z,%imm0))
4339        __(testb $fixnummask,%arg_z_b)
4340        __(je 0f)
4341        __(movl macptr.address(%arg_z),%imm0)
43420:
4343        /* Save lisp registers. */
4344        __(push %ebp)
4345        __(mov %esp,%ebp)
4346        __(push %temp0)                 
4347        __(push %temp1)                 
4348        __(push %arg_y)                 
4349        __(push %arg_z)                 
4350        __(push %fn)         
4351        __ifdef(`WIN32_ES_HACK')
4352         __(movl rcontext(tcr.linear),%ebx)
4353        __endif
4354        __(movl %esp,rcontext(tcr.save_vsp))
4355        __(movl %ebp,rcontext(tcr.save_ebp))
4356        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
4357        __(movl rcontext(tcr.foreign_sp),%esp)
4358        __(stmxcsr rcontext(tcr.lisp_mxcsr))
4359        __(emms)
4360        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
4361        __(movl (%esp),%ebp)
4362LocalLabelPrefix`'ffcall_setup:
4363        __(lea 15(%esp),%ecx)
4364        __(andl $-16,%ecx)
4365        __(movl %ecx,%esp)
4366/*      __(addl $node_size,%esp) */
4367        __ifdef(`WIN32_ES_HACK')
4368         __(push %ds)
4369         __(pop %es)
4370        __endif
4371LocalLabelPrefix`'ffcall_call:
4372        __(call *%eax)
4373C(ffcall_return):               
4374        __ifdef(`WIN32_ES_HACK')
4375         __(movw tcr.ldt_selector(%ebx),%rcontext_reg)
4376        __endif
4377LocalLabelPrefix`'ffcall_call_end:
4378        __(movl %ebp,%esp)
4379        __(movl %esp,rcontext(tcr.foreign_sp))
4380        /* The high word of a 64-bit result would be in %edx right now.
4381           There doesn't seem to be any other good place to put this,
4382           though %edx is often undefined at this point. */
4383        __(mov %edx,rcontext(tcr.unboxed1))
4384        __(clr %arg_z)
4385        __(clr %arg_y)
4386        __(clr %temp1)
4387        __(clr %temp0)
4388        __(clr %fn)
4389        __(pxor %fpzero,%fpzero)
4390        __(cmpb $0,C(bogus_fp_exceptions))
4391        __(je 0f)
4392        __(movl %arg_z,rcontext(tcr.ffi_exception))
4393        __(jmp 1f)
43940:
4395        __ifdef(`SSE2_MATH_LIB')
4396        __(stmxcsr rcontext(tcr.ffi_exception))
4397        __else
4398        __(fnstsw rcontext(tcr.ffi_exception))
4399        __(fnclex)
4400        __endif
4401        __(movl rcontext(tcr.save_vsp),%esp)
4402        __(movl rcontext(tcr.save_ebp),%ebp)
4403        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
4404        __(pop %fn)             
4405        __(pop %arg_z)           
4406        __(pop %arg_y)           
4407        __(pop %temp1) 
4408        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
4409        __(check_pending_interrupt(%temp0))
4410        __(pop %temp0)
4411        __(leave)
4412        __(ret)
4413        /* need to deal with NSExceptions and Objc-2.0 execptions */
4414_endsubp(ffcall)
4415
4416_spentry(ffcall_return_registers)
4417        __(hlt)
4418_endsubp(ffcall_return_registers)
4419
4420/* We need to reserve a frame here if (a) nothing else was already pushed
4421/* and (b) we push something (e.g., more than 2 args in the lexpr) */
4422_spentry(spread_lexprz)
4423        new_local_labels()
4424        __(movl (%arg_z),%imm0) /* lexpr count */
4425        __(leal node_size(%arg_z,%imm0),%arg_y)
4426        __(movd %arg_y,%mm1)
4427        __(test %nargs,%nargs) /* anything pushed by caller ? */
4428        __(jne 0f)              /* yes, caller has already created frame. */
4429        __(cmpl $(nargregs*node_size),%imm0) /* will we push anything ? */
4430        __(jbe 0f)
4431        __(push $reserved_frame_marker)
4432        __(push $reserved_frame_marker)
44330:      __(addl %imm0,%nargs)
4434        __(cmpl $(1*node_size),%imm0)
4435        __(ja 2f)
4436        __(je 1f)
4437        /* lexpr count was 0; vpop the args that */
4438        /* were pushed by the caller */
4439        __(test %nargs,%nargs)
4440        __(je local_label(all_args_popped))
4441        __(pop %arg_z)
4442local_label(maybe_pop_y):
4443        __(cmpl $(1*node_size),%nargs)
4444        __(je local_label(all_args_popped))
4445        __(pop %arg_y)
4446local_label(all_args_popped):   
4447        /* If all args fit in registers but some were pushed */
4448        /* by the caller, discard the reserved frame that the caller */
4449        /* pushed.         */
4450        __(cmpl %imm0,%nargs)
4451        __(je local_label(go))
4452        __(cmpl $(nargregs*node_size),%nargs)
4453        __(ja local_label(go))
4454        __(addl $(2*node_size),%esp)
4455local_label(go):
4456        __(jmp *%ra0)
4457
4458        /* lexpr count is two or more: vpush args from the lexpr until */
4459        /* we have only two left, then assign them to arg_y and arg_z */
44602:      __(cmpl $(2*node_size),%imm0)
4461        __(je local_label(push_loop_end))
4462local_label(push_loop):
4463        __(lea -1*node_size(%imm0),%imm0)
4464        __(push -node_size(%arg_y))
4465        __(lea -1*node_size(%arg_y),%arg_y)
4466        __(cmpl $(2*node_size),%imm0)
4467        __(jne 2b)
4468local_label(push_loop_end):
4469        __(movl -node_size*2(%arg_y),%arg_z)
4470        __(movl -node_size*1(%arg_y),%arg_y)
4471        __(jmp *%ra0)
4472        /* lexpr count is one: set arg_z from the lexpr, */
4473        /* maybe vpop arg_y  */
44741:      __(movl -node_size*1(%arg_y),%arg_z)
4475        __(jmp local_label(maybe_pop_y))
4476_endsubp(spread_lexprz)
4477
4478_spentry(callback)
4479        __(push %ebp)
4480        __(movl %esp,%ebp)
4481        /* C scalar args are already on the stack. */
4482        /* arg word 0 at 8(%ebp), word 1 at 12(%ebp), etc. */
4483
4484        /* %eax is passed to us via the callback trampoline.
4485           bits 0-22: callback index
4486           bit 23: flag, set if we need to discard hidden arg on return
4487                   (ignored when upper 8 bits are non-zero)
4488           bits 24-31: arg words to discard on return (_stdcall for win32) */
4489       
4490        /* Reserve some space for results, relative to the
4491           current %ebp.  We may need quite a bit of it. */
4492        __(subl $20,%esp)
4493        __(movl $0,-16(%ebp)) /* No FP result */
4494        __(btl $23,%eax)      /* set CF if we need to discard hidden arg */
4495        __(pushfl)            /* and save for later */
4496        __(movl %eax,%ecx)    /* extract args-discard count */
4497        __(shrl $24,%ecx)
4498        __(andl $0x007fffff,%eax) /* callback index */
4499        __(movl %ecx,-20(%ebp))
4500        /* If the C stack is 16-byte aligned by convention,
4501           it should still be, and this'll be a NOP. */
4502        __(andl $~15,%esp)
4503        /* C NVRs */
4504        __(push %edi)
4505        __(push %esi)
4506        __(push %ebx)
4507        __(push %ebp)
4508        __(box_fixnum(%eax,%esi))       /* put callback index in arg_y */
4509        __(cmpb $0,C(rcontext_readonly))
4510        __(jne 0f)
4511        __(ref_global(get_tcr,%eax))
4512        __(subl $12,%esp)               /* alignment */
4513        __(push $1)                     /* stack now 16-byte aligned */
4514        __(call *%eax)
4515        __(addl $16,%esp)               /* discard arg, alignment words */
4516        /* linear TCR addr now in %eax */
4517        ifdef(`WINDOWS',`
4518        ',`
4519        __(movw tcr.ldt_selector(%eax), %rcontext_reg)
4520        ')
45210:     
4522
4523        /* ebp is 16-byte aligned, and we've pushed 4 words.  Make
4524          sure that when we push old foreign_sp, %esp will be 16-byte
4525          aligned again */
4526        __(subl $8,%esp)
4527        __(pushl rcontext(tcr.save_ebp))  /* mark cstack frame's "owner" */
4528        __(push rcontext(tcr.foreign_sp))
4529        __(movl %esp,rcontext(tcr.foreign_sp))
4530        __(clr %arg_z)
4531        /* arg_y contains callback index */
4532        __(clr %temp1)
4533        __(clr %temp0)
4534        __(clr %fn)
4535        __(pxor %fpzero,%fpzero)
4536        __(movl rcontext(tcr.save_vsp),%esp)
4537        __(movl %ebp,%arg_z)
4538        __(movl rcontext(tcr.save_ebp),%ebp)
4539        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
4540        __(stmxcsr rcontext(tcr.foreign_mxcsr))
4541        __(andb $~mxcsr_all_exceptions,rcontext(tcr.foreign_mxcsr))
4542        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
4543        __(movl $nrs.callbacks,%fname)
4544        __(check_cstack_alignment())
4545        __(push $local_label(back_from_callback))
4546        __(set_nargs(2))
4547        __(jump_fname())
4548__(tra(local_label(back_from_callback)))
4549        __(movl %esp,rcontext(tcr.save_vsp))
4550        __(movl %ebp,rcontext(tcr.save_ebp))
4551        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
4552        __(movl rcontext(tcr.foreign_sp),%esp)
4553        __(stmxcsr rcontext(tcr.lisp_mxcsr))
4554        __(emms)
4555        __(pop rcontext(tcr.foreign_sp))
4556        __(addl $12,%esp)       /* discard alignment padding */
4557        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
4558        __ifdef(`WIN32_ES_HACK')
4559         __(push %ds)
4560         __(pop %es)
4561        __endif
4562        __(pop %ebp)
4563        __(pop %ebx)
4564        __(pop %esi)
4565        __(pop %edi)
4566        __(movl -12(%ebp),%ecx) /* magic value for ObjC bridge */
4567        __(cmpb $1,-16(%ebp))
4568        __(jae 1f)
4569        __(movl -8(%ebp),%eax)
4570        __(movl -4(%ebp),%edx)
4571        __ifdef(`WIN_32')
4572         __(cmpl $0,-20(%ebp))
4573         __(jne local_label(winapi_return))
4574        __endif
4575        /* since we aligned the stack after pushing flags, we're not
4576           really sure where %esp is relative to where flags were saved.
4577           We do know where the saved flags are relative to %ebp, so use
4578           that to establish %esp before the popfl.
4579        */
4580        __(lea -24(%ebp),%esp)
4581        __(popfl)       /* flags from bt way back when */
4582        __(jc local_label(discard_first_arg))
4583        __(leave)
4584        __(ret)
45851:      __(jne 2f)
4586        /* single float return in x87 */
4587        __(flds -8(%ebp))
4588        __ifdef(`WIN_32')
4589         __(cmpl $0,-20(%ebp))
4590         __(jne local_label(winapi_return))
4591        __endif
4592        __(leave)
4593        __(ret)
45942:      /* double-float return in x87 */
4595        __(fldl -8(%ebp))
4596        __ifdef(`WIN_32')
4597         __(cmpl $0,-20(%ebp))
4598         __(jne local_label(winapi_return))
4599        __endif
4600        __(leave)
4601        __(ret)
4602        __ifdef(`WIN_32')
4603local_label(winapi_return):
4604          __(movl -20(%ebp),%ecx)
4605          __(leave)
4606         /* %ecx is non-zero and contains count of arg words to pop */
4607          __(popl -4(%esp,%ecx,4))
4608          __(leal -4(%esp,%ecx,4),%esp)
4609          __(ret)
4610        __endif
4611local_label(discard_first_arg):
4612        __(leave)
4613        __(ret $4)
4614_endsubp(callback)
4615
4616/* temp0 = array, arg_y = i, arg_z = j. Typecheck everything.
4617   We don't know whether the array is alleged to be simple or
4618   not, and don't know anythng about the element type.  */
4619
4620_spentry(aref2)
4621        __(testl $fixnummask,%arg_y)
4622        __(jne 0f)
4623        __(testb $fixnummask,%arg_z_b)
4624        __(jne 1f)
4625        __(extract_typecode(%temp0,%imm0))
4626        __(cmpb $subtag_arrayH,%imm0_b)
4627        __(jne 2f)
4628        __(cmpl $2<<fixnumshift,arrayH.rank(%temp0))
4629        __(jne 2f)
4630        __(cmpl arrayH.dim0(%temp0),%arg_y)
4631        __(jae 3f)
4632        __(movl arrayH.dim0+node_size(%temp0),%imm0)
4633        __(cmpl %imm0,%arg_z)
4634        __(jae 4f)
4635        __(sarl $fixnumshift,%imm0)
4636        __(imull %arg_y,%imm0)
4637        __(addl %imm0,%arg_z)
4638        __(movl %temp0,%arg_y)
4639        __(xorl %temp1,%temp1)
46406:      __(addl arrayH.displacement(%arg_y),%arg_z)
4641        __(movl arrayH.data_vector(%arg_y),%arg_y)
4642        __(extract_subtag(%arg_y,%imm0_b))
4643        __(cmpb $subtag_vectorH,%imm0_b)
4644        __(ja C(misc_ref_common))
4645        __(jmp 6b)
46460:      __(uuo_error_reg_not_fixnum(Rarg_y))
46471:      __(uuo_error_reg_not_fixnum(Rarg_z))
46482:      __(uuo_error_reg_not_type(Rtemp0,error_object_not_array_2d))
46493:      __(uuo_error_array_bounds(Rarg_y,Rtemp0))
46504:      __(uuo_error_array_bounds(Rarg_z,Rtemp0))
4651
4652_endsubp(aref2)
4653
4654/* Like aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = k */
4655_spentry(aref3)
4656        __(testb $fixnummask,%temp0_b)
4657        __(jne 0f)
4658        __(testl $fixnummask,%arg_y)
4659        __(jne 1f)
4660        __(testb $fixnummask,%arg_z_b)
4661        __(jne 2f)
4662        __(extract_typecode(%temp1,%imm0))
4663        __(cmpb $subtag_arrayH,%imm0_b)
4664        __(jne 3f)
4665        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4666        __(jne 3f)
4667        __(cmpl arrayH.dim0(%temp1),%temp0)
4668        __(jae 4f)
4669        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4670        __(cmpl %imm0,%arg_y)
4671        __(jae 5f)
4672        __(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_z)
4673        __(jae 6f)
4674        /* index computation: k + dim2 * (j + dim1 * i) */
4675        /* (plus minor fussing for fixnum scaling) */
4676        __(sarl $fixnumshift,%imm0)
4677        __(imull %imm0,%temp0)
4678        __(addl %arg_y,%temp0)
4679        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
4680        __(sarl $fixnumshift,%imm0)
4681        __(imull %imm0,%temp0)
4682        __(addl %temp0,%arg_z)
4683        __(movl %temp1,%arg_y)
46848:      __(addl arrayH.displacement(%arg_y),%arg_z)
4685        __(movl arrayH.data_vector(%arg_y),%arg_y)
4686        __(extract_subtag(%arg_y,%imm0_b))
4687        __(cmpb $subtag_vectorH,%imm0_b)
4688        __(ja C(misc_ref_common))
4689        __(jmp 8b)
46900:      __(uuo_error_reg_not_fixnum(Rtemp0))
46911:      __(uuo_error_reg_not_fixnum(Rarg_y))
46922:      __(uuo_error_reg_not_fixnum(Rarg_z))
46933:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
46944:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
46955:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
46966:      __(uuo_error_array_bounds(Rarg_z,Rtemp1))
4697_endsubp(aref3)
4698
4699/* As with aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = new_value */
4700_spentry(aset2)
4701        __(testb $fixnummask,%temp0_b)
4702        __(jne 0f)
4703        __(testl $fixnummask,%arg_y)
4704        __(jne 1f)
4705        __(extract_typecode(%temp1,%imm0))
4706        __(cmpb $subtag_arrayH,%imm0_b)
4707        __(jne 2f)
4708        __(cmpl $2<<fixnumshift,arrayH.rank(%temp1))
4709        __(jne 2f)
4710        __(cmpl arrayH.dim0(%temp1),%temp0)
4711        __(jae 3f)
4712        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4713        __(cmpl %imm0,%arg_y)
4714        __(jae 4f)
4715        __(sarl $fixnumshift,%imm0)
4716        __(imull %temp0,%imm0)
4717        __(addl %imm0,%arg_y)
4718        __(movl %temp1,%temp0)
4719        __(xorl %temp1,%temp1)
47206:      __(addl arrayH.displacement(%temp0),%arg_y)
4721        __(movl arrayH.data_vector(%temp0),%temp0)
4722        __(extract_subtag(%temp0,%imm0_b))
4723        __(cmpb $subtag_vectorH,%imm0_b)
4724        __(ja C(misc_set_common))
4725        __(jmp 6b)
47260:      __(uuo_error_reg_not_fixnum(Rtemp0))
47271:      __(uuo_error_reg_not_fixnum(Rarg_y))
47282:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_2d))
47293:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
47304:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
4731_endsubp(aset2)
4732
4733/* temp1 = array, (%esp) = i, temp0 = j, arg_y = k, arg_z = newval */
4734_spentry(aset3)
4735        __(testb $fixnummask,(%esp))
4736        __(jne 0f)
4737        __(testb $fixnummask,%temp0_b)
4738        __(jne 1f)
4739        __(testl $fixnummask,%arg_y)
4740        __(jne 2f)
4741        __(extract_typecode(%temp1,%imm0))
4742        __(cmpb $subtag_arrayH,%imm0_b)
4743        __(jne 3f)
4744        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4745        __(jne 3f)
4746        __(movl arrayH.dim0(%temp1),%imm0)
4747        __(cmpl %imm0,(%esp))   /* i on stack */
4748        __(jae 4f)
4749        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4750        __(cmpl %imm0,%temp0)
4751        __(jae 5f)
4752        __(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_y)
4753        __(jae 6f)
4754        /* index computation: k + dim2 * (j + dim1 * i) */
4755        /* (plus minor fussing for fixnum scaling) */
4756        __(sarl $fixnumshift,%imm0)
4757        __(imull (%esp),%imm0)  /* i on stack */
4758        __(addl %imm0,%temp0)
4759        __(addl $node_size,%esp)
4760        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
4761        __(sarl $fixnumshift,%imm0)
4762        __(imull %imm0,%temp0)
4763        __(addl %temp0,%arg_y)
4764        __(movl %temp1,%temp0)
47658:      __(addl arrayH.displacement(%temp0),%arg_y)
4766        __(movl arrayH.data_vector(%temp0),%temp0)
4767        __(extract_subtag(%temp0,%imm0_b))
4768        __(cmpb $subtag_vectorH,%imm0_b)
4769        __(ja C(misc_set_common))
4770        __(jmp 8b)
47710:      __(pop %temp0)  /* supplied i */
4772        __(uuo_error_reg_not_fixnum(Rtemp0))
47731:      __(uuo_error_reg_not_fixnum(Rtemp0))
47742:      __(uuo_error_reg_not_fixnum(Rarg_y))
47753:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
47764:      __(pop %imm0)   /* supplied i is on stack */
4777        __(uuo_error_array_bounds(Rimm0,Rtemp1))
47785:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
47796:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
4780_endsubp(aset3)
4781
4782/* Prepend all but the first seven (6 words of code & other immediate data,
4783/* plus inner fn) and last (lfbits) elements of %fn to the "arglist". */
4784_spentry(call_closure)
4785        new_local_labels()
4786        __(vector_length(%fn,%imm0))
4787        __(subl $8<<fixnumshift,%imm0)  /* imm0 = inherited arg count */
4788        __(lea (%nargs,%imm0),%temp0)
4789        __(cmpl $nargregs<<fixnumshift,%temp0)
4790        __(jna local_label(regs_only))  /* either: 1 arg, 1 inherited, or */
4791                                        /* no args, 2 inherited */
4792        __(pop rcontext(tcr.save0))             /* save return address */
4793        __(cmpl $nargregs<<fixnumshift,%nargs)
4794        __(jna local_label(no_insert))
4795
4796/* Some arguments have already been pushed.  Push %imm0's worth */
4797/* of NILs, copy those arguments that have already been vpushed from */
4798/* the old TOS to the new, then insert all of the inherited args */
4799/* and go to the function. */
4800
4801        __(mov %imm0,%temp0)
4802local_label(push_nil_loop):
4803        __(push $nil_value)
4804        __(sub $fixnumone,%temp0)
4805        __(jne local_label(push_nil_loop))
4806
4807/* Need to use arg regs as temporaries.  Stash them in the spill area. */
4808        __(movl %arg_y,rcontext(tcr.save1))
4809        __(movl %arg_z,rcontext(tcr.save2))
4810
4811        __(leal (%esp,%imm0),%temp0)    /* start of already-pushed args */
4812        __(leal -nargregs<<fixnumshift(%nargs),%arg_y) /* args pushed */
4813        __(movd %imm0,%mm0)     /* save inherited arg count */
4814        __(xorl %imm0,%imm0)
4815local_label(copy_already_loop):
4816        __(movl (%temp0,%imm0),%arg_z)
4817        __(movl %arg_z,(%esp,%imm0))
4818        __(addl $fixnumone,%imm0)
4819        __(cmpl %imm0,%arg_y)
4820        __(jne local_label(copy_already_loop))
4821
4822        __(lea -node_size(%temp0,%imm0),%arg_y) /* start of args on stack */
4823        __(movl $7<<fixnumshift,%temp0) /* skip code, new fn */
4824        __(movd %mm0,%imm0)
4825local_label(insert_loop):
4826        __(movl misc_data_offset(%fn,%temp0),%arg_z)
4827        __(addl $node_size,%temp0)
4828        __(addl $fixnumone,%nargs)
4829        __(movl %arg_z,(%arg_y))
4830        __(subl $node_size,%arg_y)
4831        __(subl $fixnumone,%imm0)
4832        __(jne local_label(insert_loop))
4833
4834        /* Recover arg regs, saved earlier */
4835        __(movl rcontext(tcr.save1),%arg_y)
4836        __(movl rcontext(tcr.save2),%arg_z)
4837        __(jmp local_label(go))
4838       
4839/* Here if no args were pushed by the caller. */
4840/* cases: */
4841/* no args, more than two inherited args */
4842/* a single arg in arg_z, more than one inherited arg */
4843/* two args in arg_y and arg_z, some number of inherited args */
4844
4845/* Therefore, we're always going to have to push something (the sum of */
4846/* %nargs and %imm0 will always be greater than $nargregs), and */
4847/* we will have to reserve space for a stack frame. */
4848/* The 0 args, 2 inherited case and the 1 arg, 1 inherited case get */
4849/* handled at local_label(regs_ony). */
4850       
4851local_label(no_insert):
4852        /* Reserve space for a stack frame */
4853        __(push $reserved_frame_marker)
4854        __(push $reserved_frame_marker)
4855        __(lea 7<<fixnumshift(%imm0),%temp0)    /* last inherited arg */
4856        __(rcmpl(%nargs,$fixnumone))
4857        __(je local_label(set_arg_y))
4858        __(jb local_label(set_y_z))
4859        /* %nargs = $nargregs (i.e., 2), vpush remaining inherited vars. */
4860
4861local_label(vpush_remaining):
4862        __(movl $7<<fixnumshift,%temp0)
4863local_label(vpush_remaining_loop):
4864        __(push misc_data_offset(%fn,%temp0))
4865        __(add $node_size,%temp0)
4866        __(add $fixnumone,%nargs)
4867        __(sub $node_size,%imm0)
4868        __(jnz local_label(vpush_remaining_loop))
4869        __(jmp local_label(go))
4870       
4871local_label(set_arg_y):
4872        /* one arg in arg_z.  set arg_y and vpush remaining inherited args */
4873        __(subl $node_size,%temp0)
4874        __(movl misc_data_offset(%fn,%temp0),%arg_y)
4875        __(addl $fixnumone,%nargs)
4876        __(subl $fixnumone,%imm0)
4877        __(jmp local_label(vpush_remaining))
4878local_label(set_y_z):
4879        __(subl $node_size,%temp0)
4880        __(movl misc_data_offset(%fn,%temp0),%arg_z)
4881        __(addl $fixnumone,%nargs)
4882        __(subl $fixnumone,%imm0)
4883        __(jmp local_label(set_arg_y))
4884
4885local_label(go):
4886        __(movl misc_data_offset+(6*node_size)(%fn),%fn)
4887        __(push rcontext(tcr.save0))    /* restore return addr */
4888        __(movapd %fpzero,rcontext(tcr.save0))  /* clear out spill area */
4889        __(jmp *%fn)
4890local_label(regs_only):
4891        __(lea 7<<fixnumshift(%imm0),%temp0)
4892        __(test %nargs,%nargs)
4893        __(jne local_label(one_arg))
4894        /* no args passed, two inherited args */
4895        __(movl misc_data_offset-node_size(%fn,%temp0),%arg_z)
4896        __(cmpl $node_size,%imm0)
4897        __(je local_label(rgo))
4898        __(movl misc_data_offset-(node_size*2)(%fn,%temp0),%arg_y)
4899local_label(rgo):
4900        __(addl %imm0,%nargs)
4901        __(jmp *misc_data_offset+(6*node_size)(%fn))
4902local_label(one_arg):
4903        /* one arg was passed, so there's one inherited arg */
4904        __(movl misc_data_offset-node_size(%fn,%temp0),%arg_y)
4905        __(jmp local_label(rgo))
4906_endsubp(call_closure)
4907
4908_spentry(poweropen_callbackX)
4909        __(hlt)
4910_endsubp(poweropen_callbackX)
4911
4912_spentry(poweropen_ffcallX)
4913        __(hlt)
4914_endsubp(poweropen_ffcallX)
4915
4916_spentry(eabi_ff_call)
4917        __(hlt)
4918_endsubp(eabi_ff_call)
4919
4920_spentry(eabi_callback)
4921        __(hlt)
4922_endsubp(eabi_callback)
4923
4924
4925/* Unused, and often not used on PPC either  */
4926_spentry(callbuiltin)
4927        __(hlt)
4928_endsubp(callbuiltin)
4929
4930_spentry(callbuiltin0)
4931        __(hlt)
4932_endsubp(callbuiltin0)
4933
4934_spentry(callbuiltin1)
4935        __(hlt)
4936_endsubp(callbuiltin1)
4937
4938_spentry(callbuiltin2)
4939        __(hlt)
4940_endsubp(callbuiltin2)
4941
4942_spentry(callbuiltin3)
4943        __(hlt)
4944_endsubp(callbuiltin3)
4945
4946_spentry(restorefullcontext)
4947        __(hlt)
4948_endsubp(restorefullcontext)
4949
4950_spentry(savecontextvsp)
4951        __(hlt)
4952_endsubp(savecontextvsp)
4953
4954_spentry(savecontext0)
4955        __(hlt)
4956_endsubp(savecontext0)
4957
4958_spentry(restorecontext)
4959        __(hlt)
4960_endsubp(restorecontext)
4961
4962_spentry(stkconsyz)
4963        __(hlt)
4964_endsubp(stkconsyz)
4965
4966_spentry(stkvcell0)
4967        __(hlt)
4968_endsubp(stkvcell0)
4969
4970_spentry(stkvcellvsp)
4971        __(hlt)
4972_endsubp(stkvcellvsp)
4973
4974_spentry(breakpoint)
4975        __(hlt)
4976_endsubp(breakpoint)
4977
4978_spentry(unused_6)
4979        __(hlt)
4980Xspentry_end:
4981_endsubp(unused_6)
4982        .data
4983        .globl C(spentry_start)
4984        .globl C(spentry_end)
4985C(spentry_start):       .long Xspentry_start
4986C(spentry_end):         .long Xspentry_end
4987       
Note: See TracBrowser for help on using the repository browser.