source: release/1.4/source/lisp-kernel/x86-spentry32.s @ 13176

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

Propagate r13175 (x8632 image relocation/large functions) and
r13171 (x8632 callback winabi/ObjC exception disentanglement)
to 1.4.

File size: 155.6 KB
Line 
1        include(lisp.s)
2        _beginfile
3
4        .align 2
5define([_spentry],[ifdef([__func_name],[_endfn],[])
6        .p2align 3
7        _exportfn(_SP$1)
8])
9
10define([_endsubp],[
11        _endfn(_SP$1)
12])
13
14define([jump_builtin],[
15        ref_nrs_value(builtin_functions,%fname)
16        set_nargs($2)
17        vrefr(%fname,%fname,$1)
18        jump_fname()
19])
20
21_spentry(bad_funcall)
22Xspentry_start:                 
23        .globl C(bad_funcall)
24__(tra(C(bad_funcall)))
25        __(uuo_error_not_callable)
26_endsubp(bad_funcall)
27
28/* %arg_z has overflowed by one bit.  Make a bignum with 1 (32-bit) digit. */
29_spentry(fix_overflow)
30C(fix_one_bit_overflow):
31        __(movl $one_digit_bignum_header,%imm0)
32        __(movd %imm0,%mm0)
33        __(Misc_Alloc_Fixed([],aligned_bignum_size(1)))
34        __(unbox_fixnum(%arg_z,%imm0))
35        __(xor $0xc0000000,%imm0)
36        __(mov %temp0,%arg_z)
37        __(movl %imm0,misc_data_offset(%arg_z))
38        __(ret)
39_endsubp(fix_overflow)
40
41/* %arg_y = vector, %arg_z = unscaled-idx */
42_spentry(misc_ref)
43        __(mov %arg_y,%imm0)
44        __(andb $tagmask,%imm0_b)
45        __(cmpb $tag_misc,%imm0_b)
46        __(jne 0f)
47        __(testb $fixnummask,%arg_z_b)
48        __(jne 1f)
49        __(movl misc_header_offset(%arg_y),%imm0)
50        __(xorb %imm0_b,%imm0_b)
51        __(shrl $num_subtag_bits-fixnumshift,%imm0)
52        __(cmpl %imm0,%arg_z)
53        __(jae 2f)
54        __(movb misc_subtag_offset(%arg_y),%imm0_b)
55        __(jmp C(misc_ref_common))
56
570:      __(uuo_error_reg_not_tag(Rarg_y,tag_misc))
581:      __(uuo_error_reg_not_fixnum(Rarg_z))
592:      __(uuo_error_vector_bounds(Rarg_z,Rarg_y))
60_endsubp(misc_ref)
61
62/* %imm0_b = subtag, %arg_y = vector, %arg_z = index. */
63/* Bounds/type-checking done in caller. */
64_startfn(C(misc_ref_common))
65        __(movzbl %imm0_b,%imm0)
66        __(leal local_label(misc_ref_jmp)(,%imm0,4),%imm0)
67        __(jmp *(%imm0))
68        .p2align 2
69local_label(misc_ref_jmp):
70        /* 00-0f */
71        .long local_label(misc_ref_invalid) /* 00 even_fixnum  */
72        .long local_label(misc_ref_invalid) /* 01 cons  */
73        .long local_label(misc_ref_invalid) /* 02 nodeheader  */
74        .long local_label(misc_ref_invalid) /* 03 imm  */
75        .long local_label(misc_ref_invalid) /* 04 odd_fixnum  */
76        .long local_label(misc_ref_invalid) /* 05 tra  */
77        .long local_label(misc_ref_invalid) /* 06 misc  */
78        .long local_label(misc_ref_u32) /* 07 bignum  */
79        .long local_label(misc_ref_invalid) /* 08 even_fixnum  */
80        .long local_label(misc_ref_invalid) /* 09 cons  */
81        .long local_label(misc_ref_node) /* 0a ratio  */
82        .long local_label(misc_ref_invalid) /* 0b imm  */
83        .long local_label(misc_ref_invalid) /* 0c odd_fixnum  */
84        .long local_label(misc_ref_invalid) /* 0d tra  */
85        .long local_label(misc_ref_invalid) /* 0e misc  */
86        .long local_label(misc_ref_u32) /* 0f single_float  */
87        /* 10-1*/
88        .long local_label(misc_ref_invalid) /* 10 even_fixnum  */
89        .long local_label(misc_ref_invalid) /* 11 cons  */
90        .long local_label(misc_ref_invalid) /* 12 nodeheader  */
91        .long local_label(misc_ref_invalid) /* 13 imm  */
92        .long local_label(misc_ref_invalid) /* 14 odd_fixnum  */
93        .long local_label(misc_ref_invalid) /* 15 tra  */
94        .long local_label(misc_ref_invalid) /* 16 misc  */
95        .long local_label(misc_ref_u32) /* 17 double_float  */
96        .long local_label(misc_ref_invalid) /* 18 even_fixnum  */
97        .long local_label(misc_ref_invalid) /* 19 cons  */
98        .long local_label(misc_ref_node) /* 1a complex  */
99        .long local_label(misc_ref_invalid) /* 1b imm  */
100        .long local_label(misc_ref_invalid) /* 1c odd_fixnum  */
101        .long local_label(misc_ref_invalid) /* 1d tra  */
102        .long local_label(misc_ref_invalid) /* 1e misc  */
103        .long local_label(misc_ref_u32) /* 1f macptr  */
104        /* 20-2*/
105        .long local_label(misc_ref_invalid) /* 20 even_fixnum  */
106        .long local_label(misc_ref_invalid) /* 21 cons  */
107        .long local_label(misc_ref_node) /* 22 catch_frame  */
108        .long local_label(misc_ref_invalid) /* 23 imm  */
109        .long local_label(misc_ref_invalid) /* 24 odd_fixnum  */
110        .long local_label(misc_ref_invalid) /* 25 tra  */
111        .long local_label(misc_ref_invalid) /* 26 misc  */
112        .long local_label(misc_ref_u32) /* 27 dead_macptr  */
113        .long local_label(misc_ref_invalid) /* 28 even_fixnum  */
114        .long local_label(misc_ref_invalid) /* 29 cons  */
115        .long local_label(misc_ref_function) /* 2a function  */
116        .long local_label(misc_ref_invalid) /* 2b imm  */
117        .long local_label(misc_ref_invalid) /* 2c odd_fixnum  */
118        .long local_label(misc_ref_invalid) /* 2d tra  */
119        .long local_label(misc_ref_invalid) /* 2e misc  */
120        .long local_label(misc_ref_invalid) /* 2f immheader  */
121        /* 30-3*/
122        .long local_label(misc_ref_invalid) /* 30 even_fixnum  */
123        .long local_label(misc_ref_invalid) /* 31 cons  */
124        .long local_label(misc_ref_node) /* 32 basic_stream  */
125        .long local_label(misc_ref_invalid) /* 33 imm  */
126        .long local_label(misc_ref_invalid) /* 34 odd_fixnum  */
127        .long local_label(misc_ref_invalid) /* 35 tra  */
128        .long local_label(misc_ref_invalid) /* 36 misc  */
129        .long local_label(misc_ref_invalid) /* 37 immheader  */
130        .long local_label(misc_ref_invalid) /* 38 even_fixnum  */
131        .long local_label(misc_ref_invalid) /* 39 cons  */
132        .long local_label(misc_ref_node) /* 3a symbol  */
133        .long local_label(misc_ref_invalid) /* 3b imm  */
134        .long local_label(misc_ref_invalid) /* 3c odd_fixnum  */
135        .long local_label(misc_ref_invalid) /* 3d tra  */
136        .long local_label(misc_ref_invalid) /* 3e misc  */
137        .long local_label(misc_ref_u32) /* 3f xcode_vector  */
138        /* 40-4*/
139        .long local_label(misc_ref_invalid) /* 40 even_fixnum  */
140        .long local_label(misc_ref_invalid) /* 41 cons  */
141        .long local_label(misc_ref_node) /* 42 lock  */
142        .long local_label(misc_ref_invalid) /* 43 imm  */
143        .long local_label(misc_ref_invalid) /* 44 odd_fixnum  */
144        .long local_label(misc_ref_invalid) /* 45 tra  */
145        .long local_label(misc_ref_invalid) /* 46 misc  */
146        .long local_label(misc_ref_invalid) /* 47 immheader  */
147        .long local_label(misc_ref_invalid) /* 48 even_fixnum  */
148        .long local_label(misc_ref_invalid) /* 49 cons  */
149        .long local_label(misc_ref_node) /* 4a hash_vector  */
150        .long local_label(misc_ref_invalid) /* 4b imm  */
151        .long local_label(misc_ref_invalid) /* 4c odd_fixnum  */
152        .long local_label(misc_ref_invalid) /* 4d tra  */
153        .long local_label(misc_ref_invalid) /* 4e misc  */
154        .long local_label(misc_ref_invalid) /* 4f immheader  */
155        /* 50-5*/
156        .long local_label(misc_ref_invalid) /* 50 even_fixnum  */
157        .long local_label(misc_ref_invalid) /* 51 cons  */
158        .long local_label(misc_ref_node) /* 52 pool  */
159        .long local_label(misc_ref_invalid) /* 53 imm  */
160        .long local_label(misc_ref_invalid) /* 54 odd_fixnum  */
161        .long local_label(misc_ref_invalid) /* 55 tra  */
162        .long local_label(misc_ref_invalid) /* 56 misc  */
163        .long local_label(misc_ref_invalid) /* 57 immheader  */
164        .long local_label(misc_ref_invalid) /* 58 even_fixnum  */
165        .long local_label(misc_ref_invalid) /* 59 cons  */
166        .long local_label(misc_ref_node) /* 5a weak  */
167        .long local_label(misc_ref_invalid) /* 5b imm  */
168        .long local_label(misc_ref_invalid) /* 5c odd_fixnum  */
169        .long local_label(misc_ref_invalid) /* 5d tra  */
170        .long local_label(misc_ref_invalid) /* 5e misc  */
171        .long local_label(misc_ref_invalid) /* 5f immheader  */
172        /* 60-6*/
173        .long local_label(misc_ref_invalid) /* 60 even_fixnum  */
174        .long local_label(misc_ref_invalid) /* 61 cons  */
175        .long local_label(misc_ref_node) /* 62 package  */
176        .long local_label(misc_ref_invalid) /* 63 imm  */
177        .long local_label(misc_ref_invalid) /* 64 odd_fixnum  */
178        .long local_label(misc_ref_invalid) /* 65 tra  */
179        .long local_label(misc_ref_invalid) /* 66 misc  */
180        .long local_label(misc_ref_invalid) /* 67 immheader  */
181        .long local_label(misc_ref_invalid) /* 68 even_fixnum  */
182        .long local_label(misc_ref_invalid) /* 69 cons  */
183        .long local_label(misc_ref_node) /* 6a slot_vector  */
184        .long local_label(misc_ref_invalid) /* 6b imm  */
185        .long local_label(misc_ref_invalid) /* 6c odd_fixnum  */
186        .long local_label(misc_ref_invalid) /* 6d tra  */
187        .long local_label(misc_ref_invalid) /* 6e misc  */
188        .long local_label(misc_ref_invalid) /* 6f immheader  */
189        /* 70-7*/
190        .long local_label(misc_ref_invalid) /* 70 even_fixnum  */
191        .long local_label(misc_ref_invalid) /* 71 cons  */
192        .long local_label(misc_ref_node) /* 72 instance  */
193        .long local_label(misc_ref_invalid) /* 73 imm  */
194        .long local_label(misc_ref_invalid) /* 74 odd_fixnum  */
195        .long local_label(misc_ref_invalid) /* 75 tra  */
196        .long local_label(misc_ref_invalid) /* 76 misc  */
197        .long local_label(misc_ref_invalid) /* 77 immheader  */
198        .long local_label(misc_ref_invalid) /* 78 even_fixnum  */
199        .long local_label(misc_ref_invalid) /* 79 cons  */
200        .long local_label(misc_ref_node) /* 7a struct  */
201        .long local_label(misc_ref_invalid) /* 7b imm  */
202        .long local_label(misc_ref_invalid) /* 7c odd_fixnum  */
203        .long local_label(misc_ref_invalid) /* 7d tra  */
204        .long local_label(misc_ref_invalid) /* 7e misc  */
205        .long local_label(misc_ref_invalid) /* 7f immheader  */
206        /* 80-8*/
207        .long local_label(misc_ref_invalid) /* 80 even_fixnum  */
208        .long local_label(misc_ref_invalid) /* 81 cons  */
209        .long local_label(misc_ref_node) /* 82 istruct  */
210        .long local_label(misc_ref_invalid) /* 83 imm  */
211        .long local_label(misc_ref_invalid) /* 84 odd_fixnum  */
212        .long local_label(misc_ref_invalid) /* 85 tra  */
213        .long local_label(misc_ref_invalid) /* 86 misc  */
214        .long local_label(misc_ref_invalid) /* 87 immheader  */
215        .long local_label(misc_ref_invalid) /* 88 even_fixnum  */
216        .long local_label(misc_ref_invalid) /* 89 cons  */
217        .long local_label(misc_ref_node) /* 8a value_cell  */
218        .long local_label(misc_ref_invalid) /* 8b imm  */
219        .long local_label(misc_ref_invalid) /* 8c odd_fixnum  */
220        .long local_label(misc_ref_invalid) /* 8d tra  */
221        .long local_label(misc_ref_invalid) /* 8e misc  */
222        .long local_label(misc_ref_invalid) /* 8f immheader  */
223        /* 90-9*/
224        .long local_label(misc_ref_invalid) /* 90 even_fixnum  */
225        .long local_label(misc_ref_invalid) /* 91 cons  */
226        .long local_label(misc_ref_node) /* 92 xfunction  */
227        .long local_label(misc_ref_invalid) /* 93 imm  */
228        .long local_label(misc_ref_invalid) /* 94 odd_fixnum  */
229        .long local_label(misc_ref_invalid) /* 95 tra  */
230        .long local_label(misc_ref_invalid) /* 96 misc  */
231        .long local_label(misc_ref_invalid) /* 97 immheader  */
232        .long local_label(misc_ref_invalid) /* 98 even_fixnum  */
233        .long local_label(misc_ref_invalid) /* 99 cons  */
234        .long local_label(misc_ref_node) /* 9a arrayH  */
235        .long local_label(misc_ref_invalid) /* 9b imm  */
236        .long local_label(misc_ref_invalid) /* 9c odd_fixnum  */
237        .long local_label(misc_ref_invalid) /* 9d tra  */
238        .long local_label(misc_ref_invalid) /* 9e misc  */
239        .long local_label(misc_ref_invalid) /* 9f immheader  */
240        /* a0-af  */
241        .long local_label(misc_ref_invalid) /* a0 even_fixnum  */
242        .long local_label(misc_ref_invalid) /* a1 cons  */
243        .long local_label(misc_ref_node) /* a2 vectorH  */
244        .long local_label(misc_ref_invalid) /* a3 imm  */
245        .long local_label(misc_ref_invalid) /* a4 odd_fixnum  */
246        .long local_label(misc_ref_invalid) /* a5 tra  */
247        .long local_label(misc_ref_invalid) /* a6 misc  */
248        .long local_label(misc_ref_single_float_vector) /* a7 sf_vector  */
249        .long local_label(misc_ref_invalid) /* a8 even_fixnum  */
250        .long local_label(misc_ref_invalid) /* a9 cons  */
251        .long local_label(misc_ref_node) /* aa simple_vector  */
252        .long local_label(misc_ref_invalid) /* ab imm  */
253        .long local_label(misc_ref_invalid) /* ac odd_fixnum  */
254        .long local_label(misc_ref_invalid) /* ad tra  */
255        .long local_label(misc_ref_invalid) /* ae misc  */
256        .long local_label(misc_ref_u32) /* af u32  */
257        /* b0-bf  */
258        .long local_label(misc_ref_invalid) /* b0 even_fixnum  */
259        .long local_label(misc_ref_invalid) /* b1 cons  */
260        .long local_label(misc_ref_invalid) /* b2 nodeheader  */
261        .long local_label(misc_ref_invalid) /* b3 imm  */
262        .long local_label(misc_ref_invalid) /* b4 odd_fixnum  */
263        .long local_label(misc_ref_invalid) /* b5 tra  */
264        .long local_label(misc_ref_invalid) /* b6 misc  */
265        .long local_label(misc_ref_s32) /* b7 s32  */
266        .long local_label(misc_ref_invalid) /* b8 even_fixnum  */
267        .long local_label(misc_ref_invalid) /* b9 cons  */
268        .long local_label(misc_ref_invalid) /* ba nodeheader  */
269        .long local_label(misc_ref_invalid) /* bb imm  */
270        .long local_label(misc_ref_invalid) /* bc odd_fixnum  */
271        .long local_label(misc_ref_invalid) /* bd tra  */
272        .long local_label(misc_ref_invalid) /* be misc  */
273        .long local_label(misc_ref_fixnum_vector) /* bf fixnum_vector  */
274        /* c0-cf  */
275        .long local_label(misc_ref_invalid) /* c0 even_fixnum  */
276        .long local_label(misc_ref_invalid) /* c1 cons  */
277        .long local_label(misc_ref_invalid) /* c2 nodeheader  */
278        .long local_label(misc_ref_invalid) /* c3 imm  */
279        .long local_label(misc_ref_invalid) /* c4 odd_fixnum  */
280        .long local_label(misc_ref_invalid) /* c5 tra  */
281        .long local_label(misc_ref_invalid) /* c6 misc  */
282        .long local_label(misc_ref_string) /* c7 simple_base_string  */
283        .long local_label(misc_ref_invalid) /* c8 even_fixnum  */
284        .long local_label(misc_ref_invalid) /* c9 cons  */
285        .long local_label(misc_ref_invalid) /* ca nodeheader  */
286        .long local_label(misc_ref_invalid) /* cb imm  */
287        .long local_label(misc_ref_invalid) /* cc odd_fixnum  */
288        .long local_label(misc_ref_invalid) /* cd tra  */
289        .long local_label(misc_ref_invalid) /* ce misc  */
290        .long local_label(misc_ref_u8) /* cf u8  */
291        /* d0-df  */
292        .long local_label(misc_ref_invalid) /* d0 even_fixnum  */
293        .long local_label(misc_ref_invalid) /* d1 cons  */
294        .long local_label(misc_ref_invalid) /* d2 nodeheader  */
295        .long local_label(misc_ref_invalid) /* d3 imm  */
296        .long local_label(misc_ref_invalid) /* d4 odd_fixnum  */
297        .long local_label(misc_ref_invalid) /* d5 tra  */
298        .long local_label(misc_ref_invalid) /* d6 misc  */
299        .long local_label(misc_ref_s8)      /* d7 s8  */
300        .long local_label(misc_ref_invalid) /* d8 even_fixnum  */
301        .long local_label(misc_ref_invalid) /* d9 cons  */
302        .long local_label(misc_ref_invalid) /* da nodeheader  */
303        .long local_label(misc_ref_invalid) /* db imm  */
304        .long local_label(misc_ref_invalid) /* dc odd_fixnum  */
305        .long local_label(misc_ref_invalid) /* dd tra  */
306        .long local_label(misc_ref_invalid) /* de misc  */
307        .long local_label(misc_ref_invalid) /* df immheader  */
308        /* e0-ef  */
309        .long local_label(misc_ref_invalid) /* e0 even_fixnum  */
310        .long local_label(misc_ref_invalid) /* e1 cons  */
311        .long local_label(misc_ref_invalid) /* e2 nodeheader  */
312        .long local_label(misc_ref_invalid) /* e3 imm  */
313        .long local_label(misc_ref_invalid) /* e4 odd_fixnum  */
314        .long local_label(misc_ref_invalid) /* e5 tra  */
315        .long local_label(misc_ref_invalid) /* e6 misc  */
316        .long local_label(misc_ref_u16) /* e7 u16  */
317        .long local_label(misc_ref_invalid) /* e8 even_fixnum  */
318        .long local_label(misc_ref_invalid) /* e9 cons  */
319        .long local_label(misc_ref_invalid) /* ea nodeheader  */
320        .long local_label(misc_ref_invalid) /* eb imm  */
321        .long local_label(misc_ref_invalid) /* ec odd_fixnum  */
322        .long local_label(misc_ref_invalid) /* ed tra  */
323        .long local_label(misc_ref_invalid) /* ee misc  */
324        .long local_label(misc_ref_s16) /* ef s16  */
325        /* f0-ff  */
326        .long local_label(misc_ref_invalid) /* f0 even_fixnum  */
327        .long local_label(misc_ref_invalid) /* f1 cons  */
328        .long local_label(misc_ref_invalid) /* f2 nodeheader  */
329        .long local_label(misc_ref_invalid) /* f3 imm  */
330        .long local_label(misc_ref_invalid) /* f4 odd_fixnum  */
331        .long local_label(misc_ref_invalid) /* f5 tra  */
332        .long local_label(misc_ref_invalid) /* f6 misc  */
333        .long local_label(misc_ref_double_float_vector) /* f7 df vector  */
334        .long local_label(misc_ref_invalid) /* f8 even_fixnum  */
335        .long local_label(misc_ref_invalid) /* f9 cons  */
336        .long local_label(misc_ref_invalid) /* fa nodeheader  */
337        .long local_label(misc_ref_invalid) /* fb imm  */
338        .long local_label(misc_ref_invalid) /* fc odd_fixnum  */
339        .long local_label(misc_ref_invalid) /* fd tra  */
340        .long local_label(misc_ref_invalid) /* fe misc  */
341        .long local_label(misc_ref_bit_vector) /* ff bit_vector  */
342
343/* Functions are funny.  The first N words are treated as */
344/* (UNSIGNED-BYTE 32), where N is the low 16 bits of the first word. */
345
346local_label(misc_ref_function):
347        __(movzwl misc_data_offset(%arg_y), %imm0)
348        /* 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(heap_start),%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(heap_start),%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(heap_start),%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(heap_start),%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(heap_start),%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(heap_start),%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(heap_start),%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(heap_start),%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        __(jge 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        __(testb %imm0_bh,%imm0_bh)
2937        __(je local_label(rest_keys))
2938        __(btl $initopt_bit,%imm0)
2939        __(jc local_label(opt_supp))
2940        /* 'simple' &optionals:  no supplied-p, default to nil.   */
2941local_label(simple_opt_loop):
2942        __(compare_reg_to_nil(%arg_reg))
2943        __(je local_label(default_simple_opt))
2944        __(movb $fulltagmask,%imm0_bh)
2945        __(andb %arg_reg_b,%imm0_bh)
2946        __(cmpb $fulltag_cons,%imm0_bh)
2947        __(jne local_label(badlist))
2948        __(subb $1,%imm0_b)
2949        __(pushl cons.car(%arg_reg))
2950        __(_cdr(%arg_reg,%arg_reg))
2951        __(jne local_label(simple_opt_loop))
2952        __(jmp local_label(rest_keys))
2953local_label(default_simple_opt):
2954        __(subb $1,%imm0_b)
2955        __(pushl $nil_value)
2956        __(jne local_label(default_simple_opt))
2957        __(jmp local_label(rest_keys))
2958local_label(opt_supp):
2959        __(movb $fulltagmask,%imm0_bh)
2960        __(andb %arg_reg_b,%imm0_bh)
2961        __(compare_reg_to_nil(%arg_z))
2962        __(je local_label(default_hard_opt))
2963        __(cmpb $fulltag_cons,%imm0_bh)
2964        __(jne local_label(badlist))
2965        __(subb $1,%imm0_b)
2966        __(pushl cons.car(%arg_reg))
2967        __(_cdr(%arg_reg,%arg_reg))
2968        __(push $t_value)
2969        __(jne local_label(opt_supp))
2970        __(jmp local_label(rest_keys))
2971local_label(default_hard_opt):
2972        __(subb $1,%imm0_b)
2973        __(push $nil_value)
2974        __(push $nil_value)
2975        __(jne local_label(default_hard_opt))
2976local_label(rest_keys):
2977        __(btl $restp_bit,%imm0)
2978        __(jc local_label(have_rest))
2979        __(btl $keyp_bit,%imm0)
2980        __(jc local_label(have_keys))
2981        __(compare_reg_to_nil(%arg_reg))
2982        __(jne local_label(toomany))
2983        __(movss %fpzero,rcontext(tcr.save0))
2984        __(jmp *%ra0)
2985local_label(have_rest):
2986        __(pushl %arg_reg)
2987        __(btl $keyp_bit,%imm0)
2988        __(jc local_label(have_keys))
2989        __(movss %fpzero,rcontext(tcr.save0))
2990        __(jmp *%ra0)
2991        /* Ensure that arg_reg contains a proper,even-length list.  */
2992        /* Insist that its length is <= 512 (as a cheap circularity check.)   */
2993local_label(have_keys):
2994        __(movb $255,%imm0_b)
2995        __(push %arg_reg)
2996        __(push %arg_z)
2997        __(xorl %arg_z,%arg_z)
2998local_label(count_keys_loop):
2999        __(compare_reg_to_nil(%arg_reg))
3000        __(je local_label(counted_keys))
3001        __(subb $1,%imm0_b)
3002        __(jb local_label(toomany))
3003        __(movb $fulltagmask,%arg_z_bh)
3004        __(andb %arg_reg_b,%arg_z_bh)
3005        __(cmpb $fulltag_cons,%arg_z_bh)
3006        __(jne local_label(badlist))
3007        __(_cdr(%arg_reg,%arg_reg))
3008        __(compare_reg_to_nil(%arg_reg))
3009        __(je local_label(badlist))
3010        __(movb $fulltagmask,%arg_z_bh)
3011        __(andb %arg_reg_b,%arg_z_bh)
3012        __(cmpb $fulltag_cons,%arg_z_bh)
3013        __(jne local_label(badlist))
3014        __(_cdr(%arg_reg,%arg_reg))
3015        __(jmp local_label(count_keys_loop))
3016local_label(counted_keys):             
3017        /* We've got a proper, even-length list of key/value pairs in  */
3018        /* arg_reg. For each keyword var in the lambda-list, push a pair  */
3019        /* of NILs on the vstack.   */
3020        __(pop %arg_z)
3021        __(pop %arg_reg)
3022        __(movd %mm1,%imm0)
3023        __(shrl $16,%imm0)
3024        __(movzbl %imm0_b,%imm0)
3025        __(movl %esp,rcontext(tcr.unboxed0))    /* 0th value/supplied-p pair */
3026        __(jmp local_label(push_pair_test))
3027local_label(push_pair_loop):
3028        __(push $nil_value)
3029        __(push $nil_value)
3030local_label(push_pair_test):   
3031        __(subb $1,%imm0_b)
3032        __(jge local_label(push_pair_loop))
3033        __(push %temp0) /* keyword */
3034        __(push %arg_z) /* value */
3035        __(vector_length(%arg_y,%imm0))
3036        __(push %arg_reg)
3037        __(push %imm0)  /* keyword vector length */
3038        __(movd %mm1,%imm0)
3039        __(movl $0,rcontext(tcr.unboxed1)) /* count of unknown keywords seen */
3040local_label(match_keys_loop):
3041        __(movl 4(%esp),%arg_reg)
3042        __(compare_reg_to_nil(%arg_reg))
3043        __(je local_label(matched_keys))
3044        __(_car(%arg_reg,%temp0))
3045        __(_cdr(%arg_reg,%arg_reg))
3046        __(_car(%arg_reg,%arg_z))
3047        __(_cdr(%arg_reg,%arg_reg))
3048        __(movl %arg_reg,4(%esp))
3049        __(xorl %temp1,%temp1)
3050        __(jmp local_label(match_test))
3051local_label(match_loop):
3052        __(cmpl misc_data_offset(%arg_y,%temp1),%temp0)
3053        __(je local_label(matched))
3054        __(addl $node_size,%temp1)
3055local_label(match_test):
3056        __(cmpl %temp1,(%esp))  /* compare index, keyword vector length */
3057        __(jne local_label(match_loop))
3058        /* No match.  Note unknown keyword, check for :allow-other-keys   */
3059        __(addl $1,rcontext(tcr.unboxed1))
3060        __(cmpl $nrs.kallowotherkeys,%temp0)
3061        __(jne local_label(match_keys_loop))
3062        __(subl $1,rcontext(tcr.unboxed1))
3063        __(btsl $seen_aok_bit,%imm0)
3064        __(jc local_label(match_keys_loop))
3065        /* First time we've seen :allow-other-keys.  Maybe set aok_bit.   */
3066        __(compare_reg_to_nil(%arg_z))
3067        __(je local_label(match_keys_loop))
3068        __(btsl $aok_bit,%imm0)
3069        __(jmp local_label(match_keys_loop))
3070        /* Got a match.  Worry about :allow-other-keys here, too.   */
3071local_label(matched):
3072        __(negl %temp1)
3073        __(shll $1,%temp1)
3074        __(addl rcontext(tcr.unboxed0),%temp1)
3075        __(cmpl $nil_value,-node_size*2(%temp1))
3076        __(jne local_label(match_keys_loop))
3077        __(movl %arg_z,-node_size(%temp1))
3078        __(movl $t_value,-node_size*2(%temp1))
3079        __(cmpl $nrs.kallowotherkeys,%temp0)
3080        __(jne local_label(match_keys_loop))
3081        __(btsl $seen_aok_bit,%imm0)
3082        __(jnc local_label(match_keys_loop))
3083        __(compare_reg_to_nil(%arg_z))
3084        __(je local_label(match_keys_loop))
3085        __(btsl $aok_bit,%imm0)
3086        __(jmp local_label(match_keys_loop))
3087local_label(matched_keys):     
3088        __(cmpl $0,rcontext(tcr.unboxed1))      /* any unknown keys seen? */
3089        __(je local_label(keys_ok))
3090        __(btl $aok_bit,%imm0)
3091        __(jnc local_label(badkeys))
3092local_label(keys_ok):
3093        __(addl $(3*node_size),%esp)
3094        __(pop %ra0)
3095        __(movss %fpzero,rcontext(tcr.save0))
3096        __(jmp *%ra0)
3097        /* Some unrecognized keywords.  Complain generically about   */
3098        /* invalid keywords.   */
3099local_label(badkeys):
3100        __(movl $XBADKEYS,%arg_y)
3101        __(jmp local_label(destructure_error))
3102local_label(toomany):
3103        __(movl $XCALLTOOMANY,%arg_y)
3104        __(jmp local_label(destructure_error))
3105local_label(toofew):
3106        __(movl $XCALLTOOFEW,%arg_y)
3107        __(jmp local_label(destructure_error))
3108local_label(badlist):
3109        __(movl $XCALLNOMATCH,%arg_y)
3110local_label(destructure_error):
3111        __(movd %mm0,%esp)              /* undo everything done to the stack */
3112        __(movl rcontext(tcr.save0),%arg_z)     /* %whole_reg */
3113        __(movss %fpzero,rcontext(tcr.save0))
3114        __(set_nargs(2))
3115        __(push %ra0)
3116        __(jmp _SPksignalerr)
3117_endfn(C(destbind1))
3118
3119_spentry(macro_bind)
3120        __(movl %arg_reg,rcontext(tcr.save0))   /* %whole_reg */
3121        __(extract_fulltag(%arg_reg,%imm0))
3122        __(cmpb $fulltag_cons,%imm0_b)
3123        __(jne 1f)
3124        __(_cdr(%arg_reg,%arg_reg))
3125        __(jmp C(destbind1))
31261:      __(movl $XCALLNOMATCH,%arg_y)
3127        __(movl rcontext(tcr.save0),%arg_z)
3128        __(movss %fpzero,rcontext(tcr.save0))
3129        __(set_nargs(2))
3130        __(push %ra0)       
3131        __(jmp _SPksignalerr)
3132
3133_endsubp(macro_bind)
3134
3135_spentry(destructuring_bind)
3136        __(movl %arg_reg,rcontext(tcr.save0))   /* %whole_reg */
3137        __(jmp C(destbind1))
3138_endsubp(destructuring_bind)
3139
3140_spentry(destructuring_bind_inner)
3141        __(movl %arg_z,rcontext(tcr.save0))     /* %whole_reg */
3142        __(jmp C(destbind1))
3143_endsubp(destructuring_bind_inner)
3144
3145_spentry(vpopargregs)
3146        __(hlt)
3147_endsubp(vpopargregs)
3148
3149/* If arg_z is an integer, return in imm0 something whose sign  */
3150/* is the same as arg_z's.  If not an integer, error.   */
3151_spentry(integer_sign)
3152        __(mov %arg_z,%imm0)
3153        __(testb $tagmask,%arg_z_b)
3154        __(je 8f)
3155        __(extract_typecode(%arg_z,%imm0))
3156        __(cmpb $subtag_bignum,%imm0_b)
3157        __(jne 9f)
3158        __(getvheader(%arg_z,%imm0))
3159        __(shr $num_subtag_bits,%imm0)
3160        __(movl misc_data_offset-4(%arg_z,%imm0,4),%imm0)
31618:      __(repret)
31629:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_integer))
3163_endsubp(integer_sign)
3164
3165/* "slide" nargs worth of values up the stack.  imm0 contains */
3166/* the difference between the current stack pointer and the target. */
3167_spentry(mvslide)
3168        __(movd %nargs,%mm0)
3169        __(lea (%esp,%nargs),%arg_y)
3170        __(lea (%arg_y,%imm0),%imm0)
3171        __(test %nargs,%nargs)
3172        __(je 2f)
31731:
3174        __(subl $node_size,%arg_y)
3175        __(movl (%arg_y),%arg_z)
3176        __(subl $node_size,%imm0)
3177        __(movl %arg_z,(%imm0))
3178        __(subl $node_size,%nargs)
3179        __(jne 1b)
31802:      __(movl %imm0,%esp)
3181        __(movd %mm0,%nargs)
3182        __(jmp *%ra0)
3183_endsubp(mvslide)
3184
3185_spentry(save_values)
3186        __(movd rcontext(tcr.save_tsp),%mm1)
3187/* common exit: nargs = values in this set, mm1 = ptr to tsp before call to save_values   */
3188local_label(save_values_to_tsp):
3189        __(movl %ra0,rcontext(tcr.save0))
3190        __(movl rcontext(tcr.save_tsp),%temp0)
3191        __(dnode_align(%nargs,tsp_frame.fixed_overhead+(2*node_size),%imm0)) /* count, link   */
3192        __(TSP_Alloc_Var(%imm0,%arg_z))
3193        __(movl rcontext(tcr.save_tsp),%imm0)
3194        __(movd %mm1,(%imm0))
3195        __(movl %nargs,(%arg_z))
3196        __(movl %temp0,node_size(%arg_z))
3197        __(leal 2*node_size(%arg_z,%nargs),%arg_y)
3198        __(leal (%esp,%nargs),%imm0)
3199        __(cmpl %imm0,%esp)
3200        __(jmp 2f)
32011:      __(subl $node_size,%imm0)
3202        __(movl (%imm0),%arg_z)
3203        __(subl $node_size,%arg_y)
3204        __(cmpl %imm0,%esp)
3205        __(movl %arg_z,(%arg_y))
32062:      __(jne 1b)
3207        __(addl %nargs,%esp)
3208        __(movl rcontext(tcr.save0),%ra0)
3209        __(movl $0,rcontext(tcr.save0))
3210        __(jmp *%ra0)
3211_endsubp(save_values)
3212
3213/* Add the multiple values that are on top of the vstack to the set  */
3214/* saved in the top tsp frame, popping them off of the vstack in the  */
3215/* process.  It is an error (a bad one) if the TSP contains something  */
3216/* other than a previously saved set of multiple-values.  */
3217/* Since adding to the TSP may cause a new TSP segment to be allocated,  */
3218/* each add_values call adds another linked element to the list of  */
3219/* values. This makes recover_values harder.   */
3220_spentry(add_values)
3221        /* do we need to preserve imm0? */
3222        __(test %nargs,%nargs)
3223        __(movl rcontext(tcr.save_tsp),%imm0)
3224        __(movl (%imm0),%imm0)
3225        __(movd %imm0,%mm1)     /* for the benefit of save_values_to_tsp */
3226        __(jne local_label(save_values_to_tsp))
3227        __(jmp *%ra0)
3228_endsubp(add_values)
3229
3230/* push the values in the value set atop the sp, incrementing nargs.  */
3231/* Discard the tsp frame; leave values atop the sp.   */
3232_spentry(recover_values)
3233        __(movl %ra0,rcontext(tcr.save0)) /* temp0 */
3234        __(movd %nargs,%mm0)              /* temp1 */
3235        /* First, walk the segments reversing the pointer to previous  */
3236        /* segment pointers Can tell the end because that previous  */
3237        /* segment pointer is the prev tsp pointer   */
3238        __(movl rcontext(tcr.save_tsp),%temp1)
3239        __(movl %temp1,%temp0)  /* current segment   */
3240        __(movl %temp1,%arg_y)  /* last segment   */
3241        __(movl tsp_frame.backlink(%temp1),%arg_z)      /* previous tsp   */
3242local_label(walkloop):
3243        __(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
3244        __(cmpl %imm0,%arg_z)   /* last segment ?   */
3245        __(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
3246        __(movl %temp0,%arg_y)  /* last segment <- current segment   */
3247        __(movl %imm0,%temp0)   /* current segment <- next segment   */
3248        __(jne local_label(walkloop))
3249
3250        __(movl %temp1,%arg_z)
3251        __(movd %mm0,%nargs)
3252        /* the final segment pointer is now in %arg_y  */
3253        /* walk backwards, pushing values on the stack and incrementing %nargs   */
3254local_label(pushloop):
3255        __(movl tsp_frame.data_offset(%arg_y),%imm0)    /* nargs in segment   */
3256        __(test %imm0,%imm0)
3257        __(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
3258        __(leal (%nargs,%imm0),%nargs)
3259        __(jmp 2f)
32601:      __(push -node_size(%temp0))
3261        __(subl $node_size,%temp0)
3262        __(subl $fixnum_one,%imm0)
32632:      __(jne 1b)
3264        __(cmpl %arg_y,%arg_z)
3265        __(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
3266        __(jne local_label(pushloop))
3267        __(movl (%arg_z),%arg_z)
3268        __(movl %arg_z,rcontext(tcr.save_tsp))
3269        __(movl %arg_z,rcontext(tcr.next_tsp))
3270        __(movl rcontext(tcr.save0),%ra0)
3271        __(movl $0,rcontext(tcr.save0))
3272        __(jmp *%ra0)           
3273_endsubp(recover_values)
3274
3275/* Exactly like recover_values, but it's necessary to reserve an outgoing  */
3276/* frame if any values (which will be used as outgoing arguments) will  */
3277/* wind up on the stack.  We can assume that %nargs contains 0 (and  */
3278/* that no other arguments have been pushed) on entry.   */
3279
3280_spentry(recover_values_for_mvcall)
3281        __(movl %ra0,rcontext(tcr.save0)) /* temp0 */
3282        /* First, walk the segments reversing the pointer to previous  */
3283        /* segment pointers Can tell the end because that previous  */
3284        /* segment pointer is the prev tsp pointer   */
3285        __(xorl %nargs,%nargs)
3286        __(push %nargs)
3287        __(movl rcontext(tcr.save_tsp),%temp1)
3288        __(movl %temp1,%temp0)  /* current segment   */
3289        __(movl %temp1,%arg_y)  /* last segment   */
3290        __(movl tsp_frame.backlink(%temp1),%arg_z)      /* previous tsp   */
3291local_label(walkloop_mvcall):
3292        __(movl tsp_frame.data_offset(%temp0),%imm0)
3293        __(addl %imm0,(%esp))
3294        __(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
3295        __(cmpl %imm0,%arg_z)   /* last segment ?   */
3296        __(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
3297        __(movl %temp0,%arg_y)  /* last segment <- current segment   */
3298        __(movl %imm0,%temp0)   /* current segment <- next segment   */
3299        __(jne local_label(walkloop_mvcall))
3300
3301        __(movl %temp1,%arg_z)
3302        __(pop %nargs)
3303
3304        __(cmpl $nargregs*node_size,%nargs)
3305        __(jbe local_label(pushloop_mvcall))
3306        __(push $reserved_frame_marker)
3307        __(push $reserved_frame_marker)
3308
3309        /* the final segment pointer is now in %arg_y  */
3310        /* walk backwards, pushing values on the stack and incrementing %nargs*/
3311local_label(pushloop_mvcall):
3312        __(movl tsp_frame.data_offset(%arg_y),%imm0)    /* nargs in segment */
3313        __(test %imm0,%imm0)
3314        __(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
3315        __(jmp 2f)
33161:      __(push -node_size(%temp0))
3317        __(subl $node_size,%temp0)
3318        __(subl $fixnum_one,%imm0)
33192:      __(jne 1b)
3320        __(cmpl %arg_y,%arg_z)
3321        __(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
3322        __(jne local_label(pushloop_mvcall))
3323        __(movl (%arg_z),%arg_z)
3324        __(movl %arg_z,rcontext(tcr.save_tsp))
3325        __(movl %arg_z,rcontext(tcr.next_tsp))
3326        __(movl rcontext(tcr.save0),%ra0)
3327        __(movl $0,rcontext(tcr.save0))
3328        __(jmp *%ra0)           
3329_endsubp(recover_values_for_mvcall)
3330
3331_spentry(reset)
3332        __(hlt)
3333_endsubp(reset)
3334
3335/* temp0 = element-count, arg_y = subtag, arg_z = initval */
3336_spentry(misc_alloc_init)
3337        __(push %ebp)
3338        __(movl %esp,%ebp)
3339        __(push %arg_z)
3340        __(movl %arg_y,%arg_z)
3341        __(movl %temp0,%arg_y)
3342        __(push $local_label(misc_alloc_init_back))
3343        __(jmp _SPmisc_alloc)
3344__(tra(local_label(misc_alloc_init_back)))
3345        __(pop %arg_y)
3346        __(leave)
3347        __(movl $nrs.init_misc,%fname)
3348        __(set_nargs(2))
3349        __(jump_fname())
3350_endsubp(misc_alloc_init)
3351
3352/* %temp1 = element-count, %arg_y = subtag, %arg_z = initial-value */       
3353_spentry(stack_misc_alloc_init)
3354        __(push %ebp)
3355        __(movl %esp,%ebp)
3356        __(push %arg_z)
3357        __(movl %arg_y,%arg_z)
3358        __(movl %temp1,%arg_y)
3359        __(pushl $local_label(stack_misc_alloc_init_back))
3360        __(jmp _SPstack_misc_alloc)
3361__(tra(local_label(stack_misc_alloc_init_back)))
3362        __(popl %arg_y)
3363        __(leave)
3364        __(movl $nrs.init_misc,%fname)
3365        __(set_nargs(2))
3366        __(jump_fname())
3367_endsubp(stack_misc_alloc_init)
3368
3369        .globl C(popj)
3370_spentry(popj)
3371C(popj):
3372        __(leave)
3373        __(ret)
3374_endsubp(popj)
3375
3376/* arg_z should be of type (signed-byte 64) */
3377/* return unboxed value in mm0 */
3378_spentry(gets64)
3379        __(testb $fixnummask,%arg_z_b)
3380        __(jne 1f)
3381        __(unbox_fixnum(%arg_z,%imm0))
3382        __(movd %imm0,%mm0)
3383        __(jns 8f)
3384        /* get sign into upper half of %mm0 */
3385        __(pcmpeqd %mm1,%mm1)   /* all ones */
3386        __(psllq $32,%mm1)
3387        __(por %mm1,%mm0)
3388        __(ret)
33891:      __(movb %arg_z_b,%imm0_b)
3390        __(andb $tagmask,%imm0_b)
3391        __(cmpb $tag_misc,%imm0_b)
3392        __(jne 9f)
3393        __(movl misc_header_offset(%arg_z),%imm0)
3394        __(cmpb $subtag_bignum,%imm0_b)
3395        __(jne 9f)
3396        __(cmpl $two_digit_bignum_header,%imm0)
3397        __(ja 9f)
3398        __(movd misc_data_offset(%arg_z),%mm0)
3399        __(jne 8f)
3400        __(movq misc_data_offset(%arg_z),%mm0)
34018:      __(repret)
34029:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_s64))
3403_endsubp(gets64)
3404
3405/* arg_z should be of type (unsigned-byte 64) */
3406/* return unboxed value in mm0 */
3407_spentry(getu64)
3408        __(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
3409        __(testl %arg_z,%imm0)
3410        __(movl %arg_z,%imm0)
3411        __(jne 1f)
3412        __(sarl $fixnumshift,%imm0)
3413        __(movd %imm0,%mm0)
3414        __(ret)
34151:      __(andb $tagmask,%imm0_b)
3416        __(cmpb $tag_misc,%imm0_b)
3417        __(jne 9f)
3418        __(movl misc_header_offset(%arg_z),%imm0)
3419        __(cmpb $subtag_bignum,%imm0_b)
3420        __(jne 9f)
3421        __(cmpl $three_digit_bignum_header,%imm0)
3422        __(ja 9f)
3423        __(je 3f)
3424        __(cmpl $two_digit_bignum_header,%imm0)
3425        __(je 2f)
3426        /* must be a one digit bignum */
3427        __(movl misc_data_offset(%arg_z),%imm0)
3428        __(test %imm0,%imm0)
3429        __(js 9f)
3430        __(movd %imm0,%mm0)
3431        __(ret)
34322:      __(movl misc_data_offset+4(%arg_z),%imm0)
3433        __(testl %imm0,%imm0)
3434        __(js 9f)
3435        __(movq misc_data_offset(%arg_z),%mm0)
3436        __(ret)
34373:      __(movl misc_data_offset(%arg_z),%imm0)
3438        __(cmpl $0,misc_data_offset+8(%arg_z))
3439        __(jne 9f)
3440        __(movq misc_data_offset(%arg_z),%mm0)
3441        __(repret)
34429:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_u64))
3443_endsubp(getu64)
3444
3445/* Make unsigned integer from value in mm0 */
3446_spentry(makeu64)
3447        __(movq %mm0,%mm1)
3448        __(psrlq $32,%mm0)
3449        __(movd %mm0,%imm0)
3450        __(test %imm0,%imm0)
3451        __(js 3f)
3452        __(jnz 2f)
3453        __(movd %mm1,%imm0)
3454        __(cmpl $target_most_positive_fixnum,%imm0)
3455        __(ja 1f)
3456        __(box_fixnum(%imm0,%arg_z))
3457        __(ret)
34581:      /* maybe make a 1 digit bignum */
3459        __(test %imm0,%imm0)
3460        __(js 2f)
3461        __(movl $one_digit_bignum_header,%imm0)
3462        __(movd %imm0,%mm0)
3463        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
3464        __(movd %mm1,misc_data_offset(%arg_z))
3465        __(ret)
3466        /* make a 2 digit bignum */
34672:      __(movl $two_digit_bignum_header,%imm0)
3468        __(movd %imm0,%mm0)
3469        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
3470        __(movq %mm1,misc_data_offset(%arg_z))
3471        __(ret)
3472        /* make a 3 digit bignum */
34733:      __(movl $three_digit_bignum_header,%imm0)
3474        __(movd %imm0,%mm0)
3475        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(3)))
3476        __(movq %mm1,misc_data_offset(%arg_z))
3477        __(ret)
3478_endsubp(makeu64)
3479
3480/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly */
3481/* unbound_marker), arg_y = symbol */
3482_spentry(specref)
3483        __(movl symbol.binding_index(%arg_z),%imm0)
3484        __(cmp rcontext(tcr.tlb_limit),%imm0)
3485        __(movl rcontext(tcr.tlb_pointer),%temp1)
3486        __(movl %arg_z,%arg_y)
3487        __(jae 7f)
3488        __(movl (%temp1,%imm0),%arg_z)
3489        __(cmpb $no_thread_local_binding_marker,%arg_z_b)
3490        __(jne 8f)
34917:      __(movl symbol.vcell(%arg_y),%arg_z)
34928:      __(repret)             
3493_endsubp(specref)
3494
3495/* arg_y = special symbol, arg_z = new value. */
3496_spentry(specset)
3497        __(movl symbol.binding_index(%arg_y),%imm0)
3498        __(cmp rcontext(tcr.tlb_limit),%imm0)
3499        __(movl rcontext(tcr.tlb_pointer),%temp1)
3500        __(jae 1f)
3501        __(movl (%temp1,%imm0),%temp0)
3502        __(cmpb $no_thread_local_binding_marker,%temp0_b)
3503        __(je 1f)
3504        __(movl %arg_z,(%temp1,%imm0))
3505        __(ret)
35061:      __(movl %arg_y,%temp0)
3507        __(movl $1<<fixnumshift,%arg_y)
3508        __(jmp _SPgvset)
3509_endsubp(specset)
3510
3511_spentry(specrefcheck)
3512        __(mov %arg_z,%arg_y)
3513        __(movl symbol.binding_index(%arg_z),%imm0)
3514        __(cmp rcontext(tcr.tlb_limit),%imm0)
3515        __(jae 7f)
3516        __(movl rcontext(tcr.tlb_pointer),%temp1)
3517        __(movl (%temp1,%imm0),%arg_z)
3518        __(cmpb $no_thread_local_binding_marker,%arg_z_b)
3519        __(cmovel symbol.vcell(%arg_y),%arg_z)
3520        __(cmpb $unbound_marker,%arg_z_b)
3521        __(je 9f)
35228:      __(repret)
35237:      __(movl symbol.vcell(%arg_y),%arg_z)
3524        __(cmpb $unbound_marker,symbol.vcell(%arg_y))
3525        __(je 9f)
3526        __(repret)
35279:      __(uuo_error_reg_unbound(Rarg_y))
3528_endsubp(specrefcheck)
3529
3530_spentry(restoreintlevel)
3531        __(hlt)
3532_endsubp(restoreintlevel)
3533
3534/* Make a lisp integer from the unsigned value in imm0 */
3535_spentry(makeu32)
3536        __(cmpl $target_most_positive_fixnum,%imm0)
3537        __(ja 0f)       /* need to make a bignum */
3538        __(box_fixnum(%imm0,%arg_z))
3539        __(ret)
35400:      __(movd %imm0,%mm1)
3541        __(test %imm0,%imm0)
3542        __(js 1f)
3543        __(movl $one_digit_bignum_header,%imm0)
3544        __(movd %imm0,%mm0)
3545        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
3546        __(movd %mm1,misc_data_offset(%arg_z))
3547        __(ret)
35481:      __(movl $two_digit_bignum_header,%imm0)
3549        __(movd %imm0,%mm0)
3550        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
3551        __(movd %mm1,misc_data_offset(%arg_z))
3552        __(ret)
3553_endsubp(makeu32)
3554
3555/* arg_z is of type (signed-byte 32) */
3556/* return unboxed value in %imm0 */
3557_spentry(gets32)
3558        __(testb $fixnummask,%arg_z_b)
3559        __(jne 1f)
3560        __(unbox_fixnum(%arg_z,%imm0))
3561        __(ret)
35621:      __(movb %arg_z_b,%imm0_b)
3563        __(andb $tagmask,%imm0_b)
3564        __(cmpb $tag_misc,%imm0_b)
3565        __(jne 9f)
3566        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3567        __(cmpb $subtag_bignum,%imm0_b)
3568        __(jne 9f)
3569        __(movl misc_header_offset(%arg_z),%imm0)
3570        __(cmpl $one_digit_bignum_header,%imm0)
3571        __(jne 9f)
3572        __(movl misc_data_offset(%arg_z),%imm0)
3573        __(ret)
35749:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_signed_byte_32))
3575_endsubp(gets32)
3576
3577/* arg_z is of type (unsigned-byte 32) */
3578/* return unboxed value in %imm0 */
3579_spentry(getu32)
3580        __(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
3581        __(testl %arg_z,%imm0)
3582        __(movl %arg_z,%imm0)
3583        __(jne 1f)
3584        __(sarl $fixnumshift,%imm0)
3585        __(ret)
35861:      __(andb $tagmask,%imm0_b)
3587        __(cmpb $tag_misc,%imm0_b)
3588        __(jne 9f)
3589        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3590        __(cmpb $subtag_bignum,%imm0_b)
3591        __(jne 9f)
3592        __(movl misc_header_offset(%arg_z),%imm0)
3593        __(cmpl $two_digit_bignum_header,%imm0)
3594        __(je 2f)
3595        __(cmpl $one_digit_bignum_header,%imm0)
3596        __(jne 9f)
3597        __(movl misc_data_offset(%arg_z),%imm0)
3598        __(ret)
35992:      __(movl misc_data_offset(%arg_z),%imm0)
3600        __(cmpl $0,misc_data_offset+4(%arg_z))
3601        __(jne 9f)
3602        __(ret)
36039:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_unsigned_byte_32))
3604_endsubp(getu32)
3605
3606_spentry(mvpasssym)
3607        __(hlt)
3608_endsubp(mvpasssym)
3609
3610/* don't smash arg_z */
3611_spentry(unbind)
3612        __(push %arg_z)
3613        __(movl rcontext(tcr.db_link),%imm0)
3614        __(movl rcontext(tcr.tlb_pointer),%arg_z)
3615        __(movl binding.sym(%imm0),%temp0)
3616        __(movl binding.val(%imm0),%arg_y)
3617        __(movl binding.link(%imm0),%imm0)
3618        __(movl %arg_y,(%arg_z,%temp0))
3619        __(movl %imm0,rcontext(tcr.db_link))
3620        __(pop %arg_z)
3621        __(ret)
3622_endsubp(unbind)
3623
3624_spentry(unbind_n)
3625        __(push %temp1)         /* preserve temp1/nargs */
3626        __(push %arg_z)
3627        __(xorl %arg_z,%arg_z)
3628        __(movl rcontext(tcr.db_link),%temp1)
3629        __(movl rcontext(tcr.tlb_pointer),%arg_z)
36301:             
3631        __(movl binding.sym(%temp1),%temp0)
3632        __(movl binding.val(%temp1),%arg_y)
3633        __(movl binding.link(%temp1),%temp1)
3634        __(movl %arg_y,(%arg_z,%temp0))
3635        __(decl %imm0)
3636        __(jne 1b)
3637        __(movl %temp1,rcontext(tcr.db_link))
3638        __(pop %arg_z)
3639        __(pop %temp1)
3640        __(ret) 
3641_endsubp(unbind_n)
3642
3643_spentry(unbind_to)
3644        __(push %arg_y)
3645        __(push %arg_z)
3646        __(push %temp0)
3647        __(push %temp1)
3648       
3649        __(movl rcontext(tcr.db_link),%temp0)
3650        __(movl rcontext(tcr.tlb_pointer),%arg_z)
36511:
3652        __(movl binding.sym(%temp0),%temp1)
3653        __(movl binding.val(%temp0),%arg_y)
3654        __(movl binding.link(%temp0),%temp0)
3655        __(movl %arg_y,(%arg_z,%temp1))
3656        __(cmpl %temp0,%imm0)
3657        __(jne 1b)
3658        __(movl %temp0,rcontext(tcr.db_link))
3659
3660        __(pop %temp1)
3661        __(pop %temp0)
3662        __(pop %arg_z)
3663        __(pop %arg_y)
3664        __(ret)
3665_endsubp(unbind_to)
3666
3667_spentry(bind_interrupt_level_0)
3668        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3669        __(cmpl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3670        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3671        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3672        __(push rcontext(tcr.db_link))
3673        __(movl %esp,rcontext(tcr.db_link))
3674        __(movl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3675        __(js 1f)
36760:      __(jmp *%ra0)
3677        /* Interrupt level was negative; interrupt may be pending */
36781:      __(check_pending_enabled_interrupt(2f))
36792:      __(jmp *%ra0)
3680_endsubp(bind_interrupt_level_0)
3681
3682/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect  */
3683/* of disabling interrupts.)   */
3684_spentry(bind_interrupt_level_m1)
3685        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3686        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3687        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3688        __(push rcontext(tcr.db_link))
3689        __(movl %esp,rcontext(tcr.db_link))
3690        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3691        __(jmp *%ra0)
3692_endsubp(bind_interrupt_level_m1)
3693
3694/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0, */
3695/* do what _SPbind_interrupt_level_0 does. */
3696_spentry(bind_interrupt_level)
3697        __(test %arg_z,%arg_z)
3698        __(jz _SPbind_interrupt_level_0)
3699        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3700        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3701        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3702        __(push rcontext(tcr.db_link))
3703        __(movl %esp,rcontext(tcr.db_link))
3704        __(movl %arg_z,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3705        __(jmp *%ra0)
3706_endsubp(bind_interrupt_level)
3707
3708/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to */
3709/* non-negative, check for pending interrupts. */
3710_spentry(unbind_interrupt_level)
3711        __(btl $TCR_FLAG_BIT_PENDING_SUSPEND,rcontext(tcr.flags))
3712        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3713        __(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_y),%imm0)
3714        __(jc 5f)
37150:      __(test %imm0,%imm0)
3716        __(movl rcontext(tcr.db_link),%imm0)
3717        __(movl binding.val(%imm0),%temp0)
3718        __(movl binding.link(%imm0),%imm0)
3719        __(movl %temp0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3720        __(movl %imm0,rcontext(tcr.db_link))
3721        __(js 3f)
37222:      __(repret)
37233:      __(test %temp0,%temp0)
3724        __(js 2b)
3725        __(check_pending_enabled_interrupt(4f))
37264:      __(repret)
37275:       /* Missed a suspend request; force suspend now if we're restoring
3728          interrupt level to -1 or greater */
3729        __(cmpl $-2<<fixnumshift,%imm0)
3730        __(jne 0b)
3731        __(movl rcontext(tcr.db_link),%temp0)
3732        __(movl binding.val(%temp0),%temp0)
3733        __(cmpl %imm0,%temp0)
3734        __(je 0b)
3735        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3736        __(suspend_now())
3737        __(jmp 0b)
3738_endsubp(unbind_interrupt_level)
3739
3740_spentry(progvrestore)
3741        __(movl rcontext(tcr.save_tsp),%imm0)
3742        __(movl tsp_frame.backlink(%imm0),%imm0) /* ignore .SPnthrowXXX values frame   */
3743        __(movl tsp_frame.data_offset(%imm0),%imm0)
3744        __(shrl $fixnumshift,%imm0)
3745        __(jne _SPunbind_n)
3746        __(repret)
3747_endsubp(progvrestore)
3748
3749/* %arg_z <- %arg_y + %arg_z.  Do the fixnum case - including overflow -  */
3750/* inline.  Call out otherwise.   */
3751_spentry(builtin_plus)
3752        __(movl %arg_y,%imm0)
3753        __(orl %arg_z,%imm0)
3754        __(testb $fixnummask,%imm0_b)
3755        __(jne 1f)
3756        __(addl %arg_y,%arg_z)
3757        __(jo C(fix_one_bit_overflow))
3758        __(repret)
37591:      __(jump_builtin(_builtin_plus,2))
3760_endsubp(builtin_plus)
3761
3762/* %arg_z <- %arg_y - %arg_z.  Do the fixnum case - including overflow -  */
3763/*  inline.  Call out otherwise.   */
3764_spentry(builtin_minus)
3765        __(movl %arg_y,%imm0)
3766        __(orl %arg_z,%imm0)
3767        __(testb $fixnummask,%imm0_b)
3768        __(jne 1f)
3769        __(xchgl %arg_y,%arg_z)
3770        __(subl %arg_y,%arg_z)
3771        __(jo C(fix_one_bit_overflow))
3772        __(repret)
37731:      __(jump_builtin(_builtin_minus,2))
3774_endsubp(builtin_minus)
3775
3776/* %arg_z -< arg_y * arg_z. */
3777/* Do the fixnum case---including overflow---inline.  Call out otherwise. */
3778_spentry(builtin_times)
3779        __(movl %arg_y,%imm0)
3780        __(orb %arg_z_b,%imm0_b)
3781        __(testb $fixnummask,%imm0_b)
3782        __(jne 2f)
3783        __(unbox_fixnum(%arg_z,%imm0))
3784        /* 32-bit fixnum result in %imm0.  Overflow set if it doesn't fit. */
3785        __(imul %arg_y,%imm0)
3786        __(jo 1f)
3787        __(movl %imm0,%arg_z)
3788        __(ret)
37891:      __(unbox_fixnum(%arg_z,%eax))
3790        __(mark_as_imm(%edx))
3791        __(unbox_fixnum(%arg_y,%edx))
3792        __(imul %edx)
3793        __(movd %eax,%mm0)
3794        __(movd %edx,%mm1)
3795        __(mark_as_node(%edx))
3796        __(psllq $32,%mm1)
3797        __(por %mm1,%mm0)
3798        __(jmp _SPmakes64)
37992:      __(jump_builtin(_builtin_times,2))
3800_endsubp(builtin_times)
3801
3802_spentry(builtin_div)
3803        __(jump_builtin(_builtin_div,2))
3804
3805/* %arg_z <- (= %arg_y %arg_z).   */
3806_spentry(builtin_eq)
3807        __(movl %arg_y,%imm0)
3808        __(orb %arg_z_b,%imm0_b)
3809        __(testb $fixnummask,%imm0_b)
3810        __(jne 1f)
3811        __(rcmpl(%arg_z,%arg_y))
3812        __(condition_to_boolean(e,%imm0,%arg_z))
3813        __(ret)
38141:      __(jump_builtin(_builtin_eq,2))
3815_endsubp(builtin_eq)
3816
3817/* %arg_z <- (/= %arg_y %arg_z).          */
3818_spentry(builtin_ne)
3819        __(movl %arg_y,%imm0)
3820        __(orb %arg_z_b,%imm0_b)
3821        __(testb $fixnummask,%imm0_b)
3822        __(jne 1f)
3823        __(rcmpl(%arg_z,%arg_y))
3824        __(condition_to_boolean(ne,%imm0,%arg_z))
3825        __(ret)
38261:      __(jump_builtin(_builtin_ne,2))
3827_endsubp(builtin_ne)
3828
3829/* %arg_z <- (> %arg_y %arg_z).   */
3830_spentry(builtin_gt)
3831        __(movl %arg_y,%imm0)
3832        __(orb %arg_z_b,%imm0_b)
3833        __(testb $fixnummask,%imm0_b)
3834        __(jne 1f)
3835        __(rcmpl(%arg_y,%arg_z))
3836        __(condition_to_boolean(g,%imm0,%arg_z))
3837        __(ret)
38381:      __(jump_builtin(_builtin_gt,2))
3839_endsubp(builtin_gt)
3840
3841/* %arg_z <- (>= %arg_y %arg_z).          */
3842_spentry(builtin_ge)
3843        __(movl %arg_y,%imm0)
3844        __(orb %arg_z_b,%imm0_b)
3845        __(testb $fixnummask,%imm0_b)
3846        __(jne 1f)
3847        __(rcmpl(%arg_y,%arg_z))
3848        __(condition_to_boolean(ge,%imm0,%arg_z))
3849        __(ret)
38501:      __(jump_builtin(_builtin_ge,2))
3851_endsubp(builtin_ge)
3852
3853/* %arg_z <- (< %arg_y %arg_z).   */
3854_spentry(builtin_lt)
3855        __(movl %arg_y,%imm0)
3856        __(orb %arg_z_b,%imm0_b)
3857        __(testb $fixnummask,%imm0_b)
3858        __(jne 1f)
3859        __(rcmpl(%arg_y,%arg_z))
3860        __(condition_to_boolean(l,%imm0,%arg_z))
3861        __(ret)
38621:      __(jump_builtin(_builtin_lt,2))
3863_endsubp(builtin_lt)
3864
3865/* %arg_z <- (<= %arg_y %arg_z).   */
3866_spentry(builtin_le)
3867        __(movl %arg_y,%imm0)
3868        __(orb %arg_z_b,%imm0_b)
3869        __(testb $fixnummask,%imm0_b)
3870        __(jne 1f)
3871        __(rcmpl(%arg_y,%arg_z))
3872        __(condition_to_boolean(le,%imm0,%arg_z))
3873        __(ret)
38741:      __(jump_builtin(_builtin_le,2))
3875_endsubp(builtin_le)
3876
3877_spentry(builtin_eql)
3878        __(cmpl %arg_y,%arg_z)
3879        __(je 1f)
3880        /* Not EQ.  Could only possibly be EQL if both are tag-misc  */
3881        /* and both have the same subtag. */
3882        __(movl %arg_y,%imm0)
3883        __(andb $tagmask,%imm0_b)
3884        __(cmpb $tag_misc,%imm0_b)
3885        __(jne 2f)
3886        __(movb %arg_z_b,%imm0_bh)
3887        __(andb $tagmask,%imm0_bh)
3888        __(cmpb %imm0_bh,%imm0_b)
3889        __(jne 2f)
3890        __(extract_subtag(%arg_y,%imm0_b))
3891        __(extract_subtag(%arg_z,%imm0_bh))
3892        __(cmpb %imm0_b,%imm0_bh)
3893        __(jne 2f)
3894        __(jump_builtin(_builtin_eql,2))
38951:      __(movl $t_value,%arg_z)
3896        __(ret)
38972:      __(movl $nil_value,%arg_z)
3898        __(ret)
3899_endsubp(builtin_eql)
3900
3901_spentry(builtin_length)
3902        __(extract_fulltag(%arg_z,%imm0))
3903        __(cmpl $tag_list,%imm0)
3904        __(jz 2f)
3905        __(andl $tagmask,%imm0)
3906        __(cmpl $tag_misc,%imm0)
3907        __(jnz 8f)
3908        __(extract_subtag(%arg_z,%imm0_b))
3909        __(rcmpb(%imm0_b,$min_vector_subtag))
3910        __(jb 8f)
3911        __(je 1f)
3912        /* (simple-array * (*)) */
3913        __(movl %arg_z,%arg_y)
3914        __(vector_length(%arg_y,%arg_z))
3915        __(ret)
39161:      /* vector header */
3917        __(movl vectorH.logsize(%arg_z),%arg_z)
3918        __(ret)
39192:      /* list.  Maybe null, maybe dotted or circular. */
3920        __(movl $-fixnumone,%arg_y)
3921        __(movl %arg_z,%temp0)  /* fast pointer */
3922        __(movl %arg_z,%temp1)  /* slow pointer */
39233:      __(movb %temp0_b,%al)
3924        __(andb $fulltagmask,%al)
3925        __(addl $fixnumone,%arg_y)
3926        __(compare_reg_to_nil(%temp0))
3927        __(je 9f)
3928        __(cmpb $fulltag_cons,%al)
3929        __(jne 8f)
3930        __(movb %temp1_b,%ah)
3931        __(andb $fulltagmask,%ah)
3932        __(_cdr(%temp0,%temp0))
3933        __(testl $fixnumone,%arg_y)
3934        __(je 3b)
3935        __(cmpb $fulltag_cons,%ah)
3936        __(jne 8f)
3937        __(_cdr(%temp1,%temp1))
3938        __(cmpl %temp0,%temp1)
3939        __(jne 3b)
39408:
3941        __(jump_builtin(_builtin_length,1))
39429:
3943        __(movl %arg_y,%arg_z)
3944        __(ret)
3945_endsubp(builtin_length)
3946
3947_spentry(builtin_seqtype)
3948        __(extract_fulltag(%arg_z,%imm0))
3949        __(cmpb $fulltag_cons,%imm0_b)
3950        __(jz 1f)
3951        __(cmpb $tag_misc,%imm0_b)
3952        __(jne 2f)
3953        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3954        __(rcmpb(%imm0_b,$min_vector_subtag))
3955        __(jb 2f)
3956        __(movl $nil_value,%arg_z)
3957        __(ret)
39581:      __(movl $t_value,%arg_z)
3959        __(ret)
39602:
3961        __(jump_builtin(_builtin_seqtype,1))
3962_endsubp(builtin_seqtype)
3963
3964_spentry(builtin_assq)
3965        __(cmpl $nil_value,%arg_z)
3966        __(je 5f)
39671:      __(movl %arg_z,%imm0)
3968        __(andb $fulltagmask,%imm0_b)
3969        __(cmpb $fulltag_cons,%imm0_b)
3970        __(jne 2f)
3971        __(_car(%arg_z,%temp0))
3972        __(_cdr(%arg_z,%arg_z))
3973        __(cmpl $nil_value,%temp0)
3974        __(je 4f)
3975        __(movl %temp0,%imm0)
3976        __(andb $fulltagmask,%imm0_b)
3977        __(cmpb $fulltag_cons,%imm0_b)
3978        __(jne 3f)
3979        __(_car(%temp0,%temp1))
3980        __(cmpl %temp1,%arg_y)
3981        __(jne 4f)
3982        __(movl %temp0,%arg_z)
3983        __(ret)
39844:      __(cmpl $nil_value,%arg_z)
39855:      __(jnz 1b)
3986        __(repret)
39872:      __(uuo_error_reg_not_list(Rarg_z))
39883:      __(uuo_error_reg_not_list(Rtemp0))
3989_endsubp(builtin_assq)
3990
3991_spentry(builtin_memq)
3992        __(cmpl $nil_value,%arg_z)
3993        __(jmp 3f)
39941:      __(movb $fulltagmask,%imm0_b)
3995        __(andb %arg_z_b,%imm0_b)
3996        __(cmpb $fulltag_cons,%imm0_b)
3997        __(jne 2f)
3998        __(_car(%arg_z,%temp1))
3999        __(_cdr(%arg_z,%temp0))
4000        __(cmpl %temp1,%arg_y)
4001        __(jz 4f)
4002        __(cmpl $nil_value,%temp0)
4003        __(movl %temp0,%arg_z)
40043:      __(jnz 1b)
40054:      __(repret)
40062:      __(uuo_error_reg_not_list(Rarg_z))
4007_endsubp(builtin_memq)
4008
4009logbitp_max_bit = 30
4010
4011_spentry(builtin_logbitp)
4012        /* Call out unless: both args fixnums, arg_y in [0, logbitp_max_bit) */
4013        __(movl %arg_z,%imm0)
4014        __(orl %arg_y,%imm0)
4015        __(testb $fixnummask,%imm0_b)
4016        __(jnz 1f)
4017        __(unbox_fixnum(%arg_y,%imm0))
4018        __(js 1f)       /* bit number negative */
4019        __(addb $fixnumshift,%imm0_b)
4020        __(cmpl $logbitp_max_bit<<fixnumshift,%arg_y)
4021        __(jb 2f)
4022        __(movl $logbitp_max_bit-1+fixnumshift,%imm0)
40232:      __(bt %imm0,%arg_z)
4024        __(condition_to_boolean(b,%imm0,%arg_z))
4025        __(ret)
40261:      __(jump_builtin(_builtin_logbitp,2))
4027_endsubp(builtin_logbitp)
4028
4029_spentry(builtin_logior)
4030        __(movl %arg_y,%imm0)
4031        __(orb %arg_z_b,%imm0_b)
4032        __(testb $fixnummask,%imm0_b)
4033        __(jne 1f)
4034        __(orl %arg_y,%arg_z)
4035        __(ret)
40361:
4037        __(jump_builtin(_builtin_logior,2))
4038_endsubp(builtin_logior)
4039
4040_spentry(builtin_logand)
4041        __(movl %arg_y,%imm0)
4042        __(orb %arg_z_b,%imm0_b)
4043        __(testb $fixnummask,%imm0_b)
4044        __(jne 1f)
4045        __(andl %arg_y,%arg_z)
4046        __(ret)
40471:
4048        __(jump_builtin(_builtin_logand,2))
4049_endsubp(builtin_logand)
4050
4051_spentry(builtin_negate)
4052        __(testb $fixnummask,%arg_z_b)
4053        __(jne 1f)
4054        __(negl %arg_z)
4055        __(jo C(fix_one_bit_overflow))
4056        __(repret)
40571:
4058        __(jump_builtin(_builtin_negate,1))
4059_endsubp(builtin_negate)
4060
4061_spentry(builtin_logxor)
4062        __(movl %arg_y,%imm0)
4063        __(orb %arg_z_b,%imm0_b)
4064        __(testb $fixnummask,%imm0_b)
4065        __(jne 1f)
4066        __(xorl %arg_y,%arg_z)
4067        __(ret)
40681:
4069        __(jump_builtin(_builtin_logxor,2))
4070_endsubp(builtin_logxor)
4071
4072/* temp0 = vector, arg_y = index, arg_z = newval */
4073_spentry(aset1)
4074        __(extract_typecode(%temp0,%imm0))
4075        __(box_fixnum(%imm0,%temp1))
4076        __(cmpb $min_vector_subtag,%imm0_b)
4077        __(ja _SPsubtag_misc_set)
4078        /* push frame... */
4079        __(pop %temp1)
4080        __(push $reserved_frame_marker)
4081        __(push $reserved_frame_marker)
4082        __(push %temp0)
4083        __(push %temp1)
4084        /* and fall through... */
4085_endsubp(aset1)
4086
4087_spentry(builtin_aset1)
4088        __(jump_builtin(_builtin_aset1,3))
4089_endsubp(builtin_aset1)
4090
4091_spentry(builtin_ash)
4092        __(movl %arg_y,%imm0)
4093        __(orb %arg_z_b,%imm0_b)
4094        __(testb $fixnummask,%imm0_b)
4095        __(jne 9f)
4096        __(unbox_fixnum(%arg_z,%imm0))
4097        /* Z flag set if zero ASH shift count */
4098        __(jnz 1f)
4099        __(movl %arg_y,%arg_z) /* shift by 0 */
4100        __(ret)
41011:      __(jns 3f)
4102        __(rcmpl(%imm0,$-31))
4103        __(jg 2f)
4104        __(unbox_fixnum(%arg_y,%imm0))
4105        __(sar $31,%imm0)
4106        __(box_fixnum(%imm0,%arg_z))
4107        __(ret)
41082:      /* Right-shift by small fixnum */
4109        __(negb %imm0_b)
4110        __(movzbl %imm0_b,%ecx)
4111        __(unbox_fixnum(%arg_y,%imm0))
4112        __(sar %cl,%imm0)
4113        __(box_fixnum(%imm0,%arg_z))
4114        __(ret)
41153:      /* Left shift by fixnum.  We can't shift by more than 31 bits, */
4116        /* though shifting by 32 is actually easy. */
4117        __(rcmpl(%imm0,$32))
4118        __(jg 9f)
4119        __(jne 4f)
4120        /* left-shift by 32 bits exactly */
4121        __(unbox_fixnum(%arg_y,%imm0))
4122        __(movd %imm0,%mm0)
4123        __(psllq $32,%mm0)
4124        __(jmp _SPmakes64)
41254:      /* left-shift by 1..31 bits. Safe to move shift count to %cl */
4126        __(movd %imm0,%mm1)     /* shift count */
4127        __(unbox_fixnum(%arg_y,%imm0))
4128        __(movd %imm0,%mm0)
4129        __(sarl $31,%imm0)      /* propagate sign */
4130        __(movd %imm0,%mm2)
4131        __(pshufw $0x4e,%mm2,%mm2) /* swap hi/lo halves */
4132        __(por %mm2,%mm0)
4133        __(psllq %mm1,%mm0)
4134        __(jmp _SPmakes64)
41359:
4136        __(jump_builtin(_builtin_ash,2))
4137_endsubp(builtin_ash)
4138
4139_spentry(builtin_aref1)
4140        __(extract_typecode(%arg_y,%imm0))
4141        __(box_fixnum_no_flags(%imm0,%temp0))
4142        __(cmpb $min_vector_subtag,%imm0_b)
4143        __(ja _SPsubtag_misc_ref)
4144        __(jump_builtin(_builtin_aref1,2))
4145_endsubp(builtin_aref1)
4146
4147/* Maybe check the x87 tag word to see if st(0) is valid and pop it */
4148/* if so.  This might allow us to avoid having to have a priori */
4149/* knowledge of whether a foreign function returns a floating-point result. */
4150/* backlink to saved %esp, below */
4151/* arg n-1 */
4152/* arg n-2 */
4153/* ... */
4154/* arg 0 */
4155/* space for alignment */
4156/* previous %esp */
4157
4158_spentry(ffcall)
4159LocalLabelPrefix[]ffcall:
4160        __(unbox_fixnum(%arg_z,%imm0))
4161        __(testb $fixnummask,%arg_z_b)
4162        __(je 0f)
4163        __(movl macptr.address(%arg_z),%imm0)
41640:
4165        /* Save lisp registers. */
4166        __(push %ebp)
4167        __(mov %esp,%ebp)
4168        __(push %temp0)                 
4169        __(push %temp1)                 
4170        __(push %arg_y)                 
4171        __(push %arg_z)                 
4172        __(push %fn)         
4173        __ifdef([WIN32_ES_HACK])
4174         __(movl rcontext(tcr.linear),%ebx)
4175        __endif
4176        __(movl %esp,rcontext(tcr.save_vsp))
4177        __(movl %ebp,rcontext(tcr.save_ebp))
4178        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
4179        __(movl rcontext(tcr.foreign_sp),%esp)
4180        /* preserve state of direction flag */
4181        __(pushfl)
4182        __(popl rcontext(tcr.save_eflags))
4183        __(cld)       
4184        __(stmxcsr rcontext(tcr.lisp_mxcsr))
4185        __(emms)
4186        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
4187        __(movl (%esp),%ebp)
4188LocalLabelPrefix[]ffcall_setup:
4189        __(lea 15(%esp),%ecx)
4190        __(andl $-16,%ecx)
4191        __(movl %ecx,%esp)
4192/*      __(addl $node_size,%esp) */
4193        __ifdef([WIN32_ES_HACK])
4194         __(push %ds)
4195         __(pop %es)
4196        __endif
4197LocalLabelPrefix[]ffcall_call:
4198        __(call *%eax)
4199        __ifdef([WIN32_ES_HACK])
4200         __(movw tcr.ldt_selector(%ebx),%rcontext_reg)
4201        __endif
4202LocalLabelPrefix[]ffcall_call_end:
4203        __(movl %ebp,%esp)
4204        __(movl %esp,rcontext(tcr.foreign_sp))
4205        /* The high word of a 64-bit result would be in %edx right now.
4206           There doesn't seem to be any other good place to put this,
4207           though %edx is often undefined at this point. */
4208        __(mov %edx,rcontext(tcr.unboxed1))
4209        __(clr %arg_z)
4210        __(clr %arg_y)
4211        __(clr %temp1)
4212        __(clr %temp0)
4213        __(clr %fn)
4214        __(pxor %fpzero,%fpzero)
4215        __(cmpb $0,C(bogus_fp_exceptions))
4216        __(je 0f)
4217        __(movl %arg_z,rcontext(tcr.ffi_exception))
4218        __(jmp 1f)
42190:
4220        __ifdef([SSE2_MATH_LIB])
4221        __(stmxcsr rcontext(tcr.ffi_exception))
4222        __else
4223        __(fnstsw rcontext(tcr.ffi_exception))
4224        __(fnclex)
4225        __endif
42261:      __(pushl rcontext(tcr.save_eflags))
4227        __(popfl)
4228        __(movl rcontext(tcr.save_vsp),%esp)
4229        __(movl rcontext(tcr.save_ebp),%ebp)
4230        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
4231        __(pop %fn)             
4232        __(pop %arg_z)           
4233        __(pop %arg_y)           
4234        __(pop %temp1)
4235        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
4236        __(check_pending_interrupt(%temp0))
4237        __(pop %temp0)
4238        __(leave)
4239        __(ret)
4240        /* need to deal with NSExceptions and Objc-2.0 execptions */
4241_endsubp(ffcall)
4242
4243_spentry(ffcall_return_registers)
4244        __(hlt)
4245_endsubp(ffcall_return_registers)
4246
4247/* We need to reserve a frame here if (a) nothing else was already pushed
4248/* and (b) we push something (e.g., more than 2 args in the lexpr) */
4249_spentry(spread_lexprz)
4250        new_local_labels()
4251        __(movl (%arg_z),%imm0) /* lexpr count */
4252        __(leal node_size(%arg_z,%imm0),%arg_y)
4253        __(movd %arg_y,%mm1)
4254        __(test %nargs,%nargs) /* anything pushed by caller ? */
4255        __(jne 0f)              /* yes, caller has already created frame. */
4256        __(cmpl $(nargregs*node_size),%imm0) /* will we push anything ? */
4257        __(jbe 0f)
4258        __(push $reserved_frame_marker)
4259        __(push $reserved_frame_marker)
42600:      __(addl %imm0,%nargs)
4261        __(cmpl $(1*node_size),%imm0)
4262        __(ja 2f)
4263        __(je 1f)
4264        /* lexpr count was 0; vpop the args that */
4265        /* were pushed by the caller */
4266        __(test %nargs,%nargs)
4267        __(je local_label(all_args_popped))
4268        __(pop %arg_z)
4269local_label(maybe_pop_y):
4270        __(cmpl $(1*node_size),%nargs)
4271        __(je local_label(all_args_popped))
4272        __(pop %arg_y)
4273local_label(all_args_popped):   
4274        /* If all args fit in registers but some were pushed */
4275        /* by the caller, discard the reserved frame that the caller */
4276        /* pushed.         */
4277        __(cmpl %imm0,%nargs)
4278        __(je local_label(go))
4279        __(cmpl $(nargregs*node_size),%nargs)
4280        __(ja local_label(go))
4281        __(addl $(2*node_size),%esp)
4282local_label(go):
4283        __(jmp *%ra0)
4284
4285        /* lexpr count is two or more: vpush args from the lexpr until */
4286        /* we have only two left, then assign them to arg_y and arg_z */
42872:      __(cmpl $(2*node_size),%imm0)
4288        __(je local_label(push_loop_end))
4289local_label(push_loop):
4290        __(lea -1*node_size(%imm0),%imm0)
4291        __(push -node_size(%arg_y))
4292        __(lea -1*node_size(%arg_y),%arg_y)
4293        __(cmpl $(2*node_size),%imm0)
4294        __(jne 2b)
4295local_label(push_loop_end):
4296        __(movl -node_size*2(%arg_y),%arg_z)
4297        __(movl -node_size*1(%arg_y),%arg_y)
4298        __(jmp *%ra0)
4299        /* lexpr count is one: set arg_z from the lexpr, */
4300        /* maybe vpop arg_y  */
43011:      __(movl -node_size*1(%arg_y),%arg_z)
4302        __(jmp local_label(maybe_pop_y))
4303_endsubp(spread_lexprz)
4304
4305_spentry(callback)
4306        __(push %ebp)
4307        __(movl %esp,%ebp)
4308        /* C scalar args are already on the stack. */
4309        /* arg word 0 at 8(%ebp), word 1 at 12(%ebp), etc. */
4310
4311        /* %eax is passed to us via the callback trampoline.
4312           bits 0-22: callback index
4313           bit 23: flag, set if we need to discard hidden arg on return
4314                   (ignored when upper 8 bits are non-zero)
4315           bits 24-31: arg words to discard on return (_stdcall for win32) */
4316       
4317        /* Reserve some space for results, relative to the
4318           current %ebp.  We may need quite a bit of it. */
4319        __(subl $20,%esp)
4320        __(movl $0,-16(%ebp)) /* No FP result */
4321        __(btl $23,%eax)      /* set CF if we need to discard hidden arg */
4322        __(pushfl)            /* and save for later */
4323        __(movl %eax,%ecx)    /* extract args-discard count */
4324        __(shrl $24,%ecx)
4325        __(andl $0x007fffff,%eax) /* callback index */
4326        __(movl %ecx,-20(%ebp))
4327        /* If the C stack is 16-byte aligned by convention,
4328           it should still be, and this'll be a NOP. */
4329        __(andl $~15,%esp)
4330        /* C NVRs */
4331        __(push %edi)
4332        __(push %esi)
4333        __(push %ebx)
4334        __(push %ebp)
4335        __(box_fixnum(%eax,%esi))       /* put callback index in arg_y */
4336        __(cmpb $0,C(rcontext_readonly))
4337        __(jne 0f)
4338        __(ref_global(get_tcr,%eax))
4339        __(subl $12,%esp)               /* alignment */
4340        __(push $1)                     /* stack now 16-byte aligned */
4341        __(call *%eax)
4342        __(addl $16,%esp)               /* discard arg, alignment words */
4343        /* linear TCR addr now in %eax */
4344        __(movw tcr.ldt_selector(%eax), %rcontext_reg)
43450:     
4346
4347        /* ebp is 16-byte aligned, and we've pushed 4 words.  Make
4348          sure that when we push old foreign_sp, %esp will be 16-byte
4349          aligned again */
4350        __(subl $8,%esp)
4351        __(pushl rcontext(tcr.save_ebp))  /* mark cstack frame's "owner" */
4352        __(push rcontext(tcr.foreign_sp))
4353        __(movl %esp,rcontext(tcr.foreign_sp))
4354        __(clr %arg_z)
4355        /* arg_y contains callback index */
4356        __(clr %temp1)
4357        __(clr %temp0)
4358        __(clr %fn)
4359        __(pxor %fpzero,%fpzero)
4360        __(movl rcontext(tcr.save_vsp),%esp)
4361        __(movl %ebp,%arg_z)
4362        __(movl rcontext(tcr.save_ebp),%ebp)
4363        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
4364        __(stmxcsr rcontext(tcr.foreign_mxcsr))
4365        __(andb $~mxcsr_all_exceptions,rcontext(tcr.foreign_mxcsr))
4366        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
4367        __(movl $nrs.callbacks,%fname)
4368        __(check_cstack_alignment())
4369        __(push $local_label(back_from_callback))
4370        __(set_nargs(2))
4371        __(jump_fname())
4372__(tra(local_label(back_from_callback)))
4373        __(movl %esp,rcontext(tcr.save_vsp))
4374        __(movl %ebp,rcontext(tcr.save_ebp))
4375        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
4376        __(movl rcontext(tcr.foreign_sp),%esp)
4377        __(stmxcsr rcontext(tcr.lisp_mxcsr))
4378        __(emms)
4379        __(pop rcontext(tcr.foreign_sp))
4380        __(addl $12,%esp)       /* discard alignment padding */
4381        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
4382        __ifdef([WIN32_ES_HACK])
4383         __(push %ds)
4384         __(pop %es)
4385        __endif
4386        __(pop %ebp)
4387        __(pop %ebx)
4388        __(pop %esi)
4389        __(pop %edi)
4390        __(movl -12(%ebp),%ecx) /* magic value for ObjC bridge */
4391        __(cmpb $1,-16(%ebp))
4392        __(jae 1f)
4393        __(movl -8(%ebp),%eax)
4394        __(movl -4(%ebp),%edx)
4395        __ifdef([WIN_32])
4396         __(cmpl $0,-20(%ebp))
4397         __(jne local_label(winapi_return))
4398        __endif
4399        /* since we aligned the stack after pushing flags, we're not
4400           really sure where %esp is relative to where flags were saved.
4401           We do know where the saved flags are relative to %ebp, so use
4402           that to establish %esp before the popfl.
4403        */
4404        __(lea -24(%ebp),%esp)
4405        __(popfl)       /* flags from bt way back when */
4406        __(jc local_label(discard_first_arg))
4407        __(leave)
4408        __(ret)
44091:      __(jne 2f)
4410        /* single float return in x87 */
4411        __(flds -8(%ebp))
4412        __ifdef([WIN_32])
4413         __(cmpl $0,-20(%ebp))
4414         __(jne local_label(winapi_return))
4415        __endif
4416        __(leave)
4417        __(ret)
44182:      /* double-float return in x87 */
4419        __(fldl -8(%ebp))
4420        __ifdef([WIN_32])
4421         __(cmpl $0,-20(%ebp))
4422         __(jne local_label(winapi_return))
4423        __endif
4424        __(leave)
4425        __(ret)
4426        __ifdef([WIN_32])
4427local_label(winapi_return):
4428          __(movl -20(%ebp),%ecx)
4429          __(leave)
4430         /* %ecx is non-zero and contains count of arg words to pop */
4431          __(popl -4(%esp,%ecx,4))
4432          __(leal -4(%esp,%ecx,4),%esp)
4433          __(ret)
4434        __endif
4435local_label(discard_first_arg):
4436        __(leave)
4437        __(ret $4)
4438_endsubp(callback)
4439
4440/* temp0 = array, arg_y = i, arg_z = j. Typecheck everything.
4441   We don't know whether the array is alleged to be simple or
4442   not, and don't know anythng about the element type.  */
4443
4444_spentry(aref2)
4445        __(testl $fixnummask,%arg_y)
4446        __(jne 0f)
4447        __(testb $fixnummask,%arg_z_b)
4448        __(jne 1f)
4449        __(extract_typecode(%temp0,%imm0))
4450        __(cmpb $subtag_arrayH,%imm0_b)
4451        __(jne 2f)
4452        __(cmpl $2<<fixnumshift,arrayH.rank(%temp0))
4453        __(jne 2f)
4454        __(cmpl arrayH.dim0(%temp0),%arg_y)
4455        __(jae 3f)
4456        __(movl arrayH.dim0+node_size(%temp0),%imm0)
4457        __(cmpl %imm0,%arg_z)
4458        __(jae 4f)
4459        __(sarl $fixnumshift,%imm0)
4460        __(imull %arg_y,%imm0)
4461        __(addl %imm0,%arg_z)
4462        __(movl %temp0,%arg_y)
4463        __(xorl %temp1,%temp1)
44646:      __(addl arrayH.displacement(%arg_y),%arg_z)
4465        __(movl arrayH.data_vector(%arg_y),%arg_y)
4466        __(extract_subtag(%arg_y,%imm0_b))
4467        __(cmpb $subtag_vectorH,%imm0_b)
4468        __(ja C(misc_ref_common))
4469        __(jmp 6b)
44700:      __(uuo_error_reg_not_fixnum(Rarg_y))
44711:      __(uuo_error_reg_not_fixnum(Rarg_z))
44722:      __(uuo_error_reg_not_type(Rtemp0,error_object_not_array_2d))
44733:      __(uuo_error_array_bounds(Rarg_y,Rtemp0))
44744:      __(uuo_error_array_bounds(Rarg_z,Rtemp0))
4475
4476_endsubp(aref2)
4477
4478/* Like aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = k */
4479_spentry(aref3)
4480        __(testb $fixnummask,%temp0_b)
4481        __(jne 0f)
4482        __(testl $fixnummask,%arg_y)
4483        __(jne 1f)
4484        __(testb $fixnummask,%arg_z_b)
4485        __(jne 2f)
4486        __(extract_typecode(%temp1,%imm0))
4487        __(cmpb $subtag_arrayH,%imm0_b)
4488        __(jne 3f)
4489        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4490        __(jne 3f)
4491        __(cmpl arrayH.dim0(%temp1),%temp0)
4492        __(jae 4f)
4493        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4494        __(cmpl %imm0,%arg_y)
4495        __(jae 5f)
4496        __(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_z)
4497        __(jae 6f)
4498        /* index computation: k + dim2 * (j + dim1 * i) */
4499        /* (plus minor fussing for fixnum scaling) */
4500        __(sarl $fixnumshift,%imm0)
4501        __(imull %imm0,%temp0)
4502        __(addl %arg_y,%temp0)
4503        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
4504        __(sarl $fixnumshift,%imm0)
4505        __(imull %imm0,%temp0)
4506        __(addl %temp0,%arg_z)
4507        __(movl %temp1,%arg_y)
45088:      __(addl arrayH.displacement(%arg_y),%arg_z)
4509        __(movl arrayH.data_vector(%arg_y),%arg_y)
4510        __(extract_subtag(%arg_y,%imm0_b))
4511        __(cmpb $subtag_vectorH,%imm0_b)
4512        __(ja C(misc_ref_common))
4513        __(jmp 8b)
45140:      __(uuo_error_reg_not_fixnum(Rtemp0))
45151:      __(uuo_error_reg_not_fixnum(Rarg_y))
45162:      __(uuo_error_reg_not_fixnum(Rarg_z))
45173:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
45184:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
45195:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
45206:      __(uuo_error_array_bounds(Rarg_z,Rtemp1))
4521_endsubp(aref3)
4522
4523/* As with aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = new_value */
4524_spentry(aset2)
4525        __(testb $fixnummask,%temp0_b)
4526        __(jne 0f)
4527        __(testl $fixnummask,%arg_y)
4528        __(jne 1f)
4529        __(extract_typecode(%temp1,%imm0))
4530        __(cmpb $subtag_arrayH,%imm0_b)
4531        __(jne 2f)
4532        __(cmpl $2<<fixnumshift,arrayH.rank(%temp1))
4533        __(jne 2f)
4534        __(cmpl arrayH.dim0(%temp1),%temp0)
4535        __(jae 3f)
4536        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4537        __(cmpl %imm0,%arg_y)
4538        __(jae 4f)
4539        __(sarl $fixnumshift,%imm0)
4540        __(imull %temp0,%imm0)
4541        __(addl %imm0,%arg_y)
4542        __(movl %temp1,%temp0)
4543        __(xorl %temp1,%temp1)
45446:      __(addl arrayH.displacement(%temp0),%arg_y)
4545        __(movl arrayH.data_vector(%temp0),%temp0)
4546        __(extract_subtag(%temp0,%imm0_b))
4547        __(cmpb $subtag_vectorH,%imm0_b)
4548        __(ja C(misc_set_common))
4549        __(jmp 6b)
45500:      __(uuo_error_reg_not_fixnum(Rtemp0))
45511:      __(uuo_error_reg_not_fixnum(Rarg_y))
45522:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_2d))
45533:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
45544:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
4555_endsubp(aset2)
4556
4557/* temp1 = array, (%esp) = i, temp0 = j, arg_y = k, arg_z = newval */
4558_spentry(aset3)
4559        __(testb $fixnummask,(%esp))
4560        __(jne 0f)
4561        __(testb $fixnummask,%temp0_b)
4562        __(jne 1f)
4563        __(testl $fixnummask,%arg_y)
4564        __(jne 2f)
4565        __(extract_typecode(%temp1,%imm0))
4566        __(cmpb $subtag_arrayH,%imm0_b)
4567        __(jne 3f)
4568        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4569        __(jne 3f)
4570        __(movl arrayH.dim0(%temp1),%imm0)
4571        __(cmpl %imm0,(%esp))   /* i on stack */
4572        __(jae 4f)
4573        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4574        __(cmpl %imm0,%temp0)
4575        __(jae 5f)
4576        __(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_y)
4577        __(jae 6f)
4578        /* index computation: k + dim2 * (j + dim1 * i) */
4579        /* (plus minor fussing for fixnum scaling) */
4580        __(sarl $fixnumshift,%imm0)
4581        __(imull (%esp),%imm0)  /* i on stack */
4582        __(addl %imm0,%temp0)
4583        __(addl $node_size,%esp)
4584        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
4585        __(sarl $fixnumshift,%imm0)
4586        __(imull %imm0,%temp0)
4587        __(addl %temp0,%arg_y)
4588        __(movl %temp1,%temp0)
45898:      __(addl arrayH.displacement(%temp0),%arg_y)
4590        __(movl arrayH.data_vector(%temp0),%temp0)
4591        __(extract_subtag(%temp0,%imm0_b))
4592        __(cmpb $subtag_vectorH,%imm0_b)
4593        __(ja C(misc_set_common))
4594        __(jmp 8b)
45950:      __(pop %temp0)  /* supplied i */
4596        __(uuo_error_reg_not_fixnum(Rtemp0))
45971:      __(uuo_error_reg_not_fixnum(Rtemp0))
45982:      __(uuo_error_reg_not_fixnum(Rarg_y))
45993:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
46004:      __(pop %imm0)   /* supplied i is on stack */
4601        __(uuo_error_array_bounds(Rimm0,Rtemp1))
46025:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
46036:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
4604_endsubp(aset3)
4605
4606/* Prepend all but the first seven (6 words of code & other immediate data,
4607/* plus inner fn) and last (lfbits) elements of %fn to the "arglist". */
4608_spentry(call_closure)
4609        new_local_labels()
4610        __(vector_length(%fn,%imm0))
4611        __(subl $8<<fixnumshift,%imm0)  /* imm0 = inherited arg count */
4612        __(lea (%nargs,%imm0),%temp0)
4613        __(cmpl $nargregs<<fixnumshift,%temp0)
4614        __(jna local_label(regs_only))  /* either: 1 arg, 1 inherited, or */
4615                                        /* no args, 2 inherited */
4616        __(pop rcontext(tcr.save0))             /* save return address */
4617        __(cmpl $nargregs<<fixnumshift,%nargs)
4618        __(jna local_label(no_insert))
4619
4620/* Some arguments have already been pushed.  Push %imm0's worth */
4621/* of NILs, copy those arguments that have already been vpushed from */
4622/* the old TOS to the new, then insert all of the inherited args */
4623/* and go to the function. */
4624
4625        __(mov %imm0,%temp0)
4626local_label(push_nil_loop):
4627        __(push $nil_value)
4628        __(sub $fixnumone,%temp0)
4629        __(jne local_label(push_nil_loop))
4630
4631/* Need to use arg regs as temporaries.  Stash them in the spill area. */
4632        __(movl %arg_y,rcontext(tcr.save1))
4633        __(movl %arg_z,rcontext(tcr.save2))
4634
4635        __(leal (%esp,%imm0),%temp0)    /* start of already-pushed args */
4636        __(leal -nargregs<<fixnumshift(%nargs),%arg_y) /* args pushed */
4637        __(movd %imm0,%mm0)     /* save inherited arg count */
4638        __(xorl %imm0,%imm0)
4639local_label(copy_already_loop):
4640        __(movl (%temp0,%imm0),%arg_z)
4641        __(movl %arg_z,(%esp,%imm0))
4642        __(addl $fixnumone,%imm0)
4643        __(cmpl %imm0,%arg_y)
4644        __(jne local_label(copy_already_loop))
4645
4646        __(lea -node_size(%temp0,%imm0),%arg_y) /* start of args on stack */
4647        __(movl $7<<fixnumshift,%temp0) /* skip code, new fn */
4648        __(movd %mm0,%imm0)
4649local_label(insert_loop):
4650        __(movl misc_data_offset(%fn,%temp0),%arg_z)
4651        __(addl $node_size,%temp0)
4652        __(addl $fixnumone,%nargs)
4653        __(movl %arg_z,(%arg_y))
4654        __(subl $node_size,%arg_y)
4655        __(subl $fixnumone,%imm0)
4656        __(jne local_label(insert_loop))
4657
4658        /* Recover arg regs, saved earlier */
4659        __(movl rcontext(tcr.save1),%arg_y)
4660        __(movl rcontext(tcr.save2),%arg_z)
4661        __(jmp local_label(go))
4662       
4663/* Here if no args were pushed by the caller. */
4664/* cases: */
4665/* no args, more than two inherited args */
4666/* a single arg in arg_z, more than one inherited arg */
4667/* two args in arg_y and arg_z, some number of inherited args */
4668
4669/* Therefore, we're always going to have to push something (the sum of */
4670/* %nargs and %imm0 will always be greater than $nargregs), and */
4671/* we will have to reserve space for a stack frame. */
4672/* The 0 args, 2 inherited case and the 1 arg, 1 inherited case get */
4673/* handled at local_label(regs_ony). */
4674       
4675local_label(no_insert):
4676        /* Reserve space for a stack frame */
4677        __(push $reserved_frame_marker)
4678        __(push $reserved_frame_marker)
4679        __(lea 7<<fixnumshift(%imm0),%temp0)    /* last inherited arg */
4680        __(rcmpl(%nargs,$fixnumone))
4681        __(je local_label(set_arg_y))
4682        __(jb local_label(set_y_z))
4683        /* %nargs = $nargregs (i.e., 2), vpush remaining inherited vars. */
4684
4685local_label(vpush_remaining):
4686        __(movl $7<<fixnumshift,%temp0)
4687local_label(vpush_remaining_loop):
4688        __(push misc_data_offset(%fn,%temp0))
4689        __(add $node_size,%temp0)
4690        __(add $fixnumone,%nargs)
4691        __(sub $node_size,%imm0)
4692        __(jnz local_label(vpush_remaining_loop))
4693        __(jmp local_label(go))
4694       
4695local_label(set_arg_y):
4696        /* one arg in arg_z.  set arg_y and vpush remaining inherited args */
4697        __(subl $node_size,%temp0)
4698        __(movl misc_data_offset(%fn,%temp0),%arg_y)
4699        __(addl $fixnumone,%nargs)
4700        __(subl $fixnumone,%imm0)
4701        __(jmp local_label(vpush_remaining))
4702local_label(set_y_z):
4703        __(subl $node_size,%temp0)
4704        __(movl misc_data_offset(%fn,%temp0),%arg_z)
4705        __(addl $fixnumone,%nargs)
4706        __(subl $fixnumone,%imm0)
4707        __(jmp local_label(set_arg_y))
4708
4709local_label(go):
4710        __(movl misc_data_offset+(6*node_size)(%fn),%fn)
4711        __(push rcontext(tcr.save0))    /* restore return addr */
4712        __(movapd %fpzero,rcontext(tcr.save0))  /* clear out spill area */
4713        __(jmp *%fn)
4714local_label(regs_only):
4715        __(lea 7<<fixnumshift(%imm0),%temp0)
4716        __(test %nargs,%nargs)
4717        __(jne local_label(one_arg))
4718        /* no args passed, two inherited args */
4719        __(movl misc_data_offset-node_size(%fn,%temp0),%arg_z)
4720        __(cmpl $node_size,%imm0)
4721        __(je local_label(rgo))
4722        __(movl misc_data_offset-(node_size*2)(%fn,%temp0),%arg_y)
4723local_label(rgo):
4724        __(addl %imm0,%nargs)
4725        __(jmp *misc_data_offset+(6*node_size)(%fn))
4726local_label(one_arg):
4727        /* one arg was passed, so there's one inherited arg */
4728        __(movl misc_data_offset-node_size(%fn,%temp0),%arg_y)
4729        __(jmp local_label(rgo))
4730_endsubp(call_closure)
4731
4732_spentry(poweropen_callbackX)
4733        __(hlt)
4734_endsubp(poweropen_callbackX)
4735
4736_spentry(poweropen_ffcallX)
4737        __(hlt)
4738_endsubp(poweropen_ffcallX)
4739
4740_spentry(eabi_ff_call)
4741        __(hlt)
4742_endsubp(eabi_ff_call)
4743
4744_spentry(eabi_callback)
4745        __(hlt)
4746_endsubp(eabi_callback)
4747
4748
4749/* Unused, and often not used on PPC either  */
4750_spentry(callbuiltin)
4751        __(hlt)
4752_endsubp(callbuiltin)
4753
4754_spentry(callbuiltin0)
4755        __(hlt)
4756_endsubp(callbuiltin0)
4757
4758_spentry(callbuiltin1)
4759        __(hlt)
4760_endsubp(callbuiltin1)
4761
4762_spentry(callbuiltin2)
4763        __(hlt)
4764_endsubp(callbuiltin2)
4765
4766_spentry(callbuiltin3)
4767        __(hlt)
4768_endsubp(callbuiltin3)
4769
4770_spentry(restorefullcontext)
4771        __(hlt)
4772_endsubp(restorefullcontext)
4773
4774_spentry(savecontextvsp)
4775        __(hlt)
4776_endsubp(savecontextvsp)
4777
4778_spentry(savecontext0)
4779        __(hlt)
4780_endsubp(savecontext0)
4781
4782_spentry(restorecontext)
4783        __(hlt)
4784_endsubp(restorecontext)
4785
4786_spentry(stkconsyz)
4787        __(hlt)
4788_endsubp(stkconsyz)
4789
4790_spentry(stkvcell0)
4791        __(hlt)
4792_endsubp(stkvcell0)
4793
4794_spentry(stkvcellvsp)
4795        __(hlt)
4796_endsubp(stkvcellvsp)
4797
4798_spentry(breakpoint)
4799        __(hlt)
4800_endsubp(breakpoint)
4801
4802_spentry(unused_6)
4803        __(hlt)
4804Xspentry_end:
4805_endsubp(unused_6)
4806        .data
4807        .globl C(spentry_start)
4808        .globl C(spentry_end)
4809C(spentry_start):       .long Xspentry_start
4810C(spentry_end):         .long Xspentry_end
4811       
Note: See TracBrowser for help on using the repository browser.