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

Last change on this file since 14347 was 13561, checked in by gb, 10 years ago

In the vinsns and subprims for special variable reference, try to
use CMOVs rather than branches.

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