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

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

_SPstkconslist_star: implement, share code with _SPstkconslist.

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