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

Last change on this file since 12008 was 12008, checked in by gb, 11 years ago

When popping flags on return from callback, recognize that we may
have aligned the stack after saving flags on entry, so re-establish
%esp relative to %ebp before popfl. (This seems to have mostly affected
Linux when exception callbacks returned.)

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